Author: desruisseaux
Date: Wed Apr 13 21:59:55 2016
New Revision: 1739012
URL: http://svn.apache.org/viewvc?rev=1739012&view=rev
Log:
Javadoc and argument validations.
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java
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/feature/FeatureOperations.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1739012&r1=1739011&r2=1739012&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] Wed Apr 13 21:59:55 2016
@@ -228,7 +228,7 @@ public abstract class AbstractFeature im
final Object getOperationValue(final String name) {
final Operation operation = (Operation) type.getProperty(name);
if (operation instanceof LinkOperation) {
- return getPropertyValue(((LinkOperation) operation).propertyName);
+ return getPropertyValue(((LinkOperation) operation).referentName);
}
final Property result = operation.apply(this, null);
if (result instanceof Attribute<?>) {
@@ -246,7 +246,7 @@ public abstract class AbstractFeature im
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);
+ setPropertyValue(((LinkOperation) operation).referentName, value);
} else {
final Property result = operation.apply(this, null);
if (result != null) {
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java?rev=1739012&r1=1739011&r2=1739012&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java
[UTF-8] Wed Apr 13 21:59:55 2016
@@ -18,29 +18,37 @@ package org.apache.sis.feature;
import java.util.Map;
import java.util.Collections;
+import java.util.Set;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.util.GenericName;
+import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ObjectConverters;
+
+// Branch-dependent imports
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.Property;
-import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.util.GenericName;
-import org.apache.sis.util.ObjectConverters;
/**
- * An aggregate operation concatenating the values of multiple properties.
- * This operation is mainly used as an {@code id} generator for multiple
properties used as primary keys.
+ * An operation concatenating the string representations of the values of
multiple properties.
+ * This operation can be used for creating a <cite>compound key</cite> as a
{@link String}
+ * that consists of two or more attribute values that uniquely identify a
feature instance.
*
- * <p>This operation support both reading and writing. When setting the
operation value,
- * the value will be split and forwarded to each attribute element.</p>
+ * <p>This operation supports both reading and writing. When setting a value
on the attribute
+ * created by this operation, the value will be split and forwarded to each
single attribute.</p>
*
* @author Johann Sorel (Geomatys)
* @since 0.7
* @version 0.7
* @module
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Compound_key">Compound key on
Wikipedia</a>
*/
final class AggregateOperation extends AbstractOperation {
/**
@@ -52,28 +60,57 @@ final class AggregateOperation extends A
* The type of the result returned by the aggregate operation.
*/
private static final AttributeType<String> TYPE = new
DefaultAttributeType<>(
- Collections.singletonMap(DefaultAttributeType.NAME_KEY, "String"),
String.class, 1, 1, null);
+ Collections.singletonMap(NAME_KEY, "String"), String.class, 1, 1,
null);
/**
* The parameter descriptor for the "Aggregate" operation, which does not
take any parameter.
*/
private static final ParameterDescriptorGroup EMPTY_PARAMS =
LinkOperation.parameters("Aggregate", 1);
- private final GenericName[] attributeNames;
+ /**
+ * The name of the properties from which to get the values to concatenate.
+ */
+ private final String[] propertyNames;
+
+ /**
+ * The property names as an unmodifiable set, created when first needed.
+ */
+ private transient Set<String> dependencies;
+
+ /**
+ * The characters to use at the beginning of the concatenated string, or
an empty string if none.
+ */
private final String prefix;
+
+ /**
+ * The characters to use at the end of the concatenated string, or an
empty string if none.
+ */
private final String suffix;
+
+ /**
+ * The characters to use a delimiter between each single attribute value.
+ */
private final String separator;
- AggregateOperation(Map<String, ?> identification, String prefix, String
suffix, String separator, GenericName ... attributeNames) {
+ /**
+ * Creates a new operation for string concatenations using the given
prefix, suffix and delimeter.
+ */
+ AggregateOperation(final Map<String, ?> identification, final String
prefix, final String suffix,
+ final String separator, final GenericName[] singleProperties)
+ {
super(identification);
- this.attributeNames = attributeNames;
+ propertyNames = new String[singleProperties.length];
+ for (int i=0; i < singleProperties.length; i++) {
+ ArgumentChecks.ensureNonNullElement("singleProperties", i,
singleProperties);
+ propertyNames[i] = singleProperties[i].toString();
+ }
this.prefix = (prefix == null) ? "" : prefix;
this.suffix = (suffix == null) ? "" : suffix;
this.separator = separator;
}
/**
- * Aggregation operation do not require any parameter.
+ * Concatenate operation do not require any parameter.
*
* @return empty parameter group.
*/
@@ -83,9 +120,9 @@ final class AggregateOperation extends A
}
/**
- * Aggregation operation generates a String result.
+ * Concatenate operation generates a {@link String} result.
*
- * @return aggregation string type
+ * @return concatenated string type.
*/
@Override
public IdentifiedType getResult() {
@@ -93,16 +130,27 @@ final class AggregateOperation extends A
}
/**
- * {@inheritDoc }
+ * 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, propertyNames);
+ }
+ return dependencies;
+ }
+
+ /**
+ * Returns the concatenation of property values of the given feature.
*
- * @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 concatenation of feature property values.
*/
@Override
public Property apply(Feature feature, ParameterValueGroup parameters) {
+ ArgumentChecks.ensureNonNull("feature", feature);
return new AggregateAttribute(feature);
}
@@ -124,9 +172,9 @@ final class AggregateOperation extends A
final StringBuilder sb = new StringBuilder();
sb.append(prefix);
- for (int i=0; i < attributeNames.length; i++) {
- if (i!=0) sb.append(separator);
-
sb.append(feature.getPropertyValue(attributeNames[i].toString()));
+ for (int i=0; i < propertyNames.length; i++) {
+ if (i != 0) sb.append(separator);
+ sb.append(feature.getPropertyValue(propertyNames[i]));
}
sb.append(suffix);
@@ -144,7 +192,7 @@ final class AggregateOperation extends A
}
//split values, we don't use the regex split to avoid possible
reserverd regex characters
- final Object[] values = new Object[attributeNames.length];
+ final Object[] values = new Object[propertyNames.length];
int i = 0;
int offset = 0;
//remove prefix and suffix
@@ -154,14 +202,12 @@ final class AggregateOperation extends A
throw new IllegalArgumentException("Unvalid string,
expected "+values.length+" values, but found more");
}
final int idx = value.indexOf(separator, offset);
- if (idx == -1) {
+ if (idx < 0) {
//last element
- values[i] = value.substring(offset);
- i++;
+ values[i++] = value.substring(offset);
break;
} else {
- values[i] = value.substring(offset, idx);
- i++;
+ values[i++] = value.substring(offset, idx);
offset = (idx + separator.length());
}
}
@@ -173,7 +219,7 @@ final class AggregateOperation extends A
//set values, convert them if necessary
final FeatureType type = feature.getType();
for (int k=0; k < values.length; k++) {
- final String propName = attributeNames[k].toString();
+ final String propName = propertyNames[k];
final AttributeType<?> pt = (AttributeType<?>)
type.getProperty(propName);
final Object val = ObjectConverters.convert(values[k],
pt.getValueClass());
feature.setPropertyValue(propName, val);
Modified:
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/BoundsOperation.java?rev=1739012&r1=1739011&r2=1739012&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/BoundsOperation.java
[UTF-8] Wed Apr 13 21:59:55 2016
@@ -22,8 +22,6 @@ import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
-import static org.apache.sis.feature.AbstractIdentifiedType.NAME_KEY;
-import static org.apache.sis.feature.LinkOperation.parameters;
import org.apache.sis.geometry.Envelopes;
import org.apache.sis.geometry.GeneralEnvelope;
import org.opengis.feature.AttributeType;
@@ -52,7 +50,7 @@ import org.opengis.referencing.operation
* crs will be used.
* <br>
* This operation can only be read, not setted.
- *
+ *
* @author Johann Sorel (Geomatys)
* @since 0.7
* @version 0.7
@@ -70,12 +68,12 @@ final class BoundsOperation extends Abst
/**
* The parameter descriptor for the "Bounds" operation, which does not
take any parameter.
*/
- private static final ParameterDescriptorGroup EMPTY_PARAMS =
parameters("Link", 1);
+ private static final ParameterDescriptorGroup EMPTY_PARAMS =
LinkOperation.parameters("Bounds", 1);
private final CoordinateReferenceSystem crs;
/**
- *
+ *
* @param identification The name and other information to be given to
this operation.
* @param crs result envelope CRS, can be {@code null}
*/
@@ -198,5 +196,5 @@ final class BoundsOperation extends Abst
return bounds;
}
-
+
}
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=1739012&r1=1739011&r2=1739012&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] Wed Apr 13 21:59:55 2016
@@ -17,56 +17,102 @@
package org.apache.sis.feature;
import java.util.Collections;
-import org.apache.sis.util.Static;
import org.opengis.feature.Operation;
import org.opengis.feature.PropertyType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.util.GenericName;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Static;
+
/**
- * FeatureType operations utility methods.
+ * A set of pre-defined operations expecting a {@code Feature} as input and
producing an {@code Attribute} as output.
+ * Those operations can be used for creating <cite>dynamic properties</cite>
which compute their value on-the-fly
+ * from the values of other properties.
*
- * @author Johann Sorel (Geomatys)
+ * <p>A flexible but relatively cumbersome way to define arbitrary
computations is to subclass {@link AbstractOperation}.
+ * This {@code FeatureOperations} class provides a more convenient way to get
a few commonly-used operations.</p>
+ *
+ * @author Johann Sorel (Geomatys)
* @since 0.7
* @version 0.7
* @module
*/
public final class FeatureOperations extends Static {
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private FeatureOperations() {
+ }
/**
- * Create a link operation property type.
+ * Creates an operation which is only an alias for another property.
*
- * @param name name of the property
- * @param linkAttributeType linked property type
- * @return Operation
+ * <div class="note"><b>Example:</b>
+ * features often have a property that can be used as identifier or
primary key.
+ * But the name of that property may vary between features of different
types.
+ * For example features of type <b>Country</b> may have identifiers named
“ISO country code”
+ * while features of type <b>Car</b> may have identifiers named “license
plate number”.
+ * In order to simplify identifier usages regardless of their name,
+ * an application could choose to add in all features a virtual property
named {@code "@id"}
+ * which links to whatever property is used as an identifier in an
arbitrary feature.
+ * So the definition of the <b>Car</b> feature could contain the following
code:
+ *
+ * {@preformat java
+ * AttributeType licensePlateNumber = ...; // Attribute
creation omitted for brevity
+ * FeatureType car = new DefaultFeatureType(..., // Arguments
omitted for brevity
+ * licensePlateNumber, model, owner,
+ * FeatureOperations.link(singletonMap(NAME_KEY, "@id"),
licensePlateNumber);
+ * }
+ * </div>
+ *
+ * <div class="section">Read/write behavior</div>
+ * Since the {@link AbstractOperation#apply Operation.apply(…)} method
returns directly the property
+ * identified by the {@code referent} argument, the returned property is
writable if the referenced
+ * property is also writable.
+ *
+ * @param name name of the property to create.
+ * @param referent the referenced attribute or feature association.
+ * @return an operation which is an alias for the {@code referent}
property.
*/
- public static Operation link(GenericName name, PropertyType
linkAttributeType){
- return new LinkOperation(Collections.singletonMap("name", name),
linkAttributeType);
+ public static Operation link(final GenericName name, final PropertyType
referent) {
+ ArgumentChecks.ensureNonNull("referent", referent);
+ return new LinkOperation(Collections.singletonMap("name", name),
referent);
}
/**
- * Create an aggregation operation property type.
+ * Creates an operation concatenating the string representations of the
values of multiple properties.
+ * This operation can be used for creating a <cite>compound key</cite> as
a {@link String} that consists
+ * of two or more attribute values that uniquely identify a feature
instance.
*
- * @param name name of the property
- * @param prefix prefix of the resulting aggregated string
- * @param suffix suffix of the resulting aggregated string
- * @param separator separator between each value
- * @param aggAttributeNames aggregated attribute values
- * @return Operation
+ * <div class="section">Read/write behavior</div>
+ * This operation supports both reading and writing. When setting a value
on the attribute created by this
+ * operation, the given string value will be split around the {@code
separator} and each substring will be
+ * forwarded to the corresponding single property.
+ *
+ * @param name name of the property to create.
+ * @param prefix characters to use at the beginning of the
concatenated string, or {@code null} if none.
+ * @param suffix characters to use at the end of the concatenated
string, or {@code null} if none.
+ * @param separator the characters to use a delimiter between each
single attribute value.
+ * @param singleProperties identification of the single properties to
concatenate.
+ * @return an operation which concatenates the string representations of
all referenced single attribute values.
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Compound_key">Compound key
on Wikipedia</a>
*/
- public static Operation aggregate(GenericName name, String prefix, String
suffix, String separator, GenericName ... aggAttributeNames){
- return new AggregateOperation(Collections.singletonMap("name", name),
prefix, suffix, separator, aggAttributeNames);
+ public static Operation aggregate(GenericName name, String prefix, String
suffix, String separator, GenericName... singleProperties) {
+ ArgumentChecks.ensureNonEmpty("separator", separator);
+ ArgumentChecks.ensureNonNull("singleProperties", singleProperties);
+ return new AggregateOperation(Collections.singletonMap("name", name),
prefix, suffix, separator, singleProperties);
}
/**
- * Create a calculate bounds operation type.
+ * Creates a calculate bounds operation type.
*
* @param name name of the property
* @param baseCrs created envelope crs
* @return Operation
*/
- public static Operation bounds(GenericName name, CoordinateReferenceSystem
baseCrs){
+ public static Operation bounds(GenericName name, CoordinateReferenceSystem
baseCrs) {
return new BoundsOperation(Collections.singletonMap("name", name),
baseCrs);
}
-
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java?rev=1739012&r1=1739011&r2=1739012&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/LinkOperation.java
[UTF-8] Wed Apr 13 21:59:55 2016
@@ -82,18 +82,18 @@ final class LinkOperation extends Abstra
/**
* The name of the referenced attribute or feature association.
*/
- final String propertyName;
+ final String referentName;
/**
* Creates a new link to the given attribute or association.
*
- * @param identification The name of the link, together with optional
information.
- * @param propertyType The referenced attribute or feature association.
+ * @param identification the name of the link, together with optional
information.
+ * @param referent the referenced attribute or feature association.
*/
- LinkOperation(final Map<String, ?> identification, final PropertyType
propertyType) {
+ LinkOperation(final Map<String, ?> identification, final PropertyType
referent) {
super(identification);
- result = propertyType;
- propertyName = propertyType.getName().toString();
+ result = referent;
+ referentName = referent.getName().toString();
}
/**
@@ -117,19 +117,19 @@ final class LinkOperation extends Abstra
*/
@Override
public Set<String> getDependencies() {
- return Collections.singleton(propertyName);
+ return Collections.singleton(referentName);
}
/**
* Returns the property from the referenced attribute of feature
association.
*
- * @param feature The feature from which to get the property.
- * @param parameters Ignored.
- * @return The property from the given feature.
+ * @param feature the feature from which to get the property.
+ * @param parameters ignored (can be {@code null}).
+ * @return the linked property from the given feature.
*/
@Override
public Property apply(final Feature feature, final ParameterValueGroup
parameters) {
ArgumentChecks.ensureNonNull("feature", feature);
- return feature.getProperty(propertyName);
+ return feature.getProperty(referentName);
}
}