sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1640308 [1/2] - in /sis/branches/JDK6: ./ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/test/java/org/apache/sis/feature/ core/sis-feature/src/test/java/org/apache/sis/test/suite/ core/sis-metadata/src/main/ja...
Date Tue, 18 Nov 2014 10:58:49 GMT
Author: desruisseaux
Date: Tue Nov 18 10:58:48 2014
New Revision: 1640308

URL: http://svn.apache.org/r1640308
Log:
Merge from the JDK7 branch.
The main work is "attribute on attributes" of features derived from ISO 19109 UML schema.

Added:
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicMap.java
      - copied unchanged from r1640304, sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicMap.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java
      - copied, changed from r1640304, sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java
    sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java
      - copied, changed from r1640304, sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java
    sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java
      - copied, changed from r1640304, sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
      - copied, changed from r1640304, sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java
      - copied, changed from r1640304, sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/internal/util/AbstractMapTest.java
      - copied, changed from r1640304, sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/AbstractMapTest.java
Modified:
    sis/branches/JDK6/   (props changed)
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java   (contents, props changed)
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/PropertySingleton.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAssociation.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAttribute.java
    sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java   (contents, props changed)
    sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java
    sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/MultiValuedAttributeTest.java
    sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java
    sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
    sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakEntry.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java

Propchange: sis/branches/JDK6/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK8:r1637099-1640283
  Merged /sis/branches/JDK7:r1637101-1640304

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -34,6 +34,7 @@ import org.opengis.feature.FeatureAssoci
 
 /**
  * An instance of an {@linkplain DefaultAssociationRole feature association role} containing the associated feature.
+ * {@code AbstractAssociation} can be instantiated by calls to {@link DefaultAssociationRole#newInstance()}.
  *
  * {@section Limitations}
  * <ul>
@@ -49,9 +50,9 @@ import org.opengis.feature.FeatureAssoci
  * @version 0.5
  * @module
  *
- * @see DefaultAssociationRole
+ * @see DefaultAssociationRole#newInstance()
  */
-public abstract class AbstractAssociation extends Field<Feature> implements FeatureAssociation, Serializable {
+public abstract class AbstractAssociation extends Field<Feature> implements FeatureAssociation, Cloneable, Serializable {
     /**
      * For cross-version compatibility.
      */
@@ -78,6 +79,8 @@ public abstract class AbstractAssociatio
      *
      * @param  role Information about the association.
      * @return The new association.
+     *
+     * @see DefaultAssociationRole#newInstance()
      */
     public static AbstractAssociation create(final FeatureAssociationRole role) {
         ArgumentChecks.ensureNonNull("role", role);
@@ -236,6 +239,21 @@ public abstract class AbstractAssociatio
             public void remove() {
                 throw new UnsupportedOperationException();
             }
-        });
+        }).toString();
+    }
+
+    /**
+     * Returns a copy of this association.
+     * The default implementation returns a <em>shallow</em> copy:
+     * the association {@linkplain #getValue() value} is <strong>not</strong> cloned.
+     * However subclasses may choose to do otherwise.
+     *
+     * @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.
+     */
+    @Override
+    public AbstractAssociation clone() throws CloneNotSupportedException {
+        return (AbstractAssociation) super.clone();
     }
 }

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -16,8 +16,15 @@
  */
 package org.apache.sis.feature;
 
+import java.util.Map;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.InvalidObjectException;
+import java.io.IOException;
 import org.opengis.util.GenericName;
 import org.opengis.metadata.quality.DataQuality;
 import org.opengis.metadata.maintenance.ScopeCode;
@@ -28,18 +35,25 @@ import org.apache.sis.util.ArgumentCheck
 // Branch-dependent imports
 import org.opengis.feature.Attribute;
 import org.opengis.feature.AttributeType;
+import org.apache.sis.internal.jdk7.JDK7;
 
 
 /**
  * An instance of an {@linkplain DefaultAttributeType attribute type} containing the value of an attribute in a feature.
- * {@code Attribute} holds two main information:
+ * {@code Attribute} holds three main information:
  *
  * <ul>
- *   <li>A reference to an {@linkplain DefaultAttributeType attribute type}
+ *   <li>A {@linkplain #getType() reference to an attribute type}
  *       which define the base Java type and domain of valid values.</li>
- *   <li>A value, which may be a singleton ([0 … 1] cardinality) or multi-valued ([0 … ∞] cardinality).</li>
+ *   <li>One or more {@linkplain #getValues() values}, which may be a singleton ([0 … 1] cardinality)
+ *       or multi-valued ([0 … ∞] cardinality).</li>
+ *   <li>Optional {@linkplain #characteristics() characteristics} about the attribute
+ *       (e.g. a <var>temperature</var> attribute may have a characteristic holding the measurement <var>accuracy</var>).
+ *       Characteristics are often, but not necessarily, constant for all attributes of the same type in a dataset.</li>
  * </ul>
  *
+ * {@code AbstractAttribute} can be instantiated by calls to {@link DefaultAttributeType#newInstance()}.
+ *
  * {@section Limitations}
  * <ul>
  *   <li><b>Multi-threading:</b> {@code AbstractAttribute} instances are <strong>not</strong> thread-safe.
@@ -57,9 +71,9 @@ import org.opengis.feature.AttributeType
  * @version 0.5
  * @module
  *
- * @see DefaultAttributeType
+ * @see DefaultAttributeType#newInstance()
  */
-public abstract class AbstractAttribute<V> extends Field<V> implements Attribute<V>, Serializable {
+public abstract class AbstractAttribute<V> extends Field<V> implements Attribute<V>, Cloneable, Serializable {
     /**
      * For cross-version compatibility.
      */
@@ -71,6 +85,21 @@ public abstract class AbstractAttribute<
     final AttributeType<V> type;
 
     /**
+     * Other attributes that describes this attribute, or {@code null} if not yet created.
+     *
+     * <div class="note"><b>Design note:</b>
+     * We could question if it is a good idea to put this field here, given that this field add a slight cost
+     * to all attribute implementations while only a small fraction of them will want attribute characteristics.
+     * Since attributes may exist in a very large amount, that question may be significant.
+     * However {@link AbstractFeature} tries hard to not create {@code Attribute} instances at all (it tries to
+     * store only their value instead), so we presume that peoples who ask for {@code Attribute} instances are
+     * willing to accept their cost.</div>
+     *
+     * @see #characteristics()
+     */
+    private transient Map<String,Attribute<?>> characteristics;
+
+    /**
      * Creates a new attribute of the given type.
      *
      * @param type Information about the attribute (base Java class, domain of values, <i>etc.</i>).
@@ -88,6 +117,8 @@ public abstract class AbstractAttribute<
      * @param  <V>  The type of attribute values.
      * @param  type Information about the attribute (base Java class, domain of values, <i>etc.</i>).
      * @return The new attribute.
+     *
+     * @see DefaultAttributeType#newInstance()
      */
     public static <V> AbstractAttribute<V> create(final AttributeType<V> type) {
         ArgumentChecks.ensureNonNull("type", type);
@@ -113,6 +144,43 @@ public abstract class AbstractAttribute<
     }
 
     /**
+     * Invoked on serialization for saving the {@link #characteristics} field.
+     *
+     * @param  out The output stream where to serialize this attribute.
+     * @throws IOException If an I/O error occurred while writing.
+     */
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        final Attribute<?>[] characterizedBy;
+        if (characteristics instanceof CharacteristicMap) {
+            characterizedBy = characteristics.values().toArray(new Attribute<?>[characteristics.size()]);
+        } else {
+            characterizedBy = null;
+        }
+        out.writeObject(characterizedBy);
+    }
+
+    /**
+     * Invoked on deserialization for restoring the {@link #characteristics} field.
+     *
+     * @param  in The input stream from which to deserialize an attribute.
+     * @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();
+        try {
+            final Attribute<?>[] characterizedBy = (Attribute<?>[]) in.readObject();
+            if (characterizedBy != null) {
+                characteristics = newCharacteristicsMap();
+                characteristics.values().addAll(Arrays.asList(characterizedBy));
+            }
+        } catch (RuntimeException e) { // At least ClassCastException, NullPointerException, IllegalArgumentException and IllegalStateException.
+            throw (IOException) new InvalidObjectException(e.getMessage()).initCause(e);
+        }
+    }
+
+    /**
      * Returns the name of this attribute as defined by its {@linkplain #getType() type}.
      * This convenience method delegates to {@link AttributeType#getName()}.
      *
@@ -192,6 +260,112 @@ public abstract class AbstractAttribute<
     }
 
     /**
+     * Other attributes that describes this attribute. For example if this attribute carries a measurement,
+     * then a characteristic of this attribute could be the measurement accuracy.
+     * See "<cite>Attribute characterization</cite>" in {@link DefaultAttributeType} Javadoc for more information.
+     *
+     * <p>The map returned by this method contains only the characteristics explicitely defined for this attribute.
+     * If the map contains no characteristic for a given name, a {@linkplain DefaultAttributeType#getDefaultValue()
+     * default value} may still exist.
+     * In such cases, callers may also need to inspect the {@link DefaultAttributeType#characteristics()}
+     * as shown in the <cite>Reading a characteristic</cite> section below.</p>
+     *
+     * <div class="note"><b>Rational:</b>
+     * Very often, all attributes of a given type in the same dataset have the same characteristics.
+     * For example it is very common that all temperature measurements in a dataset have the same accuracy,
+     * and setting a different accuracy for a single measurement is relatively rare.
+     * Consequently, {@code characteristics.isEmpty()} is a convenient way to check that an attribute have
+     * all the "standard" characteristics and need no special processing.</div>
+     *
+     * {@section Reading a characteristic}
+     * If an attribute is known to be a measurement with a characteristic named "accuracy" of type {@link Float},
+     * then the accuracy value could be read as below:
+     *
+     * {@preformat java
+     *     Float getAccuracy(Attribute<?> measurement) {
+     *         Attribute<?> accuracy = measurement.characteristics().get("accuracy");
+     *         if (accuracy != null) {
+     *             return (Float) accuracy.getValue(); // Value may be null.
+     *         } else {
+     *             return (Float) measurement.getType().characteristics().get("accuracy").getDefaultValue();
+     *             // A more sophisticated implementation would probably cache the default value somewhere.
+     *         }
+     *     }
+     * }
+     *
+     * {@section Adding a characteristic}
+     * A new characteristic can be added in the map in three different ways:
+     * <ol>
+     *   <li>Putting the (<var>name</var>, <var>characteristic</var>) pair explicitely.
+     *     If an older characteristic existed for that name, it will be replaced.
+     *     Example:
+     *
+     *     {@preformat java
+     *       Attribute<?> accuracy = ...; // To be created by the caller.
+     *       characteristics.put("accuracy", accuracy);
+     *     }</li>
+     *
+     *   <li>Adding the new characteristic to the {@linkplain Map#values() values} collection.
+     *     The name is inferred automatically from the characteristic type.
+     *     If an older characteristic existed for the same name, an {@link IllegalStateException} will be thrown.
+     *     Example:
+     *
+     *     {@preformat java
+     *       Attribute<?> accuracy = ...; // To be created by the caller.
+     *       characteristics.values().add(accuracy);
+     *     }</li>
+     *
+     *   <li>Adding the characteristic name to the {@linkplain Map#keySet() key set}.
+     *     If no characteristic existed for that name, a default one will be created.
+     *     Example:
+     *
+     *     {@preformat java
+     *       characteristics.keySet().add("accuracy"); // Ensure that an entry will exist for that name.
+     *       Attribute<?> accuracy = characteristics.get("accuracy");
+     *       Features.cast(accuracy, Float.class).setValue(...); // Set new accuracy value here as a float.
+     *     }</li>
+     * </ol>
+     *
+     * @return Other attribute types that describes this attribute type, or an empty set if none.
+     *
+     * @see DefaultAttributeType#characteristics()
+     */
+    public Map<String,Attribute<?>> characteristics() {
+        if (characteristics == null) {
+            characteristics = newCharacteristicsMap();
+        }
+        return characteristics;
+    }
+
+    /**
+     * Creates an initially empty map of characteristics for this attribute.
+     * This method does not store the new map in the {@link #characteristics} field;
+     * it is caller responsibility to do so if desired.
+     */
+    private Map<String,Attribute<?>> newCharacteristicsMap() {
+        if (type instanceof DefaultAttributeType<?>) {
+            Map<String, AttributeType<?>> map = ((DefaultAttributeType<?>) type).characteristics();
+            if (!map.isEmpty()) {
+                if (!(map instanceof CharacteristicTypeMap)) {
+                    final Collection<AttributeType<?>> types = map.values();
+                    map = CharacteristicTypeMap.create(type, types.toArray(new AttributeType<?>[types.size()]));
+                }
+                return new CharacteristicMap(this, (CharacteristicTypeMap) map);
+            }
+        }
+        return Collections.emptyMap();
+    }
+
+    /**
+     * Returns the characteristics, or an empty map if the characteristics have not yet been built.
+     * Contrarily to {@link #characteristics()}, this method does not create the map. This method
+     * is suitable when then caller only wants to read the map and does not plan to write anything.
+     */
+    final Map<String,Attribute<?>> characteristicsReadOnly() {
+        return (characteristics != null) ? characteristics : Collections.<String,Attribute<?>>emptyMap();
+    }
+
+    /**
      * Evaluates the quality of this attribute at this method invocation time. The data quality reports
      * may include information about whether the attribute value mets the constraints defined by the
      * {@linkplain DefaultAttributeType attribute type}, or any other criterion at implementation choice.
@@ -268,12 +442,50 @@ public abstract class AbstractAttribute<
     /**
      * Returns a string representation of this attribute.
      * The returned string is for debugging purpose and may change in any future SIS version.
+     * The current implementation is like below:
+     *
+     * {@preformat text
+     *     Attribute[“temperature” : Float] = {20.3, 17.8, 21.1}
+     *     └─ characteristics: units=°C, accuracy=0.1
+     * }
      *
      * @return A string representation of this attribute for debugging purpose.
      */
     @Debug
     @Override
     public String toString() {
-        return FieldType.toString("Attribute", type, Classes.getShortName(type.getValueClass()), getValues().iterator());
+        final StringBuilder buffer = FieldType.toString("Attribute", type,
+                Classes.getShortName(type.getValueClass()), getValues().iterator());
+        if (characteristics != null && !characteristics.isEmpty()) {
+            buffer.append(JDK7.lineSeparator());
+            String separator = "└─ characteristics: ";
+            for (final Map.Entry<String,Attribute<?>> entry : characteristics.entrySet()) {
+                buffer.append(separator).append(entry.getKey()).append('=').append(entry.getValue().getValue());
+                separator = ", ";
+            }
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Returns a copy of this attribute.
+     * The default implementation returns a <em>shallow</em> copy:
+     * the attribute {@linkplain #getValue() value} and {@linkplain #characteristics() characteristics}
+     * are <strong>not</strong> cloned.
+     * However subclasses may choose to do otherwise.
+     *
+     * @return A clone of this attribute.
+     * @throws CloneNotSupportedException if this attribute, the {@linkplain #getValue() value}
+     *         or one of its {@linkplain #characteristics() characteristics} can not be cloned.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public AbstractAttribute<V> clone() throws CloneNotSupportedException {
+        final AbstractAttribute<V> clone = (AbstractAttribute<V>) super.clone();
+        final Map<String,Attribute<?>> c = clone.characteristics;
+        if (c instanceof CharacteristicMap) {
+            clone.characteristics = ((CharacteristicMap) c).clone();
+        }
+        return clone;
     }
 }

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -387,7 +387,7 @@ public abstract class AbstractFeature im
     }
 
     /**
-     * Verifies if the given properties can be assigned to this feature.
+     * 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.
@@ -402,7 +402,9 @@ public abstract class AbstractFeature im
             throw illegalPropertyType(base.getName(), property.getClass());
         }
         if (pt != base) {
-            throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedPropertyType_1, name));
+            throw new IllegalArgumentException(base == null
+                    ? Errors.format(Errors.Keys.PropertyNotFound_2, getName(), name)
+                    : Errors.format(Errors.Keys.MismatchedPropertyType_1, name));
         }
     }
 

Propchange: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
------------------------------------------------------------------------------
  Merged /sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java:r1600998-1640283
  Merged /sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java:r1601000-1640304

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -288,4 +288,28 @@ public class AbstractIdentifiedType impl
         }
         return false;
     }
+
+    /**
+     * 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.
+     * @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) {
+        short key = Errors.Keys.MissingValueForProperty_1;
+        if (name != null) {
+            final String s = name.toString();
+            if (!s.isEmpty()) {
+                return s;
+            }
+            key = Errors.Keys.EmptyProperty_1;
+        }
+        final StringBuilder b = new StringBuilder(40).append("Type[“").append(container.getName()).append("”].")
+                .append(argument).append('[').append(index).append("].name");
+        throw new IllegalArgumentException(Errors.format(key, b.toString()));
+    }
 }

Copied: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java (from r1640304, sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java?p2=sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java&p1=sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java&r1=1640304&r2=1640308&rev=1640308&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/CharacteristicTypeMap.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -55,7 +55,7 @@ final class CharacteristicTypeMap extend
      */
     @SuppressWarnings("unchecked")
     private static final WeakValueHashMap<AttributeType<?>[],CharacteristicTypeMap> SHARED =
-            new WeakValueHashMap<>((Class) AttributeType[].class);
+            new WeakValueHashMap<AttributeType<?>[],CharacteristicTypeMap>((Class) AttributeType[].class);
 
     /*
      * This class has intentionally no reference to the AttributeType for which we are providing characteristics.
@@ -111,7 +111,7 @@ final class CharacteristicTypeMap extend
     private CharacteristicTypeMap(final AttributeType<?> source, final AttributeType<?>[] characterizedBy) {
         this.characterizedBy = characterizedBy;
         int index = 0;
-        final Map<String,Integer> indices = new HashMap<>(Containers.hashMapCapacity(characterizedBy.length));
+        final Map<String,Integer> indices = new HashMap<String,Integer>(Containers.hashMapCapacity(characterizedBy.length));
         for (int i=0; i<characterizedBy.length; i++) {
             final AttributeType<?> attribute = characterizedBy[i];
             ensureNonNullElement("characterizedBy", i, attribute);

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -31,6 +31,7 @@ import static org.apache.sis.util.Argume
 import org.opengis.feature.PropertyType;
 import org.opengis.feature.AttributeType;
 import org.opengis.feature.FeatureType;
+import org.opengis.feature.FeatureAssociation;
 import org.opengis.feature.FeatureAssociationRole;
 
 
@@ -386,6 +387,17 @@ public class DefaultAssociationRole exte
     }
 
     /**
+     * Creates a new association instance of this role.
+     *
+     * @return A new association instance.
+     *
+     * @see AbstractAssociation#create(FeatureAssociationRole)
+     */
+    public FeatureAssociation newInstance() {
+        return AbstractAssociation.create(this);
+    }
+
+    /**
      * Returns a hash code value for this association role.
      *
      * @return {@inheritDoc}

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -17,6 +17,11 @@
 package org.apache.sis.feature;
 
 import java.util.Map;
+import java.util.Collections;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+import java.io.InvalidObjectException;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.apache.sis.util.Debug;
@@ -27,6 +32,7 @@ import static org.apache.sis.util.Argume
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.Objects;
+import org.opengis.feature.Attribute;
 import org.opengis.feature.AttributeType;
 
 
@@ -38,7 +44,9 @@ import org.opengis.feature.AttributeType
  *
  * <div class="note"><b>Note:</b>
  * Compared to the Java language, {@code AttributeType} is equivalent to {@link java.lang.reflect.Field}
- * while {@code FeatureType} is equivalent to {@link Class}.</div>
+ * while {@code FeatureType} is equivalent to {@link Class}.
+ * Attribute characterization (discussed below) is similar to {@link java.lang.annotation.Annotation}.
+ * </div>
  *
  * {@section Value type}
  * Attributes can be used for both spatial and non-spatial properties.
@@ -52,6 +60,28 @@ import org.opengis.feature.AttributeType
  *   <tr><td>Horizontal accuracy</td> <td>{@link org.opengis.metadata.quality.PositionalAccuracy}</td></tr>
  * </table>
  *
+ * {@section Attribute characterization}
+ * An {@code Attribute} can be characterized by other attributes. For example an attribute that carries a measurement
+ * (e.g. air temperature) may have another attribute that holds the measurement accuracy (e.g. ±0.1°C).
+ * The accuracy value is often constant for all instances of that attribute
+ * (e.g. for all temperature measurements in the same dataset), but this is not mandatory.
+ * Such accuracy could be stored as an ordinary, independent, attribute (like an other column in a table),
+ * but storing accuracy as a {@linkplain #characteristics() characteristic} of the measurement attribute instead
+ * provides the following advantages:
+ *
+ * <ul>
+ *   <li>The same characteristic name (e.g. “accuracy”) can be used for different attributes
+ *       (e.g. “temperature”, “humidity”, <i>etc.</i>) since all characteristics are local to their attribute.</li>
+ *   <li>A reference to an attribute gives also access to its characteristics. For example any method expecting
+ *       an {@code Attribute} argument, when given a measurement, can also get its accuracy in same time.</li>
+ *   <li>In the common case of a {@linkplain DefaultFeatureType#isSimple() simple feature} with characteristics
+ *       that are constants, declaring them as attribute characteristics allows to specify the constants only once.</li>
+ * </ul>
+ *
+ * Constant values of characteristics are given by their {@linkplain #getDefaultValue() default value}.
+ * It is still possible for any specific {@code Attribute} instance to specify their own value,
+ * but {@linkplain DefaultFeatureType#isSimple() simple feature} usually don't do that.
+ *
  * {@section Immutability and thread safety}
  * Instances of this class are immutable if all properties ({@link GenericName} and {@link InternationalString}
  * instances) and all arguments (e.g. {@code defaultValue}) given to the constructor are also immutable.
@@ -75,7 +105,7 @@ public class DefaultAttributeType<V> ext
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 8215784957556648553L;
+    private static final long serialVersionUID = -817024213677735239L;
 
     /**
      * The class that describe the type of attribute values.
@@ -92,6 +122,14 @@ public class DefaultAttributeType<V> ext
     private final V defaultValue;
 
     /**
+     * Other attribute types that describes this attribute type, or {@code null} if none.
+     * This is used for attributes of attribute (e.g. accuracy of a position).
+     *
+     * @see #characteristics()
+     */
+    private transient CharacteristicTypeMap characteristics;
+
+    /**
      * Constructs an attribute type from the given properties. The identification map is given unchanged to
      * the {@linkplain AbstractIdentifiedType#AbstractIdentifiedType(Map) super-class constructor}.
      * The following table is a reminder of main (not all) recognized map entries:
@@ -125,21 +163,59 @@ 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 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.
      */
     public DefaultAttributeType(final Map<String,?> identification, final Class<V> valueClass,
-            final int minimumOccurs, final int maximumOccurs, final V defaultValue)
+            final int minimumOccurs, final int maximumOccurs, final V defaultValue,
+            final AttributeType<?>... characterizedBy)
     {
         super(identification, minimumOccurs, maximumOccurs);
         ensureNonNull("valueClass",   valueClass);
         ensureCanCast("defaultValue", valueClass, defaultValue);
-        this.valueClass   = valueClass;
-        this.defaultValue = Numerics.cached(defaultValue);
+        this.valueClass      = valueClass;
+        this.defaultValue    = Numerics.cached(defaultValue);
+        if (characterizedBy != null && characterizedBy.length != 0) {
+            characteristics = CharacteristicTypeMap.create(this, characterizedBy.clone());
+        }
+    }
+
+    /**
+     * Invoked on serialization for saving the {@link #characteristics} field.
+     *
+     * @param  out The output stream where to serialize this attribute type.
+     * @throws IOException If an I/O error occurred while writing.
+     */
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        out.writeObject(characteristics != null ? characteristics.characterizedBy : null);
+    }
+
+    /**
+     * 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.
+     */
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        try {
+            final AttributeType<?>[] characterizedBy = (AttributeType<?>[]) in.readObject();
+            if (characterizedBy != null) {
+                characteristics = CharacteristicTypeMap.create(this, characterizedBy);
+            }
+        } catch (RuntimeException e) { // At least ClassCastException, NullPointerException and IllegalArgumentException.
+            throw (IOException) new InvalidObjectException(e.getMessage()).initCause(e);
+        }
     }
 
     /**
@@ -205,13 +281,44 @@ public class DefaultAttributeType<V> ext
     }
 
     /**
+     * Other attribute types that describes this attribute type.
+     * See "<cite>Attribute characterization</cite>" in class Javadoc for more information.
+     *
+     * <div class="note"><b>Example:</b>
+     * An attribute that carries a measurement (e.g. air temperature) may have another attribute that holds the
+     * measurement accuracy. The accuracy is often constant for all measurements in a dataset, but not necessarily.
+     * If the accuracy is a constant, then the characteristics {@linkplain #getDefaultValue() default value}
+     * shall hold that constant.
+     * </div>
+     *
+     * @return Other attribute types that describes this attribute type, or an empty set if none.
+     *
+     * @see AbstractAttribute#characteristics()
+     */
+    public Map<String,AttributeType<?>> characteristics() {
+        return (characteristics != null) ? characteristics : Collections.<String,AttributeType<?>>emptyMap();
+    }
+
+    /**
+     * Creates a new attribute instance of this type initialized to the {@linkplain #getDefaultValue() default value}.
+     *
+     * @return A new attribute instance.
+     *
+     * @see AbstractAttribute#create(AttributeType)
+     */
+    public Attribute<V> newInstance() {
+        return AbstractAttribute.create(this);
+    }
+
+    /**
      * Returns a hash code value for this attribute type.
      *
      * @return {@inheritDoc}
      */
     @Override
     public int hashCode() {
-        return super.hashCode() + valueClass.hashCode() + Objects.hashCode(defaultValue);
+        return super.hashCode() + valueClass.hashCode() + Objects.hashCode(defaultValue)
+               + Objects.hashCode(characteristics);
     }
 
     /**
@@ -227,7 +334,8 @@ public class DefaultAttributeType<V> ext
         if (super.equals(obj)) {
             final DefaultAttributeType<?> that = (DefaultAttributeType<?>) obj;
             return valueClass == that.valueClass &&
-                   Objects.equals(defaultValue, that.defaultValue);
+                   Objects.equals(defaultValue, that.defaultValue) &&
+                   Objects.equals(characteristics, that.characteristics);
         }
         return false;
     }

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -354,7 +354,7 @@ public class DefaultFeatureType extends 
         int index = -1;
         for (final PropertyType property : source.getProperties(false)) {
             ArgumentChecks.ensureNonNullElement("properties", ++index, property);
-            final String name = toString(property.getName(), source, index);
+            final String name = toString(property.getName(), source, "properties", index);
             final PropertyType previous = byName.put(name, property);
             if (previous != null) {
                 if (!isAssignableIgnoreName(previous, property)) {
@@ -385,33 +385,6 @@ public class DefaultFeatureType extends 
     }
 
     /**
-     * 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.
-     *
-     * <p>{@code this} shall be the instance in process of being created, not any other instance.</p>
-     *
-     * @param name   The name for which to get the string representation.
-     * @param source The feature which contains the property (typically {@code this}).
-     * @param index  Index of the property having the given name.
-     */
-    private String toString(final GenericName name, final FeatureType source, final int index) {
-        short key = Errors.Keys.MissingValueForProperty_1;
-        if (name != null) {
-            final String s = name.toString();
-            if (!s.isEmpty()) {
-                return s;
-            }
-            key = Errors.Keys.EmptyProperty_1;
-        }
-        final StringBuilder b = new StringBuilder(30);
-        if (source != this) {
-            b.append(source.getName()).append('.');
-        }
-        throw new IllegalArgumentException(Errors.format(key,
-                b.append("properties[").append(index).append("].name").toString()));
-    }
-
-    /**
      * If an associated feature type is a placeholder for a {@code FeatureType} to be defined later,
      * replaces the placeholder by the actual instance if available. Otherwise do nothing.
      *

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -25,7 +25,7 @@ import org.opengis.feature.AttributeType
 
 
 /**
- * Static methods working on features.
+ * Static methods working on features or attributes.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -160,7 +160,7 @@ abstract class FieldType extends Abstrac
      * @param valueType The name of value class (attribute), or the feature type name (association).
      * @param values    The actual values.
      */
-    static String toString(final String className, final PropertyType type, final Object valueType, final Iterator<?> values) {
+    static StringBuilder toString(final String className, final PropertyType type, final Object valueType, final Iterator<?> values) {
         final StringBuilder buffer = toString(className, type, valueType);
         if (values.hasNext()) {
             final Object value = values.next();
@@ -178,6 +178,6 @@ abstract class FieldType extends Abstrac
                 buffer.append('}');
             }
         }
-        return buffer.toString();
+        return buffer;
     }
 }

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -49,7 +49,7 @@ import org.opengis.feature.FeatureAssoci
  *
  * @see DefaultAssociationRole
  */
-final class MultiValuedAssociation extends AbstractAssociation implements Cloneable {
+final class MultiValuedAssociation extends AbstractAssociation {
     /**
      * For cross-version compatibility.
      */
@@ -144,14 +144,11 @@ final class MultiValuedAssociation exten
 
     /**
      * Returns a copy of this association.
-     * The default implementation returns a <em>shallow</em> copy:
+     * This implementation returns a <em>shallow</em> copy:
      * the association {@linkplain #getValues() values} are <strong>not</strong> cloned.
-     * However subclasses may choose to do otherwise.
      *
      * @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,
-     *         for example on attempt to clone the association values.
      */
     @Override
     @SuppressWarnings("unchecked")

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -50,7 +50,7 @@ import org.opengis.feature.AttributeType
  *
  * @see DefaultAttributeType
  */
-final class MultiValuedAttribute<V> extends AbstractAttribute<V> implements Cloneable {
+final class MultiValuedAttribute<V> extends AbstractAttribute<V> {
     /**
      * For cross-version compatibility.
      */
@@ -150,18 +150,15 @@ final class MultiValuedAttribute<V> exte
 
     /**
      * Returns a copy of this attribute.
-     * The default implementation returns a <em>shallow</em> copy:
+     * This implementation returns a <em>shallow</em> copy:
      * the attribute {@linkplain #getValues() values} are <strong>not</strong> cloned.
-     * However subclasses may choose to do otherwise.
      *
      * @return A clone of this attribute.
      * @throws CloneNotSupportedException if this attribute can not be cloned.
-     *         The default implementation never throw this exception. However subclasses may throw it,
-     *         for example on attempt to clone the attribute values.
      */
     @Override
     @SuppressWarnings("unchecked")
-    public MultiValuedAttribute<V> clone() throws CloneNotSupportedException {
+    public AbstractAttribute<V> clone() throws CloneNotSupportedException {
         final MultiValuedAttribute<V> clone = (MultiValuedAttribute<V>) super.clone();
         clone.values = (CheckedArrayList<V>) clone.values.clone();
         return clone;
@@ -174,7 +171,7 @@ final class MultiValuedAttribute<V> exte
      */
     @Override
     public int hashCode() {
-        return type.hashCode() + values.hashCode();
+        return type.hashCode() + values.hashCode() + characteristicsReadOnly().hashCode();
     }
 
     /**
@@ -189,7 +186,8 @@ final class MultiValuedAttribute<V> exte
         }
         if (obj instanceof MultiValuedAttribute<?>) {
             final MultiValuedAttribute<?> that = (MultiValuedAttribute<?>) obj;
-            return type.equals(that.type) && values.equals(that.values);
+            return type.equals(that.type) && values.equals(that.values) &&
+                   characteristicsReadOnly().equals(that.characteristicsReadOnly());
         }
         return false;
     }

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/PropertySingleton.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/PropertySingleton.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/PropertySingleton.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/PropertySingleton.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.feature;
 
+import java.util.List;
 import java.util.AbstractList;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
@@ -186,6 +187,37 @@ final class PropertySingleton<V> extends
     }
 
     /**
+     * Same contract than {@link AbstractList}, just slightly more efficient for this particular class.
+     */
+    @Override
+    public int hashCode() {
+        final V element = property.getValue();
+        final int hashCode = (element != null) ? 31 + element.hashCode() : 1;
+        assert hashCode == super.hashCode() : hashCode;
+        return hashCode;
+    }
+
+    /**
+     * Same contract than {@link AbstractList}, just slightly more efficient for this particular class.
+     */
+    @Override
+    public boolean equals(final Object other) {
+        if (other == this) {
+            return true;
+        }
+        if (other instanceof List<?>) {
+            final V element = property.getValue();
+            if (element == null) {
+                return ((List<?>) other).isEmpty();
+            } else {
+                final Iterator<?> it = ((List<?>) other).iterator();
+                return it.hasNext() && element.equals(it.next()) && !it.hasNext();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns an iterator over the unique element in this list.
      */
     @Override

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAssociation.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAssociation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAssociation.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -41,7 +41,7 @@ import org.opengis.feature.FeatureAssoci
  *
  * @see DefaultAssociationRole
  */
-final class SingletonAssociation extends AbstractAssociation implements Cloneable {
+final class SingletonAssociation extends AbstractAssociation {
     /**
      * For cross-version compatibility.
      */
@@ -102,21 +102,6 @@ final class SingletonAssociation extends
     }
 
     /**
-     * Returns a copy of this association.
-     * The default implementation returns a <em>shallow</em> copy:
-     * the association {@linkplain #getValue() value} is <strong>not</strong> cloned.
-     * However subclasses may choose to do otherwise.
-     *
-     * @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.
-     */
-    @Override
-    public SingletonAssociation clone() throws CloneNotSupportedException {
-        return (SingletonAssociation) super.clone();
-    }
-
-    /**
      * Returns a hash code value for this association.
      *
      * @return A hash code value.

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAttribute.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAttribute.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SingletonAttribute.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -43,7 +43,7 @@ import org.opengis.feature.AttributeType
  *
  * @see DefaultAttributeType
  */
-final class SingletonAttribute<V> extends AbstractAttribute<V> implements Cloneable {
+final class SingletonAttribute<V> extends AbstractAttribute<V> {
     /**
      * For cross-version compatibility.
      */
@@ -100,30 +100,13 @@ final class SingletonAttribute<V> extend
     }
 
     /**
-     * Returns a copy of this attribute.
-     * The default implementation returns a <em>shallow</em> copy:
-     * the attribute {@linkplain #getValue() value} is <strong>not</strong> cloned.
-     * However subclasses may choose to do otherwise.
-     *
-     * @return A clone of this attribute.
-     * @throws CloneNotSupportedException if this attribute can not be cloned.
-     *         The default implementation never throw this exception. However subclasses may throw it,
-     *         for example on attempt to clone the attribute value.
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public SingletonAttribute<V> clone() throws CloneNotSupportedException {
-        return (SingletonAttribute<V>) super.clone();
-    }
-
-    /**
      * Returns a hash code value for this attribute.
      *
      * @return A hash code value.
      */
     @Override
     public int hashCode() {
-        return type.hashCode() + Objects.hashCode(value);
+        return type.hashCode() + Objects.hashCode(value) + characteristicsReadOnly().hashCode();
     }
 
     /**
@@ -138,7 +121,8 @@ final class SingletonAttribute<V> extend
         }
         if (obj instanceof SingletonAttribute<?>) {
             final SingletonAttribute<?> that = (SingletonAttribute<?>) obj;
-            return type.equals(that.type) && Objects.equals(value, that.value);
+            return type.equals(that.type) && Objects.equals(value, that.value) &&
+                   characteristicsReadOnly().equals(that.characteristicsReadOnly());
         }
         return false;
     }

Modified: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -109,7 +109,7 @@ final class SparseFeature extends Abstra
         if (valuesKind != PROPERTIES) {
             if (!properties.isEmpty()) { // The map is typically empty when this method is first invoked.
                 if (valuesKind != VALUES) {
-                    throw new CorruptedObjectException(String.valueOf(getName()));
+                    throw new CorruptedObjectException(getName());
                 }
                 valuesKind = CORRUPTED;
                 for (final Map.Entry<String, Object> entry : properties.entrySet()) {
@@ -189,7 +189,7 @@ final class SparseFeature extends Abstra
             } else if (valuesKind == PROPERTIES) {
                 throw unsupportedPropertyType(((Property) element).getName());
             } else {
-                throw new CorruptedObjectException(String.valueOf(getName()));
+                throw new CorruptedObjectException(getName());
             }
         } else if (properties.containsKey(name)) {
             return null; // Null has been explicitely set.
@@ -229,7 +229,7 @@ final class SparseFeature extends Abstra
         } else if (valuesKind == PROPERTIES) {
             setPropertyValue(getPropertyInstance(name), value);
         } else {
-            throw new CorruptedObjectException(String.valueOf(getName()));
+            throw new CorruptedObjectException(getName());
         }
     }
 

Propchange: sis/branches/JDK6/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
------------------------------------------------------------------------------
  Merged /sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java:r1598749-1640304
  Merged /sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java:r1598745-1640283

Copied: sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java (from r1640304, sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java?p2=sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java&p1=sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java&r1=1640304&r2=1640308&rev=1640308&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicMapTest.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -46,7 +46,7 @@ public final strictfp class Characterist
      * @return A {@code "temperature"} attribute with two characteristics: {@code "accuracy"} and {@code "units"}.
      */
     public static AbstractAttribute<Float> temperature() {
-        return new SingletonAttribute<>(CharacteristicTypeMapTest.temperature(), 20f);
+        return new SingletonAttribute<Float>(CharacteristicTypeMapTest.temperature(), 20f);
     }
 
     /**
@@ -57,7 +57,7 @@ public final strictfp class Characterist
      * @return An attribute for the given name.
      */
     private static AbstractAttribute<?> create(final AbstractAttribute<?> temperature, final String name) {
-        return new SingletonAttribute<>(((DefaultAttributeType<?>) temperature.getType()).characteristics().get(name));
+        return new SingletonAttribute(((DefaultAttributeType<?>) temperature.getType()).characteristics().get(name));
     }
 
     /**
@@ -278,8 +278,8 @@ public final strictfp class Characterist
         assertArrayEquals("keySet", new String[] {"accuracy", "units"}, characteristics.keySet().toArray());
         assertArrayEquals("values", new Object[] { accuracy ,  units }, characteristics.values().toArray());
         assertArrayEquals("entrySet", new Object[] {
-                new SimpleEntry<>("accuracy", accuracy),
-                new SimpleEntry<>("units",    units)
+                new SimpleEntry<String,Attribute<?>>("accuracy", accuracy),
+                new SimpleEntry<String,Attribute<?>>("units",    units)
             }, characteristics.entrySet().toArray());
     }
 

Copied: sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java (from r1640304, sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java?p2=sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java&p1=sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java&r1=1640304&r2=1640308&rev=1640308&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/CharacteristicTypeMapTest.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -47,9 +47,9 @@ public final strictfp class Characterist
      */
     public static DefaultAttributeType<Float> temperature() {
         final DefaultAttributeType<?> units, accuracy;
-        units    = new DefaultAttributeType<>(singletonMap(NAME_KEY, "units"),      String.class, 1, 1, "°C", (DefaultAttributeType[]) null);
-        accuracy = new DefaultAttributeType<>(singletonMap(NAME_KEY, "accuracy"),    Float.class, 1, 1, 0.1f, (DefaultAttributeType[]) null);
-        return     new DefaultAttributeType<>(singletonMap(NAME_KEY, "temperature"), Float.class, 1, 1, null, accuracy, units);
+        units    = new DefaultAttributeType<String>(singletonMap(NAME_KEY, "units"),      String.class, 1, 1, "°C", (DefaultAttributeType[]) null);
+        accuracy = new DefaultAttributeType<Float> (singletonMap(NAME_KEY, "accuracy"),    Float.class, 1, 1, 0.1f, (DefaultAttributeType[]) null);
+        return     new DefaultAttributeType<Float> (singletonMap(NAME_KEY, "temperature"), Float.class, 1, 1, null, accuracy, units);
     }
 
     /**
@@ -94,8 +94,8 @@ public final strictfp class Characterist
         assertArrayEquals("keySet", new String[] {"accuracy", "units"}, characteristics.keySet().toArray());
         assertArrayEquals("values", new Object[] { accuracy ,  units }, characteristics.values().toArray());
         assertArrayEquals("entrySet", new Object[] {
-                new SimpleEntry<>("accuracy", accuracy),
-                new SimpleEntry<>("units",    units)
+                new SimpleEntry<String,AttributeType<?>>("accuracy", accuracy),
+                new SimpleEntry<String,AttributeType<?>>("units",    units)
             }, characteristics.entrySet().toArray());
     }
 

Modified: sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -32,6 +32,8 @@ import static org.apache.sis.test.Assert
 
 /**
  * Tests {@link DefaultAttributeType}.
+ * This class does not test {@link DefaultAttributeType#characteristics()}.
+ * Characteristics are tested by {@link CharacteristicTypeMapTest} instead.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5

Modified: sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/MultiValuedAttributeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/MultiValuedAttributeTest.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/MultiValuedAttributeTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/MultiValuedAttributeTest.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -140,7 +140,7 @@ public final strictfp class MultiValuedA
     @DependsOnMethod("testEquals")
     public void testClone() throws CloneNotSupportedException {
         final MultiValuedAttribute<Integer> a1 = population();
-        final MultiValuedAttribute<Integer> a2 = a1.clone();
+        final    AbstractAttribute<Integer> a2 = a1.clone();
         assertNotSame(a1, a2);
         SingletonAttributeTest.testEquals(a1, a2);
     }

Modified: sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/feature/SingletonAttributeTest.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -157,7 +157,7 @@ public final strictfp class SingletonAtt
     @DependsOnMethod("testEquals")
     public void testClone() throws CloneNotSupportedException {
         final SingletonAttribute<Integer> a1 = population();
-        final SingletonAttribute<Integer> a2 = a1.clone();
+        final  AbstractAttribute<Integer> a2 = a1.clone();
         assertNotSame(a1, a2);
         testEquals(a1, a2);
     }

Modified: sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -31,6 +31,8 @@ import org.junit.BeforeClass;
  */
 @Suite.SuiteClasses({
     org.apache.sis.feature.DefaultAttributeTypeTest.class,
+    org.apache.sis.feature.CharacteristicTypeMapTest.class,
+    org.apache.sis.feature.CharacteristicMapTest.class,
     org.apache.sis.feature.DefaultFeatureTypeTest.class,
     org.apache.sis.feature.PropertySingletonTest.class,
     org.apache.sis.feature.SingletonAttributeTest.class,

Modified: sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -20,15 +20,11 @@ import java.util.Map;
 import java.util.Set;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.Debug;
+import org.apache.sis.internal.util.AbstractMapEntry;
 
 import static org.apache.sis.metadata.PropertyAccessor.RETURN_NULL;
 import static org.apache.sis.metadata.PropertyAccessor.RETURN_PREVIOUS;
 
-// Branch-dependent imports
-import org.apache.sis.internal.jdk7.Objects;
-
 
 /**
  * A view of a metadata object as a map. Keys are property names and values
@@ -181,7 +177,7 @@ final class ValueMap extends PropertyMap
      * @version 0.3
      * @module
      */
-    final class Property implements Map.Entry<String,Object> {
+    final class Property extends AbstractMapEntry<String,Object> {
         /**
          * The property index.
          */
@@ -229,41 +225,6 @@ final class ValueMap extends PropertyMap
         public Object setValue(final Object value) {
             return accessor.set(index, metadata, value, RETURN_PREVIOUS);
         }
-
-        /**
-         * Compares the specified object with this entry for equality.
-         * Criterion are specified by the {@link Map.Entry} contract.
-         */
-        @Override
-        public boolean equals(final Object object) {
-            if (object instanceof Map.Entry<?,?>) {
-                final Map.Entry<?,?> entry = (Map.Entry<?,?>) object;
-                return Objects.equals(getKey(),   entry.getKey()) &&
-                       Objects.equals(getValue(), entry.getValue());
-            }
-            return false;
-        }
-
-        /**
-         * Returns the hash code value for this map entry. The
-         * formula is specified by the {@link Map.Entry} contract.
-         */
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
-        }
-
-        /**
-         * Returns a string representation of this entry.
-         * This method is mostly for debugging purpose.
-         */
-        @Debug
-        @Override
-        public String toString() {
-            String value = String.valueOf(getValue());
-            value = value.substring(0, CharSequences.indexOfLineStart(value, 1, 0));
-            return getKey() + '=' + value;
-        }
     }
 
 

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -17,13 +17,8 @@
 package org.apache.sis.referencing;
 
 import java.util.Map;
-import java.util.Set;
 import java.util.HashMap;
-import java.util.AbstractMap;
-import java.util.AbstractSet;
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
 import java.io.Serializable;
 import org.opengis.util.GenericName;
 import org.opengis.metadata.Identifier;
@@ -32,6 +27,7 @@ import org.opengis.referencing.Reference
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.metadata.quality.PositionalAccuracy;
+import org.apache.sis.internal.util.AbstractMap;
 
 
 /**
@@ -220,14 +216,6 @@ final class Properties extends AbstractM
     }
 
     /**
-     * Returns true if this map contains a mapping for the specified key.
-     */
-    @Override
-    public boolean containsKey(final Object key) {
-        return get(key) != null;
-    }
-
-    /**
      * Returns the value to which this map maps the specified key.
      * Returns {@code null} if the map contains no mapping for this key.
      */
@@ -238,93 +226,50 @@ final class Properties extends AbstractM
     }
 
     /**
-     * Returns a set view of the mappings contained in this map.
+     * Iterates over the {@link #KEYS}, returning only the entry having a non-null value.
      */
     @Override
-    public Set<Entry<String,Object>> entrySet() {
-        return new EntrySet();
-    }
-
-    /**
-     * The view returned by {@link #entrySet()}.
-     */
-    private final class EntrySet extends AbstractSet<Entry<String,Object>> {
-        /** Creates a new instance. */
-        EntrySet() {
-        }
-
-        /** Delegates to the enclosing map. */
-        @Override
-        public boolean isEmpty() {
-            return Properties.this.isEmpty();
-        }
-
-        /** Delegates to the enclosing map. */
-        @Override
-        public int size() {
-            return Properties.this.size();
-        }
-
-        /** Iterates over the {@link #KEYS}, returning only the entry having a non-null value. */
-        @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return new Iter();
-        }
-    }
-
-    /**
-     * The iterator returned by {@link EntrySet#iterator()}.
-     */
-    private final class Iter implements Iterator<Entry<String,Object>> {
-        /**
-         * Index of the next element to return.
-         */
-        private int nextIndex;
-
-        /**
-         * Index of the value to be returned by {@link #next()}, or {@code null} if not yet computed.
-         */
-        private Object value;
-
-        /**
-         * Creates a new iterator.
-         */
-        Iter() {
-        }
-
-        /**
-         * Returns {@code true} if there is a value to return.
-         */
-        @Override
-        public boolean hasNext() {
-            while (value == null) {
-                if (nextIndex == KEYS.length) {
-                    return false;
+    protected EntryIterator<String,Object> entryIterator() {
+        return new EntryIterator<String,Object>() {
+            /**
+             * Index of the next element to inspect.
+             */
+            private int nextIndex;
+
+            /**
+             * Index of the value to be returned by {@link #next()}, or {@code null} if not yet computed.
+             */
+            private Object value;
+
+            /**
+             * Returns {@code true} if there is a value to return.
+             */
+            @Override
+            protected boolean next() {
+                while (nextIndex < KEYS.length) {
+                    value = getAt(nextIndex++);
+                    if (value != null) {
+                        return true;
+                    }
                 }
-                value = getAt(nextIndex++);
+                return false;
             }
-            return true;
-        }
 
-        /**
-         * Returns the next element.
-         */
-        @Override
-        public Entry<String, Object> next() {
-            if (hasNext()) {
-                final Entry<String, Object> entry = new SimpleImmutableEntry<String, Object>(KEYS[nextIndex-1], value);
-                value = null; // For forcing the next call to 'hasNext()' to increment 'nextIndex'.
-                return entry;
+            /**
+             * Returns the key at the current position.
+             */
+            @Override
+            protected String getKey() {
+                return KEYS[nextIndex - 1];
             }
-            throw new NoSuchElementException();
-        }
 
-        /**
-         * Unsupported operation, since this map is read-only.
-         */
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
+            /**
+             * Returns the value at the current position.
+             */
+            @Override
+            protected Object getValue() {
+                return value;
+            }
+        };
     }
 }

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -550,7 +550,7 @@ public class IdentifierMapAdapter extend
                 buffer.append(", ");
             }
             SpecializedIdentifier.format(buffer, entry.getKey(), entry.getValue());
-	}
+        }
         return buffer.append('}').toString();
     }
 }

Copied: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java (from r1640304, sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java?p2=sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java&p1=sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java&r1=1640304&r2=1640308&rev=1640308&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -28,7 +28,7 @@ import org.apache.sis.io.TableAppender;
 import org.apache.sis.util.resources.Errors;
 
 // Branch-dependent imports
-import java.util.Objects;
+import org.apache.sis.internal.jdk7.Objects;
 
 
 /**
@@ -120,7 +120,7 @@ public abstract class AbstractMap<K,V> i
          * @return The entry at the current iterator position.
          */
         protected Entry<K,V> getEntry() {
-            return new java.util.AbstractMap.SimpleImmutableEntry<>(getKey(), getValue());
+            return new java.util.AbstractMap.SimpleImmutableEntry<K,V>(getKey(), getValue());
         }
 
         /**
@@ -277,7 +277,7 @@ public abstract class AbstractMap<K,V> i
             @Override public boolean     add(K e)           {return AbstractMap.this.addKey(e);}
             @Override public Iterator<K> iterator() {
                 final EntryIterator<K,V> it = entryIterator();
-                return (it != null) ? new Keys<>(it) : Collections.<K>emptyIterator();
+                return (it != null) ? new Keys<K,V>(it) : Collections.<K>emptySet().iterator();
             }
         };
     }
@@ -301,7 +301,7 @@ public abstract class AbstractMap<K,V> i
             @Override public boolean     add(V e)           {return AbstractMap.this.addValue(e);}
             @Override public Iterator<V> iterator() {
                 final EntryIterator<K,V> it = entryIterator();
-                return (it != null) ? new Values<>(it) : Collections.<V>emptyIterator();
+                return (it != null) ? new Values<K,V>(it) : Collections.<V>emptySet().iterator();
             }
         };
     }
@@ -336,7 +336,7 @@ public abstract class AbstractMap<K,V> i
             /** Returns an iterator compliant to the Map contract. */
             @Override public Iterator<Entry<K,V>> iterator() {
                 final EntryIterator<K,V> it = entryIterator();
-                return (it != null) ? new Entries<>(it) : Collections.<Entry<K,V>>emptyIterator();
+                return (it != null) ? new Entries<K,V>(it) : Collections.<Entry<K,V>>emptySet().iterator();
             }
         };
     }

Copied: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java (from r1640304, sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java?p2=sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java&p1=sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java&r1=1640304&r2=1640308&rev=1640308&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMapEntry.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -22,7 +22,7 @@ import org.apache.sis.util.CharSequences
 import org.apache.sis.util.resources.Errors;
 
 // Branch-dependent imports
-import java.util.Objects;
+import org.apache.sis.internal.jdk7.Objects;
 
 
 /**

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -187,7 +187,7 @@ public class Cache<K,V> extends Abstract
     /**
      * A view over the entries in the cache.
      */
-    private transient Set<Entry<K,V>> entries;
+    private volatile transient Set<Entry<K,V>> entries;
 
     /**
      * Creates a new cache with a default initial capacity and cost limit of 100.

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakEntry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakEntry.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakEntry.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakEntry.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -95,9 +95,10 @@ abstract class WeakEntry<E> extends Weak
      */
     static <E> int count(final WeakEntry<E>[] table) {
         int n = 0;
-        for (int i=0; i<table.length; i++) {
-            for (WeakEntry<E> e=table[i]; e!=null; e=e.next) {
+        for (WeakEntry<E> e : table) {
+            while (e != null) {
                 n++;
+                e = e.next;
             }
         }
         return n;
@@ -159,8 +160,8 @@ abstract class WeakEntry<E> extends Weak
         final Class<?> entryType = oldTable.getClass().getComponentType();
         @SuppressWarnings("unchecked")
         final WeakEntry<E>[] table = (WeakEntry<E>[]) Array.newInstance(entryType, capacity);
-        for (int i=0; i<oldTable.length; i++) {
-            for (WeakEntry<E> next=oldTable[i]; next!=null;) {
+        for (WeakEntry<E> next : oldTable) {
+            while (next != null) {
                 final WeakEntry<E> e = next;
                 next = next.next; // We keep 'next' right now because its value will change.
                 final int index = e.hash % table.length;

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -293,22 +293,17 @@ public class WeakValueHashMap<K,V> exten
 
     /**
      * Checks if this {@code WeakValueHashMap} is valid. This method counts the number of elements
-     * and compares it to {@link #count}. If the check fails, the number of elements is corrected
-     * (if we didn't, an {@link AssertionError} would be thrown for every operations after the first
-     * error, which make debugging more difficult). The set is otherwise unchanged, which should
-     * help to get similar behavior as if assertions hasn't been turned on.
+     * and compares it to {@link #count}. This method is invoked in assertions only.
      */
     @Debug
     final boolean isValid() {
-        assert Thread.holdsLock(this);
-        assert count <= upperCapacityThreshold(table.length);
-        final int n = count(table);
-        if (n != count) {
-            count = n;
-            return false;
-        } else {
-            return true;
+        if (!Thread.holdsLock(this)) {
+            throw new AssertionError();
         }
+        if (count > upperCapacityThreshold(table.length)) {
+            throw new AssertionError(count);
+        }
+        return count(table) == count;
     }
 
     /**
@@ -520,12 +515,13 @@ public class WeakValueHashMap<K,V> exten
                 final Map.Entry<K,V>[] elements = new Map.Entry[size()];
                 int index = 0;
                 final Entry[] table = WeakValueHashMap.this.table;
-                for (int i=0; i<table.length; i++) {
-                    for (Entry el=table[i]; el!=null; el=(Entry) el.next) {
+                for (Entry el : table) {
+                    while (el != null) {
                         final Map.Entry<K,V> entry = new SimpleEntry<K,V>(el);
                         if (entry.getValue() != null) {
                             elements[index++] = entry;
                         }
+                        el= (Entry) el.next;
                     }
                 }
                 return ArraysExt.resize(elements, index);

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java?rev=1640308&r1=1640307&r2=1640308&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java [UTF-8] Tue Nov 18 10:58:48 2014
@@ -31,6 +31,7 @@ import org.apache.sis.util.Debug;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.util.AbstractMapEntry;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.Objects;
@@ -199,7 +200,7 @@ public class DefaultRecord implements Re
      * Operations on this entry delegate to {@link DefaultRecord#locate(MemberName)}
      * and {@link DefaultRecord#set(MemberName, Object)} methods.
      */
-    private final class Entry implements Map.Entry<MemberName,Object> {
+    private final class Entry extends AbstractMapEntry<MemberName,Object> {
         /** Index of the record member represented by this entry. */
         private final int index;
 



Mime
View raw message