Modified: sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/AttributeConvention.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/AttributeConvention.java?rev=1740177&r1=1740152&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/AttributeConvention.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/AttributeConvention.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -27,11 +27,10 @@ import org.apache.sis.internal.util.Cons import org.apache.sis.util.Static; // Branch-dependent imports -import org.opengis.feature.Attribute; -import org.opengis.feature.AttributeType; -import org.opengis.feature.IdentifiedType; -import org.opengis.feature.Operation; -import org.opengis.feature.Property; +import org.apache.sis.feature.AbstractAttribute; +import org.apache.sis.feature.AbstractIdentifiedType; +import org.apache.sis.feature.AbstractOperation; +import org.apache.sis.feature.DefaultAttributeType; /** @@ -225,11 +224,11 @@ public final class AttributeConvention e * * @see #DEFAULT_GEOMETRY_PROPERTY */ - public static boolean isGeometryAttribute(IdentifiedType type) { - while (type instanceof Operation) { - type = ((Operation) type).getResult(); + public static boolean isGeometryAttribute(AbstractIdentifiedType type) { + while (type instanceof AbstractOperation) { + type = ((AbstractOperation) type).getResult(); } - return (type instanceof AttributeType<?>) && Geometries.isKnownType(((AttributeType<?>) type).getValueClass()); + return (type instanceof DefaultAttributeType<?>) && Geometries.isKnownType(((DefaultAttributeType<?>) type).getValueClass()); } /** @@ -240,7 +239,7 @@ public final class AttributeConvention e * @param type the operation or attribute type for which to get the CRS, or {@code null}. * @return {@code true} if a characteristic for Coordinate Reference System has been found. */ - public static boolean characterizedByCRS(final IdentifiedType type) { + public static boolean characterizedByCRS(final AbstractIdentifiedType type) { return hasCharacteristic(type, CRS_CHARACTERISTIC.toString(), CoordinateReferenceSystem.class); } @@ -255,7 +254,7 @@ public final class AttributeConvention e * * @see org.apache.sis.internal.feature.FeatureTypeBuilder.Property#setCRSCharacteristic(CoordinateReferenceSystem) */ - public static CoordinateReferenceSystem getCRSCharacteristic(final Property attribute) { + public static CoordinateReferenceSystem getCRSCharacteristic(final Object attribute) { return (CoordinateReferenceSystem) getCharacteristic(attribute, CRS_CHARACTERISTIC.toString()); } @@ -267,7 +266,7 @@ public final class AttributeConvention e * @param type the operation or attribute type for which to get the maximal length, or {@code null}. * @return {@code true} if a characteristic for maximal length has been found. */ - public static boolean characterizedByMaximalLength(final IdentifiedType type) { + public static boolean characterizedByMaximalLength(final AbstractIdentifiedType type) { return hasCharacteristic(type, MAXIMAL_LENGTH_CHARACTERISTIC.toString(), Integer.class); } @@ -282,7 +281,7 @@ public final class AttributeConvention e * * @see org.apache.sis.internal.feature.FeatureTypeBuilder.Property#setMaximalLengthCharacteristic(Integer) */ - public static Integer getMaximalLengthCharacteristic(final Property attribute) { + public static Integer getMaximalLengthCharacteristic(final Object attribute) { return (Integer) getCharacteristic(attribute, MAXIMAL_LENGTH_CHARACTERISTIC.toString()); } @@ -295,12 +294,12 @@ public final class AttributeConvention e * @param valueClass the expected characteristic values. * @return {@code true} if a characteristic of the given name exists and has values assignable to the given class. */ - private static boolean hasCharacteristic(IdentifiedType type, final String name, final Class<?> valueClass) { - while (type instanceof Operation) { - type = ((Operation) type).getResult(); + private static boolean hasCharacteristic(AbstractIdentifiedType type, final String name, final Class<?> valueClass) { + while (type instanceof AbstractOperation) { + type = ((AbstractOperation) type).getResult(); } - if (type instanceof AttributeType<?>) { - final AttributeType<?> at = ((AttributeType<?>) type).characteristics().get(name); + if (type instanceof DefaultAttributeType<?>) { + final DefaultAttributeType<?> at = ((DefaultAttributeType<?>) type).characteristics().get(name); if (at != null) { return valueClass.isAssignableFrom(at.getValueClass()); } @@ -317,16 +316,16 @@ public final class AttributeConvention e * @param name name of the characteristic to get. * @return the value or default value of the given characteristic in the given property, or {@code null} if none. */ - private static Object getCharacteristic(final Property attribute, final String name) { - if (attribute instanceof Attribute<?>) { - final Attribute<?> at = ((Attribute<?>) attribute).characteristics().get(name); + private static Object getCharacteristic(final Object attribute, final String name) { + if (attribute instanceof AbstractAttribute<?>) { + final AbstractAttribute<?> at = ((AbstractAttribute<?>) attribute).characteristics().get(name); if (at != null) { final Object value = at.getValue(); if (value != null) { return value; } } - final AttributeType<?> type = ((Attribute<?>) attribute).getType().characteristics().get(name); + final DefaultAttributeType<?> type = ((AbstractAttribute<?>) attribute).getType().characteristics().get(name); if (type != null) { return type.getDefaultValue(); }
Modified: sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java?rev=1740177&r1=1740152&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -39,10 +39,8 @@ import org.apache.sis.util.ArgumentCheck import org.apache.sis.util.ArraysExt; // Branch-dependent imports -import org.opengis.feature.AttributeType; -import org.opengis.feature.Feature; -import org.opengis.feature.FeatureType; -import org.opengis.feature.PropertyType; +import org.apache.sis.feature.AbstractFeature; +import org.apache.sis.feature.AbstractIdentifiedType; /** @@ -75,7 +73,7 @@ public class FeatureTypeBuilder extends /** * The parent of the feature to create. By default, new features have no parent. */ - private final List<FeatureType> superTypes; + private final List<DefaultFeatureType> superTypes; /** * Whether the feature type is abstract. The default value is {@code false}. @@ -144,7 +142,7 @@ public class FeatureTypeBuilder extends public FeatureTypeBuilder(final NameFactory factory) { nameFactory = factory; properties = new ArrayList<Property<?>>(); - superTypes = new ArrayList<FeatureType>(); + superTypes = new ArrayList<DefaultFeatureType>(); idAttributes = new ArrayList<Property<?>>(); idDelimiter = ":"; defaultMinimumOccurs = 1; @@ -192,7 +190,7 @@ public class FeatureTypeBuilder extends * @param parents the parent types from which to inherit properties, or an empty array if none. * @return {@code this} for allowing method calls chaining. */ - public FeatureTypeBuilder setSuperTypes(final FeatureType... parents) { + public FeatureTypeBuilder setSuperTypes(final DefaultFeatureType... parents) { ArgumentChecks.ensureNonNull("parents", parents); superTypes.clear(); superTypes.addAll(Arrays.asList(parents)); @@ -339,7 +337,7 @@ public class FeatureTypeBuilder extends if (valueClass == null) { throw new NullArgumentException(errors().getString(Errors.Keys.NullArgument_1, "valueClass")); } - if (Feature.class.isAssignableFrom(valueClass)) { + if (AbstractFeature.class.isAssignableFrom(valueClass)) { throw new IllegalArgumentException(errors().getString(Errors.Keys.IllegalArgumentValue_2, "valueClass", valueClass)); } } @@ -352,9 +350,9 @@ public class FeatureTypeBuilder extends * @param type the type of feature values. * @return a builder for a {@code FeatureAssociationRole}. */ - public Property<Feature> addAssociation(final FeatureType type) { + public Property<AbstractFeature> addAssociation(final DefaultFeatureType type) { ArgumentChecks.ensureNonNull("type", type); - final Property<Feature> property = new Property<Feature>(Feature.class, FeatureType.class, type); + final Property<AbstractFeature> property = new Property<AbstractFeature>(AbstractFeature.class, DefaultFeatureType.class, type); properties.add(property); return property; } @@ -367,9 +365,9 @@ public class FeatureTypeBuilder extends * @param type the name of the type of feature values. * @return a builder for a {@code FeatureAssociationRole}. */ - public Property<Feature> addAssociation(final GenericName type) { + public Property<AbstractFeature> addAssociation(final GenericName type) { ArgumentChecks.ensureNonNull("type", type); - final Property<Feature> property = new Property<Feature>(Feature.class, GenericName.class, type); + final Property<AbstractFeature> property = new Property<AbstractFeature>(AbstractFeature.class, GenericName.class, type); properties.add(property); return property; } @@ -499,7 +497,6 @@ public class FeatureTypeBuilder extends * * @see AttributeConvention#VALID_VALUES_CHARACTERISTIC */ - @SafeVarargs public final Property<V> setValidValues(final V... values) { return setCharacteristic(AttributeConvention.VALID_VALUES_CHARACTERISTIC, Set.class, CollectionsExt.immutableSet(false, values)); @@ -575,7 +572,7 @@ public class FeatureTypeBuilder extends * @throws UnsupportedOperationException if this property does not support characteristics. */ public <C> Characteristic<C> addCharacteristic(final Class<C> type) { - if (valueClass == Feature.class) { + if (valueClass == AbstractFeature.class) { throw new UnsupportedOperationException(errors().getString(Errors.Keys.IllegalOperationForValueClass_1, valueClass)); } ArgumentChecks.ensureNonNull("type", type); @@ -587,17 +584,17 @@ public class FeatureTypeBuilder extends /** * Creates a new property type from the current setting. */ - final PropertyType build() { - final PropertyType property; - if (valueClass == Feature.class) { + final AbstractIdentifiedType build() { + final AbstractIdentifiedType property; + if (valueClass == AbstractFeature.class) { final Object type = CollectionsExt.first(characteristics).defaultValue; - if (type instanceof FeatureType) { - property = new DefaultAssociationRole(identification, (FeatureType) type, minimumOccurs, maximumOccurs); + if (type instanceof DefaultFeatureType) { + property = new DefaultAssociationRole(identification, (DefaultFeatureType) type, minimumOccurs, maximumOccurs); } else { property = new DefaultAssociationRole(identification, (GenericName) type, minimumOccurs, maximumOccurs); } } else { - final AttributeType<?>[] chrts = new AttributeType<?>[characteristics.size()]; + final DefaultAttributeType<?>[] chrts = new DefaultAttributeType<?>[characteristics.size()]; for (int i=0; i<chrts.length; i++) { chrts[i] = characteristics.get(i).build(); } @@ -668,7 +665,7 @@ public class FeatureTypeBuilder extends /** * Creates a new characteristic from the current setting. */ - final AttributeType<V> build() { + final DefaultAttributeType<V> build() { return new DefaultAttributeType<V>(identification, valueClass, 0, 1, defaultValue); } } @@ -682,24 +679,24 @@ public class FeatureTypeBuilder extends * @throws IllegalStateException if the feature type contains incompatible * {@linkplain Property#setCRSCharacteristic CRS characteristics}. */ - public FeatureType build() throws IllegalStateException { + public DefaultFeatureType build() throws IllegalStateException { int numSynthetic; // Number of synthetic properties to be generated. int numSpecified = properties.size(); // Number of explicitely specified properties. - final PropertyType[] identifierTypes; + final AbstractIdentifiedType[] identifierTypes; if (idAttributes.isEmpty()) { identifierTypes = null; numSynthetic = 0; } else { - identifierTypes = new PropertyType[idAttributes.size()]; + identifierTypes = new AbstractIdentifiedType[idAttributes.size()]; numSynthetic = 1; // Reserve one slot for the synthetic property "@id". } if (defaultGeometry != null) { numSynthetic += 2; // One slot for "@defaultGeometry" and one for "@envelope". } - PropertyType[] propertyTypes = new PropertyType[numSynthetic + numSpecified]; + AbstractIdentifiedType[] propertyTypes = new AbstractIdentifiedType[numSynthetic + numSpecified]; for (int i=0,j=numSynthetic; i<numSpecified; i++, j++) { final Property<?> builder = properties.get(i); - final PropertyType instance = builder.build(); + final AbstractIdentifiedType instance = builder.build(); propertyTypes[j] = instance; final int id = idAttributes.indexOf(builder); if (id >= 0) { @@ -711,7 +708,7 @@ public class FeatureTypeBuilder extends * avoid to duplicate the property by removing the second occurrence. */ if (builder == defaultGeometry) { - final PropertyType geom; + final AbstractIdentifiedType geom; if (AttributeConvention.DEFAULT_GEOMETRY_PROPERTY.equals(instance.getName())) { propertyTypes = ArraysExt.remove(propertyTypes, j--, 1); geom = instance; @@ -734,7 +731,7 @@ public class FeatureTypeBuilder extends if (identifierTypes != null) { propertyTypes[0] = FeatureOperations.compound(name(AttributeConvention.ID_PROPERTY), idDelimiter, idPrefix, idSuffix, identifierTypes); } - return new DefaultFeatureType(identification, isAbstract, superTypes.toArray(new FeatureType[superTypes.size()]), propertyTypes); + return new DefaultFeatureType(identification, isAbstract, superTypes.toArray(new DefaultFeatureType[superTypes.size()]), propertyTypes); } /** Copied: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java (from r1740152, sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java?p2=sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java&p1=sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java&r1=1740152&r2=1740177&rev=1740177&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -36,9 +36,6 @@ import org.junit.Test; import static org.apache.sis.test.ReferencingAssert.*; -// Branch-dependent imports -import org.opengis.feature.PropertyType; - /** * Tests {@link EnvelopeOperation}. @@ -73,7 +70,7 @@ public final strictfp class EnvelopeOper final DefaultAttributeType<?> normalizedCRS = new DefaultAttributeType<CoordinateReferenceSystem>( name(AttributeConvention.CRS_CHARACTERISTIC), CoordinateReferenceSystem.class, 1, 1, HardCodedCRS.WGS84); - final PropertyType[] attributes = { + final AbstractIdentifiedType[] attributes = { new DefaultAttributeType<String> (name("name"), String.class, 1, 1, null), new DefaultAttributeType<Polygon>(name("classes"), Polygon.class, 1, 1, null, standardCRS), new DefaultAttributeType<Point> (name("climbing wall"), Point.class, 1, 1, null, standardCRS), @@ -103,7 +100,7 @@ public final strictfp class EnvelopeOper */ @Test public void testConstruction() throws FactoryException { - final PropertyType property = school(3).getProperty("bounds"); + final AbstractIdentifiedType property = school(3).getProperty("bounds"); assertInstanceOf("bounds", EnvelopeOperation.class, property); final EnvelopeOperation op = (EnvelopeOperation) property; assertSame("crs", HardCodedCRS.WGS84, op.crs); Modified: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/FeaturesTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/FeaturesTest.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/FeaturesTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/FeaturesTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -27,8 +27,9 @@ import static org.junit.Assert.*; * Tests {@link Features}. * * @author Martin Desruisseaux (Geomatys) + * @author Johann Sorel (Geomatys) * @since 0.5 - * @version 0.5 + * @version 0.7 * @module */ @DependsOn(SingletonAttributeTest.class) @@ -68,4 +69,26 @@ public final strictfp class FeaturesTest assertTrue(message, message.contains("CharSequence")); } } + + /** + * Tests {@link Features#validate(Feature)}. + */ + @Test + public void testValidate() { + final AbstractFeature feature = DefaultFeatureTypeTest.city().newInstance(); + + // Should not pass validation. + try { + Features.validate(feature); + fail("Feature is invalid because of missing property “population”. Validation should have raised an exception."); + } catch (IllegalArgumentException ex) { + String message = ex.getMessage(); + assertTrue(message, message.contains("city") || message.contains("population")); + } + + // Should pass validation. + feature.setPropertyValue("city", "Utopia"); + feature.setPropertyValue("population", 10); + Features.validate(feature); + } } Modified: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/LinkOperationTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/LinkOperationTest.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/LinkOperationTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/LinkOperationTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -42,8 +42,8 @@ public final strictfp class LinkOperatio * The feature contains the following properties: * * <ul> - * <li>{@code city} as a {@link String} (mandatory)</li> - * <li>{@code population} as an {@link Integer} (mandatory)</li> + * <li>{@code city} as a {@link String} (mandatory).</li> + * <li>{@code population} as an {@link Integer} (mandatory).</li> * <li>{@code name} as a link to the {@code city} attribute.</li> * </ul> * @@ -63,14 +63,14 @@ public final strictfp class LinkOperatio private static void run(final AbstractFeature feature) { assertEquals("Get directly", "Utopia", feature.getPropertyValue("city")); assertEquals("Get through link", "Utopia", feature.getPropertyValue("name")); - feature.setPropertyValue("name", "Atlantide"); // Set through link. + feature.setPropertyValue("name", "Atlantide"); // Set through link. assertEquals("Get directly", "Atlantide", feature.getPropertyValue("city")); assertEquals("Get through link", "Atlantide", feature.getPropertyValue("name")); assertSame(feature.getProperty("name"), feature.getProperty("name")); } /** - * Tests a dense type with operations. + * Tests a dense feature type with operations. */ @Test public void testDenseFeature() { Modified: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -105,7 +105,7 @@ public final strictfp class SingletonAtt ((AbstractAttribute) attribute).setValue(4.5f); quality = attribute.quality(); assertEquals("scope.level", ScopeCode.ATTRIBUTE, quality.getScope().getLevel()); - assertDomainConsistencyEquals("population", "Property “population” does not accept instances of ‘Float’.", + assertDomainConsistencyEquals("population", "Expected an instance of ‘Integer’ for the “population” property, but got an instance of ‘Float’.", (DomainConsistency) getSingleton(quality.getReports())); } Copied: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java (from r1740152, sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java?p2=sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java&p1=sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java&r1=1740152&r2=1740177&rev=1740177&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -25,10 +25,6 @@ import org.apache.sis.test.TestCase; import static org.junit.Assert.*; -// Branch-dependent imports -import org.opengis.feature.PropertyType; -import org.opengis.feature.InvalidPropertyValueException; - /** * Tests {@link StringJoinOperation}. @@ -58,9 +54,9 @@ public final strictfp class StringJoinOp * @return The feature for a person. */ private static DefaultFeatureType person() { - final PropertyType nameType = new DefaultAttributeType<String> (name("name"), String.class, 1, 1, null); - final PropertyType ageType = new DefaultAttributeType<Integer>(name("age"), Integer.class, 1, 1, null); - final PropertyType cmpType = FeatureOperations.compound(name("concat"), "/", "<<:", ":>>", nameType, ageType); + final AbstractIdentifiedType nameType = new DefaultAttributeType<String> (name("name"), String.class, 1, 1, null); + final AbstractIdentifiedType ageType = new DefaultAttributeType<Integer>(name("age"), Integer.class, 1, 1, null); + final AbstractIdentifiedType cmpType = FeatureOperations.compound(name("concat"), "/", "<<:", ":>>", nameType, ageType); return new DefaultFeatureType(name("person"), false, null, nameType, ageType, cmpType); } @@ -143,7 +139,7 @@ public final strictfp class StringJoinOp try { feature.setPropertyValue("concat", "((:marc/21:>>"); fail("Should fail because of mismatched prefix."); - } catch (InvalidPropertyValueException e) { + } catch (IllegalArgumentException e) { String message = e.getMessage(); assertTrue(message, message.contains("<<:")); assertTrue(message, message.contains("((")); @@ -151,7 +147,7 @@ public final strictfp class StringJoinOp try { feature.setPropertyValue("concat", "<<:marc/21:))"); fail("Should fail because of mismatched suffix."); - } catch (InvalidPropertyValueException e) { + } catch (IllegalArgumentException e) { String message = e.getMessage(); assertTrue(message, message.contains(":>>")); assertTrue(message, message.contains("))")); @@ -159,14 +155,14 @@ public final strictfp class StringJoinOp try { feature.setPropertyValue("concat", "<<:marc/21/julie:>>"); fail("Should fail because of too many components."); - } catch (InvalidPropertyValueException e) { + } catch (IllegalArgumentException e) { String message = e.getMessage(); assertTrue(message, message.contains("<<:marc/21/julie:>>")); } try { feature.setPropertyValue("concat", "<<:marc/julie:>>"); fail("Should fail because of unparsable number."); - } catch (InvalidPropertyValueException e) { + } catch (IllegalArgumentException e) { String message = e.getMessage(); assertTrue(message, message.contains("julie")); assertTrue(message, message.contains("age")); Modified: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeConventionTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeConventionTest.java?rev=1740177&r1=1740152&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeConventionTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeConventionTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -28,10 +28,6 @@ import org.junit.Test; import static org.junit.Assert.*; -// Branch-dependent imports -import org.opengis.feature.Property; -import org.opengis.feature.IdentifiedType; - /** * Tests {@link AttributeConvention}. Modified: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/FeatureTypeBuilderTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/FeatureTypeBuilderTest.java?rev=1740177&r1=1740152&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/FeatureTypeBuilderTest.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/internal/feature/FeatureTypeBuilderTest.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -27,9 +27,9 @@ import org.junit.Test; import static org.junit.Assert.*; // Branch-dependent imports -import org.opengis.feature.AttributeType; -import org.opengis.feature.FeatureType; -import org.opengis.feature.PropertyType; +import org.apache.sis.feature.AbstractIdentifiedType; +import org.apache.sis.feature.DefaultAttributeType; +import org.apache.sis.feature.DefaultFeatureType; /** @@ -56,7 +56,7 @@ public final strictfp class FeatureTypeB assertTrue(message, message.contains("name")); } builder.setName("myScope", "myName"); - final AttributeType<?> att = (AttributeType<?>) builder.build(); + final DefaultAttributeType<?> att = (DefaultAttributeType<?>) builder.build(); assertEquals("name", "myScope:myName", att.getName().toString()); assertEquals("valueClass", String.class, att.getValueClass()); @@ -90,7 +90,7 @@ public final strictfp class FeatureTypeB */ private static void testEmptyFeature(final FeatureTypeBuilder builder) { builder.setName("scope", "test"); - final FeatureType type = builder.build(); + final DefaultFeatureType type = builder.build(); assertEquals("name", "scope:test", type.getName().toString()); assertFalse ("isAbstract", type.isAbstract()); @@ -112,7 +112,7 @@ public final strictfp class FeatureTypeB builder.setDefaultValue("test default value."); builder.setCardinality(10, 60); builder.setMaximalLengthCharacteristic(80); - final AttributeType<?> att = (AttributeType<?>) builder.build(); + final DefaultAttributeType<?> att = (DefaultAttributeType<?>) builder.build(); assertEquals("name", "myScope:myName", att.getName().toString()); assertEquals("definition", "test definition", att.getDefinition().toString()); @@ -150,18 +150,18 @@ public final strictfp class FeatureTypeB builder.addAttribute(Point .class).setName("location").setCRSCharacteristic(HardCodedCRS.WGS84); builder.addAttribute(Double .class).setName("score").setCardinality(5, 50).setDefaultValue(10.0); - final FeatureType type = builder.build(); + final DefaultFeatureType type = builder.build(); assertEquals("name", "myScope:myName", type.getName().toString()); assertEquals("definition", "test definition", type.getDefinition().toString()); assertEquals("description", "test description", type.getDescription().toString()); assertEquals("designation", "test designation", type.getDesignation().toString()); assertTrue ("isAbstract", type.isAbstract()); - final Iterator<? extends PropertyType> it = type.getProperties(true).iterator(); - final AttributeType<?> a0 = (AttributeType<?>) it.next(); - final AttributeType<?> a1 = (AttributeType<?>) it.next(); - final AttributeType<?> a2 = (AttributeType<?>) it.next(); - final AttributeType<?> a3 = (AttributeType<?>) it.next(); + final Iterator<? extends AbstractIdentifiedType> it = type.getProperties(true).iterator(); + final DefaultAttributeType<?> a0 = (DefaultAttributeType<?>) it.next(); + final DefaultAttributeType<?> a1 = (DefaultAttributeType<?>) it.next(); + final DefaultAttributeType<?> a2 = (DefaultAttributeType<?>) it.next(); + final DefaultAttributeType<?> a3 = (DefaultAttributeType<?>) it.next(); assertFalse("properties count", it.hasNext()); assertEquals("name", "name", a0.getName().toString()); @@ -219,16 +219,16 @@ public final strictfp class FeatureTypeB builder.addIdentifier(String.class).setName("name"); builder.addDefaultGeometry(Geometry.class).setName("shape").setCRSCharacteristic(HardCodedCRS.WGS84); - final FeatureType type = builder.build(); + final DefaultFeatureType type = builder.build(); assertEquals("name", "scope:test", type.getName().toString()); assertFalse ("isAbstract", type.isAbstract()); - final Iterator<? extends PropertyType> it = type.getProperties(true).iterator(); - final PropertyType a0 = it.next(); - final PropertyType a1 = it.next(); - final PropertyType a2 = it.next(); - final PropertyType a3 = it.next(); - final PropertyType a4 = it.next(); + final Iterator<? extends AbstractIdentifiedType> it = type.getProperties(true).iterator(); + final AbstractIdentifiedType a0 = it.next(); + final AbstractIdentifiedType a1 = it.next(); + final AbstractIdentifiedType a2 = it.next(); + final AbstractIdentifiedType a3 = it.next(); + final AbstractIdentifiedType a4 = it.next(); assertFalse("properties count", it.hasNext()); assertEquals("name", AttributeConvention.ID_PROPERTY, a0.getName()); Modified: sis/trunk/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] (original) +++ sis/trunk/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -25,8 +25,9 @@ import org.junit.BeforeClass; * All tests from the {@code sis-feature} module, in approximative dependency order. * * @author Martin Desruisseaux (Geomatys) + * @author Johann Sorel (Geomatys) * @since 0.5 - * @version 0.5 + * @version 0.7 * @module */ @Suite.SuiteClasses({ @@ -43,8 +44,12 @@ import org.junit.BeforeClass; org.apache.sis.feature.SingletonAssociationTest.class, org.apache.sis.feature.AbstractOperationTest.class, org.apache.sis.feature.LinkOperationTest.class, + org.apache.sis.feature.StringJoinOperationTest.class, + org.apache.sis.feature.EnvelopeOperationTest.class, org.apache.sis.feature.FeatureFormatTest.class, - org.apache.sis.feature.FeaturesTest.class + org.apache.sis.feature.FeaturesTest.class, + org.apache.sis.internal.feature.AttributeConventionTest.class, + org.apache.sis.internal.feature.FeatureTypeBuilderTest.class }) public final strictfp class FeatureTestSuite extends TestSuite { /** Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -417,7 +417,7 @@ public final class AxisDirections extend * * @param cs The coordinate system from which to get the angular unit, or {@code null}. * @param unit The default unit to return if no angular unit is found. - * @return The angular unit, of {@code null} if no angular unit was found. + * @return The angular unit, of {@code unit} if no angular unit was found. * * @since 0.6 * Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -60,6 +60,8 @@ import org.apache.sis.util.Deprecable; import org.apache.sis.util.resources.Errors; // Branch-specific imports +import org.opengis.referencing.datum.Datum; +import org.opengis.referencing.datum.DatumFactory; import org.opengis.referencing.ReferenceIdentifier; import org.opengis.util.NoSuchIdentifierException; @@ -115,13 +117,23 @@ public class ReferencingServices extends public static final String OPERATION_TYPE_KEY = "operationType"; /** - * The key for specifying a {@linkplain org.opengis.referencing.operation.MathTransformFactory} - * instance to use for the construction of a geodetic object. This is usually not needed for CRS - * construction, except in the special case of a derived CRS created from a defining conversion. + * The key for specifying a {@link MathTransformFactory} instance to use for geodetic object constructions. + * This is usually not needed for CRS construction, except in the special case of a derived CRS created + * from a defining conversion. */ public static final String MT_FACTORY = "mtFactory"; /** + * The key for specifying a {@link CRSFactory} instance to use for geodetic object constructions. + */ + public static final String CRS_FACTORY = "crsFactory"; + + /** + * The key for specifying a {@link CSFactory} instance to use for geodetic object constructions. + */ + public static final String CS_FACTORY = "csFactory"; + + /** * The separator character between an identifier and its namespace in the argument given to * {@link #getOperationMethod(String)}. For example this is the separator in {@code "EPSG:9807"}. * @@ -394,6 +406,60 @@ public class ReferencingServices extends } /** + * Creates a parametric CS. This method requires the SIS factory + * since parametric CRS were not available in GeoAPI 3.0. + * + * @param properties the coordinate system name, and optionally other properties. + * @param axis the axis of the parametric coordinate system. + * @param factory the factory to use for creating the coordinate system. + * @return a parametric coordinate system using the given axes. + * @throws FactoryException if the parametric object creation failed. + * + * @since 0.7 + */ + public CoordinateSystem createParametricCS(final Map<String,?> properties, final CoordinateSystemAxis axis, + final CSFactory factory) throws FactoryException + { + throw moduleNotFound(); + } + + /** + * Creates a parametric datum. This method requires the SIS factory + * since parametric CRS were not available in GeoAPI 3.0. + * + * @param properties the datum name, and optionally other properties. + * @param factory the factory to use for creating the datum. + * @return a parametric datum using the given name. + * @throws FactoryException if the parametric object creation failed. + * + * @since 0.7 + */ + public Datum createParametricDatum(final Map<String,?> properties, final DatumFactory factory) + throws FactoryException + { + throw moduleNotFound(); + } + + /** + * Creates a parametric CRS. This method requires the SIS factory + * since parametric CRS were not available in GeoAPI 3.0. + * + * @param properties the coordinate reference system name, and optionally other properties. + * @param datum the parametric datum. + * @param cs the parametric coordinate system. + * @param factory the factory to use for creating the coordinate reference system. + * @return a parametric coordinate system using the given axes. + * @throws FactoryException if the parametric object creation failed. + * + * @since 0.7 + */ + public SingleCRS createParametricCRS(final Map<String,?> properties, final Datum datum, + final CoordinateSystem cs, final CRSFactory factory) throws FactoryException + { + throw moduleNotFound(); + } + + /** * Creates a derived CRS from the information found in a WKT 1 {@code FITTED_CS} element. * This coordinate system can not be easily constructed from the information provided by the WKT 1 format. * Note that this method is needed only for WKT 1 parsing, since WKT provides enough information for using @@ -557,11 +623,15 @@ public class ReferencingServices extends * * @param properties The default properties. * @param mtFactory The math transform factory to use. + * @param crsFactory The factory to use if the operation factory needs to create CRS for intermediate steps. + * @param csFactory The factory to use if the operation factory needs to create CS for intermediate steps. * @return The coordinate operation factory to use. * - * @since 0.6 + * @since 0.7 */ - public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties, MathTransformFactory mtFactory) { + public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties, + final MathTransformFactory mtFactory, final CRSFactory crsFactory, final CSFactory csFactory) + { /* * The check for 'properties' and 'mtFactory' is performed by the ServicesForMetadata subclass. If this code is * executed, this means that the "sis-referencing" module is not on the classpath, in which case we do not know Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/WKTKeywords.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/WKTKeywords.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/WKTKeywords.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/WKTKeywords.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -34,8 +34,9 @@ import org.apache.sis.util.Static; * This class is intended to be used only at compile-time and could be omitted from the JAR file.</div> * * @author Martin Desruisseaux (Geomatys) + * @author Johann Sorel (Geomatys) * @since 0.6 - * @version 0.6 + * @version 0.7 * @module * * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a> @@ -127,6 +128,15 @@ public final class WKTKeywords extends S BaseTimeCRS = "BaseTimeCRS"; /** + * Related to {@link org.apache.sis.referencing.crs.DefaultParametricCRS}. + */ + public static final String + ParametricDatum = "ParametricDatum", + PDatum = "PDatum", + ParametricCRS = "ParametricCRS", + BaseParamCRS = "BaseParamCRS"; + + /** * Related to {@link org.apache.sis.referencing.crs.DefaultImageCRS} * and {@link org.apache.sis.referencing.crs.DefaultEngineeringCRS}. * Former can be seen as a special case of the later. Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -413,7 +413,7 @@ public abstract class Initializer { try { ds.getConnection().close(); // Does the actual shutdown. } catch (SQLException e) { // This is the expected exception. - final LogRecord record = new LogRecord(Level.CONFIG, e.getLocalizedMessage()); + final LogRecord record = new LogRecord(Level.FINE, e.getLocalizedMessage()); if (!isSuccessfulShutdown(e)) { record.setLevel(Level.WARNING); record.setThrown(e); Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -353,11 +353,23 @@ abstract class AbstractParser implements * @param ex The non-fatal exception that occurred while parsing the element, or {@code null}. */ final void warning(final Element parent, final Element element, final InternationalString message, final Exception ex) { + warning(parent, (element != null) ? element.keyword : null, message, ex); + } + + /** + * Reports a non-fatal warning that occurred while parsing a WKT. + * + * @param parent The parent element, or {@code null} if unknown. + * @param element The name of the element that we can not parse, or {@code null} if unknown. + * @param message The message. Can be {@code null} only if {@code ex} is non-null. + * @param ex The non-fatal exception that occurred while parsing the element, or {@code null}. + */ + final void warning(final Element parent, final String element, final InternationalString message, final Exception ex) { if (warnings == null) { warnings = new Warnings(errorLocale, true, ignoredElements); } warnings.add(message, ex, (parent != null && element != null) - ? new String[] {parent.keyword, element.keyword} : null); + ? new String[] {parent.keyword, element} : null); } /** Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -54,6 +54,7 @@ import org.opengis.referencing.crs.Compo import org.opengis.referencing.cs.CoordinateSystemAxis; import org.opengis.referencing.operation.OperationMethod; import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.ConcatenatedOperation; import org.opengis.referencing.operation.MathTransform; import org.opengis.util.CodeList; @@ -768,8 +769,8 @@ public class Formatter implements Locali } else { filterID = (parent != null); if (object instanceof CoordinateOperation) { - showOthers = true; - showRemarks = true; + showOthers = !(parent instanceof ConcatenatedOperation); + showRemarks = showOthers; } else if (object instanceof ReferenceSystem) { showOthers = (parent == null); showRemarks = (parent == null) || (getEnclosingElement(2) instanceof CoordinateOperation); Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -87,6 +87,7 @@ import static java.util.Collections.sing * * @author Rémi Eve (IRD) * @author Martin Desruisseaux (IRD, Geomatys) + * @author Johann Sorel (Geomatys) * @since 0.6 * @version 0.7 * @module @@ -203,7 +204,7 @@ final class GeodeticObjectParser extends csFactory = (CSFactory) factories; datumFactory = (DatumFactory) factories; referencing = ReferencingServices.getInstance(); - opFactory = referencing.getCoordinateOperationFactory(defaultProperties, mtFactory); + opFactory = referencing.getCoordinateOperationFactory(defaultProperties, mtFactory, crsFactory, csFactory); transliterator = Transliterator.DEFAULT; usesCommonUnits = false; ignoreAxes = false; @@ -240,7 +241,7 @@ final class GeodeticObjectParser extends if (f != null) { opFactory = (CoordinateOperationFactory) f; } else { - opFactory = referencing.getCoordinateOperationFactory(null, mtFactory); + opFactory = referencing.getCoordinateOperationFactory(null, mtFactory, crsFactory, csFactory); factories.put(CoordinateOperationFactory.class, opFactory); } } @@ -299,7 +300,7 @@ final class GeodeticObjectParser extends if (ex == null) ex = e; } if (verticalElements != null) { - warning(null, null, Errors.formatInternational(Errors.Keys.CanNotAssignUnitToDimension_2, + warning(null, (String) null, Errors.formatInternational(Errors.Keys.CanNotAssignUnitToDimension_2, WKTKeywords.VerticalExtent, verticalElements.unit), ex); } } @@ -307,7 +308,7 @@ final class GeodeticObjectParser extends verticalElements = null; verticalCRS = null; axisOrder.clear(); - properties.clear(); // for letting the garbage collector do its work. + properties.clear(); // for letting the garbage collector do its work. } return object; } @@ -337,6 +338,7 @@ final class GeodeticObjectParser extends (object = parseToWGS84 (FIRST, element )) == null && (object = parseVerticalDatum (FIRST, element, false)) == null && (object = parseTimeDatum (FIRST, element )) == null && + (object = parseParametricDatum (FIRST, element )) == null && (object = parseEngineeringDatum (FIRST, element, false)) == null && (object = parseImageDatum (FIRST, element )) == null && (object = parseOperation (FIRST, element)) == null) @@ -362,6 +364,7 @@ final class GeodeticObjectParser extends (crs = parseProjectedCRS (FIRST, element, false)) == null && (crs = parseVerticalCRS (FIRST, element, false)) == null && (crs = parseTimeCRS (FIRST, element, false)) == null && + (crs = parseParametricCRS (FIRST, element, false)) == null && (crs = parseEngineeringCRS (FIRST, element, false)) == null && (crs = parseImageCRS (FIRST, element)) == null && (crs = parseCompoundCRS (FIRST, element)) == null && @@ -704,7 +707,7 @@ final class GeodeticObjectParser extends new String[] {WKTKeywords.CS, type}, element.offset); } } - if (dimension <= 0 || dimension > 1000) { // Arbitrary upper limit against badly formed CS. + if (dimension <= 0 || dimension > 1000) { // Arbitrary upper limit against badly formed CS. final short key; final Object[] args; if (dimension <= 0) { @@ -739,7 +742,7 @@ final class GeodeticObjectParser extends } while (axis != null); if (!isWKT1 || !ignoreAxes) { axes = list.toArray(new CoordinateSystemAxis[list.size()]); - Arrays.sort(axes, this); // Take ORDER[n] elements in account. + Arrays.sort(axes, this); // Take ORDER[n] elements in account. } } /* @@ -751,13 +754,13 @@ final class GeodeticObjectParser extends if (type == null) { throw parent.missingComponent(WKTKeywords.Axis); } - String nx = null, x = null; // Easting or Longitude axis name and abbreviation. - String ny = null, y = null; // Northing or latitude axis name and abbreviation. - String nz = null, z = null; // Depth, height or time axis name and abbreviation. + String nx = null, x = null; // Easting or Longitude axis name and abbreviation. + String ny = null, y = null; // Northing or latitude axis name and abbreviation. + String nz = null, z = null; // Depth, height or time axis name and abbreviation. AxisDirection dx = AxisDirection.EAST; AxisDirection dy = AxisDirection.NORTH; - AxisDirection direction = null; // Depth, height or time axis direction. - Unit<?> unit = defaultUnit; // Depth, height or time axis unit. + AxisDirection direction = null; // Depth, height or time axis direction. + Unit<?> unit = defaultUnit; // Depth, height or time axis unit. /*switch (type)*/ { /* * Cartesian — we can create axes only for geodetic datum, in which case the axes are for @@ -845,6 +848,17 @@ final class GeodeticObjectParser extends z = "t"; } /* + * Parametric — axis name and abbreviation not yet specified by ISO 19111_2. + */ + else if (type.equals(WKTKeywords.parametric)) { + if (defaultUnit == null) { + throw parent.missingComponent(WKTKeywords.ParametricUnit); + } + direction = AxisDirection.OTHER; + nz = "Parametric"; + z = "p"; + } + /* * Unknown CS type — we can not guess which axes to create. */ else { @@ -889,21 +903,21 @@ final class GeodeticObjectParser extends case 2: return csFactory.createEllipsoidalCS(csProperties, axes[0], axes[1]); case 3: return csFactory.createEllipsoidalCS(csProperties, axes[0], axes[1], axes[2]); } - dimension = (axes.length < 2) ? 2 : 3; // For error message. + dimension = (axes.length < 2) ? 2 : 3; // For error message. } else if (type.equals(WKTKeywords.Cartesian)) { switch (axes.length) { case 2: return csFactory.createCartesianCS(csProperties, axes[0], axes[1]); case 3: return csFactory.createCartesianCS(csProperties, axes[0], axes[1], axes[2]); } - dimension = (axes.length < 2) ? 2 : 3; // For error message. + dimension = (axes.length < 2) ? 2 : 3; // For error message. } else if (type.equals(WKTKeywords.affine)) { switch (axes.length) { case 2: return csFactory.createAffineCS(csProperties, axes[0], axes[1]); case 3: return csFactory.createAffineCS(csProperties, axes[0], axes[1], axes[2]); } - dimension = (axes.length < 2) ? 2 : 3; // For error message. + dimension = (axes.length < 2) ? 2 : 3; // For error message. } else if (type.equals(WKTKeywords.vertical)) { if (axes.length == (dimension = 1)) { @@ -935,11 +949,13 @@ final class GeodeticObjectParser extends return csFactory.createSphericalCS(csProperties, axes[0], axes[1], axes[2]); } } - else if (type.equals(WKTKeywords.parametric)) { // TODO: not yet supported. - return referencing.createAbstractCS(csProperties, axes); + else if (type.equals(WKTKeywords.parametric)) { + if (axes.length == (dimension = 1)) { + return referencing.createParametricCS(csProperties, axes[0], csFactory); + } } else { - warning(parent, null, Errors.formatInternational(Errors.Keys.UnknownType_1, type), null); + warning(parent, WKTKeywords.CS, Errors.formatInternational(Errors.Keys.UnknownType_1, type), null); return referencing.createAbstractCS(csProperties, axes); } } @@ -1082,9 +1098,9 @@ final class GeodeticObjectParser extends if (n2 != null) { return n1 - n2; } - return -1; // Axis 1 before Axis 2 since the later has no 'ORDER' element. + return -1; // Axis 1 before Axis 2 since the later has no 'ORDER' element. } else if (n2 != null) { - return +1; // Axis 2 before Axis 1 since the later has no 'ORDER' element. + return +1; // Axis 2 before Axis 1 since the later has no 'ORDER' element. } return 0; } @@ -1156,7 +1172,7 @@ final class GeodeticObjectParser extends for (int i=0; i<values.length;) { values[i] = element.pullDouble(ToWGS84[i]); if ((++i % 3) == 0 && element.isEmpty()) { - break; // It is legal to have only 3 or 6 elements. + break; // It is legal to have only 3 or 6 elements. } } element.close(ignoredElements); @@ -1194,7 +1210,7 @@ final class GeodeticObjectParser extends } final Map<String,?> properties = parseMetadataAndClose(element, name, null); try { - if (inverseFlattening == 0) { // OGC convention for a sphere. + if (inverseFlattening == 0) { // OGC convention for a sphere. return datumFactory.createEllipsoid(properties, semiMajorAxis, semiMajorAxis, unit); } else { return datumFactory.createFlattenedSphere(properties, semiMajorAxis, inverseFlattening, unit); @@ -1439,6 +1455,31 @@ final class GeodeticObjectParser extends } /** + * Parses a {@code "ParametricDatum"} element. This element has the following pattern: + * + * {@preformat wkt + * ParametricDatum["<name>", Anchor[...] {,<authority>}] + * } + * + * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. + * @param parent The parent element. + * @return The {@code "ParametricDatum"} element as a {@link ParametricDatum} object. + * @throws ParseException if the {@code "ParametricDatum"} element can not be parsed. + */ + private Datum parseParametricDatum(final int mode, final Element parent) throws ParseException { + final Element element = parent.pullElement(mode, WKTKeywords.ParametricDatum, WKTKeywords.PDatum); + if (element == null) { + return null; + } + final String name = element.pullString("name"); + try { + return referencing.createParametricDatum(parseAnchorAndClose(element, name), datumFactory); + } catch (FactoryException exception) { + throw element.parseFailed(exception); + } + } + + /** * Parses a {@code "EngineeringDatum"} (WKT 2) element. The syntax is given by * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#76">WKT 2 specification §11.2</a>. * @@ -1464,9 +1505,9 @@ final class GeodeticObjectParser extends if (element == null) { return null; } - final String name = element.pullString ("name"); + final String name = element.pullString("name"); if (isWKT1) { - element.pullInteger("datum"); // Ignored for now. + element.pullInteger("datum"); // Ignored for now. } try { return datumFactory.createEngineeringDatum(parseAnchorAndClose(element, name)); @@ -1519,14 +1560,14 @@ final class GeodeticObjectParser extends throws ParseException { final Element element = parent.pullElement(mode, - isBaseCRS ? new String[] {WKTKeywords.BaseEngCRS} // WKT 2 in DerivedCRS - : new String[] {WKTKeywords.EngineeringCRS, // [0] WKT 2 - WKTKeywords.EngCRS, // [1] WKT 2 - WKTKeywords.Local_CS}); // [2] WKT 1 + isBaseCRS ? new String[] {WKTKeywords.BaseEngCRS} // WKT 2 in DerivedCRS + : new String[] {WKTKeywords.EngineeringCRS, // [0] WKT 2 + WKTKeywords.EngCRS, // [1] WKT 2 + WKTKeywords.Local_CS}); // [2] WKT 1 if (element == null) { return null; } - final boolean isWKT1 = element.getKeywordIndex() == 2; // Index of "Local_CS" above. + final boolean isWKT1 = element.getKeywordIndex() == 2; // Index of "Local_CS" above. final String name = element.pullString("name"); final Unit<?> unit = parseUnit(element); /* @@ -1563,7 +1604,7 @@ final class GeodeticObjectParser extends } } } - if (baseCRS == null) { // The most usual case. + if (baseCRS == null) { // The most usual case. datum = parseEngineeringDatum(MANDATORY, element, isWKT1); } try { @@ -1639,18 +1680,18 @@ final class GeodeticObjectParser extends throws ParseException { final Element element = parent.pullElement(mode, - (csType != null) ? new String[] {WKTKeywords.BaseGeodCRS, // [0] WKT 2 in ProjectedCRS or DerivedCRS - WKTKeywords.GeogCS} // [1] WKT 1 in ProjectedCRS - : new String[] {WKTKeywords.GeodeticCRS, // [0] WKT 2 - WKTKeywords.GeogCS, // [1] WKT 1 - WKTKeywords.GeodCRS, // [2] WKT 2 - WKTKeywords.GeocCS}); // [3] WKT 1 + (csType != null) ? new String[] {WKTKeywords.BaseGeodCRS, // [0] WKT 2 in ProjectedCRS or DerivedCRS + WKTKeywords.GeogCS} // [1] WKT 1 in ProjectedCRS + : new String[] {WKTKeywords.GeodeticCRS, // [0] WKT 2 + WKTKeywords.GeogCS, // [1] WKT 1 + WKTKeywords.GeodCRS, // [2] WKT 2 + WKTKeywords.GeocCS}); // [3] WKT 1 if (element == null) { return null; } final boolean isWKT1; - Unit<?> csUnit; - Unit<Angle> angularUnit; + Unit<?> csUnit; + final Unit<Angle> angularUnit; switch (element.getKeywordIndex()) { default: { /* @@ -1683,7 +1724,7 @@ final class GeodeticObjectParser extends * We recognize those cases by a non-null 'csType' given in argument to this method. */ if (WKTKeywords.ellipsoidal.equals(csType)) { - csUnit = NonSI.DEGREE_ANGLE; // For BaseGeodCRS in ProjectedCRS. + csUnit = NonSI.DEGREE_ANGLE; // For BaseGeodCRS in ProjectedCRS. } } } @@ -1747,7 +1788,7 @@ final class GeodeticObjectParser extends return crsFactory.createDerivedCRS(properties, baseCRS, fromBase, cs); } /* - * The specifiation in §8.2.2 (ii) said: + * The specification in §8.2.2 (ii) said: * * "(snip) the prime meridian’s <irm longitude> value shall be given in the * same angular units as those for the horizontal axes of the geographic CRS." @@ -1757,18 +1798,22 @@ final class GeodeticObjectParser extends * So we re-fetch the angular unit. Normally, we will get the same value (unless * the previous value was null). */ - angularUnit = AxisDirections.getAngularUnit(cs, angularUnit); - final PrimeMeridian meridian = parsePrimeMeridian(OPTIONAL, element, isWKT1, angularUnit); + final Unit<Angle> longitudeUnit = AxisDirections.getAngularUnit(cs, angularUnit); + if (angularUnit != null && !angularUnit.equals(longitudeUnit)) { + warning(element, WKTKeywords.AngleUnit, Errors.formatInternational( + Errors.Keys.InconsistentUnitsForCS_1, angularUnit), null); + } + final PrimeMeridian meridian = parsePrimeMeridian(OPTIONAL, element, isWKT1, longitudeUnit); final GeodeticDatum datum = parseDatum(MANDATORY, element, meridian); final Map<String,?> properties = parseMetadataAndClose(element, name, datum); if (cs instanceof EllipsoidalCS) { // By far the most frequent case. return crsFactory.createGeographicCRS(properties, datum, (EllipsoidalCS) cs); } - if (cs instanceof CartesianCS) { // The second most frequent case. + if (cs instanceof CartesianCS) { // The second most frequent case. return crsFactory.createGeocentricCRS(properties, datum, referencing.upgradeGeocentricCS((CartesianCS) cs)); } - if (cs instanceof SphericalCS) { // Not very common case. + if (cs instanceof SphericalCS) { // Not very common case. return crsFactory.createGeocentricCRS(properties, datum, (SphericalCS) cs); } } catch (FactoryException exception) { @@ -1793,18 +1838,19 @@ final class GeodeticObjectParser extends * @return The {@code "VerticalCRS"} element as a {@link VerticalCRS} object. * @throws ParseException if the {@code "VerticalCRS"} element can not be parsed. */ + @SuppressWarnings("null") private SingleCRS parseVerticalCRS(final int mode, final Element parent, final boolean isBaseCRS) throws ParseException { final Element element = parent.pullElement(mode, - isBaseCRS ? new String[] {WKTKeywords.BaseVertCRS} // WKT 2 in DerivedCRS - : new String[] {WKTKeywords.VerticalCRS, // [0] WKT 2 - WKTKeywords.VertCRS, // [1] WKT 2 - WKTKeywords.Vert_CS}); // [2] WKT 1 + isBaseCRS ? new String[] {WKTKeywords.BaseVertCRS} // WKT 2 in DerivedCRS + : new String[] {WKTKeywords.VerticalCRS, // [0] WKT 2 + WKTKeywords.VertCRS, // [1] WKT 2 + WKTKeywords.Vert_CS}); // [2] WKT 1 if (element == null) { return null; } - final boolean isWKT1 = element.getKeywordIndex() == 2; // Index of "Vert_CS" above. + final boolean isWKT1 = element.getKeywordIndex() == 2; // Index of "Vert_CS" above. final String name = element.pullString("name"); final Unit<?> unit = parseUnit(element); /* @@ -1830,7 +1876,7 @@ final class GeodeticObjectParser extends baseCRS = parseVerticalCRS(MANDATORY, element, true); } } - if (baseCRS == null) { // The most usual case. + if (baseCRS == null) { // The most usual case. datum = parseVerticalDatum(MANDATORY, element, isWKT1); } final CoordinateSystem cs; @@ -1909,7 +1955,7 @@ final class GeodeticObjectParser extends baseCRS = parseTimeCRS(MANDATORY, element, true); } } - if (baseCRS == null) { // The most usual case. + if (baseCRS == null) { // The most usual case. datum = parseTimeDatum(MANDATORY, element); } final CoordinateSystem cs; @@ -1929,6 +1975,66 @@ final class GeodeticObjectParser extends } /** + * Parses {@code "ParametricCRS"} element. + * + * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. + * @param parent The parent element. + * @param isBaseCRS {@code true} if parsing the CRS inside a {@code DerivedCRS}. + * @return The {@code "ParametricCRS"} object. + * @throws ParseException if the {@code "ParametricCRS"} element can not be parsed. + */ + private SingleCRS parseParametricCRS(final int mode, final Element parent, final boolean isBaseCRS) + throws ParseException + { + final Element element = parent.pullElement(mode, isBaseCRS ? WKTKeywords.BaseParamCRS : WKTKeywords.ParametricCRS); + if (element == null) { + return null; + } + final String name = element.pullString("name"); + final Unit<?> unit = parseUnit(element); + /* + * A ParametricCRS can be either a "normal" one (with a non-null datum), or a DerivedCRS of kind ParametricCRS. + * In the later case, the datum is null and we have instead DerivingConversion element from a BaseParametricCRS. + */ + Datum datum = null; + SingleCRS baseCRS = null; + Conversion fromBase = null; + if (!isBaseCRS) { + /* + * UNIT[…] in DerivedCRS parameters are mandatory according ISO 19162 and the specification does not said + * what to do if they are missing. In this code, we default to the contextual units in the same way than + * what we do for ProjectedCRS parameters, in the hope to be consistent. + * + * An alternative would be to specify null units, in which case MathTransformParser.parseParameters(…) + * defaults to the units specified in the parameter descriptor. But this would make the CRS parser more + * implementation-dependent, because the parameter descriptors are provided by the MathTransformFactory + * instead than inferred from the WKT. + */ + fromBase = parseDerivingConversion(OPTIONAL, element, WKTKeywords.DerivingConversion, unit, null); + if (fromBase != null) { + baseCRS = parseParametricCRS(MANDATORY, element, true); + } + } + if (baseCRS == null) { // The most usual case. + datum = parseParametricDatum(MANDATORY, element); + } + final CoordinateSystem cs; + try { + cs = parseCoordinateSystem(element, WKTKeywords.parametric, 1, false, unit, datum); + final Map<String,?> properties = parseMetadataAndClose(element, name, datum); + if (cs != null) { + if (baseCRS != null) { + return crsFactory.createDerivedCRS(properties, baseCRS, fromBase, cs); + } + return referencing.createParametricCRS(properties, datum, cs, crsFactory); + } + } catch (FactoryException exception) { + throw element.parseFailed(exception); + } + throw element.illegalCS(cs); + } + + /** * Parses a {@code "ProjectedCRS"} (WKT 2) element. The syntax is given by * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#57">WKT 2 specification §9</a>. * @@ -1949,15 +2055,15 @@ final class GeodeticObjectParser extends throws ParseException { final Element element = parent.pullElement(mode, - isBaseCRS ? new String[] {WKTKeywords.BaseProjCRS} // WKT 2 in DerivedCRS - : new String[] {WKTKeywords.ProjectedCRS, // [0] WKT 2 - WKTKeywords.ProjCRS, // [1] WKT 2 - WKTKeywords.ProjCS}); // [2] WKT 1 + isBaseCRS ? new String[] {WKTKeywords.BaseProjCRS} // WKT 2 in DerivedCRS + : new String[] {WKTKeywords.ProjectedCRS, // [0] WKT 2 + WKTKeywords.ProjCRS, // [1] WKT 2 + WKTKeywords.ProjCS}); // [2] WKT 1 if (element == null) { return null; } - final boolean isWKT1 = element.getKeywordIndex() == 2; // Index of "ProjCS" above. + final boolean isWKT1 = element.getKeywordIndex() == 2; // Index of "ProjCS" above. final String name = element.pullString("name"); final SingleCRS geoCRS = parseGeodeticCRS(MANDATORY, element, 2, WKTKeywords.ellipsoidal); if (!(geoCRS instanceof GeographicCRS)) { Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] (original) +++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -358,7 +358,7 @@ public class ImmutableIdentifier extends final Map<String,?> properties, final String key, final Object value) { return new IllegalArgumentException(Errors.getResources(properties) - .getString(Errors.Keys.IllegalPropertyClass_2, key, value.getClass())); + .getString(Errors.Keys.IllegalPropertyValueClass_2, key, value.getClass())); } /** Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -195,7 +195,7 @@ public abstract class AbstractEnvelope i static CoordinateSystemAxis getAxis(final CoordinateReferenceSystem crs, final int dimension) { if (crs != null) { final CoordinateSystem cs = crs.getCoordinateSystem(); - if (cs != null) { // Paranoiac check (should never be null). + if (cs != null) { // Paranoiac check (should never be null). return cs.getAxis(dimension); } } @@ -348,7 +348,7 @@ public abstract class AbstractEnvelope i @Override public double getMinimum(final int dimension) throws IndexOutOfBoundsException { double lower = getLower(dimension); - if (isNegative(getUpper(dimension) - lower)) { // Special handling for -0.0 + if (isNegative(getUpper(dimension) - lower)) { // Special handling for -0.0 final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension); lower = (axis != null) ? axis.getMinimumValue() : Double.NEGATIVE_INFINITY; } @@ -369,7 +369,7 @@ public abstract class AbstractEnvelope i @Override public double getMaximum(final int dimension) throws IndexOutOfBoundsException { double upper = getUpper(dimension); - if (isNegative(upper - getLower(dimension))) { // Special handling for -0.0 + if (isNegative(upper - getLower(dimension))) { // Special handling for -0.0 final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension); upper = (axis != null) ? axis.getMaximumValue() : Double.POSITIVE_INFINITY; } @@ -404,7 +404,7 @@ public abstract class AbstractEnvelope i final double lower = getLower(dimension); final double upper = getUpper(dimension); double median = 0.5 * (lower + upper); - if (isNegative(upper - lower)) { // Special handling for -0.0 + if (isNegative(upper - lower)) { // Special handling for -0.0 median = fixMedian(getAxis(getCoordinateReferenceSystem(), dimension), median); } return median; @@ -451,7 +451,7 @@ public abstract class AbstractEnvelope i @Override public double getSpan(final int dimension) { double span = getUpper(dimension) - getLower(dimension); - if (isNegative(span)) { // Special handling for -0.0 + if (isNegative(span)) { // Special handling for -0.0 span = fixSpan(getAxis(getCoordinateReferenceSystem(), dimension), span); } return span; @@ -532,14 +532,14 @@ public abstract class AbstractEnvelope i */ @SuppressWarnings("ReturnOfCollectionOrArrayField") public Envelope[] toSimpleEnvelopes() { - long isWrapAround = 0; // A bitmask of the dimensions having a "wrap around" behavior. + long isWrapAround = 0; // A bitmask of the dimensions having a "wrap around" behavior. CoordinateReferenceSystem crs = null; final int dimension = getDimension(); for (int i=0; i!=dimension; i++) { - final double span = getUpper(i) - getLower(i); // Do not use getSpan(i). - if (!(span > 0)) { // Use '!' for catching NaN. + final double span = getUpper(i) - getLower(i); // Do not use getSpan(i). + if (!(span > 0)) { // Use '!' for catching NaN. if (!isNegative(span)) { - return EMPTY; // Span is positive zero. + return EMPTY; // Span is positive zero. } if (crs == null) { crs = getCoordinateReferenceSystem(); @@ -589,9 +589,9 @@ public abstract class AbstractEnvelope i * Assign the minimum and maximum ordinate values in the dimension where a wraparound has been found. * The 'for' loop below iterates only over the 'i' values for which the 'isWrapAround' bit is set to 1. */ - int mask = 1; // For identifying whether we need to set the lower or the upper ordinate. + int mask = 1; // For identifying whether we need to set the lower or the upper ordinate. @SuppressWarnings("null") - final CoordinateSystem cs = crs.getCoordinateSystem(); // Should not be null at this point. + final CoordinateSystem cs = crs.getCoordinateSystem(); // Should not be null at this point. for (int i; (i = Long.numberOfTrailingZeros(isWrapAround)) != Long.SIZE; isWrapAround &= ~(1L << i)) { final CoordinateSystemAxis axis = cs.getAxis(i); final double min = axis.getMinimumValue(); @@ -635,7 +635,7 @@ public abstract class AbstractEnvelope i return true; } for (int i=0; i<dimension; i++) { - if (!(getSpan(i) > 0)) { // Use '!' in order to catch NaN + if (!(getSpan(i) > 0)) { // Use '!' in order to catch NaN return true; } } @@ -708,7 +708,7 @@ public abstract class AbstractEnvelope i final boolean c1 = (value >= lower); final boolean c2 = (value <= upper); if (c1 & c2) { - continue; // Point inside the range, check other dimensions. + continue; // Point inside the range, check other dimensions. } if (c1 | c2) { if (isNegative(upper - lower)) { @@ -1134,7 +1134,7 @@ public abstract class AbstractEnvelope i final DirectPosition lowerCorner = envelope.getLowerCorner(); final DirectPosition upperCorner = envelope.getUpperCorner(); boolean isUpper = false; - do { // Executed exactly twice. + do { // Executed exactly twice. for (int i=0; i<dimension; i++) { buffer.append(i == 0 && !isUpper ? '(' : ' '); final double ordinate = (isUpper ? upperCorner : lowerCorner).getOrdinate(i);
