You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2014/05/21 19:31:55 UTC
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/
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));
}