Author: desruisseaux
Date: Mon Apr 18 14:43:16 2016
New Revision: 1739766
URL: http://svn.apache.org/viewvc?rev=1739766&view=rev
Log:
Rename BoundsOperation as EnvelopeOperation and refactor in a way which try to
find the
CoordinateOperation at construction time instead than searching them for every
feature instance.
Added:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/EnvelopeOperation.java
- copied, changed from r1739765,
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/BoundsOperation.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
(with props)
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java
- copied, changed from r1739765,
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/BoundsOperationTest.java
Removed:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/BoundsOperation.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/BoundsOperationTest.java
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/NameConvention.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeTypeBuilderTest.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/NameConventionTest.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
Copied:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/EnvelopeOperation.java
(from r1739765,
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/BoundsOperation.java)
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/EnvelopeOperation.java?p2=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/EnvelopeOperation.java&p1=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/BoundsOperation.java&r1=1739765&r2=1739766&rev=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/BoundsOperation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/EnvelopeOperation.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -16,77 +16,196 @@
*/
package org.apache.sis.feature;
-import java.util.Collections;
+import java.util.Arrays;
+import java.util.Set;
import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import com.esri.core.geometry.Geometry;
+import java.util.LinkedHashMap;
+import org.opengis.util.GenericName;
+import org.opengis.util.FactoryException;
import org.opengis.geometry.Envelope;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.internal.feature.NameConvention;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.geometry.Envelopes;
import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.util.resources.Errors;
// Branch-dependent imports
+import java.util.Objects;
+import org.opengis.feature.Attribute;
import org.opengis.feature.AttributeType;
import org.opengis.feature.Feature;
-import org.opengis.feature.FeatureType;
import org.opengis.feature.IdentifiedType;
-import org.opengis.feature.MultiValuedPropertyException;
+import org.opengis.feature.Operation;
import org.opengis.feature.Property;
import org.opengis.feature.PropertyType;
/**
- * Calculate feature bounds operation.
- * <br>
- * This operation loops on all first level geometry properties and compute the
- * resulting envelope.
- * <br>
- * Geometries can be in different coordinate reference systems, they will be
- * transformed to the operation crs.
- * <br>
- * If the operation CRS has not been defined then the first none-empty geometry
- * crs will be used.
- * <br>
- * This operation can only be read, not setted.
+ * An operation computing the envelope that encompass all geometries found in
a list of attributes.
+ * Geometries can be in different coordinate reference systems; they will be
transformed to the first
+ * non-null CRS in the following choices:
+ *
+ * <ol>
+ * <li>the CRS specified at construction time,</li>
+ * <li>the CRS of the default geometry, or</li>
+ * <li>the CRS of the first non-empty geometry.</li>
+ * </ol>
+ *
+ * <div class="section">Limitations</div>
+ * If a geometry contains other geometries, this operation queries only the
envelope of the root geometry.
+ * It is the root geometry responsibility to take in account the envelope of
all its children.
+ *
+ * <p>This operation is read-only. Calls to {@code
Attribute.setValue(Envelope)} will result in an
+ * {@link IllegalStateException} to be thrown.</p>
*
* @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @since 0.7
* @version 0.7
* @module
*/
-final class BoundsOperation extends AbstractOperation {
+final class EnvelopeOperation extends AbstractOperation {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 6250548001562807671L;
- private static final AttributeType<Envelope> TYPE = new
DefaultAttributeType<>(
- Collections.singletonMap(NAME_KEY,
"Envelope"),Envelope.class,1,1,null);
+ /**
+ * The parameter descriptor for the "Envelope" operation, which does not
take any parameter.
+ */
+ private static final ParameterDescriptorGroup EMPTY_PARAMS =
LinkOperation.parameters("Envelope", 1);
+
+ /**
+ * The names of all properties containing a geometry object.
+ */
+ private final String[] attributeNames;
+
+ /**
+ * The coordinate reference system of the envelope to compute, or {@code
null}
+ * for using the CRS of the default geometry or the first non-empty
geometry.
+ */
+ final CoordinateReferenceSystem crs;
+
+ /**
+ * The coordinate conversions or transformations from the CRS used by the
geometries to the CRS requested
+ * by the user, or {@code null} if there is no operation to apply. If
non-null, the length of this array
+ * shall be equal to the length of the {@link #attributeNames} array and
element at index <var>i</var> is
+ * the operation from the {@code attributeNames[i]} geometry CRS to the
{@link #crs}.
+ *
+ * <p>This array contains null element when the {@code MathTransform}
associated to the coordinate operation
+ * is the identity transform.</p>
+ */
+ private final CoordinateOperation[] attributeToCRS;
/**
- * The parameter descriptor for the "Bounds" operation, which does not
take any parameter.
+ * The property names as an unmodifiable set, created when first needed.
*/
- private static final ParameterDescriptorGroup EMPTY_PARAMS =
LinkOperation.parameters("Bounds", 1);
+ private transient Set<String> dependencies;
- private final CoordinateReferenceSystem crs;
+ /**
+ * The type of the result returned by the envelope operation.
+ */
+ private final AttributeType<Envelope> resultType;
/**
+ * Creates a new operation computing the envelope of features of the given
type.
*
- * @param identification The name and other information to be given to
this operation.
- * @param crs result envelope CRS, can be {@code null}
+ * @param identification the name and other information to be given to
this operation.
+ * @param crs the coordinate reference system of envelopes
to computes, or {@code null}.
+ * @param geometryAttributes the operation or attribute type from which to
get geometry values.
*/
- BoundsOperation(Map<String,?> identification, CoordinateReferenceSystem
crs) {
+ EnvelopeOperation(final Map<String,?> identification,
CoordinateReferenceSystem crs,
+ final PropertyType[] geometryAttributes) throws FactoryException
+ {
super(identification);
+ String defaultGeometry = null;
+ final String characteristicName =
NameConvention.CRS_CHARACTERISTIC.toString();
+ /*
+ * Get all property names without duplicated values. If a property is
a link to an attribute,
+ * then the key will be the name of the referenced attribute instead
than the operation name.
+ * The intend is to avoid querying the same geometry twice if the
attribute is also specified
+ * explicitely in the array of properties.
+ *
+ * The map values will be the default Coordinate Reference System, or
null if none.
+ */
+ boolean characterizedByCRS = false;
+ final Map<String,CoordinateReferenceSystem> names = new
LinkedHashMap<>(4);
+ for (IdentifiedType property : geometryAttributes) {
+ if (NameConvention.isGeometryAttribute(property)) {
+ final GenericName name = property.getName();
+ final String attributeName = (property instanceof
LinkOperation)
+ ? ((LinkOperation)
property).referentName : name.toString();
+ final boolean isDefault =
NameConvention.DEFAULT_GEOMETRY_PROPERTY.equals(name.tip());
+ if (isDefault) {
+ defaultGeometry = attributeName;
+ }
+ CoordinateReferenceSystem attributeCRS = null;
+ while (property instanceof Operation) {
+ property = ((Operation) property).getResult();
+ }
+ /*
+ * At this point 'property' is an attribute, otherwise
isGeometryAttribute(property) would have
+ * returned false. Set 'characterizedByCRS' to true if we find
at least one attribute which may
+ * have the "CRS" characteristic. Note that we can not rely on
'attributeCRS' being non-null
+ * because an attribute may be characterized by a CRS without
providing default CRS.
+ */
+ final AttributeType<?> at = ((AttributeType<?>)
property).characteristics().get(characteristicName);
+ if (at != null &&
CoordinateReferenceSystem.class.isAssignableFrom(at.getValueClass())) {
+ attributeCRS = (CoordinateReferenceSystem)
at.getDefaultValue(); // May still null.
+ if (crs == null && isDefault) {
+ crs = attributeCRS;
+ }
+ characterizedByCRS = true;
+ }
+ names.putIfAbsent(attributeName, attributeCRS);
+ }
+ }
+ /*
+ * Copy the names in an array with the default geometry first. If
possible, find the coordinate operations
+ * now in order to avoid the potentially costly call to
CRS.findOperation(…) for each feature on which this
+ * EnvelopeOperation will be applied.
+ */
+ names.remove(null);
// Paranoiac safety.
+ attributeNames = new String[names.size()];
+ attributeToCRS = characterizedByCRS ? new
CoordinateOperation[attributeNames.length] : null;
+ int n = (defaultGeometry == null) ? 0 : 1;
+ for (final Map.Entry<String,CoordinateReferenceSystem> entry :
names.entrySet()) {
+ final int i;
+ final String name = entry.getKey();
+ if (name.equals(defaultGeometry)) {
+ defaultGeometry = null;
+ i = 0;
+ } else {
+ i = n++;
+ }
+ attributeNames[i] = name;
+ if (characterizedByCRS) {
+ final CoordinateReferenceSystem value = entry.getValue();
+ if (value != null) {
+ if (crs == null) {
+ crs = value; //
Fallback if default geometry has no CRS.
+ }
+ final CoordinateOperation op = CRS.findOperation(value,
crs, null);
+ if (!op.getMathTransform().isIdentity()) {
+ attributeToCRS[i] = op;
+ }
+ }
+ }
+ }
+ resultType = FeatureOperations.POOL.unique(new DefaultAttributeType<>(
+ resultIdentification(identification), Envelope.class, 1, 1,
null));
this.crs = crs;
}
/**
- * Bounds operation do not require any parameter.
+ * Returns an empty group of parameters since this operation does not
require any parameter.
*
* @return empty parameter group.
*/
@@ -96,108 +215,165 @@ final class BoundsOperation extends Abst
}
/**
- * Bounds operation generates a Envelope result, or {@code null}.
+ * Returns the type of results computed by this operation, which is {@code
AttributeType<Envelope>}.
+ * The attribute type name depends on the value of {@code "result.*"}
properties (if any)
+ * given at construction time.
*
- * @return bounds envelope type
+ * @return an {@code AttributeType<Envelope>}.
*/
@Override
public IdentifiedType getResult() {
- return TYPE;
+ return resultType;
+ }
+
+ /**
+ * Returns the names of feature properties that this operation needs for
performing its task.
+ */
+ @Override
+ @SuppressWarnings("ReturnOfCollectionOrArrayField")
+ public synchronized Set<String> getDependencies() {
+ if (dependencies == null) {
+ dependencies = CollectionsExt.immutableSet(true, attributeNames);
+ }
+ return dependencies;
}
/**
- * {@inheritDoc }
+ * Returns an attribute whose value is the union of the envelopes of all
geometries in the given feature
+ * found in properties specified at construction time.
*
- * @param feature The feature on which to execute the operation.
- * Can not be {@code null}.
- * @param parameters The parameters to use for executing the operation.
- * Can be {@code null}.
- * @return The operation result, never null.
+ * @param feature the feature on which to execute the operation.
+ * @param parameters ignored (can be {@code null}).
+ * @return the envelope of geometries in feature property values.
*/
@Override
public Property apply(Feature feature, ParameterValueGroup parameters) {
- return new BoundsAttribute(feature);
+ return new Result(feature);
}
+
+
+
/**
- * Operation attribute.
+ * The attributes that contains the result of union of all envelope
extracted from other attributes.
* Value is calculated each time it is accessed.
*/
- private final class BoundsAttribute extends AbstractAttribute<Envelope> {
-
+ private final class Result extends AbstractAttribute<Envelope> {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 926172863066901618L;
+
+ /**
+ * The feature specified to the {@link
StringJoinOperation#apply(Feature, ParameterValueGroup)} method.
+ */
private final Feature feature;
- public BoundsAttribute(final Feature feature) {
- super(TYPE);
+ /**
+ * Creates a new attribute for the given feature.
+ */
+ Result(final Feature feature) {
+ super(resultType);
this.feature = feature;
}
+ /**
+ * Computes an envelope which is the union of envelope of geometry
values of all properties
+ * specified to the {@link EnvelopeOperation} constructor.
+ *
+ * @return the union of envelopes of all geometries in the attribute
specified to the constructor,
+ * or {@code null} if none.
+ */
@Override
- public Envelope getValue() throws MultiValuedPropertyException {
- try {
- return calculate(feature, crs);
- } catch (TransformException ex) {
- Logger.getLogger("org.apache.sis.feature").log(Level.WARNING,
ex.getLocalizedMessage(), ex);
+ public Envelope getValue() throws IllegalStateException {
+ final String[] attributeNames =
EnvelopeOperation.this.attributeNames;
+ GeneralEnvelope envelope = null;
// Union of all envelopes.
+ for (int i=0; i<attributeNames.length; i++) {
+ Envelope genv;
// Envelope of a single geometry.
+ final String name = attributeNames[i];
+ if (attributeToCRS == null) {
+ /*
+ * If there is no CRS characteristic on any of the
properties to query, then invoke the
+ * Feature.getPropertyValue(String) method instead than
Feature.getProperty(String) in
+ * order to avoid forcing DenseFeature and SparseFeature
implementations to wrap the
+ * property values into real property instances. This is
an optimization for reducing
+ * the amount of objects to create.
+ */
+ genv =
Geometries.getEnvelope(feature.getPropertyValue(name));
+ if (genv == null) continue;
+ } else {
+ /*
+ * If there is at least one CRS characteristic to query,
then we need the full Property instance.
+ * We do not distinguish which particular property may
have a CRS characteristic because SIS 0.7
+ * implementations of DenseFeature and SparseFeature have
a "all of nothing" behavior anyway.
+ */
+ final Property property = feature.getProperty(name);
+ genv = Geometries.getEnvelope(property.getValue());
+ if (genv == null) continue;
+ /*
+ * Get the CRS characteristic if present. Most of the
time, 'at' will be null and we will
+ * fallback on the 'attributeToCRS' operations computed at
construction time. In the rare
+ * cases where a CRS characteristic is associated to a
particular feature, we will let
+ * Envelopes.transform(…) searches a coordinate operation.
+ */
+ final Attribute<?> at = ((Attribute<?>)
property).characteristics()
+
.get(NameConvention.CRS_CHARACTERISTIC.toString());
+ try {
+ if (at == null) {
+ final CoordinateOperation op = attributeToCRS[i];
+ if (op != null) { //
Null operation means identity transform.
+ genv = Envelopes.transform(op, genv);
+ }
+ } else {
// Should be a rare case.
+ final Object geomCRS = at.getValue();
+ if (!(geomCRS instanceof
CoordinateReferenceSystem)) {
+ throw new
IllegalStateException(Errors.format(Errors.Keys.UnspecifiedCRS));
+ }
+ ((GeneralEnvelope)
genv).setCoordinateReferenceSystem((CoordinateReferenceSystem) geomCRS);
+ genv = Envelopes.transform(genv, crs);
+ }
+ } catch (TransformException e) {
+ throw new
IllegalStateException(Errors.format(Errors.Keys.CanNotTransformEnvelope), e);
+ }
+ }
+ if (envelope == null) {
+ envelope = GeneralEnvelope.castOrCopy(genv); //
Should always be a cast without copy.
+ } else {
+ envelope.add(genv);
+ }
}
- return null;
+ return envelope;
}
+ /**
+ * Unconditionally throws an {@link UnsupportedOperationException}.
+ */
@Override
public void setValue(Envelope value) {
- throw new UnsupportedOperationException("Bounds operation
attribute can not be set.");
+ throw new
UnsupportedOperationException(Errors.format(Errors.Keys.UnmodifiableObject_1,
Attribute.class));
}
-
}
- GeneralEnvelope calculate(Feature feature, CoordinateReferenceSystem crs)
throws TransformException {
-
- GeneralEnvelope bounds = null;
-
- final FeatureType type = feature.getType();
- for(PropertyType pt : type.getProperties(true)){
- if(!pt.getName().equals(NameConvention.DEFAULT_GEOMETRY_PROPERTY)){
- if(!NameConvention.isGeometryAttribute(pt)) continue;
- }
-
- final Object val =
feature.getPropertyValue(pt.getName().toString());
-
- if(val instanceof Geometry){
- final Geometry geom = (Geometry)val;
+ /**
+ * Computes a hash-code value for this operation.
+ */
+ @Override
+ public int hashCode() {
+ return super.hashCode() + Arrays.hashCode(attributeNames) +
Arrays.hashCode(attributeToCRS);
+ }
- final com.esri.core.geometry.Envelope env = new
com.esri.core.geometry.Envelope();
- geom.queryEnvelope(env);
- if(env.isEmpty()) continue;
-
- //extract geometry enveloppe
- final CoordinateReferenceSystem geomCrs =
NameConvention.getCoordinateReferenceSystem(pt);
- Envelope genv;
- if(geomCrs!=null){
- genv = new GeneralEnvelope(geomCrs);
- }else{
- genv = new GeneralEnvelope(2);
- }
- ((GeneralEnvelope)genv).setRange(0, env.getXMin(),
env.getXMax());
- ((GeneralEnvelope)genv).setRange(1, env.getYMin(),
env.getYMax());
-
- //ensure it is in the wanted crs
- if(crs!=null){
- genv = Envelopes.transform(genv, crs);
- }
-
- if(bounds==null){
- if(crs==null){
- bounds = (GeneralEnvelope)genv;
- }else{
- bounds = new GeneralEnvelope(crs);
- bounds.setEnvelope(genv);
- }
- }else{
- bounds.add(genv);
- }
- }
+ /**
+ * Compares this operation with the given object for equality.
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (super.equals(obj)) {
+ // 'this.result' is compared (indirectly) by the super class.
+ final EnvelopeOperation that = (EnvelopeOperation) obj;
+ return Arrays.equals(attributeNames, that.attributeNames) &&
+ Arrays.equals(attributeToCRS, that.attributeToCRS) &&
+ Objects.equals(crs, that.crs);
}
-
- return bounds;
+ return false;
}
-
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -18,6 +18,7 @@ package org.apache.sis.feature;
import java.util.Map;
import org.opengis.util.GenericName;
+import org.opengis.util.FactoryException;
import org.opengis.util.InternationalString;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.util.ArgumentChecks;
@@ -80,17 +81,17 @@ import org.opengis.feature.PropertyType;
* <tr>
* <td>"result.definition"</td>
* <td>{@link InternationalString} or {@link String}</td>
- * <td>{@link AbstractAttribute#getDefinition() Attribute.getDefinition()}
on the {@linkplain AbstractOperation#getResult() result}</td>
+ * <td>{@link DefaultAttributeType#getDefinition()
Attribute.getDefinition()} on the {@linkplain AbstractOperation#getResult()
result}</td>
* </tr>
* <tr>
* <td>"result.designation"</td>
* <td>{@link InternationalString} or {@link String}</td>
- * <td>{@link AbstractAttribute#getDesignation()
Attribute.getDesignation()} on the {@linkplain AbstractOperation#getResult()
result}</td>
+ * <td>{@link DefaultAttributeType#getDesignation()
Attribute.getDesignation()} on the {@linkplain AbstractOperation#getResult()
result}</td>
* </tr>
* <tr>
* <td>"result.description"</td>
* <td>{@link InternationalString} or {@link String}</td>
- * <td>{@link AbstractAttribute#getDescription()
Attribute.getDescription()} on the {@linkplain AbstractOperation#getResult()
result}</td>
+ * <td>{@link DefaultAttributeType#getDescription()
Attribute.getDescription()} on the {@linkplain AbstractOperation#getResult()
result}</td>
* </tr>
* <tr>
* <td>{@value
org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}</td>
@@ -225,13 +226,41 @@ public final class FeatureOperations ext
}
/**
- * Creates a calculate bounds operation type.
+ * Creates an operation computing the envelope that encompass all
geometries found in the given attributes.
+ * Geometries can be in different coordinate reference systems; they will
be transformed to the first non-null
+ * CRS in the following choices:
+ *
+ * <ol>
+ * <li>the CRS specified to this method,</li>
+ * <li>the CRS of the default geometry, or</li>
+ * <li>the CRS of the first non-empty geometry.</li>
+ * </ol>
+ *
+ * The {@linkplain AbstractOperation#getResult() result} of this operation
is an {@code Attribute}
+ * with values of type {@link org.opengis.geometry.Envelope}. If the
{@code crs} argument given to
+ * this method is non-null, then the
+ * {@linkplain
org.apache.sis.geometry.GeneralEnvelope#getCoordinateReferenceSystem() envelope
CRS}
+ * will be that CRS.
+ *
+ * <div class="section">Limitations</div>
+ * If a geometry contains other geometries, this operation queries only
the envelope of the root geometry.
+ * It is the root geometry responsibility to take in account the envelope
of all its children.
*
- * @param identification the name and other information to be given to
the operation.
- * @param baseCRS created envelope CRS.
- * @return Operation
+ * <div class="section">Read/write behavior</div>
+ * This operation is read-only. Calls to {@code
Attribute.setValue(Envelope)} will result in an
+ * {@link IllegalStateException} to be thrown.
+ *
+ * @param identification the name and other information to be given
to the operation.
+ * @param crs the Coordinate Reference System in which to
express the envelope, or {@code null}.
+ * @param geometryAttributes the operation or attribute type from which
to get geometry values.
+ * Any element which is {@code null} or has a
non-geometric value class will be ignored.
+ * @return an operation which will compute the envelope encompassing all
geometries in the given attributes.
+ * @throws FactoryException if a coordinate operation to the target CRS
can not be created.
*/
- public static Operation bounds(final Map<String,?> identification,
CoordinateReferenceSystem baseCRS) {
- return new BoundsOperation(identification, baseCRS);
+ public static Operation envelope(final Map<String,?> identification, final
CoordinateReferenceSystem crs,
+ final PropertyType... geometryAttributes) throws FactoryException
+ {
+ ArgumentChecks.ensureNonNull("geometryAttributes", geometryAttributes);
+ return POOL.unique(new EnvelopeOperation(identification, crs,
geometryAttributes));
}
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -168,7 +168,7 @@ final class StringJoinOperation extends
}
/**
- * Concatenate operation do not require any parameter.
+ * Returns an empty group of parameters since this operation does not
require any parameter.
*
* @return empty parameter group.
*/
@@ -178,9 +178,11 @@ final class StringJoinOperation extends
}
/**
- * Concatenate operation generates a {@link String} result.
+ * Returns the type of results computed by this operation, which is {@code
AttributeType<String>}.
+ * The attribute type name depends on the value of {@code "result.*"}
properties (if any)
+ * given at construction time.
*
- * @return concatenated string type.
+ * @return an {@code AttributeType<String>}.
*/
@Override
public IdentifiedType getResult() {
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -690,13 +690,14 @@ public class FeatureTypeBuilder {
throw new IllegalArgumentException("Property
"+defGeomAttribute+" used in default geometry does not exist");
}
final PropertyType geomAtt = properties.get(defGeomAttribute);
- final CoordinateReferenceSystem crs =
NameConvention.getCoordinateReferenceSystem(geomAtt);
+ final CoordinateReferenceSystem crs = null; // TODO
NameConvention.getCoordinateReferenceSystem(geomAtt);
final Operation att = FeatureOperations.link(
Collections.singletonMap(AbstractOperation.NAME_KEY,
DEFAULT_GEOMETRY_PROPERTY), geomAtt);
properties.put(DEFAULT_GEOMETRY_PROPERTY, att);
- final Operation boundAtt =
FeatureOperations.bounds(Collections.singletonMap(AbstractOperation.NAME_KEY,
ENVELOPE_PROPERTY), crs);
- properties.put(ENVELOPE_PROPERTY, boundAtt);
+ // TODO
+// final Operation boundAtt =
FeatureOperations.bounds(Collections.singletonMap(AbstractOperation.NAME_KEY,
ENVELOPE_PROPERTY), null, crs);
+// properties.put(ENVELOPE_PROPERTY, boundAtt);
}
Added:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java?rev=1739766&view=auto
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
(added)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -0,0 +1,76 @@
+/*
+ * 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.internal.feature;
+
+import com.esri.core.geometry.Geometry;
+import com.esri.core.geometry.Envelope2D;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.util.Static;
+
+
+/**
+ * Utility methods on geometric objects defined in libraries outside Apache
SIS.
+ * We use this class for isolating dependencies from the {@code
org.apache.feature} package
+ * to ESRI's API or to Java Topology Suite (JTS) API.
+ * This gives us a single place to review if we want to support different
geometry libraries,
+ * or if Apache SIS come with its own implementation.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.7
+ * @version 0.7
+ * @module
+ */
+public final class Geometries extends Static {
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private Geometries() {
+ }
+
+ /**
+ * Returns {@code true} if the given type is one of the type known to
Apache SIS.
+ *
+ * @param type the type to verify.
+ * @return {@code true} if the given type is one of the geometry type
known to SIS.
+ */
+ public static boolean isKnownType(final Class<?> type) {
+ return Geometry.class.isAssignableFrom(type);
+ }
+
+ /**
+ * If the given object is one of the recognized type and its envelope is
non-empty,
+ * returns that envelope as an Apache SIS implementation. Otherwise
returns {@code null}.
+ *
+ * @param geometry the geometry from which to get the envelope, or
{@code null}.
+ * @return the envelope of the given object, or {@code null} if the object
is not
+ * a recognized geometry or its envelope is empty.
+ */
+ public static GeneralEnvelope getEnvelope(final Object geometry) {
+ if (geometry instanceof Geometry) {
+ final Envelope2D bounds = new Envelope2D();
+ ((Geometry) geometry).queryEnvelope2D(bounds);
+ if (!bounds.isEmpty()) { //
Test if there is NaN values.
+ final GeneralEnvelope env = new GeneralEnvelope(2);
+ env.setRange(0, bounds.xmin, bounds.xmax);
+ env.setRange(1, bounds.ymin, bounds.ymax);
+ return env;
+ }
+ }
+ return null;
+ }
+}
Propchange:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/NameConvention.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/NameConvention.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/NameConvention.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/NameConvention.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -16,7 +16,6 @@
*/
package org.apache.sis.internal.feature;
-import com.esri.core.geometry.Geometry;
import org.opengis.util.LocalName;
import org.opengis.util.ScopedName;
import org.opengis.util.GenericName;
@@ -28,10 +27,11 @@ import org.apache.sis.internal.util.Cons
import org.apache.sis.util.Static;
// Branch-dependent imports
+import org.opengis.feature.Attribute;
import org.opengis.feature.AttributeType;
import org.opengis.feature.IdentifiedType;
import org.opengis.feature.Operation;
-import org.opengis.feature.PropertyType;
+import org.opengis.feature.Property;
/**
@@ -100,12 +100,12 @@ public final class NameConvention extend
* <p>Properties of this name are usually {@linkplain
org.apache.sis.feature.FeatureOperations#link
* operations acting as a redirection to another attribute}.</p>
*
- * <p>The {@linkplain
org.apache.sis.feature.DefaultAttributeType#getValueClass() value class} can be
the
- * {@link Geometry} class from ESRI's API, or the {@code Geometry} class
from <cite>Java Topology Suite</cite>
- * (JTS) library, or any other class defined in future SIS versions. See
{@link #isGeometryAttribute(PropertyType)}
- * for testing whether the value is a supported type.</p>
+ * <p>The {@linkplain
org.apache.sis.feature.DefaultAttributeType#getValueClass() value class} can be
+ * the {@link com.esri.core.geometry.Geometry} class from ESRI's API, or
the {@code Geometry} class from
+ * <cite>Java Topology Suite</cite> (JTS) library, or any other class
defined in future SIS versions.
+ * See {@link #isGeometryAttribute(IdentifiedType)} for testing whether
the value is a supported type.</p>
*
- * @see #isGeometryAttribute(PropertyType)
+ * @see #isGeometryAttribute(IdentifiedType)
*/
public static final LocalName DEFAULT_GEOMETRY_PROPERTY;
@@ -165,7 +165,7 @@ public final class NameConvention extend
NAMESPACE = factory.createGenericName(null,
"Apache", Constants.SIS);
NameSpace ns = factory.createNameSpace(NAMESPACE,
null);
ID_PROPERTY = factory.createLocalName(ns,
"@identifier");
- DEFAULT_GEOMETRY_PROPERTY = factory.createLocalName(ns,
"@defaultGeometry");
+ DEFAULT_GEOMETRY_PROPERTY = factory.createLocalName(ns,
"@geometry");
ENVELOPE_PROPERTY = factory.createLocalName(ns,
"@envelope");
CRS_CHARACTERISTIC = factory.createLocalName(ns, "@crs");
MAXIMAL_LENGTH_CHARACTERISTIC = factory.createLocalName(ns,
"@maximalLength");
@@ -225,49 +225,102 @@ public final class NameConvention extend
while (type instanceof Operation) {
type = ((Operation) type).getResult();
}
- if (type instanceof AttributeType<?>) {
- final Class<?> valueClass = ((AttributeType<?>)
type).getValueClass();
- return Geometry.class.isAssignableFrom(valueClass);
- }
- return false;
+ return (type instanceof AttributeType<?>) &&
Geometries.isKnownType(((AttributeType<?>) type).getValueClass());
}
/**
- * Returns the coordinate reference systems associated to the given
operation or attribute type,
- * or {@code null} if none. This method searches for a characteristic
named {@link #CRS_CHARACTERISTIC}.
+ * Returns whether the given operation or attribute type is characterized
by a coordinate reference system.
+ * This method verifies whether a characteristic named {@link
#CRS_CHARACTERISTIC} with values assignable to
+ * {@link CoordinateReferenceSystem} exists (directly or indirectly) for
the given type.
*
* @param type the operation or attribute type for which to get the CRS,
or {@code null}.
- * @return The Coordinate Reference System for the given type, or {@code
null} if none.
+ * @return {@code true} if a characteristic for Coordinate Reference
System has been found.
+ */
+ public static boolean characterizedByCRS(final IdentifiedType type) {
+ return hasCharacteristic(type, CRS_CHARACTERISTIC.toString(),
CoordinateReferenceSystem.class);
+ }
+
+ /**
+ * Returns the Coordinate Reference Systems characteristic for the given
attribute, or {@code null} if none.
+ * This method gets the value or default value from the characteristic
named {@link #CRS_CHARACTERISTIC}.
+ *
+ * @param attribute the attribute for which to get the CRS, or {@code
null}.
+ * @return The Coordinate Reference System characteristic of the given
attribute, or {@code null} if none.
* @throws ClassCastException if {@link #CRS_CHARACTERISTIC} has been
found but is associated
* to an object which is not a {@link CoordinateReferenceSystem}
instance.
*/
- public static CoordinateReferenceSystem
getCoordinateReferenceSystem(IdentifiedType type) {
+ public static CoordinateReferenceSystem getCrsCharacteristic(final
Property attribute) {
+ return (CoordinateReferenceSystem) getCharacteristic(attribute,
CRS_CHARACTERISTIC.toString());
+ }
+
+ /**
+ * Returns whether the given operation or attribute type is characterized
by a maximal length.
+ * This method verifies whether a characteristic named {@link
#MAXIMAL_LENGTH_CHARACTERISTIC}
+ * with values of class {@link Integer} exists (directly or indirectly)
for the given type.
+ *
+ * @param type the operation or attribute type for which to get the
maximal length, or {@code null}.
+ * @return {@code true} if a characteristic for maximal length has been
found.
+ */
+ public static boolean characterizedByMaximalLength(final IdentifiedType
type) {
+ return hasCharacteristic(type,
MAXIMAL_LENGTH_CHARACTERISTIC.toString(), Integer.class);
+ }
+
+ /**
+ * Returns the maximal length characteristic for the given attribute, or
{@code null} if none.
+ * This method gets the value or default value from the characteristic
named {@link #MAXIMAL_LENGTH_CHARACTERISTIC}.
+ *
+ * @param attribute the attribute for which to get the CRS, or {@code
null}.
+ * @return The Coordinate Reference System characteristic of the given
attribute, or {@code null} if none.
+ * @throws ClassCastException if {@link #MAXIMAL_LENGTH_CHARACTERISTIC}
has been found but is associated
+ * to an object which is not an {@link Integer} instance.
+ */
+ public static Integer getMaximalLengthCharacteristic(final Property
attribute) {
+ return (Integer) getCharacteristic(attribute,
MAXIMAL_LENGTH_CHARACTERISTIC.toString());
+ }
+
+ /**
+ * Returns {@code true} if the given operation or attribute type has a
characteristic of the given name,
+ * and the values of that characteristic are assignable to the given
{@code valueClass}.
+ *
+ * @param type the operation or attribute type for which to test
the existence of a characteristic.
+ * @param name the name of the characteristic to test.
+ * @param valueClass the expected characteristic values.
+ * @return {@code true} if a characteristic of the given name exists and
has values assignable to the given class.
+ */
+ private static boolean hasCharacteristic(IdentifiedType type, final String
name, final Class<?> valueClass) {
while (type instanceof Operation) {
type = ((Operation) type).getResult();
}
if (type instanceof AttributeType<?>) {
- final AttributeType<?> at = ((AttributeType<?>)
type).characteristics().get(CRS_CHARACTERISTIC.toString());
+ final AttributeType<?> at = ((AttributeType<?>)
type).characteristics().get(name);
if (at != null) {
- return (CoordinateReferenceSystem) at.getDefaultValue();
+ return valueClass.isAssignableFrom(at.getValueClass());
}
}
- return null;
+ return false;
}
/**
- * Returns the maximal string length associated to the given attribute
type, or {@code null} if none.
- * This method searches for a characteristic named {@link
#MAXIMAL_LENGTH_CHARACTERISTIC}.
- *
- * @param type the attribute type for which to get the maximal string
length, or {@code null}.
- * @return The maximal string length for the given type, or {@code null}
if none.
- * @throws ClassCastException if {@link #MAXIMAL_LENGTH_CHARACTERISTIC}
has been found
- * but is associated to an object which is not an {@link Integer}
instance.
- */
- public static Integer getMaximalLength(final AttributeType<?> type){
- if (type != null) {
- final AttributeType<?> at =
type.characteristics().get(MAXIMAL_LENGTH_CHARACTERISTIC.toString());
+ * Fetches from the given property the value or default value of the named
characteristic.
+ * If the given property is null, or is not an attribute, or does not have
characteristics
+ * of the given name, then this method returns {@code null}.
+ *
+ * @param attribute the attribute from which to get the characteristic
value or default value, or {@code null}.
+ * @param name name of the characteristic to get.
+ * @return the value or default value of the given characteristic in the
given property, or {@code null} if none.
+ */
+ private static Object getCharacteristic(final Property attribute, final
String name) {
+ if (attribute instanceof Attribute<?>) {
+ final Attribute<?> at = ((Attribute<?>)
attribute).characteristics().get(name);
if (at != null) {
- return (Integer) at.getDefaultValue();
+ final Object value = at.getValue();
+ if (value != null) {
+ return value;
+ }
+ }
+ final AttributeType<?> type = ((Attribute<?>)
attribute).getType().characteristics().get(name);
+ if (type != null) {
+ return type.getDefaultValue();
}
}
return null;
Copied:
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java
(from r1739765,
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/BoundsOperationTest.java)
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java?p2=sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java&p1=sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/BoundsOperationTest.java&r1=1739765&r2=1739766&rev=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/BoundsOperationTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/EnvelopeOperationTest.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -16,116 +16,159 @@
*/
package org.apache.sis.feature;
+import java.util.Arrays;
+import java.util.Map;
import java.util.Collections;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.Polygon;
+import org.opengis.geometry.Envelope;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.internal.feature.NameConvention;
+import org.apache.sis.referencing.crs.HardCodedCRS;
import org.apache.sis.geometry.GeneralEnvelope;
-import org.apache.sis.referencing.CommonCRS;
+
+// Test dependencies
+import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
-import org.apache.sis.util.iso.Names;
-import org.apache.sis.internal.feature.FeatureTypeBuilder;
import org.junit.Test;
-import static org.junit.Assert.*;
+import static org.apache.sis.test.ReferencingAssert.*;
+
+// Branch-dependent imports
+import org.opengis.feature.PropertyType;
/**
- * Tests {@link BoundsOperation}.
+ * Tests {@link EnvelopeOperation}.
*
* @author Johann Sorel (Geomatys)
* @since 0.7
* @version 0.7
* @module
*/
-@DependsOn({
- AbstractOperationTest.class,
- DenseFeatureTest.class
-})
-public final strictfp class BoundsOperationTest extends TestCase {
+@DependsOn(LinkOperationTest.class)
+public final strictfp class EnvelopeOperationTest extends TestCase {
/**
* Creates a feature type with a bounds operation.
* The feature contains the following properties:
*
* <ul>
- * <li>{@code name} as a {@link String}</li>
+ * <li>{@code name} as a {@link String}</li>
* <li>{@code classes} as a {@link Polygon}</li>
* <li>{@code climbing wall} as a {@link Point}</li>
* <li>{@code gymnasium} as a {@link Polygon}</li>
+ * <li>{@code @geometry} as a link to the default geometry</li>
* <li>{@code bounds} as the feature envelope attribute.</li>
* </ul>
*
- * @return The feature for a city.
+ * @param defaultGeometry 1 for using "classes" as the default geometry,
or 3 for "gymnasium".
+ * @return the feature for a school.
+ */
+ private static DefaultFeatureType school(final int defaultGeometry) throws
FactoryException {
+ final DefaultAttributeType<?> standardCRS = new DefaultAttributeType<>(
+ name(NameConvention.CRS_CHARACTERISTIC),
CoordinateReferenceSystem.class, 1, 1, HardCodedCRS.WGS84_φλ);
+
+ final DefaultAttributeType<?> normalizedCRS = new
DefaultAttributeType<>(
+ name(NameConvention.CRS_CHARACTERISTIC),
CoordinateReferenceSystem.class, 1, 1, HardCodedCRS.WGS84);
+
+ final PropertyType[] attributes = {
+ new DefaultAttributeType<>(name("name"), String.class,
1, 1, null),
+ new DefaultAttributeType<>(name("classes"), Polygon.class,
1, 1, null, standardCRS),
+ new DefaultAttributeType<>(name("climbing wall"), Point.class,
1, 1, null, standardCRS),
+ new DefaultAttributeType<>(name("gymnasium"), Polygon.class,
1, 1, null, normalizedCRS),
+ null,
+ null
+ };
+ attributes[4] =
FeatureOperations.link(name(NameConvention.DEFAULT_GEOMETRY_PROPERTY),
attributes[defaultGeometry]);
+ attributes[5] = FeatureOperations.envelope(name("bounds"), null,
attributes);
+ return new DefaultFeatureType(name("school"), false, null, attributes);
+ }
+
+ /**
+ * Creates a map of identification properties containing only an entry for
the given name.
*/
- private static DefaultFeatureType school() {
- //Create type with an aggregation
- final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
- ftb.setName("school");
- ftb.addProperty("name", String.class);
- ftb.addProperty("classes", Polygon.class,
CommonCRS.WGS84.geographic());
- ftb.addProperty("climbing wall", Point.class,
CommonCRS.WGS84.geographic());
- ftb.addProperty("gymnasium", Polygon.class,
CommonCRS.WGS84.normalizedGeographic());
- ftb.addProperty(FeatureOperations.bounds(
- Collections.singletonMap(AbstractOperation.NAME_KEY,
Names.parseGenericName(null, ":", "bounds")),
- CommonCRS.WGS84.geographic()));
- return ftb.build();
+ private static Map<String,?> name(final Object name) {
+ return Collections.singletonMap(DefaultAttributeType.NAME_KEY, name);
+ }
+
+ /**
+ * Tests the constructor. The set of attributes on which the operation
depends shall include
+ * "classes", "climbing wall" and "gymnasium" but not "name" since the
later does not contain
+ * a geometry. Furthermore the default CRS shall be {@code
HardCodedCRS.WGS84}, not
+ * {@code HardCodedCRS.WGS84_φλ}, because this test uses "gymnasium" as
the default geometry.
+ *
+ * @throws FactoryException if an error occurred while searching for the
coordinate operations.
+ */
+ @Test
+ public void testConstruction() throws FactoryException {
+ final PropertyType property = school(3).getProperty("bounds");
+ assertInstanceOf("bounds", EnvelopeOperation.class, property);
+ final EnvelopeOperation op = (EnvelopeOperation) property;
+ assertSame("crs", HardCodedCRS.WGS84, op.crs);
+ assertSetEquals(Arrays.asList("classes", "climbing wall",
"gymnasium"), op.getDependencies());
}
/**
* Implementation of the test methods.
*/
private static void run(final AbstractFeature feature) {
- GeneralEnvelope bounds;
+ assertNull("Before a geometry is set",
feature.getPropertyValue("bounds"));
+ GeneralEnvelope expected;
- //no geometry set
- assertNull(feature.getPropertyValue("bounds"));
-
- //set one geometry
+ // Set one geometry
Polygon classes = new Polygon();
classes.startPath(10, 20);
classes.lineTo(10, 30);
classes.lineTo(15, 30);
classes.lineTo(15, 20);
feature.setPropertyValue("classes", classes);
- bounds = new GeneralEnvelope(CommonCRS.WGS84.geographic());
- bounds.setRange(0, 10, 15);
- bounds.setRange(1, 20, 30);
- assertEquals(bounds,feature.getPropertyValue("bounds"));
+ expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
+ expected.setRange(0, 10, 15);
+ expected.setRange(1, 20, 30);
+ assertEnvelopeEquals(expected, (Envelope)
feature.getPropertyValue("bounds"));
- //set second geometry
+ // Set second geometry
Point wall = new Point(18, 40);
feature.setPropertyValue("climbing wall", wall);
- bounds = new GeneralEnvelope(CommonCRS.WGS84.geographic());
- bounds.setRange(0, 10, 18);
- bounds.setRange(1, 20, 40);
- assertEquals(bounds,feature.getPropertyValue("bounds"));
+ expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
+ expected.setRange(0, 10, 18);
+ expected.setRange(1, 20, 40);
+ assertEnvelopeEquals(expected, (Envelope)
feature.getPropertyValue("bounds"));
- //set third geometry, this geometry has crs axis reversed
+ // Set third geometry. This geometry has CRS axis order reversed.
Polygon gymnasium = new Polygon();
gymnasium.startPath(-5, -30);
gymnasium.lineTo(-6, -30);
gymnasium.lineTo(-6, -31);
gymnasium.lineTo(-5, -31);
feature.setPropertyValue("gymnasium", gymnasium);
- bounds = new GeneralEnvelope(CommonCRS.WGS84.geographic());
- bounds.setRange(0, -31, 18);
- bounds.setRange(1, -6, 40);
- assertEquals(bounds,feature.getPropertyValue("bounds"));
+ expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
+ expected.setRange(0, -31, 18);
+ expected.setRange(1, -6, 40);
+ assertEnvelopeEquals(expected, (Envelope)
feature.getPropertyValue("bounds"));
}
/**
* Tests a dense type with operations.
+ *
+ * @throws FactoryException if an error occurred while searching for the
coordinate operations.
*/
@Test
- public void testDenseFeature() {
- run(new DenseFeature(school()));
+ @DependsOnMethod("testConstruction")
+ public void testDenseFeature() throws FactoryException {
+ run(new DenseFeature(school(1)));
}
/**
* Tests a sparse feature type with operations.
+ *
+ * @throws FactoryException if an error occurred while searching for the
coordinate operations.
*/
@Test
- public void testSparseFeature() {
- run(new SparseFeature(school()));
+ @DependsOnMethod("testConstruction")
+ public void testSparseFeature() throws FactoryException {
+ run(new SparseFeature(school(2)));
}
}
Modified:
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -39,10 +39,7 @@ import org.opengis.feature.InvalidProper
* @version 0.7
* @module
*/
-@DependsOn({
- AbstractOperationTest.class,
- DenseFeatureTest.class
-})
+@DependsOn(LinkOperationTest.class)
public final strictfp class StringJoinOperationTest extends TestCase {
/**
* Creates a feature type with an string join operation.
Modified:
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeTypeBuilderTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeTypeBuilderTest.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeTypeBuilderTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/AttributeTypeBuilderTest.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -21,6 +21,7 @@ import org.junit.Test;
import org.opengis.feature.AttributeType;
import static org.junit.Assert.*;
+
/**
* Tests {@link AttributeTypeBuilder}.
*
@@ -48,7 +49,7 @@ public class AttributeTypeBuilderTest ex
}
atb.setName("myScope","myName");
- final AttributeType att = atb.build();
+ final AttributeType<?> att = atb.build();
assertEquals("myScope:myName", att.getName().toString());
assertEquals(Object.class, att.getValueClass());
@@ -58,7 +59,7 @@ public class AttributeTypeBuilderTest ex
assertEquals(null, att.getDesignation());
assertEquals(1, att.getMinimumOccurs());
assertEquals(1, att.getMaximumOccurs());
-
+
}
/**
@@ -77,7 +78,7 @@ public class AttributeTypeBuilderTest ex
atb.setMinimumOccurs(10);
atb.setMaximumOccurs(60);
atb.setLengthCharacteristic(80);
- final AttributeType att = atb.build();
+ final AttributeType<?> att = atb.build();
assertEquals("myScope:myName", att.getName().toString());
assertEquals("test definition", att.getDefinition().toString());
@@ -87,7 +88,7 @@ public class AttributeTypeBuilderTest ex
assertEquals("test text with words and letters.",
att.getDefaultValue());
assertEquals(10, att.getMinimumOccurs());
assertEquals(60, att.getMaximumOccurs());
- assertEquals(80, (int)NameConvention.getMaximalLength(att));
+// assertEquals(Integer.valueOf(80),
NameConvention.getMaximalLengthCharacteristic(att));
}
/**
@@ -106,7 +107,7 @@ public class AttributeTypeBuilderTest ex
atb.setMinimumOccurs(10);
atb.setMaximumOccurs(60);
atb.setLengthCharacteristic(80);
- AttributeType att = atb.build();
+ AttributeType<?> att = atb.build();
//copy the attribute
atb = new AttributeTypeBuilder();
@@ -121,7 +122,7 @@ public class AttributeTypeBuilderTest ex
assertEquals("test text with words and letters.",
att.getDefaultValue());
assertEquals(10, att.getMinimumOccurs());
assertEquals(60, att.getMaximumOccurs());
- assertEquals(80, (int)NameConvention.getMaximalLength(att));
+// assertEquals(Integer.valueOf(80),
NameConvention.getMaximalLengthCharacteristic(att));
}
/**
Modified:
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/NameConventionTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/NameConventionTest.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/NameConventionTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/internal/feature/NameConventionTest.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -29,7 +29,7 @@ import org.junit.Test;
import static org.junit.Assert.*;
// Branch-dependent imports
-import org.opengis.feature.AttributeType;
+import org.opengis.feature.Property;
import org.opengis.feature.IdentifiedType;
@@ -37,6 +37,7 @@ import org.opengis.feature.IdentifiedTyp
* Tests {@link NameConvention}.
*
* @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @since 0.7
* @version 0.7
* @module
@@ -67,13 +68,15 @@ public final strictfp class NameConventi
}
/**
- * Tests {@link
NameConvention#getCoordinateReferenceSystem(IdentifiedType)} method.
+ * Tests {@link NameConvention#characterizedByCRS(IdentifiedType)} and
+ * {@link NameConvention#getCrsCharacteristic(Property)} methods.
*/
@Test
- public void testGetCoordinateReferenceSystem() {
+ public void testGetCrsCharacteristic() {
final Map<String,?> properties =
Collections.singletonMap(DefaultAttributeType.NAME_KEY, "geometry");
DefaultAttributeType<Point> type = new
DefaultAttributeType<>(properties, Point.class, 1, 1, null);
- assertNull("Without characteristic",
NameConvention.getCoordinateReferenceSystem(type));
+ assertFalse("characterizedByCRS",
NameConvention.characterizedByCRS(type));
+ assertNull("getCrsCharacteristic",
NameConvention.getCrsCharacteristic(type.newInstance()));
/*
* Creates an attribute associated to an attribute (i.e. a
"characteristic") for storing
* the Coordinate Reference System of the "geometry" attribute. Then
test again.
@@ -83,17 +86,20 @@ public final strictfp class NameConventi
CoordinateReferenceSystem.class, 1, 1, HardCodedCRS.WGS84);
type = new DefaultAttributeType<>(properties, Point.class, 1, 1, null,
characteristic);
- assertEquals(HardCodedCRS.WGS84,
NameConvention.getCoordinateReferenceSystem(type));
+ assertTrue(NameConvention.characterizedByCRS(type));
+ assertEquals(HardCodedCRS.WGS84,
NameConvention.getCrsCharacteristic(type.newInstance()));
}
/**
- * Tests {@link NameConvention#getMaximalLength(AttributeType)} method.
+ * Tests {@link
NameConvention#characterizedByMaximalLength(IdentifiedType)} and
+ * {@link NameConvention#getMaximalLengthCharacteristic(Property)} methods.
*/
@Test
- public void testGetMaximalLength() {
+ public void testGetMaximalLengthCharacteristic() {
final Map<String,?> properties =
Collections.singletonMap(DefaultAttributeType.NAME_KEY, "name");
DefaultAttributeType<String> type = new
DefaultAttributeType<>(properties, String.class, 1, 1, null);
- assertNull("Without characteristic",
NameConvention.getMaximalLength(type));
+ assertFalse("characterizedByMaximalLength",
NameConvention.characterizedByMaximalLength(type));
+ assertNull("getMaximalLengthCharacteristic",
NameConvention.getMaximalLengthCharacteristic(type.newInstance()));
/*
* Creates an attribute associated to an attribute (i.e. a
"characteristic") for storing
* the maximal length of the "name" attribute. Then test again.
@@ -103,6 +109,7 @@ public final strictfp class NameConventi
Integer.class, 1, 1, 120);
type = new DefaultAttributeType<>(properties, String.class, 1, 1,
null, characteristic);
- assertEquals(Integer.valueOf(120),
NameConvention.getMaximalLength(type));
+ assertTrue("characterizedByMaximalLength",
NameConvention.characterizedByMaximalLength(type));
+ assertEquals(Integer.valueOf(120),
NameConvention.getMaximalLengthCharacteristic(type.newInstance()));
}
}
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=1739766&r1=1739765&r2=1739766&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] Mon Apr 18 14:43:16 2016
@@ -45,7 +45,7 @@ import org.junit.BeforeClass;
org.apache.sis.feature.AbstractOperationTest.class,
org.apache.sis.feature.LinkOperationTest.class,
org.apache.sis.feature.StringJoinOperationTest.class,
- org.apache.sis.feature.BoundsOperationTest.class,
+ org.apache.sis.feature.EnvelopeOperationTest.class,
org.apache.sis.feature.FeatureFormatTest.class,
org.apache.sis.feature.FeaturesTest.class,
org.apache.sis.filter.DefaultLiteralTest.class,
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java?rev=1739766&r1=1739765&r2=1739766&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
[UTF-8] Mon Apr 18 14:43:16 2016
@@ -35,6 +35,7 @@ import org.opengis.referencing.cs.Coordi
import org.opengis.referencing.cs.RangeMeaning;
import org.opengis.util.GenericName;
import org.apache.sis.geometry.AbstractEnvelope;
+import org.apache.sis.geometry.Envelopes;
import org.apache.sis.geometry.GeneralDirectPosition;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.referencing.IdentifiedObjects;
@@ -51,7 +52,7 @@ import static java.lang.StrictMath.*;
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.3
- * @version 0.6
+ * @version 0.7
* @module
*/
public strictfp class ReferencingAssert extends MetadataAssert {
@@ -66,8 +67,8 @@ public strictfp class ReferencingAssert
* The authority is expected to be {@link Citations#OGC}. We expect the
exact same authority
* instance because identifiers in OGC namespace are often hard-coded in
SIS.
*
- * @param expected The expected identifier code.
- * @param actual The identifier to verify.
+ * @param expected the expected identifier code.
+ * @param actual the identifier to verify.
*
* @since 0.6
*/
@@ -84,8 +85,8 @@ public strictfp class ReferencingAssert
* Asserts that the given identifier has the expected code and the {@code
"EPSG"} code space.
* The authority is expected to have the {@code "EPSG"} title, alternate
title or identifier.
*
- * @param expected The expected identifier code.
- * @param actual The identifier to verify.
+ * @param expected the expected identifier code.
+ * @param actual the identifier to verify.
*
* @since 0.5
*/
@@ -103,9 +104,9 @@ public strictfp class ReferencingAssert
* No other identifier than the given one is expected. The authority is
expected to have the {@code "EPSG"} title,
* alternate title or identifier.
*
- * @param name The expected EPSG name.
- * @param identifier The expected EPSG identifier.
- * @param object The object to verify.
+ * @param name the expected EPSG name.
+ * @param identifier the expected EPSG identifier.
+ * @param object the object to verify.
*
* @since 0.6
*/
@@ -119,8 +120,8 @@ public strictfp class ReferencingAssert
* Asserts that the tip of the unique alias of the given object is equals
to the expected value.
* As a special case if the expected value is null, then this method
verifies that the given object has no alias.
*
- * @param expected The expected alias, or {@code null} if we expect no
alias.
- * @param object The object for which to test the alias.
+ * @param expected the expected alias, or {@code null} if we expect no
alias.
+ * @param object the object for which to test the alias.
*/
public static void assertAliasTipEquals(final String expected, final
IdentifiedObject object) {
final Collection<GenericName> aliases = object.getAlias();
@@ -134,14 +135,14 @@ public strictfp class ReferencingAssert
/**
* Compares the given coordinate system axis against the expected values.
*
- * @param name The expected axis name code.
- * @param abbreviation The expected axis abbreviation.
- * @param direction The expected axis direction.
- * @param minimumValue The expected axis minimal value.
- * @param maximumValue The expected axis maximal value.
- * @param unit The expected axis unit of measurement.
- * @param rangeMeaning The expected axis range meaning.
- * @param axis The axis to verify.
+ * @param name the expected axis name code.
+ * @param abbreviation the expected axis abbreviation.
+ * @param direction the expected axis direction.
+ * @param minimumValue the expected axis minimal value.
+ * @param maximumValue the expected axis maximal value.
+ * @param unit the expected axis unit of measurement.
+ * @param rangeMeaning the expected axis range meaning.
+ * @param axis the axis to verify.
*/
public static void assertAxisEquals(final String name, final String
abbreviation, final AxisDirection direction,
final double minimumValue, final double maximumValue, final
Unit<?> unit, final RangeMeaning rangeMeaning,
@@ -161,9 +162,9 @@ public strictfp class ReferencingAssert
* a positive delta. Only the elements in the given descriptor are
compared, and
* the comparisons are done in the units declared in the descriptor.
*
- * @param expected The expected parameter values.
- * @param actual The actual parameter values.
- * @param tolerance The tolerance threshold for comparison of numerical
values.
+ * @param expected the expected parameter values.
+ * @param actual the actual parameter values.
+ * @param tolerance the tolerance threshold for comparison of numerical
values.
*/
public static void assertParameterEquals(final ParameterValueGroup
expected,
final ParameterValueGroup actual, final double tolerance)
@@ -196,13 +197,13 @@ public strictfp class ReferencingAssert
* to the given values. The matrix doesn't need to be square. The last row
is handled especially
* if the {@code affine} argument is {@code true}.
*
- * @param expected The values which are expected on the diagonal. If the
length of this array
- * is less than the matrix size, then the last element in
the array is repeated
- * for all remaining diagonal elements.
- * @param affine If {@code true}, then the last row is expected to
contains the value 1
- * in the last column, and all other columns set to 0.
- * @param matrix The matrix to test.
- * @param tolerance The tolerance threshold while comparing floating point
values.
+ * @param expected the values which are expected on the diagonal. If the
length of this array
+ * is less than the matrix size, then the last element
in the array is repeated
+ * for all remaining diagonal elements.
+ * @param affine if {@code true}, then the last row is expected to
contains the value 1
+ * in the last column, and all other columns set to 0.
+ * @param matrix the matrix to test.
+ * @param tolerance the tolerance threshold while comparing floating
point values.
*/
public static void assertDiagonalEquals(final double[] expected, final
boolean affine,
final Matrix matrix, final double tolerance)
@@ -231,9 +232,9 @@ public strictfp class ReferencingAssert
/**
* Compares two affine transforms for equality.
*
- * @param expected The expected affine transform.
- * @param actual The actual affine transform.
- * @param tolerance The tolerance threshold.
+ * @param expected the expected affine transform.
+ * @param actual the actual affine transform.
+ * @param tolerance the tolerance threshold.
*/
public static void assertTransformEquals(final AffineTransform expected,
final AffineTransform actual, final double tolerance) {
assertEquals("scaleX", expected.getScaleX(),
actual.getScaleX(), tolerance);
@@ -247,10 +248,10 @@ public strictfp class ReferencingAssert
/**
* Asserts that two rectangles have the same location and the same size.
*
- * @param expected The expected rectangle.
- * @param actual The rectangle to compare with the expected one.
- * @param tolx The tolerance threshold on location along the
<var>x</var> axis.
- * @param toly The tolerance threshold on location along the
<var>y</var> axis.
+ * @param expected the expected rectangle.
+ * @param actual the rectangle to compare with the expected one.
+ * @param tolx the tolerance threshold on location along the
<var>x</var> axis.
+ * @param toly the tolerance threshold on location along the
<var>y</var> axis.
*/
public static void assertRectangleEquals(final RectangularShape expected,
final RectangularShape actual, final double tolx, final double
toly)
@@ -266,6 +267,36 @@ public strictfp class ReferencingAssert
}
/**
+ * Asserts that two envelopes have the same minimum and maximum ordinates.
+ * This method ignores the envelope type (i.e. the implementation class)
and the CRS.
+ *
+ * @param expected the expected envelope.
+ * @param actual the envelope to compare with the expected one.
+ * @param tolerances the tolerance threshold on location along each axis.
If this array length is shorter
+ * than the number of dimensions, then the last
tolerance is reused for all remaining axes.
+ * If this array is empty, then the tolerance threshold
is zero.
+ *
+ * @since 0.7
+ */
+ public static void assertEnvelopeEquals(final Envelope expected, final
Envelope actual, final double... tolerances) {
+ final int dimension = expected.getDimension();
+ assertEquals("dimension", dimension, actual.getDimension());
+ double tolerance = 0;
+ for (int i=0; i<dimension; i++) {
+ if (i < tolerances.length) {
+ tolerance = tolerances[i];
+ }
+ if (abs(expected.getMinimum(i) - actual.getMinimum(i)) > tolerance
||
+ abs(expected.getMaximum(i) - actual.getMaximum(i)) > tolerance)
+ {
+ fail("Envelopes are not equal:\n"
+ + "expected " + Envelopes.toString(expected) + "\n"
+ + " but got " + Envelopes.toString(actual));
+ }
+ }
+ }
+
+ /**
* Tests if the given {@code outer} shape contains the given {@code inner}
rectangle.
* This method will also verify class consistency by invoking the {@code
intersects}
* method, and by interchanging the arguments.
@@ -273,8 +304,8 @@ public strictfp class ReferencingAssert
* <p>This method can be used for testing the {@code outer} implementation
-
* it should not be needed for standard JDK implementations.</p>
*
- * @param outer The shape which is expected to contains the given
rectangle.
- * @param inner The rectangle which should be contained by the shape.
+ * @param outer the shape which is expected to contains the given
rectangle.
+ * @param inner the rectangle which should be contained by the shape.
*/
public static void assertContains(final RectangularShape outer, final
Rectangle2D inner) {
assertTrue("outer.contains(inner)", outer.contains (inner));
@@ -292,8 +323,8 @@ public strictfp class ReferencingAssert
* This method will also verify class consistency by invoking the {@code
intersects}
* method, and by interchanging the arguments.
*
- * @param outer The envelope which is expected to contains the given inner
envelope.
- * @param inner The envelope which should be contained by the outer
envelope.
+ * @param outer the envelope which is expected to contains the given
inner envelope.
+ * @param inner the envelope which should be contained by the outer
envelope.
*/
public static void assertContains(final AbstractEnvelope outer, final
Envelope inner) {
assertTrue("outer.contains(inner)", outer.contains (inner, true));
@@ -322,8 +353,8 @@ public strictfp class ReferencingAssert
* <p>This method can be used for testing the {@code r1} implementation -
it should not
* be needed for standard implementations.</p>
*
- * @param r1 The first shape to test.
- * @param r2 The second rectangle to test.
+ * @param r1 the first shape to test.
+ * @param r2 the second rectangle to test.
*/
public static void assertDisjoint(final RectangularShape r1, final
Rectangle2D r2) {
assertFalse("r1.intersects(r2)", r1.intersects(r2));
@@ -355,8 +386,8 @@ public strictfp class ReferencingAssert
* This method will also verify class consistency by invoking the {@code
contains} method,
* and by interchanging the arguments.
*
- * @param e1 The first envelope to test.
- * @param e2 The second envelope to test.
+ * @param e1 the first envelope to test.
+ * @param e2 the second envelope to test.
*/
public static void assertDisjoint(final AbstractEnvelope e1, final
Envelope e2) {
assertFalse("e1.intersects(e2)", e1.intersects(e2, false));
@@ -395,7 +426,7 @@ public strictfp class ReferencingAssert
* Tests if the given transform is the identity transform.
* If the current transform is linear, then this method will also verifies
{@link Matrix#isIdentity()}.
*
- * @param transform The transform to test.
+ * @param transform the transform to test.
*
* @since 0.6
*/
@@ -410,7 +441,7 @@ public strictfp class ReferencingAssert
* Tests if the given transform is <strong>not</strong> the identity
transform.
* If the current transform is linear, then this method will also verifies
{@link Matrix#isIdentity()}.
*
- * @param transform The transform to test.
+ * @param transform the transform to test.
*
* @since 0.6
*/