Author: desruisseaux
Date: Wed Jun 8 17:08:03 2016
New Revision: 1747422
URL: http://svn.apache.org/viewvc?rev=1747422&view=rev
Log:
Better inference of whether an argument given to an application (console or OpenOffice add-ins)
should be understood as an AUTHORITY:CODE pattern or a PROTOCOL:FILE pattern.
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/CodeType.java
- copied, changed from r1747421, sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/CodeType.java
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java
(with props)
Removed:
sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/CodeType.java
Modified:
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Referencing.java
sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Transformer.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
Modified: sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataCommand.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -16,11 +16,8 @@
*/
package org.apache.sis.console;
-import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
import java.io.Console;
import java.io.IOException;
import javax.xml.bind.Marshaller;
@@ -39,6 +36,7 @@ import org.apache.sis.referencing.CRS;
import org.apache.sis.storage.DataStore;
import org.apache.sis.storage.DataStores;
import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.internal.storage.CodeType;
import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.collection.TreeTableFormat;
@@ -58,18 +56,6 @@ import org.apache.sis.xml.XML;
*/
class MetadataCommand extends CommandRunner {
/**
- * The protocol part of the filename to be recognized as a CRS authority.
- * In such case, this class will delegate to {@link CRS#forCode(String)}
- * instead of opening the file.
- */
- static final Set<String> AUTHORITIES = new HashSet<>(Arrays.asList("URN",
"EPSG", "CRS", "AUTO", "AUTO2"));
-
- /**
- * Length of the longest authority name declared in {@link #AUTHORITIES}.
- */
- static final int MAX_AUTHORITY_LENGTH = 5;
-
- /**
* The output format.
*/
static enum Format {
@@ -142,39 +128,7 @@ class MetadataCommand extends CommandRun
}
/**
- * Returns {@code true} if the given argument begins with one of the known authorities
- * ("URN", "EPSG", "CRS", "AUTO", <i>etc.</i>).
- */
- static boolean isAuthorityCode(final String code) {
- final char[] authority = new char[MAX_AUTHORITY_LENGTH];
- final int length = code.length();
- int p = 0, i = 0;
- while (i < length) {
- final int c = code.codePointAt(i);
- if (c == ':') {
- if (!AUTHORITIES.contains(new String(authority, 0, p))) {
- break;
- }
- return true;
- }
- if (!Character.isWhitespace(c)) {
- if (p >= MAX_AUTHORITY_LENGTH || !Character.isLetterOrDigit(c)) {
- break;
- }
- /*
- * Casting to char is okay because AUTHORITIES contains only ASCII values.
- * If 'c' was a supplemental Unicode value, then the result of the cast
- * would not match any AUTHORITIES value anyway.
- */
- authority[p++] = (char) Character.toUpperCase(c);
- }
- i += Character.charCount(c);
- }
- return false;
- }
-
- /**
- * If the given argument begins with one of the known authorities ("URN", "EPSG", "CRS",
"AUTO", <i>etc.</i>),
+ * If the given argument seems to be an authority code ("URN", "EPSG", "CRS", "AUTO",
<i>etc.</i>),
* delegates to {@link CRS#forCode(String)}. Otherwise reads the metadata using a datastore.
*
* @return A {@link Metadata} or {@link CoordinateReferenceSystem} instance, or {@code
null} if none.
@@ -189,7 +143,7 @@ class MetadataCommand extends CommandRun
return null;
} else {
final String file = files.get(0);
- if (isAuthorityCode(file)) {
+ if (CodeType.guess(file).isCRS) {
return CRS.forCode(file);
} else {
try (DataStore store = DataStores.open(file)) {
Modified: sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/TransformCommand.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -53,6 +53,7 @@ import org.apache.sis.geometry.Immutable
import org.apache.sis.internal.referencing.Formulas;
import org.apache.sis.internal.referencing.DirectPositionView;
import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.storage.CodeType;
import org.apache.sis.internal.util.PatchedUnitFormat;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.CRS;
@@ -164,7 +165,7 @@ final class TransformCommand extends Met
final String name = option.label();
throw new InvalidOptionException(Errors.format(Errors.Keys.MissingValueForOption_1,
name), name);
}
- if (isAuthorityCode(identifier)) try {
+ if (CodeType.guess(identifier).isCRS) try {
return CRS.forCode(identifier);
} catch (NoSuchAuthorityCodeException e) {
final String name = option.label();
Modified: sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-console/src/test/java/org/apache/sis/console/MetadataCommandTest.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -37,19 +37,6 @@ import static org.junit.Assert.*;
@DependsOn(CommandRunnerTest.class)
public final strictfp class MetadataCommandTest extends TestCase {
/**
- * Verifies the {@link MetadataCommand#MAX_AUTHORITY_LENGTH} value.
- */
- @Test
- public void verifyMaxAuthorityLength() {
- int length = 0;
- for (final String authority : MetadataCommand.AUTHORITIES) {
- final int c = authority.length();
- if (c > length) length = c;
- }
- assertEquals("MAX_AUTHORITY_LENGTH", length, MetadataCommand.MAX_AUTHORITY_LENGTH);
- }
-
- /**
* Tests the sub-command on a NetCDF file.
*
* @throws Exception Should never happen.
Modified: sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Referencing.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Referencing.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Referencing.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Referencing.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -18,6 +18,7 @@ package org.apache.sis.openoffice;
import java.text.ParseException;
+import org.opengis.metadata.Metadata;
import org.opengis.util.FactoryException;
import org.opengis.util.InternationalString;
import org.opengis.metadata.extent.Extent;
@@ -38,6 +39,10 @@ import org.apache.sis.util.Classes;
import org.apache.sis.util.collection.Cache;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.util.PatchedUnitFormat;
+import org.apache.sis.internal.storage.CodeType;
+import org.apache.sis.storage.DataStore;
+import org.apache.sis.storage.DataStores;
+import org.apache.sis.storage.DataStoreException;
/**
@@ -128,10 +133,14 @@ public class Referencing extends CalcAdd
* This method caches the result.
*
* @param codeOrPath the code allocated by an authority, or the path to a file.
+ * @param type how to interpret {@code codeOrPath}, or {@code null} for guessing.
* @return the identified object for the given code.
* @throws FactoryException if an error occurred while creating the object.
+ * @throws DataStoreException if an error occurred while reading a data file.
*/
- private static IdentifiedObject getIdentifiedObject(final String codeOrPath) throws FactoryException
{
+ private IdentifiedObject getIdentifiedObject(final String codeOrPath, CodeType type)
+ throws FactoryException, DataStoreException
+ {
final CacheKey<IdentifiedObject> key = new CacheKey<>(IdentifiedObject.class,
codeOrPath, null, null);
IdentifiedObject object = key.peek();
if (object == null) {
@@ -139,9 +148,34 @@ public class Referencing extends CalcAdd
try {
object = handler.peek();
if (object == null) {
- switch (CodeType.guess(codeOrPath)) {
- case URN: object = CRS.getAuthorityFactory(null).createObject(codeOrPath);
break;
- default: object = CRS.forCode(codeOrPath); break;
+ if (type == null) {
+ type = CodeType.guess(codeOrPath);
+ }
+ if (type.equals(CodeType.URN)) {
+ object = CRS.getAuthorityFactory(null).createObject(codeOrPath);
+ } else if (type.isCRS) {
+ object = CRS.forCode(codeOrPath);
+ } else {
+ /*
+ * Apparently not an AUTHORITY:CODE string.
+ * Try to read a dataset from a file or URL, then get its CRS.
+ */
+ final Metadata metadata;
+ try (DataStore store = DataStores.open(codeOrPath)) {
+ metadata = store.getMetadata();
+ }
+ if (metadata != null) {
+ for (final ReferenceSystem rs : metadata.getReferenceSystemInfo())
{
+ if (rs instanceof CoordinateReferenceSystem) {
+ return rs;
+ } else if (object == null) {
+ object = rs; // Will be used as a fallback
if we find no CRS.
+ }
+ }
+ }
+ if (object == null) {
+ throw new FactoryException(Errors.getResources(getJavaLocale()).getString(Errors.Keys.UnspecifiedCRS));
+ }
}
}
} finally {
@@ -163,17 +197,18 @@ public class Referencing extends CalcAdd
final InternationalString name;
try {
final IdentifiedObject object;
- switch (CodeType.guess(codeOrPath)) {
- case URN:
- case CRS: object = new CacheKey<>(IdentifiedObject.class, codeOrPath,
null, null).peek(); break;
- default: object = getIdentifiedObject(codeOrPath); break;
+ final CodeType type = CodeType.guess(codeOrPath);
+ if (type.isCRS) {
+ object = new CacheKey<>(IdentifiedObject.class, codeOrPath, null, null).peek();
+ } else {
+ object = getIdentifiedObject(codeOrPath, type);
}
if (object != null) {
return object.getName().getCode();
}
// In Apache SIS implementation, 'getDescriptionText' returns the name.
name = CRS.getAuthorityFactory(null).getDescriptionText(codeOrPath);
- } catch (FactoryException exception) {
+ } catch (Exception exception) {
return getLocalizedMessage(exception);
}
return (name != null) ? name.toString(getJavaLocale()) : noResultString();
@@ -199,8 +234,8 @@ public class Referencing extends CalcAdd
if (name == null) {
final IdentifiedObject object;
try {
- object = getIdentifiedObject(codeOrPath);
- } catch (FactoryException exception) {
+ object = getIdentifiedObject(codeOrPath, null);
+ } catch (Exception exception) {
return getLocalizedMessage(exception);
}
final CoordinateSystemAxis axis;
@@ -255,12 +290,12 @@ public class Referencing extends CalcAdd
try {
area = handler.peek();
if (area == null) try {
- final IdentifiedObject object = getIdentifiedObject(codeOrPath);
+ final IdentifiedObject object = getIdentifiedObject(codeOrPath, null);
final Object domain = IdentifiedObjects.getProperties(object).get(ReferenceSystem.DOMAIN_OF_VALIDITY_KEY);
if (domain instanceof Extent) {
area = Extents.getGeographicBoundingBox((Extent) domain);
}
- } catch (FactoryException exception) {
+ } catch (Exception exception) {
reportException("getGeographicArea", exception, THROW_EXCEPTION);
}
} finally {
@@ -281,9 +316,10 @@ public class Referencing extends CalcAdd
* @param codeOrPath the code allocated by an authority, or the path to a file.
* @return the coordinate reference system for the given code.
* @throws FactoryException if an error occurred while creating the object.
+ * @throws DataStoreException if an error occurred while reading a data file.
*/
- final CoordinateReferenceSystem getCRS(final String codeOrPath) throws FactoryException
{
- final IdentifiedObject object = getIdentifiedObject(codeOrPath);
+ final CoordinateReferenceSystem getCRS(final String codeOrPath) throws FactoryException,
DataStoreException {
+ final IdentifiedObject object = getIdentifiedObject(codeOrPath, null);
if (object == null || object instanceof CoordinateReferenceSystem) {
return (CoordinateReferenceSystem) object;
}
@@ -307,7 +343,7 @@ public class Referencing extends CalcAdd
{
try {
return new Transformer(this, getCRS(sourceCRS), targetCRS, points).getAccuracy();
- } catch (FactoryException exception) {
+ } catch (Exception exception) {
reportException("getAccuracy", exception, THROW_EXCEPTION);
return Double.NaN;
}
@@ -328,7 +364,7 @@ public class Referencing extends CalcAdd
{
try {
return new Transformer(this, getCRS(sourceCRS), targetCRS, points).transform(points);
- } catch (FactoryException exception) {
+ } catch (Exception exception) {
reportException("transformCoordinates", exception, THROW_EXCEPTION);
return getFailure(points.length, 2);
}
Modified: sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Transformer.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Transformer.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Transformer.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Transformer.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -28,6 +28,7 @@ import org.apache.sis.util.collection.Ca
import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
+import org.apache.sis.storage.DataStoreException;
/**
@@ -62,7 +63,7 @@ final class Transformer {
* Creates a new transformer.
*/
Transformer(final Referencing caller, final CoordinateReferenceSystem sourceCRS,
- final String targetCRS, final double[][] points) throws FactoryException
+ final String targetCRS, final double[][] points) throws FactoryException, DataStoreException
{
/*
* Computes the area of interest.
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -182,6 +182,9 @@ abstract class AuthorityFactoryProxy<T>
@Override InternationalString createFromAPI(AuthorityFactory factory, String
code) throws FactoryException {
return factory.getDescriptionText(code);
}
+ @Override AuthorityFactoryProxy<InternationalString> specialize(String
typeName) {
+ return this;
+ }
};
/**
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -748,7 +748,8 @@ public class MultiAuthoritiesFactory ext
if (code == null) {
message = Errors.format(Errors.Keys.MissingComponentInElement_2, s, "code");
} else {
- message = Errors.format(Errors.Keys.CanNotCreateObjectAsInstanceOf_2,
type, uri.type);
+ message = Errors.format(Errors.Keys.CanNotCreateObjectAsInstanceOf_2,
type,
+ DefinitionURI.PREFIX + DefinitionURI.SEPARATOR + uri.type);
}
throw new NoSuchAuthorityCodeException(message, authority, code, s);
}
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -46,7 +46,7 @@ import static org.apache.sis.test.Assert
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.7
- * @version 0.7
+ * @version 0.8
* @module
*/
public final strictfp class AuthorityFactoriesTest extends TestCase {
@@ -66,6 +66,20 @@ public final strictfp class AuthorityFac
}
/**
+ * Tests {@link CRSAuthorityFactory#getDescriptionText(String)}.
+ *
+ * @throws FactoryException if the EPSG:4326 name can not be obtained.
+ *
+ * @since 0.8
+ */
+ @Test
+ public void testGetDescriptionText() throws FactoryException {
+ final CRSAuthorityFactory factory = AuthorityFactories.ALL;
+ assertEquals("WGS 84", factory.getDescriptionText("EPSG:4326").toString());
+ assertEquals("WGS 84", factory.getDescriptionText("urn:ogc:def:crs:epsg::4326").toString());
+ }
+
+ /**
* Tests creation of {@code CRS:84} from various codes.
*
* @throws FactoryException if a CRS:84 creation failed.
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -125,7 +125,7 @@ public final class DefinitionURI {
/**
* The domain of URLs in the OGC namespace.
*/
- private static final String DOMAIN = "www.opengis.net";
+ public static final String DOMAIN = "www.opengis.net";
/**
* Server and path portions of HTTP URL for various types (currently {@code "crs"}).
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -86,6 +86,12 @@ public final class Logging extends Stati
*/
private static volatile LoggerFactory<?> factory;
static {
+ /*
+ * Use ServiceLoader.load(…), not DefaultFactories.createServiceLoader(…), for
avoiding a never-ending
+ * loop if a warning occurs in DefaultFactories. This risk exists because DefaultFactories
may use the
+ * logging services. Anyway, Apache SIS does not define any custom logger factory,
so DefaultFactories
+ * is not needed in this case.
+ */
LoggerFactory<?> factory = null;
for (final LoggerFactory<?> found : ServiceLoader.load(LoggerFactory.class))
{
if (factory == null) {
Copied: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/CodeType.java
(from r1747421, sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/CodeType.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/CodeType.java?p2=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/CodeType.java&p1=sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/CodeType.java&r1=1747421&r2=1747422&rev=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/CodeType.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/CodeType.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -14,36 +14,167 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.openoffice;
+package org.apache.sis.internal.storage;
+
+import java.io.File;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Locale;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.internal.util.DefinitionURI;
/**
- * Whether an authority code is defined in the URN namespace.
+ * Heuristic rules for determining whether an authority code seems to be actually a file
path,
+ * or a code defined in the URN namespace, or a simple code.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.8
* @version 0.8
* @module
*/
-enum CodeType {
+public enum CodeType {
+ /**
+ * The code is a filename like {@code "/path/to/file"} or {@code "C:\path\to\file"}.
+ * Could also be a directory name.
+ */
+ FILE(false),
+
+ /**
+ * The code is a URL like {@code "http:"} or {@code "file:"},
+ * with the exception of HTTP in the "www.opengis.net" domain.
+ * The later case is identified by {@link #HTTP_OGC} instead than this enum.
+ */
+ URL(false),
+
+ /**
+ * The code is an authority code defined in the {@code "urn:"} namespace.
+ */
+ URN(true),
+
+ /**
+ * The code is an URL in the {@code "http://www.opengis.net"} namespace.
+ */
+ HTTP_OGC(true),
+
+ /**
+ * The code is not defined in the URN namespace but is nevertheless presumed to be an
authority code.
+ * Example: {@code "EPSG:4326"}.
+ */
+ IDENTIFIER(true),
+
+ /**
+ * Can not resolve whether the code is a local file like {@code "myfile.wkt"} or an identifier
without
+ * authority like {@code "4326"}. Such code without can not be decoded by {@code CRS.forCode(String)},
+ * but may be understood by a more specific authority factory.
+ */
+ UNKNOWN(false);
+
+ /**
+ * Whether the code may be understood by the {@link org.apache.sis.referencing.CRS#forCode(String)}.
+ * A value of {@code true} does not guaranteed the the code is valid. It only said that
there is some
+ * chances that the code is valid.
+ */
+ public final boolean isCRS;
+
/**
- * The authority code is defined in the {@code "urn:"} namespace.
+ * Creates a new enum value.
*/
- URN,
+ private CodeType(final boolean isCRS) {
+ this.isCRS = isCRS;
+ }
/**
- * The code is not defined in the URN namespace but is nevertheless presumed to be a
CRS authority code.
+ * The types for a list of known protocols. Protocol must be lower-cases.
+ *
+ * <p>This map is used for resolving ambiguity between "PROTOCOL:FILE" and "AUTHORITY:CODE".
+ * If the given path begins with a file separator like "PROTOCOL:/PATH/FILE", then the
path
+ * is presumed to be a URL even if the protocol is not in this map.</p>
*/
- CRS;
+ private static final Map<String,CodeType> FOR_PROTOCOL;
+ static {
+ FOR_PROTOCOL = new HashMap<>();
+ FOR_PROTOCOL.put("urn", CodeType.URN);
+ FOR_PROTOCOL.put("http", CodeType.HTTP_OGC); // Will actually need verification.
+ FOR_PROTOCOL.put("https", CodeType.HTTP_OGC); // Will actually need verification.
+ FOR_PROTOCOL.put("shttp", CodeType.HTTP_OGC); // Not widely used but nevertheless
exist.
+ for (final String p : new String[] {"cvs", "dav", "file", "ftp", "git", "jar", "nfs",
"sftp", "ssh", "svn"}) {
+ if (FOR_PROTOCOL.put(p, CodeType.URL) != null) {
+ throw new AssertionError(p);
+ }
+ }
+ }
/**
* Infers the type for the given authority code.
+ *
+ * @param codeOrPath the code or file path.
+ * @return whether the given argument seems to be a file path, URL, URN of authority
code.
*/
- static CodeType guess(final String codeOrPath) {
- if (codeOrPath.regionMatches(true, 0, "urn:", 0, 4)) {
- return URN;
- } else {
- return CRS;
+ public static CodeType guess(final String codeOrPath) {
+ final int length = codeOrPath.length();
+ final int start = CharSequences.skipLeadingWhitespaces(codeOrPath, 0, length);
+ int separator = codeOrPath.indexOf(':', start);
+ final int end = CharSequences.skipTrailingWhitespaces(codeOrPath, start, separator);
+ if (end <= start) {
+ // Check for presence of file separator, including the Unix and Windows ones.
+ if (codeOrPath.contains(File.separator) || codeOrPath.indexOf('/') >= 0 ||
codeOrPath.indexOf('\\') >= 0) {
+ return FILE;
+ }
+ return UNKNOWN;
+ }
+ /*
+ * Characters in the [start … end) range may be the authority ("EPSG", "CRS", "AUTO2",
etc.),
+ * the protocol ("http", "ftp", etc.) or a drive letter on a Windows system ("A",
"C", etc.).
+ * Skip following spaces and dots so if codeOrPath="C:.\path", then the separator
is at the
+ * position of \.
+ */
+ char c;
+ do {
+ separator = CharSequences.skipLeadingWhitespaces(codeOrPath, separator+1, length);
+ if (separator >= length) {
+ return FILE; // Relative directory name, for example "C:..".
+ }
+ c = codeOrPath.charAt(separator);
+ } while (c == '.');
+ /*
+ * If the the ':' if followed by at least one '/' (ignoring spaces and dots), then
it is presumed
+ * to be a URL protocol. In the special case where the protocol is "http(s)" and
the domain after
+ * the '/' characters is "www.opengis.net", return HTTP_OGC instead than URL.
+ */
+ final CodeType known = FOR_PROTOCOL.get(codeOrPath.substring(start, end).toLowerCase(Locale.US));
+ if (known != null) {
+ if (known != HTTP_OGC) {
+ return known;
+ }
+ if (c == '/') {
+ while (++separator < length) {
+ c = codeOrPath.charAt(separator);
+ if (c != '/') {
+ separator = CharSequences.skipLeadingWhitespaces(codeOrPath, separator,
length);
+ if (CharSequences.regionMatches(codeOrPath, separator, DefinitionURI.DOMAIN,
true)) {
+ separator += DefinitionURI.DOMAIN.length();
+ if (separator >= length || codeOrPath.charAt(separator) ==
'/') {
+ return known;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return URL;
+ }
+ if (c == '/') {
+ return URL;
+ }
+ /*
+ * If the ':' is followed by '\', then the part before ':' is presumed to be a Windows
drive letter.
+ * Example "C:\file" or "C:..\file". Note that it does NOT include "C:file" since
the later can not
+ * be distinguished from an authority code. If a relative filename is desired, use
"C:.\file".
+ */
+ if (c == '\\' || c == File.separatorChar || end == start+1) {
+ return FILE;
}
+ return IDENTIFIER;
}
}
Added: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java?rev=1747422&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java
(added)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.storage;
+
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests {@link CodeType}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ */
+public final strictfp class CodeTypeTest extends TestCase {
+ /**
+ * The expected value.
+ */
+ private CodeType expected;
+
+ /**
+ * Asserts that {@link CodeType#guess(String)} returns the expected value.
+ */
+ private void verify(final String code) {
+ assertEquals(code, expected, CodeType.guess(code));
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#IDENTIFIER} type.
+ */
+ @Test
+ public void testCRS() {
+ expected = CodeType.IDENTIFIER;
+ verify("EPSG:4326");
+ verify("epsg:4326");
+ verify(" ePsG : 4326 ");
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#URN} type.
+ */
+ @Test
+ public void testURN() {
+ expected = CodeType.URN;
+ verify("urn:ogc:def:crs:epsg::4326");
+ verify("URN:OGC:DEF:CRS:EPSG::4326");
+ verify(" uRn :ogc:def:crs:ogc::84");
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#URL} type.
+ */
+ @Test
+ public void testURL() {
+ expected = CodeType.URL;
+ verify("ftp://server/file.txt");
+ verify("http://server/file.txt");
+ verify("test://server/file.txt");
+ verify(" http : // server/file.txt");
+ verify("file:./file.txt");
+ verify("test:./file.txt");
+ verify("jar:file.txt"); // Special case required by some tests.
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#HTTP_OGC} type.
+ */
+ @Test
+ public void testHTTP() {
+ expected = CodeType.HTTP_OGC;
+ verify("http: // www.opengis.net/");
+ verify("http://www.opengis.net/gml/srs/epsg.xml#4326");
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#FILE} type.
+ */
+ @Test
+ public void testFile() {
+ expected = CodeType.FILE;
+ verify("path/file.txt");
+ verify("../file.txt");
+ verify("..\\file.txt");
+ verify("C:file.txt");
+ verify("C:.\\file.txt");
+ verify("ABC:.\\file.txt");
+ verify("C : \\path\\file.txt");
+ verify("ABC : \\path\\file.txt");
+ verify("C:..");
+ verify("ABC:..");
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#IDENTIFIER} type.
+ */
+ @Test
+ public void testIdentifier() {
+ expected = CodeType.IDENTIFIER;
+ verify("EPSG:4326");
+ verify("AB:C\\D.x");
+ verify("AB:C/D.x");
+ }
+
+ /**
+ * Tests {@link CodeType#guess(String)} for the {@link CodeType#UNKNOWN} type.
+ */
+ @Test
+ public void testUnknown() {
+ expected = CodeType.UNKNOWN;
+ verify("4326");
+ verify("file.txt");
+ }
+}
Propchange: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/CodeTypeTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java?rev=1747422&r1=1747421&r2=1747422&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] Wed Jun 8 17:08:03 2016
@@ -26,10 +26,11 @@ import org.junit.BeforeClass;
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.3
- * @version 0.7
+ * @version 0.8
* @module
*/
@Suite.SuiteClasses({
+ org.apache.sis.internal.storage.CodeTypeTest.class,
org.apache.sis.internal.storage.IOUtilitiesTest.class,
org.apache.sis.internal.storage.ChannelDataInputTest.class,
org.apache.sis.internal.storage.ChannelDataOutputTest.class,
|