sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1740177 [2/8] - in /sis/trunk: ./ core/sis-feature/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/main/java/org/apache/sis/internal/ core/sis-feature/src/main/java/org/apache/sis/internal/feature/ core/sis-fea...
Date Wed, 20 Apr 2016 17:40:13 GMT
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);



Mime
View raw message