sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1755610 [1/7] - in /sis/branches/JDK7: ./ core/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/main/java/org/apache/sis/feature/builder/ core/sis-feature/src/test/java/org/apache/sis/feature/ core/sis-feature/s...
Date Tue, 09 Aug 2016 14:48:05 GMT
Author: desruisseaux
Date: Tue Aug  9 14:48:04 2016
New Revision: 1755610

URL: http://svn.apache.org/viewvc?rev=1755610&view=rev
Log:
Merge from the JDK8 branch the addition of sis-geotiff module and the work on FeatureTypeBuilder.

Added:
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java
      - copied, changed from r1755594, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/builder/AttributeTypeBuilderTest.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/AttributeTypeBuilderTest.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/builder/CharacteristicTypeBuilderTest.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/CharacteristicTypeBuilderTest.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/LocalDate.java   (with props)
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
      - copied, changed from r1755594, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java
      - copied, changed from r1755594, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java
      - copied unchanged from r1755594, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java
      - copied, changed from r1755594, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
      - copied, changed from r1755594, sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
    sis/branches/JDK7/ide-project/NetBeans/nbproject/build-impl.xml~
      - copied, changed from r1755594, sis/branches/JDK7/ide-project/NetBeans/nbproject/build-impl.xml
    sis/branches/JDK7/storage/sis-geotiff/
      - copied from r1755594, sis/branches/JDK8/storage/sis-geotiff/
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
      - copied, changed from r1755594, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreContentException.java
      - copied unchanged from r1755594, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreContentException.java
    sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/MetadataBuilderTest.java
      - copied unchanged from r1755594, sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/MetadataBuilderTest.java
Removed:
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataHelper.java
Modified:
    sis/branches/JDK7/   (props changed)
    sis/branches/JDK7/core/pom.xml
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AssociationRoleBuilder.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeRole.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeTypeBuilder.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/CharacteristicTypeBuilder.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/PropertyTypeBuilder.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/RemoveOnlyList.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/TypeBuilder.java
    sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/builder/package-info.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java
    sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataUtilities.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/InvalidMetadataException.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultConstraints.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java
    sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/MetadataAssert.java
    sis/branches/JDK7/core/sis-referencing/pom.xml
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ProjectionException.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearInterpolator1D.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/OperationMethodSet.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/TransformSeparator.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/AlbersEqualAreaTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/CylindricalEqualAreaTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CartesianToSphericalTest.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Instant.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Loggers.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractIterator.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/LazySet.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/SetOfUnknownSize.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/math/package-info.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/setup/OptionKey.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/BackingStoreException.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedSet.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
    sis/branches/JDK7/ide-project/NetBeans/nbproject/build-impl.xml
    sis/branches/JDK7/ide-project/NetBeans/nbproject/genfiles.properties
    sis/branches/JDK7/ide-project/NetBeans/nbproject/project.properties
    sis/branches/JDK7/ide-project/NetBeans/nbproject/project.xml
    sis/branches/JDK7/pom.xml
    sis/branches/JDK7/storage/pom.xml
    sis/branches/JDK7/storage/sis-geotiff/pom.xml
    sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Reader.java
    sis/branches/JDK7/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java
    sis/branches/JDK7/storage/sis-netcdf/pom.xml
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
    sis/branches/JDK7/storage/sis-storage/pom.xml
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreException.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/UnsupportedStorageException.java
    sis/branches/JDK7/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java

Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Aug  9 14:48:04 2016
@@ -1,4 +1,4 @@
 /sis/branches/Android:1430670-1480699
 /sis/branches/JDK6:1394913-1508480
-/sis/branches/JDK8:1584960-1753654
+/sis/branches/JDK8:1584960-1755608
 /sis/trunk:1394364-1508466,1519089-1519674

Modified: sis/branches/JDK7/core/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/pom.xml?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/pom.xml (original)
+++ sis/branches/JDK7/core/pom.xml Tue Aug  9 14:48:04 2016
@@ -71,7 +71,7 @@
       <id>rmarechal</id>
       <email>remi.marechal@geomatys.com</email>
       <organization>Geomatys</organization>
-      <organizationUrl>http://www.geomatys.com/</organizationUrl>
+      <organizationUrl>http://www.geomatys.com</organizationUrl>
       <timezone>+1</timezone>
       <roles>
         <role>developer</role>
@@ -117,7 +117,7 @@
       <name>Johann Sorel</name>
       <email>johann.sorel@geomatys.com</email>
       <organization>Geomatys</organization>
-      <organizationUrl>http://www.geomatys.com/</organizationUrl>
+      <organizationUrl>http://www.geomatys.com</organizationUrl>
       <timezone>+1</timezone>
       <roles>
         <role>developer</role>

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -69,7 +69,7 @@ public abstract class AbstractAssociatio
     /**
      * Creates a new association of the given role.
      *
-     * @param role Information about the association.
+     * @param role  information about the association.
      *
      * @see #create(FeatureAssociationRole)
      */
@@ -80,8 +80,8 @@ public abstract class AbstractAssociatio
     /**
      * Creates a new association of the given role.
      *
-     * @param  role Information about the association.
-     * @return The new association.
+     * @param  role  information about the association.
+     * @return the new association.
      *
      * @see DefaultAssociationRole#newInstance()
      */
@@ -95,9 +95,9 @@ public abstract class AbstractAssociatio
     /**
      * Creates a new association of the given role initialized to the given value.
      *
-     * @param  role  Information about the association.
-     * @param  value The initial value (may be {@code null}).
-     * @return The new association.
+     * @param  role   information about the association.
+     * @param  value  the initial value (may be {@code null}).
+     * @return the new association.
      */
     static AbstractAssociation create(final FeatureAssociationRole role, final Object value) {
         ArgumentChecks.ensureNonNull("role", role);
@@ -110,7 +110,7 @@ public abstract class AbstractAssociatio
      * Returns the name of this association as defined by its {@linkplain #getRole() role}.
      * This convenience method delegates to {@link FeatureAssociationRole#getName()}.
      *
-     * @return The association name specified by its role.
+     * @return the association name specified by its role.
      */
     @Override
     public GenericName getName() {
@@ -120,7 +120,7 @@ public abstract class AbstractAssociatio
     /**
      * Returns information about the association.
      *
-     * @return Information about the association.
+     * @return information about the association.
      */
     @Override
     public FeatureAssociationRole getRole() {
@@ -132,7 +132,7 @@ public abstract class AbstractAssociatio
      * the common case where the {@linkplain DefaultAssociationRole#getMaximumOccurs() maximum number} of
      * features is restricted to 1 or 0.
      *
-     * @return The associated feature (may be {@code null}).
+     * @return the associated feature (may be {@code null}).
      * @throws MultiValuedPropertyException if this association contains more than one value.
      *
      * @see AbstractFeature#getPropertyValue(String)
@@ -148,7 +148,7 @@ public abstract class AbstractAssociatio
      * <p>The default implementation returns a collection which will delegate its work to
      * {@link #getValue()} and {@link #setValue(Object)}.</p>
      *
-     * @return The features in a <cite>live</cite> collection.
+     * @return the features in a <cite>live</cite> collection.
      */
     @Override
     public Collection<Feature> getValues() {
@@ -164,8 +164,8 @@ public abstract class AbstractAssociatio
      * and also because some rules may be temporarily broken while constructing a feature.
      * A more exhaustive verification can be performed by invoking the {@link #quality()} method.
      *
-     * @param  value The new value, or {@code null}.
-     * @throws InvalidPropertyValueException If the given feature is not valid for this association.
+     * @param  value  the new value, or {@code null}.
+     * @throws InvalidPropertyValueException if the given feature is not valid for this association.
      *
      * @see AbstractFeature#setPropertyValue(String, Object)
      */
@@ -178,7 +178,7 @@ public abstract class AbstractAssociatio
      * <p>The default implementation ensures that the given collection contains at most one element,
      * then delegates to {@link #setValue(Feature)}.</p>
      *
-     * @param  values The new values.
+     * @param  values  the new values.
      * @throws InvalidPropertyValueException if the given collection contains too many elements.
      */
     @Override
@@ -208,7 +208,7 @@ public abstract class AbstractAssociatio
      * {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult conformance result} having a
      * {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult#pass() pass} value of {@code false}.</p>
      *
-     * @return Reports on all constraint violations found.
+     * @return reports on all constraint violations found.
      *
      * @see AbstractFeature#quality()
      */
@@ -222,14 +222,16 @@ public abstract class AbstractAssociatio
      * Returns a string representation of this association.
      * The returned string is for debugging purpose and may change in any future SIS version.
      *
-     * @return A string representation of this association for debugging purpose.
+     * @return a string representation of this association for debugging purpose.
      */
     @Debug
     @Override
     public String toString() {
         final String pt = DefaultAssociationRole.getTitleProperty(role);
         final Iterator<Feature> it = getValues().iterator();
-        return FieldType.toString("FeatureAssociation", role, DefaultAssociationRole.getValueTypeName(role), new Iterator<Object>() {
+        return FieldType.toString("FeatureAssociation", role.getName(),
+                DefaultAssociationRole.getValueTypeName(role), new Iterator<Object>()
+        {
             @Override public boolean hasNext() {
                 return it.hasNext();
             }
@@ -251,7 +253,7 @@ public abstract class AbstractAssociatio
      * the association {@linkplain #getValue() value} is <strong>not</strong> cloned.
      * However subclasses may choose to do otherwise.
      *
-     * @return A clone of this association.
+     * @return a clone of this association.
      * @throws CloneNotSupportedException if this association can not be cloned.
      *         The default implementation never throw this exception. However subclasses may throw it.
      */

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -464,7 +464,7 @@ public abstract class AbstractAttribute<
     @Debug
     @Override
     public String toString() {
-        final StringBuilder buffer = FieldType.toString("Attribute", type,
+        final StringBuilder buffer = FieldType.toString("Attribute", type.getName(),
                 Classes.getShortName(type.getValueClass()), getValues().iterator());
         if (characteristics != null && !characteristics.isEmpty()) {
             buffer.append(System.lineSeparator());

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -25,10 +25,12 @@ import org.opengis.metadata.quality.Data
 import org.opengis.metadata.maintenance.ScopeCode;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.CorruptedObjectException;
 import org.apache.sis.internal.util.CheckedArrayList;
 
 // Branch-dependent imports
+import java.util.Objects;
 import org.opengis.feature.Property;
 import org.opengis.feature.PropertyType;
 import org.opengis.feature.PropertyNotFoundException;
@@ -74,7 +76,7 @@ import org.opengis.feature.Operation;
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.7
+ * @version 0.8
  * @module
  *
  * @see DefaultFeatureType#newInstance()
@@ -93,7 +95,7 @@ public abstract class AbstractFeature im
     /**
      * Creates a new feature of the given type.
      *
-     * @param type Information about the feature (name, characteristics, <i>etc.</i>).
+     * @param type  information about the feature (name, characteristics, <i>etc.</i>).
      *
      * @see DefaultFeatureType#newInstance()
      */
@@ -113,7 +115,7 @@ public abstract class AbstractFeature im
     /**
      * Returns information about the feature (name, characteristics, <i>etc.</i>).
      *
-     * @return Information about the feature.
+     * @return information about the feature.
      */
     @Override
     public FeatureType getType() {
@@ -126,19 +128,32 @@ public abstract class AbstractFeature im
      * method may return the result of {@linkplain AbstractOperation#apply executing} the operation
      * on this feature, at implementation choice.
      *
-     * <div class="note"><b>Tip:</b> This method returns the property <em>instance</em>. If only the property
-     * <em>value</em> is desired, then {@link #getPropertyValue(String)} is preferred since it gives to SIS a
-     * chance to avoid the creation of {@link AbstractAttribute} or {@link AbstractAssociation} instances.</div>
+     * <p>This method returns the property <em>instance</em>. If only the property <em>value</em> is
+     * desired, then {@link #getPropertyValue(String)} is preferred since it gives to SIS a chance to
+     * avoid the creation of {@link AbstractAttribute} or {@link AbstractAssociation} instances.</p>
+     *
+     * <div class="note"><b>Note for subclass implementors:</b>
+     * the default implementation returns an instance that redirect all read and write operations to
+     * {@link #getPropertyValue(String)} and {@link #setPropertyValue(String, Object)} respectively.
+     * That default implementation is intended to make easier for developers to create their own
+     * customized <code>AbstractFacture</code> implementations, but has drawbacks:
+     * a new {@code Property} instance is created every time that this {@code getProperty(String)} method is invoked,
+     * and the returned {@code Property} implementation is not very efficient
+     * since it has to perform multiple lookups and type checks.
+     * Implementors are encouraged to override this method if they can provide a more efficient implementation.
+     * Note that this is already the case when using implementations created by {@link DefaultFeatureType#newInstance()}.</div>
      *
-     * @param  name The property name.
-     * @return The property of the given name (never {@code null}).
+     * @param  name  the property name.
+     * @return the property of the given name (never {@code null}).
      * @throws PropertyNotFoundException if the given argument is not a property name of this feature.
      *
      * @see #getPropertyValue(String)
      * @see DefaultFeatureType#getProperty(String)
      */
     @Override
-    public abstract Property getProperty(final String name) throws PropertyNotFoundException;
+    public Property getProperty(final String name) throws PropertyNotFoundException {
+        return PropertyView.create(this, type.getProperty(name));
+    }
 
     /**
      * Sets the property (attribute or feature association).
@@ -156,11 +171,22 @@ public abstract class AbstractFeature im
      *     assert property.getType() == getType().getProperty(property.getName());
      * }
      *
-     * <div class="note"><b>Note:</b> This method is useful for storing non-default {@code Attribute} or
-     * {@code FeatureAssociation} implementations in this feature. When default implementations are sufficient,
-     * the {@link #setPropertyValue(String, Object)} method is preferred.</div>
+     * This method is useful for storing non-default {@code Attribute} or {@code FeatureAssociation} implementations
+     * in this feature. When default implementations are sufficient, the {@link #setPropertyValue(String, Object)}
+     * method is preferred.
+     *
+     * <div class="note"><b>Note for subclass implementors:</b>
+     * the default implementation verifies that the given property has the expected type and a null or empty
+     * {@linkplain AbstractAttribute#characteristics() map of characteristics}, then delegates to
+     * {@link #setPropertyValue(String, Object)}.
+     * That default implementation is intended to make easier for developers to create their own
+     * customized <code>AbstractFacture</code> implementations, but has drawbacks:
+     * the given {@code Property} instance is not stored (only its {@linkplain AbstractAttribute#getValue() value}
+     * is stored), and it can not have custom {@linkplain AbstractAttribute#characteristics() characteristics}.
+     * Implementors are encouraged to override this method if they can provide a better implementation.
+     * Note that this is already the case when using implementations created by {@link DefaultFeatureType#newInstance()}.</div>
      *
-     * @param  property The property to set.
+     * @param  property  the property to set.
      * @throws PropertyNotFoundException if the name of the given property is not a property name of this feature.
      * @throws InvalidPropertyValueException if the value of the given property is not valid.
      * @throws IllegalArgumentException if the property can not be set for another reason.
@@ -168,14 +194,22 @@ public abstract class AbstractFeature im
      * @see #setPropertyValue(String, Object)
      */
     @Override
-    public abstract void setProperty(final Property property) throws IllegalArgumentException;
+    public void setProperty(final Property property) throws IllegalArgumentException {
+        ArgumentChecks.ensureNonNull("property", property);
+        final String name = property.getName().toString();
+        verifyPropertyType(name, property);
+        if (property instanceof Attribute<?> && !Containers.isNullOrEmpty(((Attribute<?>) property).characteristics())) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.CanNotAssignCharacteristics_1, name));
+        }
+        setPropertyValue(name, property.getValue());
+    }
 
     /**
      * Wraps the given value in a {@link Property} object. This method is invoked only by
      * {@link #getProperty(String)} when it needs to converts its {@code properties} data.
      *
-     * @param  name  The name of the property to create.
-     * @param  value The value to wrap.
+     * @param  name   the name of the property to create.
+     * @param  value  the value to wrap.
      * @return A {@code Property} wrapping the given value.
      */
     final Property createProperty(final String name, final Object value) {
@@ -193,8 +227,8 @@ public abstract class AbstractFeature im
     /**
      * Creates a new property initialized to its default value.
      *
-     * @param  name The name of the property to create.
-     * @return A {@code Property} of the given name.
+     * @param  name  the name of the property to create.
+     * @return a {@code Property} of the given name.
      * @throws PropertyNotFoundException if the given argument is not the name of an attribute or
      *         feature association of this feature.
      */
@@ -261,8 +295,8 @@ public abstract class AbstractFeature im
      * Returns the default value to be returned by {@link #getPropertyValue(String)}
      * for the property of the given name.
      *
-     * @param  name The name of the property for which to get the default value.
-     * @return The default value for the {@code Property} of the given name.
+     * @param  name  the name of the property for which to get the default value.
+     * @return the default value for the {@code Property} of the given name.
      * @throws PropertyNotFoundException if the given argument is not an attribute or association name of this feature.
      */
     final Object getDefaultValue(final String name) throws PropertyNotFoundException {
@@ -308,8 +342,20 @@ public abstract class AbstractFeature im
      * number of occurrences} and does not depend on the actual number of values. If an attribute allows more than one
      * value, then this method will always return a collection for that attribute even if the collection is empty.</div>
      *
-     * @param  name The property name.
-     * @return The value for the given property, or {@code null} if none.
+     * <div class="section">Multi-valued properties and collections</div>
+     * In the case of multi-valued properties (“max. occurs” &gt; 1), the collection returned by this method may
+     * or may not be modifiable, at implementation choice. Generally the caller can not add new elements into the
+     * returned collection anyway since {@code Collection<?>} does not allow such operations, and more specific
+     * casts (e.g. {@code Collection<String>} can not be checked at runtime (at least as of Java 8).
+     * If a type-safe modifiable collection is desired, the following approach can be used instead:
+     *
+     * {@preformat java
+     *   Attribute<String> attribute = Features.cast((Attribute<?>) feature.getProperty(name), String.class);
+     *   Collection<String> values = attribute.getValues();    // This collection is guaranteed to be "live".
+     * }
+     *
+     * @param  name  the property name.
+     * @return the value for the given property, or {@code null} if none.
      * @throws PropertyNotFoundException if the given argument is not an attribute or association name of this feature.
      *
      * @see AbstractAttribute#getValue()
@@ -326,8 +372,8 @@ public abstract class AbstractFeature im
      * and also because some rules may be temporarily broken while constructing a feature.
      * A more exhaustive verification can be performed by invoking the {@link #quality()} method.
      *
-     * @param  name  The attribute name.
-     * @param  value The new value for the given attribute (may be {@code null}).
+     * @param  name   the attribute name.
+     * @param  value  the new value for the given attribute (may be {@code null}).
      * @throws PropertyNotFoundException if the given name is not an attribute or association name of this feature.
      * @throws ClassCastException if the value is not assignable to the expected value class.
      * @throws InvalidPropertyValueException if the given value is not valid for a reason other than its type.
@@ -427,9 +473,9 @@ public abstract class AbstractFeature im
      * the same class. Since the type check has already been done by the previous assignation, we do not
      * need to perform it again.
      *
-     * @param previous The previous value, or {@code null}.
-     * @param value    The new value, or {@code null}.
-     * @return         {@code true} if the caller can skip the verification performed by {@code verifyPropertyValue}.
+     * @param  previous  the previous value, or {@code null}.
+     * @param  value     the new value, or {@code null}.
+     * @return {@code true} if the caller can skip the verification performed by {@code verifyPropertyValue}.
      */
     static boolean canSkipVerification(final Object previous, final Object value) {
         if (previous != null) {
@@ -446,8 +492,8 @@ public abstract class AbstractFeature im
     /**
      * Verifies if the given property can be assigned to this feature.
      *
-     * @param name Shall be {@code property.getName().toString()}.
-     * @param property The property to verify.
+     * @param name      shall be {@code property.getName().toString()}.
+     * @param property  the property to verify.
      */
     final void verifyPropertyType(final String name, final Property property) {
         final PropertyType pt, base = type.getProperty(name);
@@ -495,7 +541,7 @@ public abstract class AbstractFeature im
      *   <li>May be a collection, in which case the class each elements in the collection is verified.</li>
      * </ul>
      *
-     * @param value The value, which shall be non-null.
+     * @param value  the value, which shall be non-null.
      */
     private static <T> Object verifyAttributeValue(final AttributeType<T> type, final Object value) {
         final Class<T> valueClass = type.getValueClass();
@@ -517,7 +563,7 @@ public abstract class AbstractFeature im
      *   <li>May be a collection, in which case the class each elements in the collection is verified.</li>
      * </ul>
      *
-     * @param value The value, which shall be non-null.
+     * @param value  the value, which shall be non-null.
      */
     private static Object verifyAssociationValue(final FeatureAssociationRole role, final Object value) {
         final boolean isSingleton = Field.isSingleton(role.getMaximumOccurs());
@@ -639,7 +685,7 @@ public abstract class AbstractFeature im
      * }
      * </div>
      *
-     * @return Reports on all constraint violations found.
+     * @return reports on all constraint violations found.
      *
      * @see AbstractAttribute#quality()
      * @see AbstractAssociation#quality()
@@ -653,7 +699,7 @@ public abstract class AbstractFeature im
     /**
      * Formats this feature in a tabular format.
      *
-     * @return A string representation of this feature in a tabular format.
+     * @return a string representation of this feature in a tabular format.
      *
      * @see FeatureFormat
      */
@@ -661,4 +707,82 @@ public abstract class AbstractFeature im
     public String toString() {
         return FeatureFormat.sharedFormat(this);
     }
+
+    /**
+     * Returns a hash code value for this feature.
+     * The default implementation performs the following algorithm:
+     *
+     * <ul>
+     *   <li>Iterate over all properties returned by {@code type.getProperty(true)} –
+     *       thus including properties inherited from parent types (if any):
+     *   <ul>
+     *     <li>For each property type, get the value with {@link #getPropertyValue(String)}.</li>
+     *     <li>Compute the hash code from the property name and value, ignoring the properties
+     *         having a null value.</li>
+     *   </ul></li>
+     * </ul>
+     *
+     * Subclasses should override this method with a more efficient algorithm for their internal structure.
+     * There is no need to reproduce the same hash code value than the one computed by this default method.
+     *
+     * @return a hash code value.
+     *
+     * @since 0.8
+     */
+    @Override
+    public int hashCode() {
+        int code = type.hashCode() * 37;
+        for (final PropertyType pt : type.getProperties(true)) {
+            final String name = pt.getName().toString();
+            if (name != null) {                                             // Paranoiac check.
+                final Object value = getPropertyValue(name);
+                if (value != null) {
+                    code += name.hashCode() ^ value.hashCode();
+                }
+            }
+        }
+        return code;
+    }
+
+    /**
+     * Compares this feature with the given object for equality.
+     * The default implementation performs the following algorithm:
+     *
+     * <ul>
+     *   <li>Verify that both objects are non-null and of the same class.</li>
+     *   <li>Iterate over all properties returned by {@code type.getProperty(true)} –
+     *       thus including properties inherited from parent types (if any):
+     *   <ul>
+     *     <li>For each property type, get the value from both {@code FeatureType}
+     *         by a call to {@link #getPropertyValue(String)}.</li>
+     *     <li>Verify that the two values are either both null, or equal in the sense of
+     *         {@link Object#equals(Object)}.</li>
+     *   </ul></li>
+     * </ul>
+     *
+     * Subclasses should override this method with a more efficient algorithm for their internal structure.
+     *
+     * @return {@code true} if both objects are equal.
+     *
+     * @since 0.8
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj != this) {
+            if (obj == null || obj.getClass() != getClass()) {
+                return false;
+            }
+            final AbstractFeature that = (AbstractFeature) obj;
+            if (!type.equals(that.type)) {
+                return false;
+            }
+            for (final PropertyType pt : type.getProperties(true)) {
+                final String name = pt.getName().toString();
+                if (!Objects.equals(getPropertyValue(name), that.getPropertyValue(name))) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
 }

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -209,7 +209,7 @@ public class AbstractIdentifiedType impl
      * and need some guarantees about its stability.
      * </div>
      *
-     * @return The type name.
+     * @return the type name.
      */
     @Override
     public final GenericName getName() {
@@ -219,7 +219,7 @@ public class AbstractIdentifiedType impl
     /**
      * Returns a concise definition of the element.
      *
-     * @return Concise definition of the element.
+     * @return concise definition of the element.
      */
     @Override
     public InternationalString getDefinition() {
@@ -230,7 +230,7 @@ public class AbstractIdentifiedType impl
      * Returns a natural language designator for the element.
      * This can be used as an alternative to the {@linkplain #getName() name} in user interfaces.
      *
-     * @return Natural language designator for the element, or {@code null} if none.
+     * @return natural language designator for the element, or {@code null} if none.
      */
     @Override
     public InternationalString getDesignation() {
@@ -241,7 +241,7 @@ public class AbstractIdentifiedType impl
      * Returns optional information beyond that required for concise definition of the element.
      * The description may assist in understanding the element scope and application.
      *
-     * @return Information beyond that required for concise definition of the element, or {@code null} if none.
+     * @return information beyond that required for concise definition of the element, or {@code null} if none.
      */
     @Override
     public InternationalString getDescription() {
@@ -263,7 +263,7 @@ public class AbstractIdentifiedType impl
     /**
      * Returns a hash code value for this type.
      *
-     * @return The hash code for this type.
+     * @return the hash code for this type.
      */
     @Override
     public int hashCode() {
@@ -273,7 +273,7 @@ public class AbstractIdentifiedType impl
     /**
      * Compares this type with the given object for equality.
      *
-     * @param  obj The object to compare with this type.
+     * @param  obj  the object to compare with this type.
      * @return {@code true} if the given object is equals to this type.
      */
     @Override
@@ -292,10 +292,10 @@ public class AbstractIdentifiedType impl
      * Returns the string representation of the given name, making sure that the name is non-null
      * and the string non-empty. This method is used for checking argument validity.
      *
-     * @param name      The name for which to get the string representation.
-     * @param container The feature or attribute which contains the named characteristics.
-     * @param argument  The name of the argument ({@code "properties"} or {@code "characterizedBy"}).
-     * @param index     Index of the characteristics having the given name.
+     * @param  name       the name for which to get the string representation.
+     * @param  container  the feature or attribute which contains the named characteristics.
+     * @param  argument   the name of the argument ({@code "properties"} or {@code "characterizedBy"}).
+     * @param  index      index of the characteristics having the given name.
      * @throws IllegalArgumentException if the given name is null or have an empty string representation.
      */
     static String toString(final GenericName name, final IdentifiedType container, final String argument, final int index) {

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -80,7 +80,7 @@ public abstract class AbstractOperation
      * Constructs an operation from the given properties. The identification map is given unchanged to
      * the {@linkplain AbstractIdentifiedType#AbstractIdentifiedType(Map) super-class constructor}.
      *
-     * @param identification The name and other information to be given to this operation.
+     * @param  identification  the name and other information to be given to this operation.
      */
     public AbstractOperation(final Map<String,?> identification) {
         super(identification);
@@ -92,7 +92,7 @@ public abstract class AbstractOperation
      * If the given map contains at least one key prefixed by {@value #RESULT_PREFIX}, then the values
      * associated to those keys will be used.
      *
-     * @param identification the map given by user to sub-class constructor.
+     * @param  identification  the map given by user to sub-class constructor.
      */
     final Map<String,Object> resultIdentification(final Map<String,?> identification) {
         final Map<String,Object> properties = new HashMap<>(6);
@@ -114,7 +114,7 @@ public abstract class AbstractOperation
     /**
      * Returns a description of the input parameters.
      *
-     * @return Description of the input parameters.
+     * @return description of the input parameters.
      */
     @Override
     public abstract ParameterDescriptorGroup getParameters();
@@ -122,7 +122,7 @@ public abstract class AbstractOperation
     /**
      * Returns the expected result type, or {@code null} if none.
      *
-     * @return The type of the result, or {@code null} if none.
+     * @return the type of the result, or {@code null} if none.
      */
     @Override
     public abstract IdentifiedType getResult();
@@ -148,11 +148,11 @@ public abstract class AbstractOperation
      * in the Java language, and may be {@code null} if the operation does not need a feature instance
      * (like static methods in the Java language).</div>
      *
-     * @param  feature    The feature on which to execute the operation.
-     *                    Can be {@code null} if the operation does not need feature instance.
-     * @param  parameters The parameters to use for executing the operation.
-     *                    Can be {@code null} if the operation does not take any parameters.
-     * @return The operation result, or {@code null} if this operation does not produce any result.
+     * @param  feature     the feature on which to execute the operation.
+     *                     Can be {@code null} if the operation does not need feature instance.
+     * @param  parameters  the parameters to use for executing the operation.
+     *                     Can be {@code null} if the operation does not take any parameters.
+     * @return the operation result, or {@code null} if this operation does not produce any result.
      */
     @Override
     public abstract Property apply(Feature feature, ParameterValueGroup parameters);
@@ -171,7 +171,7 @@ public abstract class AbstractOperation
      *
      * The default implementation returns an empty set.
      *
-     * @return The names of feature properties needed by this operation for performing its task.
+     * @return the names of feature properties needed by this operation for performing its task.
      */
     public Set<String> getDependencies() {
         return Collections.emptySet();
@@ -253,7 +253,7 @@ public abstract class AbstractOperation
      * Appends a string representation of the "formula" used for computing the result.
      * The "formula" may be for example a link to another property.
      *
-     * @param  buffer where to format the "formula".
+     * @param  buffer  where to format the "formula".
      * @return {@code true} if this method has formatted a formula, or {@code false} otherwise.
      */
     boolean formatResultFormula(Appendable buffer) {

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -116,11 +116,11 @@ public class DefaultAssociationRole exte
      *   </tr>
      * </table>
      *
-     * @param identification The name and other information to be given to this association role.
-     * @param valueType      The type of feature values.
-     * @param minimumOccurs  The minimum number of occurrences of the association within its containing entity.
-     * @param maximumOccurs  The maximum number of occurrences of the association within its containing entity,
-     *                       or {@link Integer#MAX_VALUE} if there is no restriction.
+     * @param identification  the name and other information to be given to this association role.
+     * @param valueType       the type of feature values.
+     * @param minimumOccurs   the minimum number of occurrences of the association within its containing entity.
+     * @param maximumOccurs   the maximum number of occurrences of the association within its containing entity,
+     *                        or {@link Integer#MAX_VALUE} if there is no restriction.
      *
      * @see org.apache.sis.feature.builder.AssociationRoleBuilder
      */
@@ -162,11 +162,11 @@ public class DefaultAssociationRole exte
      * If more than one {@code FeatureType} instance of the given name is found at resolution time, the selected one
      * is undetermined.
      *
-     * @param identification The name and other information to be given to this association role.
-     * @param valueType      The name of the type of feature values.
-     * @param minimumOccurs  The minimum number of occurrences of the association within its containing entity.
-     * @param maximumOccurs  The maximum number of occurrences of the association within its containing entity,
-     *                       or {@link Integer#MAX_VALUE} if there is no restriction.
+     * @param identification  the name and other information to be given to this association role.
+     * @param valueType       the name of the type of feature values.
+     * @param minimumOccurs   the minimum number of occurrences of the association within its containing entity.
+     * @param maximumOccurs   the maximum number of occurrences of the association within its containing entity,
+     *                        or {@link Integer#MAX_VALUE} if there is no restriction.
      */
     public DefaultAssociationRole(final Map<String,?> identification, final GenericName valueType,
             final int minimumOccurs, final int maximumOccurs)
@@ -184,7 +184,7 @@ public class DefaultAssociationRole exte
      * to feature <var>B</var> which has an association back to <var>A</var>. It may also be <var>A</var>
      * having an association to itself, <i>etc.</i>
      *
-     * @param  creating The feature type in process of being constructed.
+     * @param  creating  the feature type in process of being constructed.
      * @return {@code true} if this association references a resolved feature type after this method call.
      */
     final boolean resolve(final DefaultFeatureType creating) {
@@ -192,7 +192,7 @@ public class DefaultAssociationRole exte
         if (type instanceof NamedFeatureType) {
             final GenericName name = type.getName();
             if (name.equals(creating.getName())) {
-                type = creating; // This is the most common case.
+                type = creating;                                        // This is the most common case.
             } else {
                 /*
                  * The feature that we need to resolve is not the one we just created. Maybe we can find
@@ -225,10 +225,10 @@ public class DefaultAssociationRole exte
      * <p>Current implementation does not check that there is no duplicated names.
      * See {@link #deepSearch(List, GenericName)} for a rational.</p>
      *
-     * @param  feature The feature in which to search.
-     * @param  name The name of the feature to search.
-     * @param  deferred Where to store {@code FeatureType}s to be eventually used for a deep search.
-     * @return The feature of the given name, or {@code null} if none.
+     * @param  feature   the feature in which to search.
+     * @param  name      the name of the feature to search.
+     * @param  deferred  where to store {@code FeatureType}s to be eventually used for a deep search.
+     * @return the feature of the given name, or {@code null} if none.
      */
     @SuppressWarnings("null")
     private static FeatureType search(final FeatureType feature, final GenericName name, final List<FeatureType> deferred) {
@@ -243,7 +243,7 @@ public class DefaultAssociationRole exte
                 if (property instanceof DefaultAssociationRole) {
                     valueType = ((DefaultAssociationRole) property).valueType;
                     if (valueType instanceof NamedFeatureType) {
-                        continue; // Skip unresolved feature types.
+                        continue;                                   // Skip unresolved feature types.
                     }
                 } else {
                     valueType = ((FeatureAssociationRole) property).getValueType();
@@ -281,10 +281,10 @@ public class DefaultAssociationRole exte
      * later. We rather put a warning in {@link #DefaultAssociationRole(Map, GenericName, int, int)}
      * javadoc.</p>
      *
-     * @param  feature The feature in which to search.
-     * @param  name The name of the feature to search.
-     * @param  done The feature types collected by {@link #search(FeatureType, GenericName, List)}.
-     * @return The feature of the given name, or {@code null} if none.
+     * @param  feature  the feature in which to search.
+     * @param  name     the name of the feature to search.
+     * @param  done     the feature types collected by {@link #search(FeatureType, GenericName, List)}.
+     * @return the feature of the given name, or {@code null} if none.
      */
     private static FeatureType deepSearch(final List<FeatureType> deferred, final GenericName name) {
         final Map<FeatureType,Boolean> done = new IdentityHashMap<>(8);
@@ -305,7 +305,7 @@ public class DefaultAssociationRole exte
     /**
      * Returns the type of feature values.
      *
-     * @return The type of feature values.
+     * @return the type of feature values.
      * @throws IllegalStateException if the feature type has been specified
      *         {@linkplain #DefaultAssociationRole(Map, GenericName, int, int) only by its name}
      *         and not yet resolved.
@@ -369,7 +369,7 @@ public class DefaultAssociationRole exte
      * Returns the minimum number of occurrences of the association within its containing entity.
      * The returned value is greater than or equal to zero.
      *
-     * @return The minimum number of occurrences of the association within its containing entity.
+     * @return the minimum number of occurrences of the association within its containing entity.
      */
     @Override
     public final int getMinimumOccurs() {
@@ -381,7 +381,7 @@ public class DefaultAssociationRole exte
      * The returned value is greater than or equal to the {@link #getMinimumOccurs()} value.
      * If there is no maximum, then this method returns {@link Integer#MAX_VALUE}.
      *
-     * @return The maximum number of occurrences of the association within its containing entity,
+     * @return the maximum number of occurrences of the association within its containing entity,
      *         or {@link Integer#MAX_VALUE} if none.
      */
     @Override
@@ -392,7 +392,7 @@ public class DefaultAssociationRole exte
     /**
      * Creates a new association instance of this role.
      *
-     * @return A new association instance.
+     * @return a new association instance.
      *
      * @see AbstractAssociation#create(FeatureAssociationRole)
      */
@@ -437,11 +437,11 @@ public class DefaultAssociationRole exte
      * Returns a string representation of this association role.
      * The returned string is for debugging purpose and may change in any future SIS version.
      *
-     * @return A string representation of this association role for debugging purpose.
+     * @return a string representation of this association role for debugging purpose.
      */
     @Debug
     @Override
     public String toString() {
-        return toString("FeatureAssociationRole", this, valueType.getName()).toString();
+        return toString("FeatureAssociationRole", getName(), valueType.getName()).toString();
     }
 }

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -167,16 +167,16 @@ public class DefaultAttributeType<V> ext
      *   </tr>
      * </table>
      *
-     * @param identification  The name and other information to be given to this attribute type.
-     * @param valueClass      The type of attribute values.
-     * @param minimumOccurs   The minimum number of occurrences of the attribute within its containing entity.
-     * @param maximumOccurs   The maximum number of occurrences of the attribute within its containing entity,
-     *                        or {@link Integer#MAX_VALUE} if there is no restriction.
-     * @param defaultValue    The default value for the attribute, or {@code null} if none.
-     * @param characterizedBy Other attribute types that describes this attribute type (can be {@code null} for none).
-     *                        For example if this new {@code DefaultAttributeType} describes a measurement,
-     *                        then {@code characterizedBy} could holds the measurement accuracy.
-     *                        See <cite>"Attribute characterization"</cite> in class Javadoc for more information.
+     * @param identification   the name and other information to be given to this attribute type.
+     * @param valueClass       the type of attribute values.
+     * @param minimumOccurs    the minimum number of occurrences of the attribute within its containing entity.
+     * @param maximumOccurs    the maximum number of occurrences of the attribute within its containing entity,
+     *                         or {@link Integer#MAX_VALUE} if there is no restriction.
+     * @param defaultValue     the default value for the attribute, or {@code null} if none.
+     * @param characterizedBy  other attribute types that describes this attribute type (can be {@code null} for none).
+     *                         For example if this new {@code DefaultAttributeType} describes a measurement,
+     *                         then {@code characterizedBy} could holds the measurement accuracy.
+     *                         See <cite>"Attribute characterization"</cite> in class Javadoc for more information.
      *
      * @see org.apache.sis.feature.builder.AttributeTypeBuilder
      */
@@ -208,9 +208,9 @@ public class DefaultAttributeType<V> ext
     /**
      * Invoked on deserialization for restoring the {@link #characteristics} field.
      *
-     * @param  in The input stream from which to deserialize an attribute type.
-     * @throws IOException If an I/O error occurred while reading or if the stream contains invalid data.
-     * @throws ClassNotFoundException If the class serialized on the stream is not on the classpath.
+     * @param  in  the input stream from which to deserialize an attribute type.
+     * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
+     * @throws ClassNotFoundException if the class serialized on the stream is not on the classpath.
      */
     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
@@ -227,7 +227,7 @@ public class DefaultAttributeType<V> ext
     /**
      * Returns the type of attribute values.
      *
-     * @return The type of attribute values.
+     * @return the type of attribute values.
      */
     @Override
     public final Class<V> getValueClass() {
@@ -253,7 +253,7 @@ public class DefaultAttributeType<V> ext
      * <p>To be valid, an {@code Attribute} instance of this {@code AttributeType} shall have at least
      * this minimum number of elements in its {@link AbstractAttribute#getValues() collection of values}.</p>
      *
-     * @return The minimum number of attribute values.
+     * @return the minimum number of attribute values.
      */
     @Override
     public final int getMinimumOccurs() {
@@ -268,7 +268,7 @@ public class DefaultAttributeType<V> ext
      * <p>To be valid, an {@code Attribute} instance of this {@code AttributeType} shall have no more than
      * this maximum number of elements in its {@link AbstractAttribute#getValues() collection of values}.</p>
      *
-     * @return The maximum number of attribute values, or {@link Integer#MAX_VALUE} if none.
+     * @return the maximum number of attribute values, or {@link Integer#MAX_VALUE} if none.
      */
     @Override
     public final int getMaximumOccurs() {
@@ -279,7 +279,7 @@ public class DefaultAttributeType<V> ext
      * Returns the default value for the attribute.
      * This value is used when an attribute is created and no value for it is specified.
      *
-     * @return The default value for the attribute, or {@code null} if none.
+     * @return the default value for the attribute, or {@code null} if none.
      */
     @Override
     public V getDefaultValue() {
@@ -301,7 +301,7 @@ public class DefaultAttributeType<V> ext
      * The {@linkplain Map#keySet() map keys} are the {@code String} representations
      * of characteristics {@linkplain #getName() name}, for more convenient lookups.
      *
-     * @return Other attribute types that describes this attribute type, or an empty map if none.
+     * @return other attribute types that describes this attribute type, or an empty map if none.
      *
      * @see AbstractAttribute#characteristics()
      */
@@ -313,7 +313,7 @@ public class DefaultAttributeType<V> ext
     /**
      * Creates a new attribute instance of this type initialized to the {@linkplain #getDefaultValue() default value}.
      *
-     * @return A new attribute instance.
+     * @return a new attribute instance.
      *
      * @see AbstractAttribute#create(AttributeType)
      */
@@ -356,11 +356,11 @@ public class DefaultAttributeType<V> ext
      * Returns a string representation of this attribute type.
      * The returned string is for debugging purpose and may change in any future SIS version.
      *
-     * @return A string representation of this attribute type for debugging purpose.
+     * @return a string representation of this attribute type for debugging purpose.
      */
     @Debug
     @Override
     public String toString() {
-        return toString("AttributeType", this, Classes.getShortName(valueClass)).toString();
+        return toString("AttributeType", getName(), Classes.getShortName(valueClass)).toString();
     }
 }

Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java?rev=1755610&r1=1755609&r2=1755610&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] Tue Aug  9 14:48:04 2016
@@ -16,7 +16,7 @@
  */
 package org.apache.sis.feature;
 
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.HashSet;
@@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
 import java.util.IdentityHashMap;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import org.opengis.util.NameFactory;
@@ -41,6 +42,7 @@ import org.apache.sis.internal.util.Unmo
 // Branch-dependent imports
 import java.util.Objects;
 import org.apache.sis.internal.jdk8.JDK8;
+import org.opengis.feature.IdentifiedType;
 import org.opengis.feature.PropertyType;
 import org.opengis.feature.AttributeType;
 import org.opengis.feature.Feature;
@@ -97,7 +99,7 @@ import org.opengis.feature.PropertyNotFo
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.6
+ * @version 0.8
  * @module
  *
  * @see DefaultAttributeType
@@ -166,6 +168,7 @@ public class DefaultFeatureType extends
     /**
      * Any feature operation, any feature attribute type and any feature association role
      * that carries characteristics of a feature type.
+     * This list does not include the properties inherited from the super-types.
      *
      * @see #getProperties(boolean)
      */
@@ -237,11 +240,11 @@ public class DefaultFeatureType extends
      *   </tr>
      * </table>
      *
-     * @param identification The name and other information to be given to this feature type.
-     * @param isAbstract     If {@code true}, the feature type acts as an abstract super-type.
-     * @param superTypes     The parents of this feature type, or {@code null} or empty if none.
-     * @param properties     Any feature operation, any feature attribute type and any feature
-     *                       association role that carries characteristics of a feature type.
+     * @param identification  the name and other information to be given to this feature type.
+     * @param isAbstract      if {@code true}, the feature type acts as an abstract super-type.
+     * @param superTypes      the parents of this feature type, or {@code null} or empty if none.
+     * @param properties      any feature operation, any feature attribute type and any feature
+     *                        association role that carries characteristics of a feature type.
      *
      * @see org.apache.sis.feature.builder.FeatureTypeBuilder
      */
@@ -263,13 +266,40 @@ public class DefaultFeatureType extends
                 }
             }
         }
-        switch (properties.length) {
+        /*
+         * We need to copy the properties in a temporary modifiable list in order to allow removal of elements
+         * in case of duplicated values. Opportunistically verify for null values. The same verification could
+         * be done in the scanPropertiesFrom(…) method, but doing it here produces a less confusing stacktrace.
+         */
+        final List<PropertyType> sourceProperties = new ArrayList<>(properties.length);
+        for (int i=0; i<properties.length; i++) {
+            final PropertyType property = properties[i];
+            ArgumentChecks.ensureNonNullElement("properties", i, property);
+            sourceProperties.add(property);
+        }
+        computeTransientFields(sourceProperties);
+        final int size = sourceProperties.size();
+        switch (size) {
             case 0:  this.properties = Collections.emptyList(); break;
-            case 1:  this.properties = Collections.singletonList(properties[0]); break;
-            default: this.properties = UnmodifiableArrayList.wrap(Arrays.copyOf(properties, properties.length, PropertyType[].class)); break;
+            case 1:  this.properties = Collections.singletonList(sourceProperties.get(0)); break;
+            default: this.properties = UnmodifiableArrayList.wrap(sourceProperties.toArray(new PropertyType[size])); break;
+        }
+        /*
+         * Before to resolve cyclic associations, verify that operations depend only on existing properties.
+         * Note: the 'allProperties' collection has been created by computeTransientFields(…) above.
+         */
+        for (final PropertyType property : allProperties) {
+            if (property instanceof AbstractOperation) {
+                for (final String dependency : ((AbstractOperation) property).getDependencies()) {
+                    if (!byName.containsKey(dependency)) {
+                        throw new IllegalArgumentException(Errors.format(Errors.Keys.DependencyNotFound_3,
+                                property.getName(), dependency, super.getName()));
+                    }
+                }
+            }
         }
-        computeTransientFields();
-        isResolved = resolve(this, null, isSimple);
+        // Do not invoke before DefaultFeatureType construction succeed.
+        isResolved = resolve(this, this.properties, null, isSimple);
     }
 
     /**
@@ -284,14 +314,19 @@ public class DefaultFeatureType extends
     /**
      * Invoked on deserialization for restoring the {@link #byName} and other transient fields.
      *
-     * @param  in The input stream from which to deserialize a feature type.
-     * @throws IOException If an I/O error occurred while reading or if the stream contains invalid data.
-     * @throws ClassNotFoundException If the class serialized on the stream is not on the classpath.
+     * @param  in  the input stream from which to deserialize a feature type.
+     * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
+     * @throws ClassNotFoundException if the class serialized on the stream is not on the classpath.
      */
     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
-        computeTransientFields();
-        isResolved = isSimple; // Conservative value. The 'resolve' method will compute a more accurate value if needed.
+        computeTransientFields(properties);
+        /*
+         * Set isResolved to a conservative value. The 'resolve' method will compute a more accurate value if needed,
+         * the first time that another DefaultFeatureType will have a dependency to this DefaultFeatureType through a
+         * DefaultAssociationRole.
+         */
+        isResolved = isSimple;
     }
 
     /**
@@ -299,15 +334,18 @@ public class DefaultFeatureType extends
      *
      * <p>As a side effect, this method checks for missing or duplicated names.</p>
      *
+     * @param  properties  same content as {@link #properties} (may be the reference to the same list), but
+     *         optionally in a temporarily modifiable list if we want to allow removal of duplicated values.
+     *         See {@link #scanPropertiesFrom(FeatureType, Collection)} javadoc for more explanation.
      * @throws IllegalArgumentException if two properties have the same name.
      */
-    private void computeTransientFields() {
+    private void computeTransientFields(final List<PropertyType> properties) {
         final int capacity = Containers.hashMapCapacity(properties.size());
         byName       = new LinkedHashMap<>(capacity);
         indices      = new LinkedHashMap<>(capacity);
         assignableTo = new HashSet<>(4);
         assignableTo.add(super.getName());
-        scanPropertiesFrom(this);
+        scanPropertiesFrom(this, properties);
         allProperties = UnmodifiableArrayList.wrap(byName.values().toArray(new PropertyType[byName.size()]));
         /*
          * Now check if the feature is simple/complex or dense/sparse. We perform this check after we finished
@@ -316,7 +354,7 @@ public class DefaultFeatureType extends
          */
         isSimple = true;
         int index = 0;
-        int mandatory = 0; // Count of mandatory properties.
+        int mandatory = 0;                                                  // Count of mandatory properties.
         for (final Map.Entry<String,PropertyType> entry : byName.entrySet()) {
             final int minimumOccurs, maximumOccurs;
             final PropertyType property = entry.getValue();
@@ -332,7 +370,7 @@ public class DefaultFeatureType extends
                 if (isParameterlessOperation(property)) {
                     indices.put(entry.getKey(), OPERATION_INDEX);
                 }
-                continue; // For feature operations, maximumOccurs is implicitly 0.
+                continue;                           // For feature operations, maximumOccurs is implicitly 0.
             }
             if (maximumOccurs != 0) {
                 isSimple &= (maximumOccurs == 1);
@@ -353,7 +391,7 @@ public class DefaultFeatureType extends
         for (final PropertyType property : allProperties) {
             final GenericName name = property.getName();
             final LocalName tip = name.tip();
-            if (tip != name) {  // Slight optimization for a common case.
+            if (tip != name) {                                          // Slight optimization for a common case.
                 final String key = tip.toString();
                 if (key != null && !key.isEmpty() && !key.equals(name.toString())) {
                     aliases.put(key, aliases.containsKey(key) ? null : property);
@@ -401,23 +439,38 @@ public class DefaultFeatureType extends
      * <p>{@code this} shall be the instance in process of being created, not any other instance
      * (i.e. recursive method invocations are performed on the same {@code this} instance).</p>
      *
-     * @param  source The feature from which to get properties.
+     * <p>This method requires that the caller gives {@code source.getProperties(false)} himself for two reasons:</p>
+     * <ul>
+     *   <li>Avoid a call to the user-overrideable {@link #getProperties(boolean)} method
+     *       while this {@code DefaultFeatureType} instance is still under constructor.</li>
+     *   <li>Allow the {@link #DefaultFeatureType(Map, boolean, FeatureType[], PropertyType[])} constructor
+     *       to pass a temporary modifiable list that allow element removal.</li>
+     * </ul>
+     *
+     * @param  source            the feature from which to get properties.
+     * @param  sourceProperties  {@code source.getProperties(false)} (see above method javadoc).
      * @throws IllegalArgumentException if two properties have the same name.
      */
-    private void scanPropertiesFrom(final FeatureType source) {
+    private void scanPropertiesFrom(final FeatureType source, final Collection<? extends PropertyType> sourceProperties) {
         for (final FeatureType parent : source.getSuperTypes()) {
             if (assignableTo.add(parent.getName())) {
-                scanPropertiesFrom(parent);
+                scanPropertiesFrom(parent, parent.getProperties(false));
             }
         }
         int index = -1;
-        for (final PropertyType property : source.getProperties(false)) {
-            ArgumentChecks.ensureNonNullElement("properties", ++index, property);
-            final String name = toString(property.getName(), source, "properties", index);
+        final Iterator<? extends PropertyType> it = sourceProperties.iterator();
+        while (it.hasNext()) {
+            final PropertyType property = it.next();
+            final String name = toString(property.getName(), source, "properties", ++index);
             final PropertyType previous = byName.put(name, property);
             if (previous != null) {
-                if (!isAssignableIgnoreName(previous, property)) {
-                    final GenericName owner = ownerOf(this, previous);
+                if (previous.equals(property)) {
+                    byName.put(name, previous);         // Keep the instance declared in super-type.
+                    if (source == this) {
+                        it.remove();                    // Remove duplicated values in instance under construction.
+                    }
+                } else if (!isAssignableIgnoreName(previous, property)) {
+                    final GenericName owner = ownerOf(this, sourceProperties, previous);
                     throw new IllegalArgumentException(Errors.format(Errors.Keys.PropertyAlreadyExists_2,
                             (owner != null) ? owner : "?", name));
                 }
@@ -430,12 +483,14 @@ public class DefaultFeatureType extends
      * This method is for information purpose when producing an error message - its implementation does
      * not need to be efficient.
      */
-    private static GenericName ownerOf(final FeatureType type, final PropertyType property) {
-        if (type.getProperties(false).contains(property)) {
+    private static GenericName ownerOf(final FeatureType type, final Collection<? extends PropertyType> properties,
+            final PropertyType toSearch)
+    {
+        if (properties.contains(toSearch)) {
             return type.getName();
         }
         for (final FeatureType superType : type.getSuperTypes()) {
-            final GenericName owner = ownerOf(superType, property);
+            final GenericName owner = ownerOf(superType, superType.getProperties(false), toSearch);
             if (owner != null) {
                 return owner;
             }
@@ -454,8 +509,8 @@ public class DefaultFeatureType extends
      * <p>{@code this} shall be the instance in process of being created, not other instance
      * (i.e. recursive method invocations are performed on the same {@code this} instance).</p>
      *
-     * @param  feature  The feature type for which to resolve the properties.
-     * @param  previous Previous results, for avoiding never ending loop.
+     * @param  feature   the feature type for which to resolve the properties.
+     * @param  previous  previous results, for avoiding never ending loop.
      * @return {@code true} if all names have been resolved.
      */
     private boolean resolve(final FeatureType feature, final Map<FeatureType,Boolean> previous) {
@@ -467,27 +522,33 @@ public class DefaultFeatureType extends
          */
         if (feature instanceof DefaultFeatureType) {
             final DefaultFeatureType dt = (DefaultFeatureType) feature;
-            return dt.isResolved = resolve(feature, previous, dt.isResolved);
+            return dt.isResolved = resolve(feature, dt.properties, previous, dt.isResolved);
         } else {
-            return resolve(feature, previous, feature.isSimple());
+            return resolve(feature, feature.getProperties(false), previous, feature.isSimple());
         }
     }
 
     /**
      * Implementation of {@link #resolve(FeatureType, Map)}, also to be invoked from the constructor.
      *
-     * @param  feature  The feature type for which to resolve the properties.
-     * @param  previous Previous results, for avoiding never ending loop. Initially {@code null}.
-     * @param  resolved {@code true} if we already know that all names are resolved.
+     * <p>{@code this} shall be the instance in process of being created, not other instance
+     * (i.e. recursive method invocations are performed on the same {@code this} instance).</p>
+     *
+     * @param  feature     the feature type for which to resolve the properties.
+     * @param  toUpdate    {@code feature.getProperties(false)}, which may contain the associations to update.
+     * @param  previous    previous results, for avoiding never ending loop. Initially {@code null}.
+     * @param  resolved    {@code true} if we already know that all names are resolved.
      * @return {@code true} if all names have been resolved.
      */
-    private boolean resolve(final FeatureType feature, Map<FeatureType,Boolean> previous, boolean resolved) {
+    private boolean resolve(final FeatureType feature, final Collection<? extends PropertyType> toUpdate,
+            Map<FeatureType,Boolean> previous, boolean resolved)
+    {
         if (!resolved) {
             resolved = true;
             for (final FeatureType type : feature.getSuperTypes()) {
                 resolved &= resolve(type, previous);
             }
-            for (final PropertyType property : feature.getProperties(false)) {
+            for (final PropertyType property : toUpdate) {
                 if (property instanceof FeatureAssociationRole) {
                     if (property instanceof DefaultAssociationRole) {
                         if (!((DefaultAssociationRole) property).resolve(this)) {
@@ -600,13 +661,13 @@ public class DefaultFeatureType extends
      * if we compare {@code FeatureType} to {@link Class} in the Java language, then this method is equivalent
      * to {@link Class#isAssignableFrom(Class)}.</div>
      *
-     * @param  type The type to be checked.
+     * @param  type  the type to be checked.
      * @return {@code true} if instances of the given type can be assigned to association of this type.
      */
     @Override
     public boolean isAssignableFrom(final FeatureType type) {
         if (type == this) {
-            return true; // Optimization for a common case.
+            return true;                            // Optimization for a common case.
         }
         ArgumentChecks.ensureNonNull("type", type);
         if (!maybeAssignableFrom(this, type)) {
@@ -669,9 +730,31 @@ public class DefaultFeatureType extends
                 }
                 final FeatureType f0 = p0.getValueType();
                 final FeatureType f1 = p1.getValueType();
-                if (f0 != f1) {
-                    if (!f0.isAssignableFrom(f1)) {
-                        return false;
+                if (f0 != f1 && !f0.isAssignableFrom(f1)) {
+                    return false;
+                }
+            }
+            if (base instanceof Operation) {
+                if (!(other instanceof Operation)) {
+                    return false;
+                }
+                final Operation p0 = (Operation) base;
+                final Operation p1 = (Operation) other;
+                if (!Objects.equals(p0.getParameters(), p1.getParameters())) {
+                    return false;
+                }
+                final IdentifiedType r0 = p0.getResult();
+                final IdentifiedType r1 = p1.getResult();
+                if (r0 != r1) {
+                    if (r0 instanceof FeatureType) {
+                        if (!(r1 instanceof FeatureType) || !((FeatureType) r0).isAssignableFrom((FeatureType) r1)) {
+                            return false;
+                        }
+                    }
+                    if (r0 instanceof PropertyType) {
+                        if (!(r1 instanceof PropertyType) || !isAssignableIgnoreName((PropertyType) r0, (PropertyType) r1)) {
+                            return false;
+                        }
                     }
                 }
             }
@@ -692,7 +775,7 @@ public class DefaultFeatureType extends
      * the stability of this collection.
      * </div>
      *
-     * @return The parents of this feature type, or an empty set if none.
+     * @return  the parents of this feature type, or an empty set if none.
      */
     @Override
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
@@ -706,28 +789,22 @@ public class DefaultFeatureType extends
      * inherited from the {@linkplain #getSuperTypes() super-types} only if {@code includeSuperTypes}
      * is {@code true}.
      *
-     * <div class="note"><b>Note for subclasses:</b>
-     * this method is final because it is invoked (indirectly) by constructors, and invoking a user-overrideable
-     * method at construction time is not recommended. Furthermore, many Apache SIS methods need guarantees about
-     * the stability of this collection.
-     * </div>
-     *
      * @param  includeSuperTypes {@code true} for including the properties inherited from the super-types,
      *         or {@code false} for returning only the properties defined explicitely in this type.
-     * @return Feature operation, attribute type and association role that carries characteristics of this
+     * @return feature operation, attribute type and association role that carries characteristics of this
      *         feature type (not including parent types).
      */
     @Override
-    public final Collection<PropertyType> getProperties(final boolean includeSuperTypes) {
+    public Collection<PropertyType> getProperties(final boolean includeSuperTypes) {
         return includeSuperTypes ? allProperties : properties;
     }
 
     /**
      * Returns the attribute, operation or association role for the given name.
      *
-     * @param  name The name of the property to search.
-     * @return The property for the given name, or {@code null} if none.
-     * @throws PropertyNotFoundException If the given argument is not a property name of this feature.
+     * @param  name  the name of the property to search.
+     * @return the property for the given name, or {@code null} if none.
+     * @throws PropertyNotFoundException if the given argument is not a property name of this feature.
      *
      * @see AbstractFeature#getProperty(String)
      */
@@ -756,7 +833,7 @@ public class DefaultFeatureType extends
      * if we compare {@code FeatureType} to {@link Class} and {@code Feature} to {@link Object} in the Java language,
      * then this method is equivalent to {@link Class#newInstance()}.</div>
      *
-     * @return A new feature instance.
+     * @return a new feature instance.
      * @throws FeatureInstantiationException if this feature type {@linkplain #isAbstract() is abstract}.
      */
     @Override
@@ -799,7 +876,7 @@ public class DefaultFeatureType extends
     /**
      * Formats this feature in a tabular format.
      *
-     * @return A string representation of this feature in a tabular format.
+     * @return a string representation of this feature in a tabular format.
      *
      * @see FeatureFormat
      */



Mime
View raw message