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 2016/07/29 17:53:10 UTC
svn commit: r1754559 [1/2] - in /sis/branches/JDK8/core:
sis-feature/src/main/java/org/apache/sis/feature/
sis-feature/src/test/java/org/apache/sis/feature/
sis-feature/src/test/java/org/apache/sis/test/suite/
sis-utility/src/main/java/org/apache/sis/u...
Author: desruisseaux
Date: Fri Jul 29 17:53:09 2016
New Revision: 1754559
URL: http://svn.apache.org/viewvc?rev=1754559&view=rev
Log:
Provide more default implementations in AbstractMethod methods, for making easier the task of developers who want to create their own subtypes.
Added:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java (with props)
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java (with props)
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java (with props)
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java (with props)
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
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/DefaultAttributeType.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java?rev=1754559&r1=1754558&r2=1754559&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -69,7 +69,7 @@ public abstract class AbstractAssociatio
/**
* Creates a new association of the given role.
*
- * @param role Information about the association.
+ * @param role information about the association.
*
* @see #create(FeatureAssociationRole)
*/
@@ -80,8 +80,8 @@ public abstract class AbstractAssociatio
/**
* Creates a new association of the given role.
*
- * @param role Information about the association.
- * @return The new association.
+ * @param role information about the association.
+ * @return the new association.
*
* @see DefaultAssociationRole#newInstance()
*/
@@ -95,9 +95,9 @@ public abstract class AbstractAssociatio
/**
* Creates a new association of the given role initialized to the given value.
*
- * @param role Information about the association.
- * @param value The initial value (may be {@code null}).
- * @return The new association.
+ * @param role information about the association.
+ * @param value the initial value (may be {@code null}).
+ * @return the new association.
*/
static AbstractAssociation create(final FeatureAssociationRole role, final Object value) {
ArgumentChecks.ensureNonNull("role", role);
@@ -110,7 +110,7 @@ public abstract class AbstractAssociatio
* Returns the name of this association as defined by its {@linkplain #getRole() role}.
* This convenience method delegates to {@link FeatureAssociationRole#getName()}.
*
- * @return The association name specified by its role.
+ * @return the association name specified by its role.
*/
@Override
public GenericName getName() {
@@ -120,7 +120,7 @@ public abstract class AbstractAssociatio
/**
* Returns information about the association.
*
- * @return Information about the association.
+ * @return information about the association.
*/
@Override
public FeatureAssociationRole getRole() {
@@ -132,7 +132,7 @@ public abstract class AbstractAssociatio
* the common case where the {@linkplain DefaultAssociationRole#getMaximumOccurs() maximum number} of
* features is restricted to 1 or 0.
*
- * @return The associated feature (may be {@code null}).
+ * @return the associated feature (may be {@code null}).
* @throws MultiValuedPropertyException if this association contains more than one value.
*
* @see AbstractFeature#getPropertyValue(String)
@@ -148,7 +148,7 @@ public abstract class AbstractAssociatio
* <p>The default implementation returns a collection which will delegate its work to
* {@link #getValue()} and {@link #setValue(Object)}.</p>
*
- * @return The features in a <cite>live</cite> collection.
+ * @return the features in a <cite>live</cite> collection.
*/
@Override
public Collection<Feature> getValues() {
@@ -164,8 +164,8 @@ public abstract class AbstractAssociatio
* and also because some rules may be temporarily broken while constructing a feature.
* A more exhaustive verification can be performed by invoking the {@link #quality()} method.
*
- * @param value The new value, or {@code null}.
- * @throws InvalidPropertyValueException If the given feature is not valid for this association.
+ * @param value the new value, or {@code null}.
+ * @throws InvalidPropertyValueException if the given feature is not valid for this association.
*
* @see AbstractFeature#setPropertyValue(String, Object)
*/
@@ -178,7 +178,7 @@ public abstract class AbstractAssociatio
* <p>The default implementation ensures that the given collection contains at most one element,
* then delegates to {@link #setValue(Feature)}.</p>
*
- * @param values The new values.
+ * @param values the new values.
* @throws InvalidPropertyValueException if the given collection contains too many elements.
*/
@Override
@@ -208,7 +208,7 @@ public abstract class AbstractAssociatio
* {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult conformance result} having a
* {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult#pass() pass} value of {@code false}.</p>
*
- * @return Reports on all constraint violations found.
+ * @return reports on all constraint violations found.
*
* @see AbstractFeature#quality()
*/
@@ -222,14 +222,16 @@ public abstract class AbstractAssociatio
* Returns a string representation of this association.
* The returned string is for debugging purpose and may change in any future SIS version.
*
- * @return A string representation of this association for debugging purpose.
+ * @return a string representation of this association for debugging purpose.
*/
@Debug
@Override
public String toString() {
final String pt = DefaultAssociationRole.getTitleProperty(role);
final Iterator<Feature> it = getValues().iterator();
- return FieldType.toString("FeatureAssociation", role, DefaultAssociationRole.getValueTypeName(role), new Iterator<Object>() {
+ return FieldType.toString("FeatureAssociation", role.getName(),
+ DefaultAssociationRole.getValueTypeName(role), new Iterator<Object>()
+ {
@Override public boolean hasNext() {
return it.hasNext();
}
@@ -246,7 +248,7 @@ public abstract class AbstractAssociatio
* the association {@linkplain #getValue() value} is <strong>not</strong> cloned.
* However subclasses may choose to do otherwise.
*
- * @return A clone of this association.
+ * @return a clone of this association.
* @throws CloneNotSupportedException if this association can not be cloned.
* The default implementation never throw this exception. However subclasses may throw it.
*/
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java?rev=1754559&r1=1754558&r2=1754559&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAttribute.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -464,7 +464,7 @@ public abstract class AbstractAttribute<
@Debug
@Override
public String toString() {
- final StringBuilder buffer = FieldType.toString("Attribute", type,
+ final StringBuilder buffer = FieldType.toString("Attribute", type.getName(),
Classes.getShortName(type.getValueClass()), getValues().iterator());
if (characteristics != null && !characteristics.isEmpty()) {
buffer.append(System.lineSeparator());
Modified: sis/branches/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=1754559&r1=1754558&r2=1754559&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] Fri Jul 29 17:53:09 2016
@@ -25,10 +25,12 @@ import org.opengis.metadata.quality.Data
import org.opengis.metadata.maintenance.ScopeCode;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.CorruptedObjectException;
import org.apache.sis.internal.util.CheckedArrayList;
// Branch-dependent imports
+import java.util.Objects;
import org.opengis.feature.Property;
import org.opengis.feature.PropertyType;
import org.opengis.feature.PropertyNotFoundException;
@@ -74,7 +76,7 @@ import org.opengis.feature.Operation;
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.7
+ * @version 0.8
* @module
*
* @see DefaultFeatureType#newInstance()
@@ -93,7 +95,7 @@ public abstract class AbstractFeature im
/**
* Creates a new feature of the given type.
*
- * @param type Information about the feature (name, characteristics, <i>etc.</i>).
+ * @param type information about the feature (name, characteristics, <i>etc.</i>).
*
* @see DefaultFeatureType#newInstance()
*/
@@ -113,7 +115,7 @@ public abstract class AbstractFeature im
/**
* Returns information about the feature (name, characteristics, <i>etc.</i>).
*
- * @return Information about the feature.
+ * @return information about the feature.
*/
@Override
public FeatureType getType() {
@@ -130,15 +132,31 @@ public abstract class AbstractFeature im
* <em>value</em> is desired, then {@link #getPropertyValue(String)} is preferred since it gives to SIS a
* chance to avoid the creation of {@link AbstractAttribute} or {@link AbstractAssociation} instances.</div>
*
- * @param name The property name.
- * @return The property of the given name (never {@code null}).
+ * <div class="note"><b>Note for subclass implementors:</b>
+ * the default implementation returns an instance that redirect all read and write operations to
+ * {@link #getPropertyValue(String)} and {@link #setPropertyValue(String, Object)} respectively.
+ * That default implementation is intended to make easier for developers to create their own
+ * customized <code>AbstractFacture</code> implementations, but has drawbacks:
+ *
+ * <ul>
+ * <li>A new {@code Property} instance is created every time that this {@code getProperty(String)} method is invoked.</li>
+ * <li>The returned {@code Property} implementation is not very efficient since it has to perform multiple lookups and type checks.</li>
+ * </ul>
+ *
+ * Implementors are encouraged to override this method if they can provide a more efficient implementation.
+ * Note that this is already the case when using implementations created by {@link DefaultFeatureType#newInstance()}.</div>
+ *
+ * @param name the property name.
+ * @return the property of the given name (never {@code null}).
* @throws PropertyNotFoundException if the given argument is not a property name of this feature.
*
* @see #getPropertyValue(String)
* @see DefaultFeatureType#getProperty(String)
*/
@Override
- public abstract Property getProperty(final String name) throws PropertyNotFoundException;
+ public Property getProperty(final String name) throws PropertyNotFoundException {
+ return PropertyView.create(this, type.getProperty(name));
+ }
/**
* Sets the property (attribute or feature association).
@@ -160,7 +178,22 @@ public abstract class AbstractFeature im
* {@code FeatureAssociation} implementations in this feature. When default implementations are sufficient,
* the {@link #setPropertyValue(String, Object)} method is preferred.</div>
*
- * @param property The property to set.
+ * <div class="note"><b>Note for subclass implementors:</b>
+ * the default implementation verifies that the given property has the expected type and a null or empty
+ * {@linkplain AbstractAttribute#characteristics() map of characteristics}, then delegates to
+ * {@link #setPropertyValue(String, Object)}.
+ * That default implementation is intended to make easier for developers to create their own
+ * customized <code>AbstractFacture</code> implementations, but has drawbacks:
+ *
+ * <ul>
+ * <li>The given {@code Property} instance is not retained; only its {@linkplain AbstractAttribute#getValue() value} is stored.</li>
+ * <li>The given {@code Property} instance can not have custom {@linkplain AbstractAttribute#characteristics() characteristics}.</li>
+ * </ul>
+ *
+ * Implementors are encouraged to override this method if they can provide a better implementation.
+ * Note that this is already the case when using implementations created by {@link DefaultFeatureType#newInstance()}.</div>
+ *
+ * @param property the property to set.
* @throws PropertyNotFoundException if the name of the given property is not a property name of this feature.
* @throws InvalidPropertyValueException if the value of the given property is not valid.
* @throws IllegalArgumentException if the property can not be set for another reason.
@@ -168,14 +201,22 @@ public abstract class AbstractFeature im
* @see #setPropertyValue(String, Object)
*/
@Override
- public abstract void setProperty(final Property property) throws IllegalArgumentException;
+ public void setProperty(final Property property) throws IllegalArgumentException {
+ ArgumentChecks.ensureNonNull("property", property);
+ final String name = property.getName().toString();
+ verifyPropertyType(name, property);
+ if (property instanceof Attribute<?> && !Containers.isNullOrEmpty(((Attribute<?>) property).characteristics())) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.CanNotAssignCharacteristics_1, name));
+ }
+ setPropertyValue(name, property.getValue());
+ }
/**
* Wraps the given value in a {@link Property} object. This method is invoked only by
* {@link #getProperty(String)} when it needs to converts its {@code properties} data.
*
- * @param name The name of the property to create.
- * @param value The value to wrap.
+ * @param name the name of the property to create.
+ * @param value the value to wrap.
* @return A {@code Property} wrapping the given value.
*/
final Property createProperty(final String name, final Object value) {
@@ -193,8 +234,8 @@ public abstract class AbstractFeature im
/**
* Creates a new property initialized to its default value.
*
- * @param name The name of the property to create.
- * @return A {@code Property} of the given name.
+ * @param name the name of the property to create.
+ * @return a {@code Property} of the given name.
* @throws PropertyNotFoundException if the given argument is not the name of an attribute or
* feature association of this feature.
*/
@@ -261,8 +302,8 @@ public abstract class AbstractFeature im
* Returns the default value to be returned by {@link #getPropertyValue(String)}
* for the property of the given name.
*
- * @param name The name of the property for which to get the default value.
- * @return The default value for the {@code Property} of the given name.
+ * @param name the name of the property for which to get the default value.
+ * @return the default value for the {@code Property} of the given name.
* @throws PropertyNotFoundException if the given argument is not an attribute or association name of this feature.
*/
final Object getDefaultValue(final String name) throws PropertyNotFoundException {
@@ -308,8 +349,8 @@ public abstract class AbstractFeature im
* number of occurrences} and does not depend on the actual number of values. If an attribute allows more than one
* value, then this method will always return a collection for that attribute even if the collection is empty.</div>
*
- * @param name The property name.
- * @return The value for the given property, or {@code null} if none.
+ * @param name the property name.
+ * @return the value for the given property, or {@code null} if none.
* @throws PropertyNotFoundException if the given argument is not an attribute or association name of this feature.
*
* @see AbstractAttribute#getValue()
@@ -326,8 +367,8 @@ public abstract class AbstractFeature im
* and also because some rules may be temporarily broken while constructing a feature.
* A more exhaustive verification can be performed by invoking the {@link #quality()} method.
*
- * @param name The attribute name.
- * @param value The new value for the given attribute (may be {@code null}).
+ * @param name the attribute name.
+ * @param value the new value for the given attribute (may be {@code null}).
* @throws PropertyNotFoundException if the given name is not an attribute or association name of this feature.
* @throws ClassCastException if the value is not assignable to the expected value class.
* @throws InvalidPropertyValueException if the given value is not valid for a reason other than its type.
@@ -427,9 +468,9 @@ public abstract class AbstractFeature im
* the same class. Since the type check has already been done by the previous assignation, we do not
* need to perform it again.
*
- * @param previous The previous value, or {@code null}.
- * @param value The new value, or {@code null}.
- * @return {@code true} if the caller can skip the verification performed by {@code verifyPropertyValue}.
+ * @param previous the previous value, or {@code null}.
+ * @param value the new value, or {@code null}.
+ * @return {@code true} if the caller can skip the verification performed by {@code verifyPropertyValue}.
*/
static boolean canSkipVerification(final Object previous, final Object value) {
if (previous != null) {
@@ -446,8 +487,8 @@ public abstract class AbstractFeature im
/**
* Verifies if the given property can be assigned to this feature.
*
- * @param name Shall be {@code property.getName().toString()}.
- * @param property The property to verify.
+ * @param name shall be {@code property.getName().toString()}.
+ * @param property the property to verify.
*/
final void verifyPropertyType(final String name, final Property property) {
final PropertyType pt, base = type.getProperty(name);
@@ -495,7 +536,7 @@ public abstract class AbstractFeature im
* <li>May be a collection, in which case the class each elements in the collection is verified.</li>
* </ul>
*
- * @param value The value, which shall be non-null.
+ * @param value the value, which shall be non-null.
*/
private static <T> Object verifyAttributeValue(final AttributeType<T> type, final Object value) {
final Class<T> valueClass = type.getValueClass();
@@ -517,7 +558,7 @@ public abstract class AbstractFeature im
* <li>May be a collection, in which case the class each elements in the collection is verified.</li>
* </ul>
*
- * @param value The value, which shall be non-null.
+ * @param value the value, which shall be non-null.
*/
private static Object verifyAssociationValue(final FeatureAssociationRole role, final Object value) {
final boolean isSingleton = Field.isSingleton(role.getMaximumOccurs());
@@ -639,7 +680,7 @@ public abstract class AbstractFeature im
* }
* </div>
*
- * @return Reports on all constraint violations found.
+ * @return reports on all constraint violations found.
*
* @see AbstractAttribute#quality()
* @see AbstractAssociation#quality()
@@ -653,7 +694,7 @@ public abstract class AbstractFeature im
/**
* Formats this feature in a tabular format.
*
- * @return A string representation of this feature in a tabular format.
+ * @return a string representation of this feature in a tabular format.
*
* @see FeatureFormat
*/
@@ -661,4 +702,82 @@ public abstract class AbstractFeature im
public String toString() {
return FeatureFormat.sharedFormat(this);
}
+
+ /**
+ * Returns a hash code value for this feature.
+ * The default implementation performs the following algorithm:
+ *
+ * <ul>
+ * <li>Iterate over all properties returned by {@code type.getProperty(true)} \u2013
+ * thus including properties inherited from parent types (if any):
+ * <ul>
+ * <li>For each property type, get the value with {@link #getPropertyValue(String)}.</li>
+ * <li>Compute the hash code from the property name and value, ignoring the properties
+ * having a null value.</li>
+ * </ul></li>
+ * </ul>
+ *
+ * Subclasses should override this method with a more efficient algorithm for their internal structure.
+ * There is no need to reproduce the same hash code value than the one computed by this default method.
+ *
+ * @return a hash code value.
+ *
+ * @since 0.8
+ */
+ @Override
+ public int hashCode() {
+ int code = type.hashCode() * 37;
+ for (final PropertyType pt : type.getProperties(true)) {
+ final String name = pt.getName().toString();
+ if (name != null) { // Paranoiac check.
+ final Object value = getPropertyValue(name);
+ if (value != null) {
+ code += name.hashCode() ^ value.hashCode();
+ }
+ }
+ }
+ return code;
+ }
+
+ /**
+ * Compares this feature with the given object for equality.
+ * The default implementation performs the following algorithm:
+ *
+ * <ul>
+ * <li>Verify that both objects are non-null and of the same class.</li>
+ * <li>Iterate over all properties returned by {@code type.getProperty(true)} \u2013
+ * thus including properties inherited from parent types (if any):
+ * <ul>
+ * <li>For each property type, get the value from both {@code FeatureType}
+ * by a call to {@link #getPropertyValue(String)}.</li>
+ * <li>Verify that the two values are either both null, or equal in the sense of
+ * {@link Object#equals(Object)}.</li>
+ * </ul></li>
+ * </ul>
+ *
+ * Subclasses should override this method with a more efficient algorithm for their internal structure.
+ *
+ * @return {@code true} if both objects are equal.
+ *
+ * @since 0.8
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj != this) {
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+ final AbstractFeature that = (AbstractFeature) obj;
+ if (!type.equals(that.type)) {
+ return false;
+ }
+ for (final PropertyType pt : type.getProperties(true)) {
+ final String name = pt.getName().toString();
+ if (!Objects.equals(getPropertyValue(name), that.getPropertyValue(name))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
}
Added: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java?rev=1754559&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java (added)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -0,0 +1,142 @@
+/*
+ * 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 java.util.Collection;
+import org.opengis.util.GenericName;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureAssociation;
+import org.opengis.feature.FeatureAssociationRole;
+
+
+/**
+ * An association implementation which delegate its work to the parent feature.
+ * This class is used for default implementation of {@link AbstractFeature#getProperty(String)}.
+ *
+ * <p><strong>This implementation is inefficient!</strong>
+ * This class is for making easier to begin with a custom {@link AbstractFeature} implementation,
+ * but developers are encouraged to provide their own {@link AbstractFeature#getProperty(String)}
+ * implementation.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ */
+class AssociationView extends PropertyView<Feature> implements FeatureAssociation {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -148100967531766909L;
+
+ /**
+ * The role of this association. Must be one of the properties listed in the {@link #feature}.
+ */
+ private final FeatureAssociationRole role;
+
+ /**
+ * Creates a new association which will delegate its work to the given feature.
+ */
+ private AssociationView(final Feature feature, final FeatureAssociationRole role) {
+ super(feature, role.getName().toString());
+ this.role = role;
+ }
+
+ /**
+ * Creates a new association which will delegate its work to the given feature.
+ *
+ * @param feature the feature from which to read and where to write the association value.
+ * @param role the role of this association. Must be one of the properties listed in the
+ * {@link #feature} (this is not verified by this constructor).
+ */
+ static FeatureAssociation create(final Feature feature, final FeatureAssociationRole role) {
+ if (isSingleton(role.getMaximumOccurs())) {
+ return new Singleton(feature, role);
+ } else {
+ return new AssociationView(feature, role);
+ }
+ }
+
+ /**
+ * Returns the name of the role specified at construction time.
+ */
+ @Override
+ public final GenericName getName() {
+ return role.getName();
+ }
+
+ /**
+ * Returns the role specified at construction time.
+ */
+ @Override
+ public final FeatureAssociationRole getRole() {
+ return role;
+ }
+
+ /**
+ * Returns the class of values.
+ */
+ @Override
+ final Class<Feature> getValueClass() {
+ return Feature.class;
+ }
+
+ /**
+ * Specialization of {@code AssociationView} when the amount of values can be only zero or one.
+ * This implementation takes shortcuts for the {@code getValue()} and {@code getValues()} methods.
+ * This specialization is provided because it is the most common case.
+ */
+ private static final class Singleton extends AssociationView {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 2574475751526292380L;
+
+ /**
+ * Creates a new association which will delegate its work to the given feature.
+ */
+ Singleton(final Feature feature, final FeatureAssociationRole role) {
+ super(feature, role);
+ }
+
+ /**
+ * Returns the single value, or {@code null} if none.
+ */
+ @Override
+ public Feature getValue() {
+ return (Feature) this.feature.getPropertyValue(this.name);
+ }
+
+ /**
+ * Sets the value of this association. This method assumes that the
+ * {@link Feature#setPropertyValue(String, Object)} implementation
+ * will verify the argument type.
+ */
+ @Override
+ public void setValue(final Feature value) {
+ this.feature.setPropertyValue(this.name, value);
+ }
+
+ /**
+ * Wraps the property value in a set.
+ */
+ @Override
+ public Collection<Feature> getValues() {
+ return singletonOrEmpty(getValue());
+ }
+ }
+}
Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AssociationView.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Added: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java?rev=1754559&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java (added)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -0,0 +1,152 @@
+/*
+ * 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 java.util.Map;
+import java.util.Collection;
+import java.util.Collections;
+import org.opengis.util.GenericName;
+import org.opengis.feature.Feature;
+import org.opengis.feature.Attribute;
+import org.opengis.feature.AttributeType;
+
+
+/**
+ * An attribute implementation which delegate its work to the parent feature.
+ * This class is used for default implementation of {@link AbstractFeature#getProperty(String)}.
+ *
+ * <p><strong>This implementation is inefficient!</strong>
+ * This class is for making easier to begin with a custom {@link AbstractFeature} implementation,
+ * but developers are encouraged to provide their own {@link AbstractFeature#getProperty(String)}
+ * implementation.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ */
+class AttributeView<V> extends PropertyView<V> implements Attribute<V> {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 3617999929561826634L;
+
+ /**
+ * The type of this attribute. Must be one of the properties listed in the {@link #feature}.
+ */
+ final AttributeType<V> type;
+
+ /**
+ * Creates a new attribute which will delegate its work to the given feature.
+ */
+ private AttributeView(final Feature feature, final AttributeType<V> type) {
+ super(feature, type.getName().toString());
+ this.type = type;
+ }
+
+ /**
+ * Creates a new attribute which will delegate its work to the given feature.
+ *
+ * @param feature the feature from which to read and where to write the attribute value.
+ * @param type the type of this attribute. Must be one of the properties listed in the
+ * {@link #feature} (this is not verified by this constructor).
+ */
+ static <V> Attribute<V> create(final Feature feature, final AttributeType<V> type) {
+ if (isSingleton(type.getMaximumOccurs())) {
+ return new Singleton<>(feature, type);
+ } else {
+ return new AttributeView<>(feature, type);
+ }
+ }
+
+ /**
+ * Returns the name of the type specified at construction time.
+ */
+ @Override
+ public final GenericName getName() {
+ return type.getName();
+ }
+
+ /**
+ * Returns the type specified at construction time.
+ */
+ @Override
+ public final AttributeType<V> getType() {
+ return type;
+ }
+
+ /**
+ * Returns the class of values.
+ */
+ @Override
+ final Class<V> getValueClass() {
+ return type.getValueClass();
+ }
+
+ /**
+ * Returns an empty map since this simple view does not support characteristics.
+ */
+ @Override
+ public final Map<String,Attribute<?>> characteristics() {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Specialization of {@code AttributeView} when the amount of values can be only zero or one.
+ * This implementation takes shortcuts for the {@code getValue()} and {@code getValues()} methods.
+ * This specialization is provided because it is the most common case.
+ */
+ private static final class Singleton<V> extends AttributeView<V> {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -808239726590009163L;
+
+ /**
+ * Creates a new attribute which will delegate its work to the given feature.
+ */
+ Singleton(final Feature feature, final AttributeType<V> type) {
+ super(feature, type);
+ }
+
+ /**
+ * Returns the single value, or {@code null} if none.
+ */
+ @Override
+ public V getValue() {
+ return this.type.getValueClass().cast(this.feature.getPropertyValue(this.name));
+ }
+
+ /**
+ * Sets the value of this attribute. This method assumes that the
+ * {@link Feature#setPropertyValue(String, Object)} implementation
+ * will verify the argument type.
+ */
+ @Override
+ public void setValue(final V value) {
+ this.feature.setPropertyValue(this.name, value);
+ }
+
+ /**
+ * Wraps the property value in a set.
+ */
+ @Override
+ public Collection<V> getValues() {
+ return singletonOrEmpty(getValue());
+ }
+ }
+}
Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AttributeView.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
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=1754559&r1=1754558&r2=1754559&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] Fri Jul 29 17:53:09 2016
@@ -116,11 +116,11 @@ public class DefaultAssociationRole exte
* </tr>
* </table>
*
- * @param identification The name and other information to be given to this association role.
- * @param valueType The type of feature values.
- * @param minimumOccurs The minimum number of occurrences of the association within its containing entity.
- * @param maximumOccurs The maximum number of occurrences of the association within its containing entity,
- * or {@link Integer#MAX_VALUE} if there is no restriction.
+ * @param identification the name and other information to be given to this association role.
+ * @param valueType the type of feature values.
+ * @param minimumOccurs the minimum number of occurrences of the association within its containing entity.
+ * @param maximumOccurs the maximum number of occurrences of the association within its containing entity,
+ * or {@link Integer#MAX_VALUE} if there is no restriction.
*
* @see org.apache.sis.feature.builder.AssociationRoleBuilder
*/
@@ -162,11 +162,11 @@ public class DefaultAssociationRole exte
* If more than one {@code FeatureType} instance of the given name is found at resolution time, the selected one
* is undetermined.
*
- * @param identification The name and other information to be given to this association role.
- * @param valueType The name of the type of feature values.
- * @param minimumOccurs The minimum number of occurrences of the association within its containing entity.
- * @param maximumOccurs The maximum number of occurrences of the association within its containing entity,
- * or {@link Integer#MAX_VALUE} if there is no restriction.
+ * @param identification the name and other information to be given to this association role.
+ * @param valueType the name of the type of feature values.
+ * @param minimumOccurs the minimum number of occurrences of the association within its containing entity.
+ * @param maximumOccurs the maximum number of occurrences of the association within its containing entity,
+ * or {@link Integer#MAX_VALUE} if there is no restriction.
*/
public DefaultAssociationRole(final Map<String,?> identification, final GenericName valueType,
final int minimumOccurs, final int maximumOccurs)
@@ -184,7 +184,7 @@ public class DefaultAssociationRole exte
* to feature <var>B</var> which has an association back to <var>A</var>. It may also be <var>A</var>
* having an association to itself, <i>etc.</i>
*
- * @param creating The feature type in process of being constructed.
+ * @param creating the feature type in process of being constructed.
* @return {@code true} if this association references a resolved feature type after this method call.
*/
final boolean resolve(final DefaultFeatureType creating) {
@@ -225,10 +225,10 @@ public class DefaultAssociationRole exte
* <p>Current implementation does not check that there is no duplicated names.
* See {@link #deepSearch(List, GenericName)} for a rational.</p>
*
- * @param feature The feature in which to search.
- * @param name The name of the feature to search.
- * @param deferred Where to store {@code FeatureType}s to be eventually used for a deep search.
- * @return The feature of the given name, or {@code null} if none.
+ * @param feature the feature in which to search.
+ * @param name the name of the feature to search.
+ * @param deferred where to store {@code FeatureType}s to be eventually used for a deep search.
+ * @return the feature of the given name, or {@code null} if none.
*/
@SuppressWarnings("null")
private static FeatureType search(final FeatureType feature, final GenericName name, final List<FeatureType> deferred) {
@@ -281,10 +281,10 @@ public class DefaultAssociationRole exte
* later. We rather put a warning in {@link #DefaultAssociationRole(Map, GenericName, int, int)}
* javadoc.</p>
*
- * @param feature The feature in which to search.
- * @param name The name of the feature to search.
- * @param done The feature types collected by {@link #search(FeatureType, GenericName, List)}.
- * @return The feature of the given name, or {@code null} if none.
+ * @param feature the feature in which to search.
+ * @param name the name of the feature to search.
+ * @param done the feature types collected by {@link #search(FeatureType, GenericName, List)}.
+ * @return the feature of the given name, or {@code null} if none.
*/
private static FeatureType deepSearch(final List<FeatureType> deferred, final GenericName name) {
final Map<FeatureType,Boolean> done = new IdentityHashMap<>(8);
@@ -305,7 +305,7 @@ public class DefaultAssociationRole exte
/**
* Returns the type of feature values.
*
- * @return The type of feature values.
+ * @return the type of feature values.
* @throws IllegalStateException if the feature type has been specified
* {@linkplain #DefaultAssociationRole(Map, GenericName, int, int) only by its name}
* and not yet resolved.
@@ -369,7 +369,7 @@ public class DefaultAssociationRole exte
* Returns the minimum number of occurrences of the association within its containing entity.
* The returned value is greater than or equal to zero.
*
- * @return The minimum number of occurrences of the association within its containing entity.
+ * @return the minimum number of occurrences of the association within its containing entity.
*/
@Override
public final int getMinimumOccurs() {
@@ -381,7 +381,7 @@ public class DefaultAssociationRole exte
* The returned value is greater than or equal to the {@link #getMinimumOccurs()} value.
* If there is no maximum, then this method returns {@link Integer#MAX_VALUE}.
*
- * @return The maximum number of occurrences of the association within its containing entity,
+ * @return the maximum number of occurrences of the association within its containing entity,
* or {@link Integer#MAX_VALUE} if none.
*/
@Override
@@ -392,7 +392,7 @@ public class DefaultAssociationRole exte
/**
* Creates a new association instance of this role.
*
- * @return A new association instance.
+ * @return a new association instance.
*
* @see AbstractAssociation#create(FeatureAssociationRole)
*/
@@ -437,11 +437,11 @@ public class DefaultAssociationRole exte
* Returns a string representation of this association role.
* The returned string is for debugging purpose and may change in any future SIS version.
*
- * @return A string representation of this association role for debugging purpose.
+ * @return a string representation of this association role for debugging purpose.
*/
@Debug
@Override
public String toString() {
- return toString("FeatureAssociationRole", this, valueType.getName()).toString();
+ return toString("FeatureAssociationRole", getName(), valueType.getName()).toString();
}
}
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java?rev=1754559&r1=1754558&r2=1754559&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAttributeType.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -167,16 +167,16 @@ public class DefaultAttributeType<V> ext
* </tr>
* </table>
*
- * @param identification The name and other information to be given to this attribute type.
- * @param valueClass The type of attribute values.
- * @param minimumOccurs The minimum number of occurrences of the attribute within its containing entity.
- * @param maximumOccurs The maximum number of occurrences of the attribute within its containing entity,
- * or {@link Integer#MAX_VALUE} if there is no restriction.
- * @param defaultValue The default value for the attribute, or {@code null} if none.
- * @param characterizedBy Other attribute types that describes this attribute type (can be {@code null} for none).
- * For example if this new {@code DefaultAttributeType} describes a measurement,
- * then {@code characterizedBy} could holds the measurement accuracy.
- * See <cite>"Attribute characterization"</cite> in class Javadoc for more information.
+ * @param identification the name and other information to be given to this attribute type.
+ * @param valueClass the type of attribute values.
+ * @param minimumOccurs the minimum number of occurrences of the attribute within its containing entity.
+ * @param maximumOccurs the maximum number of occurrences of the attribute within its containing entity,
+ * or {@link Integer#MAX_VALUE} if there is no restriction.
+ * @param defaultValue the default value for the attribute, or {@code null} if none.
+ * @param characterizedBy other attribute types that describes this attribute type (can be {@code null} for none).
+ * For example if this new {@code DefaultAttributeType} describes a measurement,
+ * then {@code characterizedBy} could holds the measurement accuracy.
+ * See <cite>"Attribute characterization"</cite> in class Javadoc for more information.
*
* @see org.apache.sis.feature.builder.AttributeTypeBuilder
*/
@@ -208,9 +208,9 @@ public class DefaultAttributeType<V> ext
/**
* Invoked on deserialization for restoring the {@link #characteristics} field.
*
- * @param in The input stream from which to deserialize an attribute type.
- * @throws IOException If an I/O error occurred while reading or if the stream contains invalid data.
- * @throws ClassNotFoundException If the class serialized on the stream is not on the classpath.
+ * @param in the input stream from which to deserialize an attribute type.
+ * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
+ * @throws ClassNotFoundException if the class serialized on the stream is not on the classpath.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
@@ -227,7 +227,7 @@ public class DefaultAttributeType<V> ext
/**
* Returns the type of attribute values.
*
- * @return The type of attribute values.
+ * @return the type of attribute values.
*/
@Override
public final Class<V> getValueClass() {
@@ -253,7 +253,7 @@ public class DefaultAttributeType<V> ext
* <p>To be valid, an {@code Attribute} instance of this {@code AttributeType} shall have at least
* this minimum number of elements in its {@link AbstractAttribute#getValues() collection of values}.</p>
*
- * @return The minimum number of attribute values.
+ * @return the minimum number of attribute values.
*/
@Override
public final int getMinimumOccurs() {
@@ -268,7 +268,7 @@ public class DefaultAttributeType<V> ext
* <p>To be valid, an {@code Attribute} instance of this {@code AttributeType} shall have no more than
* this maximum number of elements in its {@link AbstractAttribute#getValues() collection of values}.</p>
*
- * @return The maximum number of attribute values, or {@link Integer#MAX_VALUE} if none.
+ * @return the maximum number of attribute values, or {@link Integer#MAX_VALUE} if none.
*/
@Override
public final int getMaximumOccurs() {
@@ -279,7 +279,7 @@ public class DefaultAttributeType<V> ext
* Returns the default value for the attribute.
* This value is used when an attribute is created and no value for it is specified.
*
- * @return The default value for the attribute, or {@code null} if none.
+ * @return the default value for the attribute, or {@code null} if none.
*/
@Override
public V getDefaultValue() {
@@ -301,7 +301,7 @@ public class DefaultAttributeType<V> ext
* The {@linkplain Map#keySet() map keys} are the {@code String} representations
* of characteristics {@linkplain #getName() name}, for more convenient lookups.
*
- * @return Other attribute types that describes this attribute type, or an empty map if none.
+ * @return other attribute types that describes this attribute type, or an empty map if none.
*
* @see AbstractAttribute#characteristics()
*/
@@ -313,7 +313,7 @@ public class DefaultAttributeType<V> ext
/**
* Creates a new attribute instance of this type initialized to the {@linkplain #getDefaultValue() default value}.
*
- * @return A new attribute instance.
+ * @return a new attribute instance.
*
* @see AbstractAttribute#create(AttributeType)
*/
@@ -356,11 +356,11 @@ public class DefaultAttributeType<V> ext
* Returns a string representation of this attribute type.
* The returned string is for debugging purpose and may change in any future SIS version.
*
- * @return A string representation of this attribute type for debugging purpose.
+ * @return a string representation of this attribute type for debugging purpose.
*/
@Debug
@Override
public String toString() {
- return toString("AttributeType", this, Classes.getShortName(valueClass)).toString();
+ return toString("AttributeType", getName(), Classes.getShortName(valueClass)).toString();
}
}
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java?rev=1754559&r1=1754558&r2=1754559&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FieldType.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -36,7 +36,7 @@ import org.opengis.feature.PropertyType;
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.5
+ * @version 0.8
* @module
*/
abstract class FieldType extends AbstractIdentifiedType implements PropertyType {
@@ -60,10 +60,10 @@ abstract class FieldType extends Abstrac
* Constructs a field type from the given properties. The identification map is given unchanged to
* the {@linkplain AbstractIdentifiedType#AbstractIdentifiedType(Map) super-class constructor}.
*
- * @param identification The name and other information to be given to this field type.
- * @param minimumOccurs The minimum number of occurrences of the property within its containing entity.
- * @param maximumOccurs The maximum number of occurrences of the property within its containing entity,
- * or {@link Integer#MAX_VALUE} if there is no restriction.
+ * @param identification the name and other information to be given to this field type.
+ * @param minimumOccurs the minimum number of occurrences of the property within its containing entity.
+ * @param maximumOccurs the maximum number of occurrences of the property within its containing entity,
+ * or {@link Integer#MAX_VALUE} if there is no restriction.
*/
FieldType(final Map<String,?> identification, final int minimumOccurs, final int maximumOccurs) {
super(identification);
@@ -79,7 +79,7 @@ abstract class FieldType extends Abstrac
* Returns the minimum number of occurrences of the property within its containing entity.
* The returned value is greater than or equal to zero.
*
- * @return The minimum number of occurrences of the property within its containing entity.
+ * @return the minimum number of occurrences of the property within its containing entity.
*/
public int getMinimumOccurs() {
return minimumOccurs;
@@ -90,7 +90,7 @@ abstract class FieldType extends Abstrac
* The returned value is greater than or equal to the {@link #getMinimumOccurs()} value.
* If there is no maximum, then this method returns {@link Integer#MAX_VALUE}.
*
- * @return The maximum number of occurrences of the property within its containing entity,
+ * @return the maximum number of occurrences of the property within its containing entity,
* or {@link Integer#MAX_VALUE} if none.
*/
public int getMaximumOccurs() {
@@ -130,13 +130,12 @@ abstract class FieldType extends Abstrac
* PropertyType[\u201cname\u201d : ValueClass]
* }
*
- * @param className The interface name of the object on which {@code toString()} is invoked.
- * @param type The property type, sometime {@code this} or sometime an other object.
- * @param valueType The name of value class (attribute), or the feature type name (association).
+ * @param className the interface name of the object on which {@code toString()} is invoked.
+ * @param name the property type name, sometime {@link #getName()} or sometime the name of another object.
+ * @param valueType the name of value class (attribute), or the feature type name (association).
*/
- static StringBuilder toString(final String className, final PropertyType type, final Object valueType) {
+ static StringBuilder toString(final String className, final GenericName name, final Object valueType) {
final StringBuilder buffer = new StringBuilder(40).append(className).append('[');
- final GenericName name = type.getName();
if (name != null) {
buffer.append('\u201c');
}
@@ -155,13 +154,13 @@ abstract class FieldType extends Abstrac
* Property[\u201cname\u201d : ValueClass] = {value1, value2, ...}
* }
*
- * @param className The interface name of the object on which {@code toString()} is invoked.
- * @param type The property type associated to the object to format.
- * @param valueType The name of value class (attribute), or the feature type name (association).
- * @param values The actual values.
+ * @param className the interface name of the object on which {@code toString()} is invoked.
+ * @param name the property type name, sometime {@link #getName()} or sometime the name of another object.
+ * @param valueType the name of value class (attribute), or the feature type name (association).
+ * @param values the actual values.
*/
- static StringBuilder toString(final String className, final PropertyType type, final Object valueType, final Iterator<?> values) {
- final StringBuilder buffer = toString(className, type, valueType);
+ static StringBuilder toString(final String className, final GenericName name, final Object valueType, final Iterator<?> values) {
+ final StringBuilder buffer = toString(className, name, valueType);
if (values.hasNext()) {
final Object value = values.next();
final boolean isMultiValued = values.hasNext();
Added: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java?rev=1754559&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java (added)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -0,0 +1,215 @@
+/*
+ * 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 java.util.List;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.Collections;
+import java.io.Serializable;
+import org.apache.sis.util.collection.CheckedContainer;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.Debug;
+
+// Branch-dependent imports
+import java.util.Objects;
+import org.opengis.feature.Feature;
+import org.opengis.feature.Property;
+import org.opengis.feature.Operation;
+import org.opengis.feature.PropertyType;
+import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureAssociationRole;
+import org.opengis.feature.MultiValuedPropertyException;
+
+
+/**
+ * An attribute or association implementation which delegate its work to the parent feature.
+ * This class is used for default implementation of {@link AbstractFeature#getProperty(String)}.
+ *
+ * <p><strong>This implementation is inefficient!</strong>
+ * This class is for making easier to begin with a custom {@link AbstractFeature} implementation,
+ * but developers are encouraged to provide their own {@link AbstractFeature#getProperty(String)}
+ * implementation.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ */
+abstract class PropertyView<V> extends Field<V> implements Property, Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -5605415150581699255L;
+
+ /**
+ * The feature from which to read and where to write the attribute or association value.
+ */
+ final Feature feature;
+
+ /**
+ * The string representation of the property name. This is the value to be given in calls to
+ * {@link Feature#getPropertyValue(String)} and {@link Feature#setPropertyValue(String, Object)}.
+ */
+ final String name;
+
+ /**
+ * Creates a new property which will delegate its work to the given feature.
+ *
+ * @param feature the feature from which to read and where to write the property value.
+ * @param name the string representation of the property name.
+ */
+ PropertyView(final Feature feature, final String name) {
+ this.feature = feature;
+ this.name = name;
+ }
+
+ /**
+ * Creates a new property which will delegate its work to the given feature.
+ *
+ * @param feature the feature from which to read and where to write the property value.
+ * @param type the type of the property. Must be one of the properties listed in the
+ * {@code feature} (this is not verified by this constructor).
+ */
+ static Property create(final Feature feature, final PropertyType type) {
+ if (type instanceof AttributeType<?>) {
+ return AttributeView.create(feature, (AttributeType<?>) type);
+ } else if (type instanceof FeatureAssociationRole) {
+ return AssociationView.create(feature, (FeatureAssociationRole) type);
+ } else if (type instanceof Operation) {
+ return ((Operation) type).apply(feature, null);
+ } else {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1, Classes.getClass(type)));
+ }
+ }
+
+ /**
+ * Returns the class of values.
+ */
+ abstract Class<V> getValueClass();
+
+ /**
+ * Returns the singleton value. This default implementation assumes that the property is multi-valued
+ * (single-valued properties shall override this method), but we nevertheless provide a fallback for
+ * non-{@code Iterable} values as a safety against implementations that are not strictly compliant
+ * to our {@link Feature#getPropertyValue(String)} method contract. Then this method verifies that
+ * the value is a collection containing zero or one element and returns that element or {@code null}.
+ */
+ @Override
+ public V getValue() throws MultiValuedPropertyException {
+ Object value = feature.getPropertyValue(name);
+ if (value instanceof Iterable<?>) {
+ final Iterator<?> it = ((Iterable<?>) value).iterator();
+ if (!it.hasNext()) {
+ return null;
+ }
+ value = it.next();
+ if (it.hasNext()) {
+ throw new MultiValuedPropertyException(Errors.format(Errors.Keys.NotASingleton_1, name));
+ }
+ }
+ return getValueClass().cast(value);
+ }
+
+ /**
+ * Sets the values of the given attribute. This default implementation assumes that the property
+ * is multi-valued (single-valued properties shall override this method) and that the
+ * {@link Feature#setPropertyValue(String, Object)} implementation will verify the argument type.
+ */
+ @Override
+ public void setValue(final V value) {
+ feature.setPropertyValue(name, singletonOrEmpty(value));
+ }
+
+ /**
+ * Returns the given value as a singleton if non-null, or returns an empty list otherwise.
+ *
+ * @param <V> the element type.
+ * @param element the element to returns in a collection if non-null.
+ * @return a collection containing the given element if non-null, or an empty collection otherwise.
+ */
+ static <V> List<V> singletonOrEmpty(final V element) {
+ return (element != null) ? Collections.singletonList(element) : Collections.emptyList();
+ }
+
+ /**
+ * Returns the values as a collection. This method tries to verify that the collection
+ * contains elements of the expected type, but this verification is not always possible.
+ * Consequently this method may, sometime, be actually unsafe.
+ */
+ @Override
+ @SuppressWarnings("unchecked") // Actually not 100% safe, but we have done our best.
+ public Collection<V> getValues() {
+ final Object values = feature.getPropertyValue(name);
+ if (values instanceof Collection<?>) {
+ if (values instanceof CheckedContainer<?>) {
+ final Class<?> expected = getValueClass();
+ final Class<?> actual = ((CheckedContainer<?>) values).getElementType();
+ if (expected != actual) { // Really exact match, not Class.isAssignableFrom(Class).
+ throw new ClassCastException(Errors.format(Errors.Keys.UnexpectedTypeForReference_3, name, expected, actual));
+ }
+ }
+ return (Collection<V>) values;
+ } else {
+ return singletonOrEmpty(getValueClass().cast(values));
+ }
+ }
+
+ /**
+ * Sets the values of the given attribute. This method assumes that the
+ * {@link Feature#setPropertyValue(String, Object)} implementation will
+ * verify the argument type.
+ */
+ @Override
+ public final void setValues(final Collection<? extends V> values) {
+ feature.setPropertyValue(name, values);
+ }
+
+ /**
+ * Returns a hash code value for this property.
+ */
+ @Override
+ public final int hashCode() {
+ return Objects.hashCode(name) ^ System.identityHashCode(feature);
+ }
+
+ /**
+ * Compares this attribute with the given object for equality.
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj != null && obj.getClass() == getClass()) {
+ final PropertyView<?> that = (PropertyView<?>) obj;
+ return feature == that.feature && Objects.equals(name, that.name);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a string representation of this property for debugging purposes.
+ */
+ @Debug
+ @Override
+ public final String toString() {
+ return FieldType.toString(getClass().getSimpleName(), getName(),
+ Classes.getShortName(getValueClass()), getValues().iterator()).toString();
+ }
+}
Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/PropertyView.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java?rev=1754559&r1=1754558&r2=1754559&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -82,10 +82,10 @@ final class Validator {
* We are not strictly forbidden to use the same identifier for both the quality measurement than the measurement
* itself. However strictly speaking, maybe we should use a different scope.</div>
*
- * @param report Where to add the result, or {@code null} if not yet created.
- * @param type Description of the property for which a constraint violation has been found.
- * @param explanation Explanation of the constraint violation.
- * @return The {@code report}, or a new report if {@code report} was null.
+ * @param report where to add the result, or {@code null} if not yet created.
+ * @param type description of the property for which a constraint violation has been found.
+ * @param explanation explanation of the constraint violation.
+ * @return the {@code report}, or a new report if {@code report} was null.
*/
private AbstractElement addViolationReport(AbstractElement report,
final PropertyType type, final InternationalString explanation)
@@ -128,10 +128,10 @@ final class Validator {
} else if (property instanceof AbstractAssociation) {
pq = ((AbstractAssociation) property).quality();
} else if (property instanceof Attribute<?>) {
- validateAny(((Attribute<?>) property).getType(), ((Attribute<?>) property).getValues());
+ validate(((Attribute<?>) property).getType(), ((Attribute<?>) property).getValues());
continue;
} else if (property instanceof FeatureAssociation) {
- validateAny(((FeatureAssociation) property).getRole(), ((FeatureAssociation) property).getValues());
+ validate(((FeatureAssociation) property).getRole(), ((FeatureAssociation) property).getValues());
continue;
} else {
continue;
@@ -202,7 +202,7 @@ final class Validator {
/**
* Verifies if the given value mets the cardinality constraint.
*
- * @param report Where to add the result, or {@code null} if not yet created.
+ * @param report where to add the result, or {@code null} if not yet created.
*/
private void verifyCardinality(final AbstractElement report, final PropertyType type,
final int minimumOccurs, final int maximumOccurs, final int count)
Added: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java?rev=1754559&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java (added)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -0,0 +1,163 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.sis.test.DependsOn;
+
+import static org.apache.sis.test.Assert.*;
+
+// Branch-dependent imports
+import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureType;
+import org.opengis.feature.Property;
+import org.opengis.feature.PropertyType;
+
+
+/**
+ * Tests some default method implementations provided in {@link AbstractFeature}.
+ * This test also has the side-effect of testing {@link Validator} with attribute
+ * instances that are not {@link AbstractAttribute}.
+ *
+ * <p>This class inherits all tests defined in {@link FeatureTestCase}.</p>
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ */
+@DependsOn({
+ DenseFeatureTest.class,
+ SparseFeatureTest.class
+})
+public final strictfp class AbstractFeatureTest extends FeatureTestCase {
+ /**
+ * A minimalist feature implementation on top of {@link AbstractFeature}. In order to get the tests to pass,
+ * we need to reproduce in this class some of the verifications performed by the more sophisticated
+ * {@link SingletonAttribute} and {@link MultiValuedAttribute} implementations.
+ * However other developers that provide their own implementations may not perform all those checks.
+ */
+ @SuppressWarnings("serial")
+ private static final class CustomFeature extends AbstractFeature implements Cloneable {
+ /**
+ * All property values.
+ */
+ private HashMap<String,Object> values = new HashMap<>();
+
+ /**
+ * Creates a new feature of the given type.
+ */
+ CustomFeature(final DefaultFeatureType type) {
+ super(type);
+ for (final PropertyType pt : type.getProperties(true)) {
+ if (pt instanceof AttributeType<?>) {
+ Object value = ((AttributeType<?>) pt).getDefaultValue();
+ if (isMultiValued(pt)) {
+ value = new ArrayList<>(PropertyView.singletonOrEmpty(value));
+ }
+ if (value != null) {
+ values.put(pt.getName().toString(), value);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns {@code true} if the given property can contains more than one value.
+ */
+ private static boolean isMultiValued(final PropertyType pt) {
+ return (pt instanceof AttributeType<?>) && (((AttributeType<?>) pt).getMaximumOccurs() > 1);
+ }
+
+ @Override
+ public Object getPropertyValue(final String name) {
+ return values.get(name);
+ }
+
+ @Override
+ public void setPropertyValue(final String name, Object value) {
+ final PropertyType type = getType().getProperty(name);
+ final boolean isMultiValued = isMultiValued(type);
+ if (isMultiValued && !(value instanceof Collection<?>)) {
+ value = new ArrayList<>(PropertyView.singletonOrEmpty(value));
+ }
+ if (value != null) {
+ final Class<?> base;
+ if (type instanceof AttributeType<?>) {
+ base = ((AttributeType<?>) type).getValueClass();
+ } else {
+ base = FeatureType.class;
+ }
+ for (final Object element : (isMultiValued ? (Iterable<?>) value : PropertyView.singletonOrEmpty(value))) {
+ if (!base.isInstance(element)) {
+ throw new ClassCastException("Can not cast " + value.getClass() + " to " + base + " in " + name + '.');
+ }
+ }
+ }
+ values.put(name, value);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public CustomFeature clone() {
+ final CustomFeature c;
+ try {
+ c = (CustomFeature) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ c.values = (HashMap<String,Object>) c.values.clone();
+ return c;
+ }
+ }
+
+ /**
+ * Relax the requirements about {@link AbstractFeature#getProperty(String)} to return the exact same instance.
+ */
+ @Override
+ boolean assertSameProperty(final String name, final Property expected, final boolean modified) {
+ final Property actual = feature.getProperty(name);
+ if ((expected instanceof PropertyView) == (actual instanceof PropertyView)) {
+ assertEquals(name, expected, actual);
+ }
+ assertSame("name", expected.getName(), actual.getName());
+ if (!modified) {
+ assertSame("value", expected.getValue(), actual.getValue());
+ }
+ return actual == expected;
+ }
+
+ /**
+ * Creates a new feature for the given type.
+ */
+ @Override
+ final AbstractFeature createFeature(final DefaultFeatureType type) {
+ return new CustomFeature(type);
+ }
+
+ /**
+ * Clones the {@link #feature} instance.
+ */
+ @Override
+ final AbstractFeature cloneFeature() throws CloneNotSupportedException {
+ return ((CustomFeature) feature).clone();
+ }
+
+ // Inherit all tests from the super-class.
+}
Propchange: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractFeatureTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
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=1754559&r1=1754558&r2=1754559&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] Fri Jul 29 17:53:09 2016
@@ -31,6 +31,10 @@ import org.junit.Test;
import static org.apache.sis.test.Assert.*;
+// Branch-dependent imports
+import org.opengis.feature.Attribute;
+import org.opengis.feature.Property;
+
/**
* Tests common to {@link DenseFeatureTest} and {@link SparseFeatureTest}.
@@ -38,7 +42,7 @@ import static org.apache.sis.test.Assert
* @author Martin Desruisseaux (Geomatys)
* @author Marc le Bihan
* @since 0.5
- * @version 0.6
+ * @version 0.8
* @module
*/
public abstract strictfp class FeatureTestCase extends TestCase {
@@ -70,12 +74,27 @@ public abstract strictfp class FeatureTe
abstract AbstractFeature cloneFeature() throws CloneNotSupportedException;
/**
+ * Asserts that {@link AbstractFeature#getProperty(String)} returns the given instance.
+ * This method is overridden in subclasses than need to relax this check.
+ *
+ * @param name the property name to check.
+ * @param expected the expected property instance.
+ * @param modified {@code true} if {@code expected} has been modified <strong>after</strong> it has been set
+ * to the {@link #feature} instance. Not all feature implementations can see such changes.
+ * @return {@code true} if the property is the expected instance, or {@code false} if it is another instance.
+ */
+ boolean assertSameProperty(final String name, final Property expected, final boolean modified) {
+ assertSame(name, expected, feature.getProperty(name));
+ return true;
+ }
+
+ /**
* Returns the attribute value of the current {@link #feature} for the given name.
*/
private Object getAttributeValue(final String name) {
final Object value = feature.getPropertyValue(name);
if (getValuesFromProperty) {
- final AbstractAttribute<?> property = (AbstractAttribute<?>) feature.getProperty(name);
+ final Attribute<?> property = (Attribute<?>) feature.getProperty(name);
// The AttributeType shall be the same than the one provided by FeatureType for the given name.
assertSame(name, feature.getType().getProperty(name), property.getType());
@@ -92,7 +111,7 @@ public abstract strictfp class FeatureTe
}
// Invoking getProperty(name) twice shall return the same Property instance.
- assertSame(name, property, feature.getProperty(name));
+ assertSameProperty(name, property, false);
}
return value;
}
@@ -102,9 +121,9 @@ public abstract strictfp class FeatureTe
* First, this method verifies that the previous value is equals to the given one.
* Then, this method set the attribute to the given value and check if the result.
*
- * @param name The name of the attribute to set.
- * @param oldValue The expected old value (may be {@code null}).
- * @param newValue The new value to set.
+ * @param name the name of the attribute to set.
+ * @param oldValue the expected old value (may be {@code null}).
+ * @param newValue the new value to set.
*/
private void setAttributeValue(final String name, final Object oldValue, final Object newValue) {
assertEquals(name, oldValue, getAttributeValue(name));
@@ -167,9 +186,9 @@ public abstract strictfp class FeatureTe
* Before we set the population attribute, the feature should be considered invalid.
* After we set it, the feature should be valid since all mandatory attributes are set.
*/
- assertQualityReports("population");
+ verifyQualityReports("population");
setAttributeValue("population", null, 1000);
- assertQualityReports();
+ verifyQualityReports();
/*
* Opportunist tests using the existing instance.
*/
@@ -242,9 +261,9 @@ public abstract strictfp class FeatureTe
* Before we set the 'isGlobal' attribute, the feature should be considered invalid.
* After we set it, the feature should be valid since all mandatory attributes are set.
*/
- assertQualityReports("isGlobal", "temperature");
+ verifyQualityReports("isGlobal", "temperature");
setAttributeValue("isGlobal", null, Boolean.TRUE);
- assertQualityReports("temperature");
+ verifyQualityReports("temperature");
/*
* Opportunist tests using the existing instance.
*/
@@ -277,33 +296,34 @@ public abstract strictfp class FeatureTe
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");
- 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()));
+ if (assertSameProperty("city", city, true)) {
+ /*
+ * The quality report is expected to contains a custom element.
+ */
+ int numOccurrences = 0;
+ final DataQuality quality = verifyQualityReports("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);
}
- assertEquals("Number of reports.", 1, numOccurrences);
}
/**
* Asserts that {@link AbstractFeature#quality()} reports no anomaly, or only anomalies for the given properties.
*
- * @param anomalousProperties The property for which we expect a report.
- * @return The data quality report.
+ * @param anomalousProperties the property for which we expect a report.
+ * @return the data quality report.
*/
- private DataQuality assertQualityReports(final String... anomalousProperties) {
+ private DataQuality verifyQualityReports(final String... anomalousProperties) {
int anomalyIndex = 0;
final DataQuality quality = feature.quality();
for (final Element report : quality.getReports()) {
@@ -327,9 +347,9 @@ public abstract strictfp class FeatureTe
* Tests the {@link AbstractFeature#clone()} method on the current {@link #feature} instance.
* This method is invoked from other test methods using the existing feature instance in an opportunist way.
*
- * @param property The name of a property to change.
- * @param oldValue The old value of the given property.
- * @param newValue The new value of the given property.
+ * @param property the name of a property to change.
+ * @param oldValue the old value of the given property.
+ * @param newValue the new value of the given property.
* @throws CloneNotSupportedException Should never happen.
*/
private void testClone(final String property, final Object oldValue, final Object newValue)
Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java?rev=1754559&r1=1754558&r2=1754559&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] Fri Jul 29 17:53:09 2016
@@ -27,7 +27,7 @@ import org.junit.BeforeClass;
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
* @since 0.5
- * @version 0.7
+ * @version 0.8
* @module
*/
@Suite.SuiteClasses({
@@ -40,6 +40,7 @@ import org.junit.BeforeClass;
org.apache.sis.feature.MultiValuedAttributeTest.class,
org.apache.sis.feature.DenseFeatureTest.class,
org.apache.sis.feature.SparseFeatureTest.class,
+ org.apache.sis.feature.AbstractFeatureTest.class,
org.apache.sis.feature.DefaultAssociationRoleTest.class,
org.apache.sis.feature.SingletonAssociationTest.class,
org.apache.sis.feature.AbstractOperationTest.class,