Author: desruisseaux
Date: Thu Apr 30 20:57:36 2015
New Revision: 1677070
URL: http://svn.apache.org/r1677070
Log:
Merge from the JDK8 branch:
- Initial draft of DefaultProjectedCRS.
- Initial support of "virtual attribute" in Feature.
Added:
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
- copied, changed from r1677068, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractOperationTest.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AbstractOperationTest.java
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/NoOperation.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/NoOperation.java
sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/CharEncoding.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/CharEncoding.java
sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/CharEncodingTest.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/CharEncodingTest.java
sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/mock/CoordinateSystemAxisMock.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/test/mock/CoordinateSystemAxisMock.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
- copied, changed from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
- copied, changed from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConicProjection.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConicProjection.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCylindricalProjection.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCylindricalProjection.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPlanarProjection.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPlanarProjection.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultProjection.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultProjection.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/AbstractSingleOperationTest.java
- copied unchanged from r1677068, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/AbstractSingleOperationTest.java
Removed:
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultOperationTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/OperationMethodsTest.java
Modified:
sis/branches/JDK7/ (props changed)
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultOperation.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java
sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java
sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java
sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/FormatterTest.java
sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/SubTypes.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultImageDatum.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultFormula.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeocentricCRSTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultVerticalCRSTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRS.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxisTest.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/HardCodedAxes.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationsTest.java
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/StringBuildersTest.java
Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Apr 30 20:57:36 2015
@@ -1,4 +1,4 @@
/sis/branches/Android:1430670-1480699
/sis/branches/JDK6:1394913-1508480
-/sis/branches/JDK8:1584960-1675086
+/sis/branches/JDK8:1584960-1677068
/sis/trunk:1394364-1508466,1519089-1519674
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -37,6 +37,7 @@ import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.FeatureAssociation;
import org.opengis.feature.FeatureAssociationRole;
+import org.opengis.feature.Operation;
/**
@@ -46,7 +47,7 @@ import org.opengis.feature.FeatureAssoci
* <ul>
* <li>{@linkplain AbstractAttribute Attributes}</li>
* <li>{@linkplain AbstractAssociation Associations to other features}</li>
- * <li>{@linkplain DefaultOperation Operations}</li>
+ * <li>{@linkplain AbstractOperation Operations}</li>
* </ul>
*
* {@code AbstractFeature} can be instantiated by calls to {@link DefaultFeatureType#newInstance()}.
@@ -71,7 +72,7 @@ import org.opengis.feature.FeatureAssoci
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.5
+ * @version 0.6
* @module
*
* @see DefaultFeatureType#newInstance()
@@ -118,7 +119,10 @@ public abstract class AbstractFeature im
}
/**
- * Returns the property (attribute, operation or association) of the given name.
+ * Returns the property (attribute, feature association or operation result) of the given name.
+ * If the property type is a parameterless {@linkplain AbstractOperation operation}, then this
+ * method may return the result of {@linkplain AbstractOperation#apply executing} the operation
+ * on this feature, at implementation choice.
*
* <div class="note"><b>Tip:</b> This method returns the property <em>instance</em>. If only the property
* <em>value</em> is desired, then {@link #getPropertyValue(String)} is preferred since it gives to SIS a
@@ -135,7 +139,7 @@ public abstract class AbstractFeature im
public abstract Property getProperty(final String name) throws IllegalArgumentException;
/**
- * Sets the property (attribute, operation or association).
+ * Sets the property (attribute or feature association).
* The given property shall comply to the following conditions:
*
* <ul>
@@ -188,7 +192,8 @@ public abstract class AbstractFeature im
*
* @param name The name of the property to create.
* @return A {@code Property} of the given name.
- * @throws IllegalArgumentException If the given argument is not an attribute or association name of this feature.
+ * @throws IllegalArgumentException If the given argument is not the name of an attribute or
+ * feature association of this feature.
*/
final Property createProperty(final String name) throws IllegalArgumentException {
final PropertyType pt = type.getProperty(name);
@@ -201,6 +206,54 @@ public abstract class AbstractFeature im
}
}
+ /**
+ * Executes the parameterless operation of the given name and returns its result.
+ */
+ final Property getOperationResult(final String name) {
+ /*
+ * The (Operation) cast below should never fail (unless the DefaultFeatureType in not really immutable,
+ * which would be a contract violation) because all callers shall ensure that this method is invoked in
+ * a context where the following assertion holds.
+ */
+ assert DefaultFeatureType.OPERATION_INDEX.equals(((DefaultFeatureType) type).indices().get(name)) : name;
+ return ((Operation) type.getProperty(name)).apply(this, null);
+ }
+
+ /**
+ * Executes the parameterless operation of the given name and returns the value of its result.
+ */
+ final Object getOperationValue(final String name) {
+ final Operation operation = (Operation) type.getProperty(name);
+ if (operation instanceof LinkOperation) {
+ return getPropertyValue(((LinkOperation) operation).propertyName);
+ }
+ final Property result = operation.apply(this, null);
+ if (result instanceof Attribute<?>) {
+ return getAttributeValue((Attribute<?>) result);
+ } else if (result instanceof FeatureAssociation) {
+ return getAssociationValue((FeatureAssociation) result);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Executes the parameterless operation of the given name and sets the value of its result.
+ */
+ final void setOperationValue(final String name, final Object value) {
+ final Operation operation = (Operation) type.getProperty(name);
+ if (operation instanceof LinkOperation) {
+ setPropertyValue(((LinkOperation) operation).propertyName, value);
+ } else {
+ final Property result = operation.apply(this, null);
+ if (result != null) {
+ setPropertyValue(result, value);
+ } else {
+ throw new IllegalStateException(Errors.format(Errors.Keys.CanNotSetPropertyValue_1, name));
+ }
+ }
+ }
+
/**
* Returns the default value to be returned by {@link #getPropertyValue(String)}
* for the property of the given name.
Copied: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java (from r1677068, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java?p2=sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java&p1=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java&r1=1677068&r2=1677070&rev=1677070&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -26,7 +26,6 @@ import org.apache.sis.util.Debug;
// Branch-dependent imports
import java.util.Objects;
-import java.util.function.BiFunction;
import org.opengis.feature.Attribute;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureAssociation;
@@ -58,9 +57,7 @@ import org.opengis.feature.Property;
* @version 0.6
* @module
*/
-public abstract class AbstractOperation extends AbstractIdentifiedType implements Operation,
- BiFunction<Feature, ParameterValueGroup, Property>
-{
+public abstract class AbstractOperation extends AbstractIdentifiedType implements Operation {
/**
* For cross-version compatibility.
*/
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -21,7 +21,6 @@ import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.IdentityHashMap;
import java.util.Collection;
@@ -29,8 +28,10 @@ import java.util.Collections;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.opengis.util.NameFactory;
+import org.opengis.util.LocalName;
import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
+import org.opengis.parameter.ParameterDescriptorGroup;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.collection.Containers;
@@ -39,11 +40,13 @@ import org.apache.sis.internal.util.Unmo
// Branch-dependent imports
import java.util.Objects;
+import org.apache.sis.internal.jdk8.JDK8;
import org.opengis.feature.PropertyType;
import org.opengis.feature.AttributeType;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.FeatureAssociationRole;
+import org.opengis.feature.Operation;
/**
@@ -65,7 +68,7 @@ import org.opengis.feature.FeatureAssoci
* <ul>
* <li>{@linkplain DefaultAttributeType Attributes}</li>
* <li>{@linkplain DefaultAssociationRole Associations to other features}</li>
- * <li>{@linkplain DefaultOperation Operations}</li>
+ * <li>{@linkplain AbstractOperation Operations}</li>
* </ul>
*
* In addition, a feature type can inherit the properties of one or more other feature types.
@@ -86,7 +89,7 @@ import org.opengis.feature.FeatureAssoci
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.5
+ * @version 0.6
* @module
*
* @see AbstractFeature
@@ -177,6 +180,7 @@ public class DefaultFeatureType extends
/**
* Indices of properties in an array of properties similar to {@link #properties},
* but excluding operations. This map includes the properties from the super-types.
+ * Parameterless operations (to be handled in a special way) are identified by index -1.
*
* The size of this map may be smaller than the {@link #byName} size.
* This map shall not be modified after construction.
@@ -184,6 +188,12 @@ public class DefaultFeatureType extends
private transient Map<String, Integer> indices;
/**
+ * Value in {@link #indices} map for parameterless operations. Those operations are not stored
+ * in feature instances, but can be handled as virtual attributes computed on-the-fly.
+ */
+ static final Integer OPERATION_INDEX = -1;
+
+ /**
* Constructs a feature type from the given properties. The identification map is given unchanged to
* the {@linkplain AbstractIdentifiedType#AbstractIdentifiedType(Map) super-class constructor}.
* The following table is a reminder of main (not all) recognized map entries:
@@ -285,18 +295,14 @@ public class DefaultFeatureType extends
assignableTo = new HashSet<>(4);
assignableTo.add(super.getName());
scanPropertiesFrom(this);
- byName = CollectionsExt.compact(byName);
- assignableTo = CollectionsExt.unmodifiableOrCopy(assignableTo);
- allProperties = byName.values();
- if (byName instanceof HashMap<?,?>) {
- allProperties = Collections.unmodifiableCollection(allProperties);
- }
+ allProperties = UnmodifiableArrayList.wrap(byName.values().toArray(new PropertyType[byName.size()]));
/*
* Now check if the feature is simple/complex or dense/sparse. We perform this check after we finished
* to create the list of all properties, because some properties may be overridden and we want to take
* in account only the most specific ones.
*/
isSimple = true;
+ int index = 0;
int mandatory = 0; // Count of mandatory properties.
for (final Map.Entry<String,PropertyType> entry : byName.entrySet()) {
final int minimumOccurs, maximumOccurs;
@@ -310,17 +316,57 @@ public class DefaultFeatureType extends
maximumOccurs = ((FeatureAssociationRole) property).getMaximumOccurs();
isSimple = false;
} else {
+ if (isParameterlessOperation(property)) {
+ indices.put(entry.getKey(), OPERATION_INDEX);
+ }
continue; // For feature operations, maximumOccurs is implicitly 0.
}
if (maximumOccurs != 0) {
isSimple &= (maximumOccurs == 1);
- indices.put(entry.getKey(), indices.size());
+ indices.put(entry.getKey(), index++);
if (minimumOccurs != 0) {
mandatory++;
}
}
}
- indices = CollectionsExt.compact(indices);
+ /*
+ * If some properties use long name of the form "head:tip", creates short aliases containing only the "tip"
+ * name for convenience, provided that it does not create ambiguity. If an short alias could map to two or
+ * more properties, then this alias is not added.
+ *
+ * In the 'aliases' map below, null values will be assigned to ambiguous short names.
+ */
+ final Map<String, PropertyType> aliases = new LinkedHashMap<>();
+ for (final PropertyType property : allProperties) {
+ final GenericName name = property.getName();
+ final LocalName tip = name.tip();
+ if (tip != name) { // Slight optimization for a common case.
+ final String key = tip.toString();
+ if (key != null && !key.isEmpty() && !key.equals(name.toString())) {
+ aliases.put(key, aliases.containsKey(key) ? null : property);
+ }
+ }
+ }
+ for (final Map.Entry<String,PropertyType> entry : aliases.entrySet()) {
+ final PropertyType property = entry.getValue();
+ if (property != null) {
+ final String tip = entry.getKey();
+ if (JDK8.putIfAbsent(byName, tip, property) == null) {
+ // This block is skipped if there is properties named "tip" and "head:tip".
+ // The 'indices' value may be null if the property is an operation.
+ final Integer value = indices.get(property.getName().toString());
+ if (value != null && indices.put(tip, value) != null) {
+ throw new AssertionError(tip); // Should never happen.
+ }
+ }
+ }
+ }
+ /*
+ * Trim the collections. Especially useful when the collections have less that 2 elements.
+ */
+ byName = CollectionsExt.compact(byName);
+ indices = CollectionsExt.compact(indices);
+ assignableTo = CollectionsExt.unmodifiableOrCopy(assignableTo);
/*
* Rational for choosing whether the feature is sparse: By default, java.util.HashMap implementation creates
* an internal array of length 16 (see HashMap.DEFAULT_INITIAL_CAPACITY). In addition, the HashMap instance
@@ -460,6 +506,20 @@ public class DefaultFeatureType extends
return resolved;
}
+ /**
+ * Returns {@code true} if the given property type stands for a parameterless operation which return a result.
+ *
+ * @see #OPERATION_INDEX
+ */
+ private static boolean isParameterlessOperation(final PropertyType type) {
+ if (type instanceof Operation) {
+ final ParameterDescriptorGroup parameters = ((Operation) type).getParameters();
+ return ((parameters == null) || parameters.descriptors().isEmpty())
+ && ((Operation) type).getResult() != null;
+ }
+ return false;
+ }
+
// -------- END OF CONSTRUCTORS ------------------------------------------------------------------------------
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultOperation.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultOperation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultOperation.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -17,40 +17,26 @@
package org.apache.sis.feature;
import java.util.Map;
-import org.opengis.util.GenericName;
-import org.opengis.parameter.GeneralParameterDescriptor;
+import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterDescriptorGroup;
-import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.Debug;
// Branch-dependent imports
-import java.util.Objects;
+import org.opengis.feature.Feature;
import org.opengis.feature.IdentifiedType;
-import org.opengis.feature.Operation;
+import org.opengis.feature.Property;
/**
- * Describes the behaviour of a feature type as a function or a method.
- * Operations can:
- *
- * <ul>
- * <li>Compute values from the attributes.</li>
- * <li>Perform actions that change the attribute values.</li>
- * </ul>
- *
- * <div class="note"><b>Example:</b> a mutator operation may raise the height of a dam. This changes
- * may affect other properties like the watercourse and the reservoir associated with the dam.</div>
- *
- * <div class="warning"><b>Warning:</b> this class is experimental and may change after we gained more
- * experience on this aspect of ISO 19109.</div>
+ * @deprecated Replaced by {@link AbstractOperation}.
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.5
+ * @version 0.6
* @module
*/
-public class DefaultOperation extends AbstractIdentifiedType implements Operation {
+@Deprecated
+public class DefaultOperation extends AbstractOperation {
/**
* For cross-version compatibility.
*/
@@ -104,62 +90,13 @@ public class DefaultOperation extends Ab
}
/**
- * Returns a hash code value for this operation.
- *
- * @return {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return super.hashCode() + parameters.hashCode() + Objects.hashCode(result);
- }
-
- /**
- * Compares this operation with the given object for equality.
+ * Subclasses should override.
+ * Default implementation throws {@link UnsupportedOperationException}.
*
* @return {@inheritDoc}
*/
@Override
- public boolean equals(final Object obj) {
- if (obj == this) {
- return true;
- }
- if (super.equals(obj)) {
- final DefaultOperation that = (DefaultOperation) obj;
- return parameters.equals(that.parameters) &&
- Objects.equals(result, that.result);
- }
- return false;
- }
-
- /**
- * Returns a string representation of this operation.
- * The returned string is for debugging purpose and may change in any future SIS version.
- *
- * @return A string representation of this operation for debugging purpose.
- */
- @Debug
- @Override
- public String toString() {
- final StringBuilder buffer = new StringBuilder(40).append("Operation").append('[');
- final GenericName name = getName();
- if (name != null) {
- buffer.append('“');
- }
- buffer.append(name);
- if (name != null) {
- buffer.append('”');
- }
- String separator = " (";
- for (final GeneralParameterDescriptor param : parameters.descriptors()) {
- buffer.append(separator).append(IdentifiedObjects.toString(param.getName()));
- separator = ", ";
- }
- if (separator == ", ") { // Identity comparaison is okay here.
- buffer.append(')');
- }
- if (result != null) {
- buffer.append(" : ").append(result.getName());
- }
- return buffer.append(']').toString();
+ public Property apply(Feature feature, ParameterValueGroup parameters) {
+ throw new UnsupportedOperationException();
}
}
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -38,7 +38,7 @@ import org.opengis.feature.FeatureAssoci
* @author Martin Desruisseaux (Geomatys)
* @author Marc le Bihan
* @since 0.5
- * @version 0.5
+ * @version 0.6
* @module
*
* @see SparseFeature
@@ -58,7 +58,7 @@ final class DenseFeature extends Abstrac
private final Map<String, Integer> indices;
/**
- * The properties (attributes, operations, feature associations) of this feature.
+ * The properties (attributes or feature associations) in this feature.
*
* Conceptually, values in this array are {@link Property} instances. However at first we will store only
* the property <em>values</em>, and convert to an array of type {@code Property[]} only when at least one
@@ -78,10 +78,12 @@ final class DenseFeature extends Abstrac
}
/**
- * Returns the index for the property of the given name.
+ * Returns the index for the property of the given name, or {@link DefaultFeatureType#OPERATION_INDEX}
+ * if the property is a parameterless operation.
*
* @param name The property name.
- * @return The index for the property of the given name.
+ * @return The index for the property of the given name,
+ * or a negative value if the property is a parameterless operation.
* @throws IllegalArgumentException If the given argument is not a property name of this feature.
*/
private int getIndex(final String name) throws IllegalArgumentException {
@@ -102,17 +104,22 @@ final class DenseFeature extends Abstrac
@Override
public Property getProperty(final String name) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("name", name);
- final int index = getIndex(name); // Invoked first because this method checks name validity.
-
- // Are the properties currently initialized? If not, wrap the values we can find.
+ final int index = getIndex(name);
+ if (index < 0) {
+ return getOperationResult(name);
+ }
+ /*
+ * Are the Property instances currently initialized? If not, wrap the values we can find.
+ * This is a all-or-nothing converion (we do not wrap only the requested property)
+ * for avoiding the additional complexity of remembering which values were wrapped.
+ */
if (!(properties instanceof Property[])) {
wrapValuesInProperties();
}
-
- // Find the wanted property.
+ /*
+ * Find the wanted property. If the property still have a null value, we create it from its type.
+ */
Property property = ((Property[]) properties)[index];
-
- // If the property still have a null value, we create it, but we can only tell its type.
if (property == null) {
property = createProperty(name);
properties[index] = property;
@@ -135,6 +142,10 @@ final class DenseFeature extends Abstrac
if (!(properties instanceof Property[])) {
wrapValuesInProperties();
}
+ /*
+ * Following index should never be OPERATION_INDEX (a negative value) because the call
+ * to 'verifyPropertyType(name, property)' shall have rejected all Operation types.
+ */
properties[indices.get(name)] = property;
}
@@ -167,8 +178,12 @@ final class DenseFeature extends Abstrac
@Override
public Object getPropertyValue(final String name) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("name", name);
+ final int index = getIndex(name);
+ if (index < 0) {
+ return getOperationValue(name);
+ }
if (properties != null) {
- final Object element = properties[getIndex(name)];
+ final Object element = properties[index];
if (element != null) {
if (!(properties instanceof Property[])) {
return element; // Most common case.
@@ -196,6 +211,10 @@ final class DenseFeature extends Abstrac
public void setPropertyValue(final String name, Object value) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("name", name);
final int index = getIndex(name);
+ if (index < 0) {
+ setOperationValue(name, value);
+ return;
+ }
if (properties == null) {
final int n = indices.size();
properties = (value != null) ? new Object[n] : new Property[n];
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -24,6 +24,7 @@ import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.ParseException;
import java.util.concurrent.atomic.AtomicReference;
+import org.opengis.referencing.IdentifiedObject;
import org.opengis.util.InternationalString;
import org.opengis.util.GenericName;
import org.apache.sis.io.TableAppender;
@@ -31,10 +32,13 @@ import org.apache.sis.io.TabularFormat;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.referencing.IdentifiedObjects;
// Branch-dependent imports
import org.opengis.feature.IdentifiedType;
+import org.opengis.feature.Property;
import org.opengis.feature.PropertyType;
+import org.opengis.feature.Attribute;
import org.opengis.feature.AttributeType;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
@@ -157,6 +161,9 @@ public class FeatureFormat extends Tabul
public void format(final Object object, final Appendable toAppendTo) throws IOException {
ArgumentChecks.ensureNonNull("object", object);
ArgumentChecks.ensureNonNull("toAppendTo", toAppendTo);
+ /*
+ * Separate the Feature (optional) and the FeatureType (mandatory) instances.
+ */
final FeatureType featureType;
final Feature feature;
if (object instanceof Feature) {
@@ -169,11 +176,25 @@ public class FeatureFormat extends Tabul
throw new IllegalArgumentException(Errors.getResources(displayLocale)
.getString(Errors.Keys.UnsupportedType_1, object.getClass()));
}
+ /*
+ * Check if at least one attribute has at least one characteritic. In many cases there is none.
+ * In none we will ommit the "characteristics" column, which is the last column.
+ */
+ boolean hasCharacteristics = false;
+ for (final PropertyType propertyType : featureType.getProperties(true)) {
+ if (propertyType instanceof AttributeType<?>) {
+ if (!((AttributeType<?>) propertyType).characteristics().isEmpty()) {
+ hasCharacteristics = true;
+ break;
+ }
+ }
+ }
+ /*
+ * Format the column header.
+ */
toAppendTo.append(toString(featureType.getName())).append(getLineSeparator());
- final StringBuffer buffer = new StringBuffer();
- final FieldPosition dummyFP = new FieldPosition(-1);
- final Vocabulary resources = Vocabulary.getResources(displayLocale);
- final TableAppender table = new TableAppender(toAppendTo, columnSeparator);
+ final Vocabulary resources = Vocabulary.getResources(displayLocale);
+ final TableAppender table = new TableAppender(toAppendTo, columnSeparator);
table.setMultiLinesCells(true);
table.nextLine('─');
header: for (int i=0; ; i++) {
@@ -183,6 +204,15 @@ header: for (int i=0; ; i++) {
case 1: nextColumn(table); key = Vocabulary.Keys.Type; break;
case 2: nextColumn(table); key = Vocabulary.Keys.Cardinality; break;
case 3: nextColumn(table); key = (feature != null) ? Vocabulary.Keys.Value : Vocabulary.Keys.DefaultValue; break;
+ case 4: {
+ if (hasCharacteristics) {
+ nextColumn(table);
+ key = Vocabulary.Keys.Characteristics;
+ break;
+ } else {
+ break header;
+ }
+ }
default: break header;
}
table.append(resources.getString(key));
@@ -193,6 +223,8 @@ header: for (int i=0; ; i++) {
* Done writing the header. Now write all property rows.
* Rows without value will be skipped only if optional.
*/
+ final StringBuffer buffer = new StringBuffer();
+ final FieldPosition dummyFP = new FieldPosition(-1);
for (final PropertyType propertyType : featureType.getProperties(true)) {
Object value;
if (feature != null) {
@@ -201,12 +233,12 @@ header: for (int i=0; ; i++) {
if (propertyType instanceof AttributeType &&
((AttributeType) propertyType).getMinimumOccurs() == 0)
{
- continue; // If no value, skip the full row.
+ continue; // If no value, skip the full row.
}
if (propertyType instanceof FeatureAssociationRole &&
((FeatureAssociationRole) propertyType).getMinimumOccurs() == 0)
{
- continue; // If no value, skip the full row.
+ continue; // If no value, skip the full row.
}
}
} else if (propertyType instanceof AttributeType<?>) {
@@ -272,8 +304,6 @@ header: for (int i=0; ; i++) {
final Format format = getFormat(valueClass);
if (format != null) {
value = format.format(value, buffer, dummyFP);
- } else if (value instanceof InternationalString) {
- value = ((InternationalString) value).toString(displayLocale);
} else if (value instanceof Feature && propertyType instanceof FeatureAssociationRole) {
final String p = DefaultAssociationRole.getTitleProperty((FeatureAssociationRole) propertyType);
if (p != null) {
@@ -281,10 +311,33 @@ header: for (int i=0; ; i++) {
}
}
if (value != null) {
- table.append(value.toString());
+ table.append(formatValue(value));
}
buffer.setLength(0);
}
+ /*
+ * Column 4 - Characteristics.
+ */
+ if (hasCharacteristics) {
+ nextColumn(table);
+ if (propertyType instanceof AttributeType<?>) {
+ String separator = "";
+ for (final AttributeType<?> attribute : ((AttributeType<?>) propertyType).characteristics().values()) {
+ table.append(separator).append(toString(attribute.getName()));
+ Object c = attribute.getDefaultValue();
+ if (feature != null) {
+ final Property p = feature.getProperty(propertyType.getName().toString());
+ if (p instanceof Attribute<?>) { // Should always be true, but we are paranoiac.
+ c = ((Attribute<?>) p).characteristics().get(attribute.getName().toString());
+ }
+ }
+ if (c != null) {
+ table.append(" = ").append(formatValue(c));
+ }
+ separator = ", ";
+ }
+ }
+ }
table.nextLine();
}
table.nextLine('─');
@@ -309,6 +362,22 @@ header: for (int i=0; ; i++) {
}
/**
+ * Formats the given attribute value.
+ */
+ private String formatValue(final Object value) {
+ if (value instanceof InternationalString) {
+ return ((InternationalString) value).toString(displayLocale);
+ } else if (value instanceof GenericName) {
+ return toString((GenericName) value);
+ } else if (value instanceof IdentifiedType) {
+ return toString(((IdentifiedType) value).getName());
+ } else if (value instanceof IdentifiedObject) {
+ return IdentifiedObjects.getIdentifierOrName((IdentifiedObject) value);
+ }
+ return value.toString();
+ }
+
+ /**
* Formats the given object using a shared instance of {@code ParameterFormat}.
* This is used for {@link DefaultParameterDescriptorGroup#toString()} implementation.
*/
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -129,16 +129,18 @@ final class MultiValuedAssociation exten
/**
* Sets the feature values. All previous values are replaced by the given collection.
*
- * @param values The new values.
+ * @param newValues The new values.
*/
@Override
- public void setValues(final Collection<? extends Feature> values) {
- ArgumentChecks.ensureNonNull("values", values);
- final FeatureType base = role.getValueType();
- this.values.clear();
- for (final Feature value : values) {
- ensureValid(base, value.getType());
- this.values.add(value);
+ public void setValues(final Collection<? extends Feature> newValues) {
+ if (newValues != values) {
+ ArgumentChecks.ensureNonNull("values", newValues); // The parameter name in public API is "values".
+ final FeatureType base = role.getValueType();
+ values.clear();
+ for (final Feature value : newValues) {
+ ensureValid(base, value.getType());
+ values.add(value);
+ }
}
}
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAttribute.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -139,13 +139,15 @@ final class MultiValuedAttribute<V> exte
/**
* Sets the attribute values. All previous values are replaced by the given collection.
*
- * @param values The new values.
+ * @param newValues The new values.
*/
@Override
- public void setValues(final Collection<? extends V> values) {
- ArgumentChecks.ensureNonNull("values", values);
- this.values.clear();
- this.values.addAll(values);
+ public void setValues(final Collection<? extends V> newValues) {
+ if (newValues != values) {
+ ArgumentChecks.ensureNonNull("values", newValues); // The parameter name in public API is "values".
+ values.clear();
+ values.addAll(newValues);
+ }
}
/**
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -24,12 +24,11 @@ import org.opengis.metadata.quality.Data
import org.apache.sis.internal.util.Cloner;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.CorruptedObjectException;
+import org.apache.sis.util.resources.Errors;
// Branch-dependent imports
import org.opengis.feature.Property;
-import org.opengis.feature.PropertyType;
import org.opengis.feature.Attribute;
-import org.opengis.feature.FeatureType;
import org.opengis.feature.FeatureAssociation;
@@ -42,7 +41,7 @@ import org.opengis.feature.FeatureAssoci
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.5
+ * @version 0.6
* @module
*
* @see DenseFeature
@@ -52,7 +51,7 @@ final class SparseFeature extends Abstra
/**
* For cross-version compatibility.
*/
- private static final long serialVersionUID = -4486200659005766093L;
+ private static final long serialVersionUID = 2954323576287152427L;
/**
* A {@link #valuesKind} flag meaning that the {@link #properties} map contains raw values.
@@ -70,7 +69,17 @@ final class SparseFeature extends Abstra
private static final byte CORRUPTED = 2;
/**
- * The properties (attributes, operations, feature associations) of this feature.
+ * The map of property names to keys in the {@link #properties} map. This map is a reference to the
+ * {@link DefaultFeatureType#indices} map (potentially shared by many feature instances) and shall
+ * not be modified.
+ *
+ * <p>We use those indices as {@link #properties} keys instead than using directly the property names
+ * in order to resolve aliases.</p>
+ */
+ private final Map<String, Integer> indices;
+
+ /**
+ * The properties (attributes or feature associations) in this feature.
*
* Conceptually, values in this map are {@link Property} instances. However at first we will store
* only the property <em>values</em>, and build the full {@code Property} objects only if they are
@@ -79,7 +88,7 @@ final class SparseFeature extends Abstra
*
* @see #valuesKind
*/
- private HashMap<String, Object> properties;
+ private HashMap<Integer, Object> properties;
/**
* {@link #PROPERTIES} if the values in the {@link #properties} map are {@link Property} instances,
@@ -96,24 +105,56 @@ final class SparseFeature extends Abstra
*
* @param type Information about the feature (name, characteristics, <i>etc.</i>).
*/
- public SparseFeature(final FeatureType type) {
+ public SparseFeature(final DefaultFeatureType type) {
super(type);
+ indices = type.indices();
properties = new HashMap<>();
}
/**
+ * Returns the index for the property of the given name, or {@link DefaultFeatureType#OPERATION_INDEX}
+ * if the property is a parameterless operation.
+ *
+ * @param name The property name.
+ * @return The index for the property of the given name,
+ * or a negative value if the property is a parameterless operation.
+ * @throws IllegalArgumentException If the given argument is not a property name of this feature.
+ */
+ private int getIndex(final String name) throws IllegalArgumentException {
+ final Integer index = indices.get(name);
+ if (index != null) {
+ return index;
+ }
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.PropertyNotFound_2, getName(), name));
+ }
+
+ /**
+ * Returns the property name at the given index.
+ * Current implementation is inefficient, but this method should rarely be invoked.
+ */
+ private String nameOf(final Integer index) {
+ for (final Map.Entry<String, Integer> entry : indices.entrySet()) {
+ if (index.equals(entry.getValue())) {
+ return entry.getKey();
+ }
+ }
+ // Should never reach this point.
+ throw new AssertionError(index);
+ }
+
+ /**
* 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.
*/
- private void ensurePropertyMap() {
+ private void requireMapOfProperties() {
if (valuesKind != PROPERTIES) {
if (!properties.isEmpty()) { // The map is typically empty when this method is first invoked.
if (valuesKind != VALUES) {
throw new CorruptedObjectException(getName());
}
valuesKind = CORRUPTED;
- for (final Map.Entry<String, Object> entry : properties.entrySet()) {
- final String key = entry.getKey();
+ for (final Map.Entry<Integer, Object> entry : properties.entrySet()) {
+ final String key = nameOf(entry.getKey());
final Object value = entry.getValue();
if (entry.setValue(createProperty(key, value)) != value) {
throw new ConcurrentModificationException(key);
@@ -134,7 +175,7 @@ final class SparseFeature extends Abstra
@Override
public Property getProperty(final String name) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("name", name);
- ensurePropertyMap();
+ requireMapOfProperties();
return getPropertyInstance(name);
}
@@ -144,10 +185,14 @@ final class SparseFeature extends Abstra
*/
private Property getPropertyInstance(final String name) throws IllegalArgumentException {
assert valuesKind == PROPERTIES : valuesKind;
- Property property = (Property) properties.get(name);
+ final Integer index = getIndex(name);
+ if (index < 0) {
+ return getOperationResult(name);
+ }
+ Property property = (Property) properties.get(index);
if (property == null) {
property = createProperty(name);
- replace(name, null, property);
+ replace(index, null, property);
}
return property;
}
@@ -164,8 +209,12 @@ final class SparseFeature extends Abstra
ArgumentChecks.ensureNonNull("property", property);
final String name = property.getName().toString();
verifyPropertyType(name, property);
- ensurePropertyMap();
- properties.put(name, property);
+ requireMapOfProperties();
+ /*
+ * Following index should never be OPERATION_INDEX (a negative value) because the call
+ * to 'verifyPropertyType(name, property)' shall have rejected all Operation types.
+ */
+ properties.put(indices.get(name), property);
}
/**
@@ -178,7 +227,11 @@ final class SparseFeature extends Abstra
@Override
public Object getPropertyValue(final String name) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("name", name);
- final Object element = properties.get(name);
+ final Integer index = getIndex(name);
+ if (index < 0) {
+ return getOperationValue(name);
+ }
+ final Object element = properties.get(index);
if (element != null) {
if (valuesKind == VALUES) {
return element; // Most common case.
@@ -191,7 +244,7 @@ final class SparseFeature extends Abstra
} else {
throw new CorruptedObjectException(getName());
}
- } else if (properties.containsKey(name)) {
+ } else if (properties.containsKey(index)) {
return null; // Null has been explicitely set.
} else {
return getDefaultValue(name);
@@ -209,8 +262,13 @@ final class SparseFeature extends Abstra
@Override
public void setPropertyValue(final String name, final Object value) throws IllegalArgumentException {
ArgumentChecks.ensureNonNull("name", name);
+ final Integer index = getIndex(name);
+ if (index < 0) {
+ setOperationValue(name, value);
+ return;
+ }
if (valuesKind == VALUES) {
- final Object previous = properties.put(name, value);
+ final Object previous = properties.put(index, value);
/*
* 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
@@ -222,7 +280,7 @@ final class SparseFeature extends Abstra
toStore = verifyPropertyValue(name, value);
} finally {
if (toStore != value) {
- replace(name, value, toStore);
+ replace(index, value, toStore);
}
}
}
@@ -236,13 +294,13 @@ final class SparseFeature extends Abstra
/**
* Sets a value in the {@link #properties} map.
*
- * @param name The name of the property to set.
+ * @param index The key of the property to set.
* @param oldValue The old value, used for verification purpose.
* @param newValue The new value.
*/
- private void replace(final String name, final Object oldValue, final Object newValue) {
- if (properties.put(name, newValue) != oldValue) {
- throw new ConcurrentModificationException(name);
+ private void replace(final Integer index, final Object oldValue, final Object newValue) {
+ if (properties.put(index, newValue) != oldValue) {
+ throw new ConcurrentModificationException(nameOf(index));
}
}
@@ -255,8 +313,8 @@ final class SparseFeature extends Abstra
public DataQuality quality() {
if (valuesKind == VALUES) {
final Validator v = new Validator(ScopeCode.FEATURE);
- for (final PropertyType pt : type.getProperties(true)) {
- v.validateAny(pt, properties.get(pt.getName().toString()));
+ for (final Map.Entry<String, Integer> entry : indices.entrySet()) {
+ v.validateAny(type.getProperty(entry.getKey()), properties.get(entry.getValue()));
}
return v.quality;
}
@@ -281,14 +339,14 @@ final class SparseFeature extends Abstra
@SuppressWarnings("unchecked")
public SparseFeature clone() throws CloneNotSupportedException {
final SparseFeature clone = (SparseFeature) super.clone();
- clone.properties = (HashMap<String,Object>) clone.properties.clone();
+ clone.properties = (HashMap<Integer,Object>) clone.properties.clone();
switch (clone.valuesKind) {
default: throw new AssertionError(clone.valuesKind);
case CORRUPTED: throw new CorruptedObjectException(clone.getName());
case VALUES: break; // Nothing to do.
case PROPERTIES: {
final Cloner cloner = new Cloner();
- for (final Map.Entry<String,Object> entry : clone.properties.entrySet()) {
+ for (final Map.Entry<Integer,Object> entry : clone.properties.entrySet()) {
final Property property = (Property) entry.getValue();
if (property instanceof Cloneable) {
entry.setValue(cloner.clone(property));
Modified: sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -24,7 +24,7 @@
* <li><b>{@linkplain org.apache.sis.feature.DefaultFeatureType Feature types}</b><br>
* Define the <em>structure</em> of real-world representations. A feature type lists the
* {@linkplain org.apache.sis.feature.DefaultAttributeType attributes},
- * {@linkplain org.apache.sis.feature.DefaultOperation operations} or
+ * {@linkplain org.apache.sis.feature.AbstractOperation operations} or
* {@linkplain org.apache.sis.feature.DefaultAssociationRole associations to other features}
* (collectively called “{@linkplain org.apache.sis.feature.DefaultFeatureType#getProperties(boolean) properties}”
* or “characteristics”) that a feature can have.
@@ -70,7 +70,7 @@
* {@code └─} Property type<br>
* {@code ├─} {@linkplain org.apache.sis.feature.DefaultAttributeType Attribute type}<br>
* {@code ├─} {@linkplain org.apache.sis.feature.DefaultAssociationRole Feature association role}<br>
- * {@code └─} {@linkplain org.apache.sis.feature.DefaultOperation Operation}<br>
+ * {@code └─} {@linkplain org.apache.sis.feature.AbstractOperation Operation}<br>
* </td><td class="sep" style="width: 50%; white-space: nowrap">
* {@linkplain org.apache.sis.feature.AbstractFeature Feature} (<cite>sparse</cite> or <cite>dense</cite>)<br>
* Property<br>
Modified: sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -20,7 +20,9 @@ import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Collection;
+import org.opengis.util.NameFactory;
import org.opengis.util.InternationalString;
+import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
@@ -39,7 +41,7 @@ import org.opengis.feature.PropertyType;
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.5
- * @version 0.5
+ * @version 0.6
* @module
*/
@DependsOn(DefaultAttributeTypeTest.class)
@@ -129,20 +131,25 @@ public final strictfp class DefaultFeatu
* {@link InternationalString} and an arbitrary amount of universities.
*/
static DefaultFeatureType worldMetropolis() {
- return worldMetropolis(metropolis(), universityCity(), InternationalString.class);
+ return worldMetropolis(metropolis(), universityCity(), CharacteristicTypeMapTest.temperature(), InternationalString.class);
}
/**
* Creates a sub-type of the "metropolis" type with the "region" attribute overridden to the given type.
- * The given type should be {@link InternationalString}, but we allow other type for testing argument checks.
+ * The given type should be {@link InternationalString}, but we allow other types for testing argument checks.
*/
private static DefaultFeatureType worldMetropolis(final DefaultFeatureType metropolis,
- final DefaultFeatureType universityCity, final Class<?> regionType)
+ final DefaultFeatureType universityCity, final DefaultAttributeType<?> temperature, final Class<?> regionType)
{
return new DefaultFeatureType(singletonMap(DefaultFeatureType.NAME_KEY, "World metropolis"), false,
- new DefaultFeatureType[] {metropolis, universityCity},
- new DefaultAttributeType<>(singletonMap(DefaultAttributeType.NAME_KEY, "region"),
- regionType, 1, 1, null));
+ new DefaultFeatureType[] {
+ metropolis,
+ universityCity
+ },
+ new DefaultAttributeType<?>[] {
+ new DefaultAttributeType<>(singletonMap(DefaultAttributeType.NAME_KEY, "region"), regionType, 1, 1, null),
+ temperature
+ });
}
@@ -306,8 +313,51 @@ public final strictfp class DefaultFeatu
fail("Duplicated attribute names shall not be allowed.");
} catch (IllegalArgumentException e) {
final String message = e.getMessage();
- assertTrue(message, message.contains("name")); // Property name.
- assertTrue(message, message.contains("City")); // Feature name.
+ assertTrue(message, message.contains("name")); // Property name.
+ assertTrue(message, message.contains("City")); // Feature name.
+ }
+ }
+
+ /**
+ * Same than {@link #testNameCollision()}, but resolving collisions with usage of names
+ * of the form {@code "head:tip"}.
+ *
+ * @since 0.6
+ */
+ @Test
+ @DependsOnMethod("testNameCollision")
+ public void testQualifiedNames() {
+ final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
+ final DefaultAttributeType<String> city = new DefaultAttributeType<>(
+ singletonMap(DefaultAttributeType.NAME_KEY, factory.createGenericName(null, "ns1", "name")),
+ String.class, 1, 1, null);
+ final DefaultAttributeType<Integer> cityId = new DefaultAttributeType<>(
+ singletonMap(DefaultAttributeType.NAME_KEY, factory.createGenericName(null, "ns2", "name")),
+ Integer.class, 1, 1, null);
+ final DefaultAttributeType<Integer> population = new DefaultAttributeType<>(
+ singletonMap(DefaultAttributeType.NAME_KEY, factory.createGenericName(null, "ns1", "population")),
+ Integer.class, 1, 1, null);
+ final DefaultFeatureType feature = new DefaultFeatureType(
+ singletonMap(DefaultAttributeType.NAME_KEY, "City"),
+ false, null, city, cityId, population);
+
+ final Iterator<PropertyType> it = feature.getProperties(false).iterator();
+ assertSame ("properties[0]", city, it.next());
+ assertSame ("properties[1]", cityId, it.next());
+ assertSame ("properties[2]", population, it.next());
+ assertFalse(it.hasNext());
+
+ assertSame("Shall get from fully qualified name.", city, feature.getProperty("ns1:name"));
+ assertSame("Shall get from fully qualified name.", cityId, feature.getProperty("ns2:name"));
+ assertSame("Shall get from fully qualified name.", population, feature.getProperty("ns1:population"));
+ assertSame("Shall get from short alias.", population, feature.getProperty( "population"));
+ try {
+ feature.getProperty("name");
+ fail("Expected no alias because of ambiguity.");
+ } catch (IllegalArgumentException e) {
+ final String message = e.getMessage();
+ assertTrue(message, message.contains("name")); // Property name.
+ assertTrue(message, message.contains("City")); // Feature name.
}
}
@@ -319,7 +369,7 @@ public final strictfp class DefaultFeatu
@Test
@DependsOnMethod({"testComplex", "testEquals"})
public void testInheritance() {
- final DefaultFeatureType city = city(); // Tested by 'testSimple()'.
+ final DefaultFeatureType city = city(); // Tested by 'testSimple()'.
final DefaultFeatureType capital = capital();
assertUnmodifiable(capital);
assertEquals("name", "Capital", capital.getName().toString());
@@ -349,7 +399,7 @@ public final strictfp class DefaultFeatu
@DependsOnMethod("testInheritance")
public void testMultiInheritance() {
final DefaultFeatureType metropolis = metropolis();
- final DefaultFeatureType capital = capital(); // Tested by 'testComplex()'.
+ final DefaultFeatureType capital = capital(); // Tested by 'testComplex()'.
final DefaultFeatureType metroCapital = new DefaultFeatureType(
singletonMap(DefaultFeatureType.NAME_KEY, "Metropolis and capital"), false,
new DefaultFeatureType[] {metropolis, capital},
@@ -390,25 +440,26 @@ public final strictfp class DefaultFeatu
public void testPropertyOverride() {
final DefaultFeatureType metropolis = metropolis();
final DefaultFeatureType universityCity = universityCity();
+ final DefaultAttributeType<?> temperature = CharacteristicTypeMapTest.temperature();
try {
- worldMetropolis(metropolis, universityCity, Integer.class);
+ worldMetropolis(metropolis, universityCity, temperature, Integer.class);
fail("Shall not be allowed to override a 'CharSequence' attribute with an 'Integer' one.");
} catch (IllegalArgumentException e) {
final String message = e.getMessage();
assertTrue(message, message.contains("region"));
assertTrue(message, message.contains("Metropolis"));
}
- final DefaultFeatureType worldMetropolis = worldMetropolis(metropolis, universityCity, InternationalString.class);
+ final DefaultFeatureType worldMetropolis = worldMetropolis(metropolis, universityCity, temperature, InternationalString.class);
assertUnmodifiable(worldMetropolis);
assertEquals ("name", "World metropolis", worldMetropolis.getName().toString());
assertArrayEquals("superTypes", new Object[] {metropolis, universityCity}, worldMetropolis.getSuperTypes().toArray());
assertFalse ("isAbstract", worldMetropolis.isAbstract());
assertFalse ("isSparse", worldMetropolis.isSparse());
assertFalse ("isSimple", worldMetropolis.isSimple()); // Because of the arbitrary amount of universities.
- assertEquals ("instanceSize", 5, worldMetropolis.indices().size());
+ assertEquals ("instanceSize", 6, worldMetropolis.indices().size());
- assertPropertiesEquals(worldMetropolis, false, "region");
- assertPropertiesEquals(worldMetropolis, true, "city", "population", "region", "isGlobal", "universities");
+ assertPropertiesEquals(worldMetropolis, false, "region", "temperature");
+ assertPropertiesEquals(worldMetropolis, true, "city", "population", "region", "isGlobal", "universities", "temperature");
assertEquals("property(“region”).valueClass", InternationalString.class,
((DefaultAttributeType) worldMetropolis.getProperty("region")).getValueClass());
Modified: sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -34,7 +34,10 @@ import static org.apache.sis.test.Assert
* @version 0.5
* @module
*/
-@DependsOn(DenseFeatureTest.class)
+@DependsOn({
+ DenseFeatureTest.class,
+ CharacteristicMapTest.class
+})
public final strictfp class FeatureFormatTest extends TestCase {
/**
* Tests the formatting of a {@link DefaultFeatureType}.
@@ -45,15 +48,16 @@ public final strictfp class FeatureForma
final FeatureFormat format = new FeatureFormat(Locale.US, null);
final String text = format.format(feature);
assertMultilinesEquals("World metropolis\n" +
- "┌──────────────┬─────────────────────┬─────────────┬───────────────┐\n" +
- "│ Name │ Type │ Cardinality │ Default value │\n" +
- "├──────────────┼─────────────────────┼─────────────┼───────────────┤\n" +
- "│ city │ String │ [1 … 1] │ Utopia │\n" +
- "│ population │ Integer │ [1 … 1] │ │\n" +
- "│ region │ InternationalString │ [1 … 1] │ │\n" +
- "│ isGlobal │ Boolean │ [1 … 1] │ │\n" +
- "│ universities │ String │ [0 … ∞] │ │\n" +
- "└──────────────┴─────────────────────┴─────────────┴───────────────┘\n", text);
+ "┌──────────────┬─────────────────────┬─────────────┬───────────────┬────────────────────────────┐\n" +
+ "│ Name │ Type │ Cardinality │ Default value │ Characteristics │\n" +
+ "├──────────────┼─────────────────────┼─────────────┼───────────────┼────────────────────────────┤\n" +
+ "│ city │ String │ [1 … 1] │ Utopia │ │\n" +
+ "│ population │ Integer │ [1 … 1] │ │ │\n" +
+ "│ region │ InternationalString │ [1 … 1] │ │ │\n" +
+ "│ isGlobal │ Boolean │ [1 … 1] │ │ │\n" +
+ "│ universities │ String │ [0 … ∞] │ │ │\n" +
+ "│ temperature │ Float │ [1 … 1] │ │ accuracy = 0.1, units = °C │\n" +
+ "└──────────────┴─────────────────────┴─────────────┴───────────────┴────────────────────────────┘\n", text);
}
/**
Modified: sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -184,9 +184,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", "population");
+ assertQualityReports("population");
setAttributeValue("population", null, 1000);
- assertQualityReports(null, null);
+ assertQualityReports();
/*
* Opportunist tests using the existing instance.
*/
@@ -259,9 +259,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", "isGlobal");
+ assertQualityReports("isGlobal", "temperature");
setAttributeValue("isGlobal", null, Boolean.TRUE);
- assertQualityReports(null, null);
+ assertQualityReports("temperature");
/*
* Opportunist tests using the existing instance.
*/
@@ -299,7 +299,7 @@ public abstract strictfp class FeatureTe
* The quality report is expected to contains a custom element.
*/
int numOccurrences = 0;
- final DataQuality quality = assertQualityReports("population", "population");
+ final DataQuality quality = assertQualityReports("population");
for (final Element report : quality.getReports()) {
final String identifier = report.getMeasureIdentification().toString();
if (identifier.equals("city")) {
@@ -315,27 +315,28 @@ public abstract strictfp class FeatureTe
}
/**
- * Asserts that {@link AbstractFeature#quality()} reports no anomaly, or only an anomaly for the given property.
+ * Asserts that {@link AbstractFeature#quality()} reports no anomaly, or only anomalies for the given properties.
*
- * @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 anomalousProperties The property for which we expect a report.
* @return The data quality report.
*/
- private DataQuality assertQualityReports(final String property, final String keyword) {
- int numOccurrences = 0;
+ private DataQuality assertQualityReports(final String... anomalousProperties) {
+ int anomalyIndex = 0;
final DataQuality quality = feature.quality();
for (final Element report : quality.getReports()) {
for (final Result result : report.getResults()) {
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);
- assertTrue("quality.report.result.explanation", explanation.contains(keyword));
- numOccurrences++;
+ assertTrue("Too many reports", anomalyIndex < anomalousProperties.length);
+ final String propertyName = anomalousProperties[anomalyIndex];
+ final String identifier = report.getMeasureIdentification().toString();
+ final String explanation = ((ConformanceResult) result).getExplanation().toString();
+ assertEquals("quality.report.measureIdentification", propertyName, identifier);
+ assertTrue ("quality.report.result.explanation", explanation.contains(propertyName));
+ anomalyIndex++;
}
}
}
- assertEquals("Number of reports.", property == null ? 0 : 1, numOccurrences);
+ assertEquals("Number of reports.", anomalousProperties.length, anomalyIndex);
return quality;
}
Modified: sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -41,7 +41,7 @@ import org.junit.BeforeClass;
org.apache.sis.feature.SparseFeatureTest.class,
org.apache.sis.feature.DefaultAssociationRoleTest.class,
org.apache.sis.feature.SingletonAssociationTest.class,
- org.apache.sis.feature.DefaultOperationTest.class,
+ org.apache.sis.feature.AbstractOperationTest.class,
org.apache.sis.feature.FeatureFormatTest.class,
org.apache.sis.feature.FeaturesTest.class
})
Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java?rev=1677070&r1=1677069&r2=1677070&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] Thu Apr 30 20:57:36 2015
@@ -55,13 +55,7 @@ import org.apache.sis.metadata.iso.citat
public enum Convention {
/**
* The ISO 19162 format, also known as “WKT 2”.
- * This convention follows the ISO recommendations with the following exceptions:
- *
- * <ul>
- * <li>{@code Axis} element omits the {@code Order} sub-element.</li>
- * </ul>
- *
- * Since the {@code Order} element is optional, the WKT is still valid.
+ * This convention follows the ISO recommendations.
*
* <p>Unless otherwise specified by {@link WKTFormat#setNameAuthority(Citation)}, projections
* and parameters formatted with this convention will use the {@linkplain Citations#EPSG EPSG}
@@ -77,6 +71,8 @@ public enum Convention {
* to the {@link #WKT2} convention except for the following aspects:
*
* <ul>
+ * <li>{@code PrimeMeridian} element omitted if the meridian is Greenwich.</li>
+ * <li>{@code Axis} element omits the {@code Order} sub-element.</li>
* <li>{@code VerticalExtent} element omits the {@code LengthUnit} sub-element
* if the unit is {@link javax.measure.unit.SI#METRE}.</li>
* <li>{@code Ellipsoid} element omits the {@code LengthUnit} sub-element
|