sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1596632 - in /sis/branches/JDK8/core: sis-feature/src/main/java/org/apache/sis/feature/ sis-feature/src/test/java/org/apache/sis/feature/ sis-referencing/src/main/java/org/apache/sis/parameter/
Date Wed, 21 May 2014 17:31:55 GMT
Author: desruisseaux
Date: Wed May 21 17:31:55 2014
New Revision: 1596632

URL: http://svn.apache.org/r1596632
Log:
Test the plugin of custom Feature quality evaluation procedures.

Added:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
  (with props)
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTest.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -124,13 +124,50 @@ public abstract class AbstractFeature im
      * <div class="warning"><b>Warning:</b> In a future SIS version, the
return type may be changed
      * to {@code org.opengis.feature.Property}. This change is pending GeoAPI revision.</div>
      *
+     * <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 DefaultAttribute} or {@link DefaultAssociation}
instances.</div>
+     *
      * @param  name The property name.
-     * @return The property of the given name.
+     * @return The property of the given name (never {@code null}).
      * @throws IllegalArgumentException If the given argument is not a property name of this
feature.
+     *
+     * @see #getPropertyValue(String)
      */
     public abstract Object getProperty(final String name) throws IllegalArgumentException;
 
     /**
+     * Sets the property (attribute, operation or association).
+     * The given property shall comply to the following conditions:
+     *
+     * <ul>
+     *   <li>It must be non-null.</li>
+     *   <li>Its {@linkplain Property#getName() name} shall be the name of the property
to set in this feature.</li>
+     *   <li>Its type shall be the same instance than the {@linkplain AbstractFeature#getPropertyType(String)
+     *       property type} defined by the feature type for the above name.
+     *       In other words, the following condition shall hold:</li>
+     * </ul>
+     *
+     * {@preformat java
+     *     assert property.getType() == getType().getPropertyType(property.getName());
+     * }
+     *
+     * <div class="note"><b>Note:</b> This method is useful for storing
non-default {@code Attribute} or
+     * {@code Association} implementations in this feature. When default implementations
are sufficient,
+     * the {@link #setPropertyValue(String, Object)} method is preferred.</div>
+     *
+     * <div class="warning"><b>Warning:</b> In a future SIS version, the
argument may be changed
+     * to {@code org.opengis.feature.Property}. This change is pending GeoAPI revision.</div>
+     *
+     * @param  property The property to set.
+     * @throws IllegalArgumentException if the type of the given property is not one of the
types
+     *         known to this feature, or if the property can not be set of an other reason.
+     *
+     * @see #setPropertyValue(String, Object)
+     */
+    public abstract void setProperty(final Object property) throws IllegalArgumentException;
+
+    /**
      * 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.
      *
@@ -272,6 +309,28 @@ public abstract class AbstractFeature im
     }
 
     /**
+     * Returns {@code true} if the caller can skip the call to {@link #verifyValueType(String,
Object)}.
+     * This is a slight optimization for the case when we replaced an attribute value by
a new value of
+     * 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 verifyValueType}.
+     */
+    static boolean canSkipVerification(final Object previous, final Object value) {
+        if (previous != null) {
+            if (value == null) {
+                return true;
+            }
+            if (previous.getClass() == value.getClass() && !(value instanceof AbstractFeature))
{
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Verifies the validity of the given value for the property of the given name. If a
check failed,
      * returns the exception to throw. Otherwise returns {@code null}. This method does not
throw the
      * exception immediately in order to give to the caller a chance to perform cleanup operation
first.
@@ -302,6 +361,27 @@ public abstract class AbstractFeature im
     }
 
     /**
+     * Verifies if the given properties can be assigned to this feature.
+     *
+     * @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 type;
+        if (property instanceof DefaultAttribute<?>) {
+            type = ((DefaultAttribute<?>) property).getType();
+        } else if (property instanceof DefaultAssociation) {
+            type = ((DefaultAssociation) property).getRole();
+        } else {
+            throw new IllegalArgumentException(Errors.format(
+                    Errors.Keys.IllegalArgumentClass_2, "property", property.getClass()));
+        }
+        if (type != getPropertyType(name)) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedPropertyType_1,
name));
+        }
+    }
+
+    /**
      * Returns the exception message for a property type which neither an attribute or an
association.
      */
     static String unsupportedPropertyType(final GenericName name) {

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -31,8 +31,8 @@ import static org.apache.sis.util.Argume
  * <ul>
  *   <li><b>Aggregation</b> represents associations between features which
can exist even if the aggregate is destroyed.</li>
  *   <li><b>Composition</b> represents relationships where the owned features
are destroyed together with the composite.</li>
- *   <li><b>Spatial</b> represents spatial or topological relationships
that may exist between features (e.g. “east of”).</li>
- *   <li><b>Temporal</b> may represent for example a sequence of changes
over time involving the replacement of some
+ *   <li><b>Spatial</b> association represents spatial or topological relationships
that may exist between features (e.g. “<cite>east of</cite>”).</li>
+ *   <li><b>Temporal</b> association may represent for example a sequence
of changes over time involving the replacement of some
  *       feature instances by other feature instances.</li>
  * </ul>
  *

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -102,8 +102,6 @@ final class DenseFeature extends Abstrac
             if (property != null) {
                 return property;
             }
-        } else if (properties == null) {
-            properties = new Property[indices.size()];
         } else {
             wrapValuesInProperties();
         }
@@ -113,16 +111,37 @@ final class DenseFeature extends Abstrac
     }
 
     /**
+     * Sets the property (attribute, operation or association).
+     *
+     * @param  property The property to set.
+     * @throws IllegalArgumentException if the type of the given property is not one of the
types
+     *         known to this feature.
+     */
+    @Override
+    public void setProperty(final Object property) throws IllegalArgumentException {
+        ArgumentChecks.ensureNonNull("property", property);
+        final String name = ((Property) property).getName().toString();
+        verifyPropertyType(name, (Property) property);
+        if (!(properties instanceof Property[])) {
+            wrapValuesInProperties();
+        }
+        properties[indices.get(name)] = property;
+    }
+
+    /**
      * Wraps values in {@code Property} objects for all elements in the {@link #properties}
array.
      * This operation is executed at most once per feature.
      */
     private void wrapValuesInProperties() {
-        final Property[] c = new Property[properties.length];
-        for (final Map.Entry<String, Integer> entry : indices.entrySet()) {
-            final int   index  = entry.getValue();
-            final Object value = properties[index];
-            if (value != null) {
-                c[index] = createProperty(entry.getKey(), value);
+        final Property[] c = new Property[indices.size()];
+        if (properties != null) {
+            assert c.length == properties.length;
+            for (final Map.Entry<String, Integer> entry : indices.entrySet()) {
+                final int   index  = entry.getValue();
+                final Object value = properties[index];
+                if (value != null) {
+                    c[index] = createProperty(entry.getKey(), value);
+                }
             }
         }
         properties = c; // Store only on success.
@@ -173,8 +192,7 @@ final class DenseFeature extends Abstrac
         }
         if (!(properties instanceof Property[])) {
             if (value != null) {
-                final Object previous = properties[index];
-                if (previous == null || previous.getClass() != value.getClass()) {
+                if (!canSkipVerification(properties[index], value)) {
                     final RuntimeException e = verifyValueType(name, value);
                     if (e != null) {
                         throw e;

Added: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java?rev=1596632&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
(added)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.feature;
+
+import org.apache.sis.util.Static;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Static methods working on features.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.5
+ * @version 0.5
+ * @module
+ */
+public final class Features extends Static {
+    /**
+     * Do not allow instantiation of this class.
+     */
+    private Features() {
+    }
+
+    /**
+     * Casts the given attribute type to the given parameterized type.
+     * An exception is thrown immediately if the type does not have the expected
+     * {@linkplain DefaultAttributeType#getValueClass() value class}.
+     *
+     * @param  <T>        The expected value class.
+     * @param  type       The attribute type to cast, or {@code null}.
+     * @param  valueClass The expected value class.
+     * @return The attribute type casted to the given value class, or {@code null} if the
given type was null.
+     * @throws ClassCastException if the given attribute type does not have the expected
value class.
+     *
+     * @category verification
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> DefaultAttributeType<T> cast(final DefaultAttributeType<?>
type, final Class<T> valueClass)
+            throws ClassCastException
+    {
+        if (type != null) {
+            final Class<?> actual = type.getValueClass();
+            // We require a strict equality - not type.isAssignableFrom(actual) - because
in
+            // the later case we could have (to be strict) to return a <? extends T>
type.
+            if (!valueClass.equals(actual)) {
+                throw new ClassCastException(Errors.format(Errors.Keys.MismatchedPropertyType_1,
type.getName()));
+            }
+        }
+        return (DefaultAttributeType<T>) type;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Features.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -96,19 +96,10 @@ final class SparseFeature extends Abstra
     }
 
     /**
-     * Returns the property (attribute, operation or association) of the given name.
-     *
-     * @param  name The property name.
-     * @return The property of the given name.
-     * @throws IllegalArgumentException If the given argument is not a property name of this
feature.
+     * Ensures that the {@link #properties} map contains {@link Property} instances instead
than
+     * property values. The conversion, if needed, will be performed at most once per feature.
      */
-    @Override
-    public Object getProperty(final String name) throws IllegalArgumentException {
-        ArgumentChecks.ensureNonNull("name", name);
-        /*
-         * Wraps values in Property objects for all entries in the properties map,
-         * if not already done. This operation is executed at most once per feature.
-         */
+    private void ensurePropertyMap() {
         if (valuesKind != PROPERTIES) {
             if (!properties.isEmpty()) { // The map is typically empty when this method is
first invoked.
                 if (valuesKind != VALUES) {
@@ -125,6 +116,19 @@ final class SparseFeature extends Abstra
             }
             valuesKind = PROPERTIES; // Set only on success.
         }
+    }
+
+    /**
+     * Returns the property (attribute, operation or association) of the given name.
+     *
+     * @param  name The property name.
+     * @return The property of the given name.
+     * @throws IllegalArgumentException If the given argument is not a property name of this
feature.
+     */
+    @Override
+    public Object getProperty(final String name) throws IllegalArgumentException {
+        ArgumentChecks.ensureNonNull("name", name);
+        ensurePropertyMap();
         return getPropertyInstance(name);
     }
 
@@ -143,6 +147,22 @@ final class SparseFeature extends Abstra
     }
 
     /**
+     * Sets the property (attribute, operation or association).
+     *
+     * @param  property The property to set.
+     * @throws IllegalArgumentException if the type of the given property is not one of the
types
+     *         known to this feature.
+     */
+    @Override
+    public void setProperty(final Object property) throws IllegalArgumentException {
+        ArgumentChecks.ensureNonNull("property", property);
+        final String name = ((Property) property).getName().toString();
+        verifyPropertyType(name, (Property) property);
+        ensurePropertyMap();
+        properties.put(name, property);
+    }
+
+    /**
      * Returns the value for the property of the given name.
      *
      * @param  name The property name.
@@ -186,11 +206,11 @@ final class SparseFeature extends Abstra
         if (valuesKind == VALUES) {
             final Object previous = properties.put(name, value);
             /*
-             * Slight optimisation:  if we replaced a previous value of the same class, then
we can skip the
+             * Slight optimization:  if we replaced a previous value of the same class, then
we can skip the
              * checks for name and type validity since those checks have been done previously.
But if we add
              * a new value or a value of a different type, then we need to check the name
and type validity.
              */
-            if (previous == null || (value != null && previous.getClass() != value.getClass()))
{
+            if (!canSkipVerification(previous, value)) {
                 final RuntimeException e = verifyValueType(name, value);
                 if (e != null) {
                     replace(name, value, previous); // Restore the previous value.

Added: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java?rev=1596632&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java
(added)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.feature;
+
+import org.opengis.metadata.quality.DataQuality;
+import org.apache.sis.metadata.iso.quality.DefaultDataQuality;
+import org.apache.sis.metadata.iso.quality.DefaultDomainConsistency;
+import org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult;
+import org.apache.sis.util.iso.SimpleInternationalString;
+import org.apache.sis.referencing.NamedIdentifier;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * For testing {@link DefaultAttribute} customization.
+ * This implementation adds its own criterion to the attribute quality evaluation.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.5
+ * @version 0.5
+ * @module
+ */
+@SuppressWarnings("serial")
+final strictfp class CustomAttribute<V> extends DefaultAttribute<V> {
+    /**
+     * A quality information that this attribute will report in addition to the default ones.
+     */
+    static final String ADDITIONAL_QUALITY_INFO = "Some statistical quality measurement.";
+
+    /**
+     * Creates a new attribute.
+     */
+    public CustomAttribute(final DefaultAttributeType<V> type) {
+        super(type);
+    }
+
+    /**
+     * Evaluates the quality of this attribute with a custom rule.
+     */
+    @Override
+    public DataQuality quality() {
+        final DefaultDataQuality        quality = (DefaultDataQuality) super.quality();
+        final DefaultDomainConsistency  report  = new DefaultDomainConsistency();
+        final DefaultQuantitativeResult result  = new DefaultQuantitativeResult();
+        result.setErrorStatistic(new SimpleInternationalString(ADDITIONAL_QUALITY_INFO));
+        report.setMeasureIdentification(new NamedIdentifier(getName()));
+        assertTrue(report .getResults().add(result));
+        assertTrue(quality.getReports().add(report));
+        return quality;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/CustomAttribute.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTest.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTest.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -58,6 +58,14 @@ public final strictfp class DefaultAttri
     }
 
     /**
+     * Creates an attribute for a singleton value.
+     * This attribute has no default value.
+     */
+    static DefaultAttribute<String> parliament() {
+        return new DefaultAttribute<>(DefaultAttributeTypeTest.parliament());
+    }
+
+    /**
      * Tests getting and setting an attribute value.
      */
     @Test

Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultAttributeTypeTest.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -26,6 +26,7 @@ import org.apache.sis.test.DependsOnMeth
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
+import static java.util.Collections.singletonMap;
 import static org.apache.sis.test.Assert.*;
 
 
@@ -72,6 +73,14 @@ public final strictfp class DefaultAttri
     }
 
     /**
+     * Creates an attribute type for a parliament name.
+     */
+    static DefaultAttributeType<String> parliament() {
+        return new DefaultAttributeType<>(singletonMap(DefaultAttributeType.NAME_KEY,
"parliament"),
+                        String.class, 1, 1, null);
+    }
+
+    /**
      * Tests the creation of a simple {@link DefaultAttributeType} instance for a mandatory
singleton.
      */
     @Test

Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -76,9 +76,7 @@ public final strictfp class DefaultFeatu
      */
     public static DefaultFeatureType capital() {
         return new DefaultFeatureType(singletonMap(DefaultFeatureType.NAME_KEY, "Capital"),
false,
-                new DefaultFeatureType[] {city()},
-                new DefaultAttributeType<>(singletonMap(DefaultAttributeType.NAME_KEY,
"parliament"),
-                        String.class, 1, 1, null));
+                new DefaultFeatureType[] {city()}, DefaultAttributeTypeTest.parliament());
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -16,11 +16,14 @@
  */
 package org.apache.sis.feature;
 
+import org.opengis.metadata.quality.DataQuality;
 import org.opengis.metadata.quality.Element;
 import org.opengis.metadata.quality.Result;
 import org.opengis.metadata.quality.ConformanceResult;
+import org.opengis.metadata.quality.QuantitativeResult;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.TestUtilities;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -127,6 +130,7 @@ abstract strictfp class FeatureTestCase 
         setAttributeValue("city", "Utopia", "Atlantide");
         try {
             feature.setPropertyValue("city", 2000);
+            fail("Shall not be allowed to set a value of the wrong type.");
         } catch (ClassCastException e) {
             final String message = e.getMessage();
             assertTrue(message, message.contains("city"));
@@ -187,6 +191,7 @@ abstract strictfp class FeatureTestCase 
          */
         try {
             feature.setPropertyValue("region", "State of New York");
+            fail("Shall not be allowed to set a value of the wrong type.");
         } catch (ClassCastException e) {
             final String message = e.getMessage();
             assertTrue(message, message.contains("region"));
@@ -212,17 +217,59 @@ abstract strictfp class FeatureTestCase 
     }
 
     /**
+     * Tests the possibility to plugin custom attributes via {@link AbstractFeature#setProperty(Property)}.
+     */
+    @Test
+    @DependsOnMethod({"testSimpleValues", "testSimpleProperties"})
+    public void testCustomAttribute() {
+        feature = createFeature(DefaultFeatureTypeTest.city());
+        final DefaultAttribute<String> wrong = DefaultAttributeTest.parliament();
+        final CustomAttribute<String> city = new CustomAttribute<>(Features.cast(
+                (DefaultAttributeType<?>) feature.getType().getProperty("city"), String.class));
+
+        feature.setProperty(city);
+        setAttributeValue("city", "Utopia", "Atlantide");
+        try {
+            feature.setProperty(wrong);
+            fail("Shall not be allowed to set a property of the wrong type.");
+        } catch (IllegalArgumentException e) {
+            final String message = e.getMessage();
+            assertTrue(message, message.contains("parliament"));
+            assertTrue(message, message.contains("City"));
+        }
+        assertSame(city, feature.getProperty("city"));
+        /*
+         * The quality report is expected to contains a custom element.
+         */
+        int numOccurrences = 0;
+        final DataQuality quality = assertQualityReports("population", "population");
+        for (final Element report : quality.getReports()) {
+            final String identifier = report.getMeasureIdentification().toString();
+            if (identifier.equals("city")) {
+                numOccurrences++;
+                final Result result = TestUtilities.getSingleton(report.getResults());
+                assertInstanceOf("result", QuantitativeResult.class, result);
+                assertEquals("quality.report.result.errorStatistic",
+                        CustomAttribute.ADDITIONAL_QUALITY_INFO,
+                        String.valueOf(((QuantitativeResult) result).getErrorStatistic()));
+            }
+        }
+        assertEquals("Number of reports.", 1, numOccurrences);
+    }
+
+    /**
      * Asserts that {@link AbstractFeature#quality()} reports no anomaly, or only an anomaly
for the given property.
      *
-     * @param property The property for which we expect a report, or {@code null} if none.
-     * @param keyword  A keyword which is expected to exists in the explanation.
+     * @param  property The property for which we expect a report, or {@code null} if none.
+     * @param  keyword  A keyword which is expected to exists in the explanation.
+     * @return The data quality report.
      */
-    private void assertQualityReports(final String property, final String keyword) {
+    private DataQuality assertQualityReports(final String property, final String keyword)
{
         int numOccurrences = 0;
-        for (final Element report : feature.quality().getReports()) {
+        final DataQuality quality = feature.quality();
+        for (final Element report : quality.getReports()) {
             for (final Result result : report.getResults()) {
-                assertInstanceOf("result", ConformanceResult.class, result);
-                if (!((ConformanceResult) result).pass()) {
+                if (result instanceof ConformanceResult && !((ConformanceResult)
result).pass()) {
                     final String identifier  = report.getMeasureIdentification().toString();
                     final String explanation = ((ConformanceResult) result).getExplanation().toString();
                     assertEquals("quality.report.measureIdentification", property, identifier);
@@ -232,6 +279,7 @@ abstract strictfp class FeatureTestCase 
             }
         }
         assertEquals("Number of reports.", property == null ? 0 : 1, numOccurrences);
+        return quality;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java?rev=1596632&r1=1596631&r2=1596632&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java
[UTF-8] Wed May 21 17:31:55 2014
@@ -43,25 +43,26 @@ public final class Parameters extends St
 
     /**
      * Casts the given parameter descriptor to the given type.
-     * An exception is thrown immediately if the parameter does not have the expected value
class.
+     * An exception is thrown immediately if the parameter does not have the expected
+     * {@linkplain DefaultParameterDescriptor#getValueClass() value class}.
      *
-     * @param  <T> The expected value class.
+     * @param  <T>        The expected value class.
      * @param  descriptor The descriptor to cast, or {@code null}.
-     * @param  type The expected value class.
-     * @return The descriptor casted to the given type, or {@code null} if the given descriptor
was null.
-     * @throws ClassCastException if the given descriptor doesn't have the expected value
class.
+     * @param  valueClass The expected value class.
+     * @return The descriptor casted to the given value class, or {@code null} if the given
descriptor was null.
+     * @throws ClassCastException if the given descriptor does not have the expected value
class.
      *
      * @category verification
      */
     @SuppressWarnings("unchecked")
-    public static <T> ParameterDescriptor<T> cast(final ParameterDescriptor<?>
descriptor, final Class<T> type)
+    public static <T> ParameterDescriptor<T> cast(final ParameterDescriptor<?>
descriptor, final Class<T> valueClass)
             throws ClassCastException
     {
         if (descriptor != null) {
             final Class<?> actual = descriptor.getValueClass();
             // We require a strict equality - not type.isAssignableFrom(actual) - because
in
             // the later case we could have (to be strict) to return a <? extends T>
type.
-            if (!type.equals(actual)) {
+            if (!valueClass.equals(actual)) {
                 throw new ClassCastException(Errors.format(Errors.Keys.IllegalParameterType_2,
                         descriptor.getName().getCode(), actual));
             }



Mime
View raw message