sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1739058 - in /sis/branches/JDK8/core/sis-feature/src: main/java/org/apache/sis/feature/ main/java/org/apache/sis/internal/feature/ test/java/org/apache/sis/feature/ test/java/org/apache/sis/test/suite/
Date Thu, 14 Apr 2016 11:24:59 GMT
Author: desruisseaux
Date: Thu Apr 14 11:24:59 2016
New Revision: 1739058

URL: http://svn.apache.org/viewvc?rev=1739058&view=rev
Log:
Rename AggregateOperation as StringJoinOperation.
Replace GenericName argument by a map of identification info.
Document how the identification info are used for the operation result.

Added:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
      - copied, changed from r1739057, sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
      - copied, changed from r1739057, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AggregateOperationTest.java
Removed:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AggregateOperationTest.java
Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.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
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/BoundsOperationTest.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java?rev=1739058&r1=1739057&r2=1739058&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractIdentifiedType.java
[UTF-8] Thu Apr 14 11:24:59 2016
@@ -162,7 +162,7 @@ public class AbstractIdentifiedType impl
      * is used only on a <cite>best effort</cite> basis. The locale is discarded
after successful construction
      * since localizations are applied by the {@link InternationalString#toString(Locale)}
method.</p>
      *
-     * @param  identification The name and other information to be given to this identified
type.
+     * @param  identification  the name and other information to be given to this identified
type.
      * @throws IllegalArgumentException if a property has an invalid value.
      */
     @SuppressWarnings("OverridableMethodCallDuringObjectConstruction")

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java?rev=1739058&r1=1739057&r2=1739058&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractOperation.java
[UTF-8] Thu Apr 14 11:24:59 2016
@@ -19,6 +19,7 @@ package org.apache.sis.feature;
 import java.util.Map;
 import java.util.Set;
 import java.util.Collections;
+import java.util.HashMap;
 import org.opengis.util.GenericName;
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
@@ -69,6 +70,12 @@ public abstract class AbstractOperation
     private static final long serialVersionUID = -179930765502963170L;
 
     /**
+     * The prefix for result identification entries in the {@code identification} map.
+     * This prefix is documented in {@link FeatureOperations} javadoc.
+     */
+    static final String RESULT_PREFIX = "result.";
+
+    /**
      * Constructs an operation from the given properties. The identification map is given
unchanged to
      * the {@linkplain AbstractIdentifiedType#AbstractIdentifiedType(Map) super-class constructor}.
      *
@@ -79,6 +86,27 @@ public abstract class AbstractOperation
     }
 
     /**
+     * Returns a map that can be used for creating the {@link #getResult()} type.
+     * This method can be invoked for subclass constructor.
+     */
+    final Map<String,Object> resultIdentification(final Map<String,?> identification)
{
+        final Map<String,Object> properties = new HashMap<>(6);
+        for (final Map.Entry<String,?> entry : identification.entrySet()) {
+            final String key = entry.getKey();
+            if (key != null && key.startsWith(RESULT_PREFIX)) {
+                properties.put(key.substring(RESULT_PREFIX.length()), entry.getValue());
+            }
+        }
+        if (properties.isEmpty()) {
+            properties.put(NAME_KEY,        super.getName());           // Do not invoke
user-overrideable method.
+            properties.put(DEFINITION_KEY,  super.getDefinition());
+            properties.put(DESIGNATION_KEY, super.getDesignation());
+            properties.put(DESCRIPTION_KEY, super.getDescription());
+        }
+        return properties;
+    }
+
+    /**
      * Returns a description of the input parameters.
      *
      * @return Description of the input parameters.

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=1739058&r1=1739057&r2=1739058&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] Thu Apr 14 11:24:59 2016
@@ -16,14 +16,21 @@
  */
 package org.apache.sis.feature;
 
-import org.apache.sis.internal.feature.AttributeConvention;
-import com.esri.core.geometry.Geometry;
 import java.util.Collections;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import com.esri.core.geometry.Geometry;
+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.TransformException;
+import org.apache.sis.internal.feature.AttributeConvention;
 import org.apache.sis.geometry.Envelopes;
 import org.apache.sis.geometry.GeneralEnvelope;
+
+// Branch-dependent imports
 import org.opengis.feature.AttributeType;
 import org.opengis.feature.Feature;
 import org.opengis.feature.FeatureType;
@@ -31,11 +38,7 @@ import org.opengis.feature.IdentifiedTyp
 import org.opengis.feature.MultiValuedPropertyException;
 import org.opengis.feature.Property;
 import org.opengis.feature.PropertyType;
-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.TransformException;
+
 
 /**
  * Calculate feature bounds operation.
@@ -51,7 +54,7 @@ import org.opengis.referencing.operation
  * <br>
  * This operation can only be read, not setted.
  *
- * @author Johann Sorel (Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @since   0.7
  * @version 0.7
  * @module
@@ -77,7 +80,7 @@ final class BoundsOperation extends Abst
      * @param identification The name and other information to be given to this operation.
      * @param crs result envelope CRS, can be {@code null}
      */
-    BoundsOperation(Map<String, ?> identification, CoordinateReferenceSystem crs) {
+    BoundsOperation(Map<String,?> identification, CoordinateReferenceSystem crs) {
         super(identification);
         this.crs = crs;
     }

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=1739058&r1=1739057&r2=1739058&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] Thu Apr 14 11:24:59 2016
@@ -16,14 +16,17 @@
  */
 package org.apache.sis.feature;
 
-import java.util.Collections;
-import org.opengis.feature.Operation;
-import org.opengis.feature.PropertyType;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import java.util.Map;
 import org.opengis.util.GenericName;
+import org.opengis.util.InternationalString;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Static;
 
+// Branch-dependent imports
+import org.opengis.feature.Operation;
+import org.opengis.feature.PropertyType;
+
 
 /**
  * A set of pre-defined operations expecting a {@code Feature} as input and producing an
{@code Attribute} as output.
@@ -33,7 +36,72 @@ import org.apache.sis.util.Static;
  * <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>
  *
+ * <div class="section">Operation name, designation and description</div>
+ * All operations are identified by a programmatic name, but can also have a more human-readable
designation
+ * for Graphical User Interfaces (GUI). Those identification information are specified in
a {@code Map<String,?>}.
+ * The recognized entries are the same than the ones documented in {@link AbstractIdentifiedType},
augmented with
+ * entries that describe the operation <em>result</em>. Those entries are summarized
below:
+ *
+ * <table class="sis">
+ *   <caption>Recognized map entries</caption>
+ *   <tr>
+ *     <th>Map key</th>
+ *     <th>Value type</th>
+ *     <th>Returned by</th>
+ *   </tr>
+ *   <tr>
+ *     <td>{@value org.apache.sis.feature.AbstractOperation#NAME_KEY}</td>
+ *     <td>{@link GenericName} or {@link String}</td>
+ *     <td>{@link AbstractOperation#getName() Operation.getName()} (mandatory)</td>
+ *   </tr>
+ *   <tr>
+ *     <td>{@value org.apache.sis.feature.AbstractOperation#DEFINITION_KEY}</td>
+ *     <td>{@link InternationalString} or {@link String}</td>
+ *     <td>{@link AbstractOperation#getDefinition() Operation.getDefinition()}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>{@value org.apache.sis.feature.AbstractOperation#DESIGNATION_KEY}</td>
+ *     <td>{@link InternationalString} or {@link String}</td>
+ *     <td>{@link AbstractOperation#getDesignation() Operation.getDesignation()}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>{@value org.apache.sis.feature.AbstractOperation#DESCRIPTION_KEY}</td>
+ *     <td>{@link InternationalString} or {@link String}</td>
+ *     <td>{@link AbstractOperation#getDescription() Operation.getDescription()}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>"result.name"</td>
+ *     <td>{@link GenericName} or {@link String}</td>
+ *     <td>{@link AbstractAttribute#getName() Attribute.getName()} on the {@linkplain
AbstractOperation#getResult() result}</td>
+ *   </tr>
+ *   <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>
+ *   </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>
+ *   </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>
+ *   </tr>
+ *   <tr>
+ *     <td>{@value org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}</td>
+ *     <td>{@link Locale}</td>
+ *     <td>(none)</td>
+ *   </tr>
+ * </table>
+ *
+ * If no {@code "result.*"} entry is provided, then the methods in this class will use some
default name, designation
+ * and other information for the result type. Those defaults are operation specific; they
are often, but not necessarily,
+ * the same than the operation name, designation, <i>etc.</i>
+ *
  * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
  * @since   0.7
  * @version 0.7
  * @module
@@ -66,18 +134,21 @@ public final class FeatureOperations ext
      * }
      * </div>
      *
+     * Since this method does not create new property (it only redirects to an existing property),
+     * this method ignores all {@code "result.*"} entries in the given {@code identification}
map.
+     *
      * <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.
+     * @param  identification  the name and other information to be given to the operation.
+     * @param  referent        the referenced attribute or feature association.
      * @return an operation which is an alias for the {@code referent} property.
      */
-    public static Operation link(final GenericName name, final PropertyType referent) {
+    public static Operation link(final Map<String,?> identification, final PropertyType
referent) {
         ArgumentChecks.ensureNonNull("referent", referent);
-        return new LinkOperation(Collections.singletonMap("name", name), referent);
+        return new LinkOperation(identification, referent);
     }
 
     /**
@@ -85,34 +156,45 @@ public final class FeatureOperations ext
      * 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>The {@code delimiter}, {@code prefix} and {@code suffix} arguments given
to this method are used in
+     * the same way than {@link java.util.StringJoiner}. Null prefix, suffix and property
values are handled
+     * as an empty string.</p>
+     *
+     * <div class="section">Restrictions</div>
+     * The single properties can be either attributes or operations that produce attributes;
+     * feature associations are not allowed.
+     * Furthermore each attribute shall contain at most one value; multi-valued attributes
are not allowed.
+     *
      * <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
+     * operation, the given string value will be split around the {@code delimiter} 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  identification    the name and other information to be given to the operation.
+     * @param  delimiter         the characters to use a delimiter between each single property
value.
+     * @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  singleProperties  identification of the single properties to concatenate.
-     * @return an operation which concatenates the string representations of all referenced
single attribute values.
+     * @return an operation which concatenates the string representations of all referenced
single property 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... singleProperties) {
-        ArgumentChecks.ensureNonEmpty("separator", separator);
+    public static Operation compound(final Map<String,?> identification, final String
delimiter,
+            final String prefix, final String suffix, final GenericName... singleProperties)
+    {
+        ArgumentChecks.ensureNonEmpty("delimiter", delimiter);
         ArgumentChecks.ensureNonNull("singleProperties", singleProperties);
-        return new AggregateOperation(Collections.singletonMap("name", name), prefix, suffix,
separator, singleProperties);
+        return new StringJoinOperation(identification, delimiter, prefix, suffix, singleProperties);
     }
 
     /**
      * Creates a calculate bounds operation type.
      *
-     * @param name name of the property
-     * @param baseCrs created envelope crs
+     * @param  identification  the name and other information to be given to the operation.
+     * @param  baseCRS         created envelope CRS.
      * @return Operation
      */
-    public static Operation bounds(GenericName name, CoordinateReferenceSystem baseCrs) {
-        return new BoundsOperation(Collections.singletonMap("name", name), baseCrs);
+    public static Operation bounds(final Map<String,?> identification, CoordinateReferenceSystem
baseCRS) {
+        return new BoundsOperation(identification, 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=1739058&r1=1739057&r2=1739058&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] Thu Apr 14 11:24:59 2016
@@ -90,7 +90,7 @@ final class LinkOperation extends Abstra
      * @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 referent)
{
+    LinkOperation(final Map<String,?> identification, final PropertyType referent)
{
         super(identification);
         result = referent;
         referentName = referent.getName().toString();
@@ -117,6 +117,9 @@ final class LinkOperation extends Abstra
      */
     @Override
     public Set<String> getDependencies() {
+        if (result instanceof AbstractOperation) {
+            return ((AbstractOperation) result).getDependencies();
+        }
         return Collections.singleton(referentName);
     }
 

Copied: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java
(from r1739057, 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/StringJoinOperation.java?p2=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/StringJoinOperation.java&p1=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AggregateOperation.java&r1=1739057&r2=1739058&rev=1739058&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/StringJoinOperation.java
[UTF-8] Thu Apr 14 11:24:59 2016
@@ -17,7 +17,6 @@
 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;
@@ -31,7 +30,7 @@ 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.InvalidPropertyValueException;
 import org.opengis.feature.Property;
 
 
@@ -50,22 +49,16 @@ import org.opengis.feature.Property;
  *
  * @see <a href="https://en.wikipedia.org/wiki/Compound_key">Compound key on Wikipedia</a>
  */
-final class AggregateOperation extends AbstractOperation {
+final class StringJoinOperation extends AbstractOperation {
     /**
      * For cross-version compatibility.
      */
     private static final long serialVersionUID = 2303047827010821381L;
 
     /**
-     * The type of the result returned by the aggregate operation.
-     */
-    private static final AttributeType<String> TYPE = new DefaultAttributeType<>(
-            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 static final ParameterDescriptorGroup EMPTY_PARAMS = LinkOperation.parameters("StringJoin",
1);
 
     /**
      * The name of the properties from which to get the values to concatenate.
@@ -78,6 +71,11 @@ final class AggregateOperation extends A
     private transient Set<String> dependencies;
 
     /**
+     * The type of the result returned by the string concatenation operation.
+     */
+    private final AttributeType<String> resultType;
+
+    /**
      * The characters to use at the beginning of the concatenated string, or an empty string
if none.
      */
     private final String prefix;
@@ -90,13 +88,15 @@ final class AggregateOperation extends A
     /**
      * The characters to use a delimiter between each single attribute value.
      */
-    private final String separator;
+    private final String delimiter;
 
     /**
      * Creates a new operation for string concatenations using the given prefix, suffix and
delimeter.
+     * It is caller's responsibility to ensure that {@code delimiter} and {@code singleProperties}
are not null.
+     * This private constructor does not verify that condition on the assumption that the
public API did.
      */
-    AggregateOperation(final Map<String, ?> identification, final String prefix, final
String suffix,
-            final String separator, final GenericName[] singleProperties)
+    StringJoinOperation(final Map<String,?> identification, final String delimiter,
+            final String prefix, final String suffix, final GenericName[] singleProperties)
     {
         super(identification);
         propertyNames = new String[singleProperties.length];
@@ -104,9 +104,10 @@ final class AggregateOperation extends A
             ArgumentChecks.ensureNonNullElement("singleProperties", i, singleProperties);
             propertyNames[i] = singleProperties[i].toString();
         }
+        resultType = new DefaultAttributeType<>(resultIdentification(identification),
String.class, 1, 1, null);
+        this.delimiter = delimiter;
         this.prefix = (prefix == null) ? "" : prefix;
         this.suffix = (suffix == null) ? "" : suffix;
-        this.separator = separator;
     }
 
     /**
@@ -126,7 +127,7 @@ final class AggregateOperation extends A
      */
     @Override
     public IdentifiedType getResult() {
-        return TYPE;
+        return resultType;
     }
 
     /**
@@ -144,51 +145,70 @@ final class AggregateOperation extends A
     /**
      * Returns the concatenation of property values of the given feature.
      *
-     * @param  feature    the feature on which to execute the operation.
-     * @param  parameters ignored (can be {@code 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);
+        return new Result(feature);
     }
 
     /**
-     * Operation attribute.
+     * The attributes that contains the result of concatenating the string representation
of other attributes.
      * Value is calculated each time it is accessed.
      */
-    private final class AggregateAttribute extends AbstractAttribute<String> {
-
+    private final class Result extends AbstractAttribute<String> {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = -8435975199763452547L;
+
+        /**
+         * The feature specified to the {@link StringJoinOperation#apply(Feature, ParameterValueGroup)}
method.
+         */
         private final Feature feature;
 
-        public AggregateAttribute(final Feature feature) {
-            super(TYPE);
+        /**
+         * Creates a new attribute for the given feature.
+         */
+        Result(final Feature feature) {
+            super(resultType);
             this.feature = feature;
         }
 
+        /**
+         * Creates a string which is the concatenation of attribute values of all properties
+         * specified to the {@link StringJoinOperation} constructor.
+         */
         @Override
-        public String getValue() throws MultiValuedPropertyException {
+        public String getValue() {
             final StringBuilder sb = new StringBuilder();
-            sb.append(prefix);
-
-            for (int i=0; i < propertyNames.length; i++) {
-                if (i != 0) sb.append(separator);
-                sb.append(feature.getPropertyValue(propertyNames[i]));
+            String sep = prefix;
+            for (final String name : propertyNames) {
+                final Object value = feature.getPropertyValue(name);
+                sb.append(sep);
+                if (value != null) {
+                    sb.append(value);
+                }
+                sep = delimiter;
             }
-
-            sb.append(suffix);
-            return sb.toString();
+            return sb.append(suffix).toString();
         }
 
+        /**
+         * Given a concatenated string as produced by {@link #getValue()}, separates the
components around
+         * the separator and forward the values to the original attributes.
+         */
         @Override
         public void setValue(String value) {
             //check prefix
             if (!value.startsWith(prefix)) {
-                throw new IllegalArgumentException("Unvalid string, does not start with "+prefix);
+                throw new InvalidPropertyValueException("Unvalid string, does not start with
"+prefix);
             }
             if (!value.endsWith(suffix)) {
-                throw new IllegalArgumentException("Unvalid string, does not end with "+suffix);
+                throw new InvalidPropertyValueException("Unvalid string, does not end with
"+suffix);
             }
 
             //split values, we don't use the regex split to avoid possible reserverd regex
characters
@@ -199,21 +219,21 @@ final class AggregateOperation extends A
             value = value.substring(prefix.length(), value.length() - suffix.length());
             while (true) {
                 if (i >= values.length) {
-                    throw new IllegalArgumentException("Unvalid string, expected "+values.length+"
values, but found more");
+                    throw new InvalidPropertyValueException("Unvalid string, expected "+values.length+"
values, but found more");
                 }
-                final int idx = value.indexOf(separator, offset);
+                final int idx = value.indexOf(delimiter, offset);
                 if (idx < 0) {
                     //last element
                     values[i++] = value.substring(offset);
                     break;
                 } else {
                     values[i++] = value.substring(offset, idx);
-                    offset = (idx + separator.length());
+                    offset = (idx + delimiter.length());
                 }
             }
 
             if (i != values.length) {
-                throw new IllegalArgumentException("Unvalid string, number of values do not
match, found "+(i)+" but expected "+values.length);
+                throw new InvalidPropertyValueException("Unvalid string, number of values
do not match, found "+(i)+" but expected "+values.length);
             }
 
             //set values, convert them if necessary

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=1739058&r1=1739057&r2=1739058&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] Thu Apr 14 11:24:59 2016
@@ -47,7 +47,7 @@ import org.opengis.util.ScopedName;
  * Helper class for the creation of {@link FeatureType} instances.
  * This builder can create the parameters to be given to {@linkplain DefaultFeatureType feature
type constructor}
  * from simpler parameters given to this builder.
- * 
+ *
  * @author Johann Sorel (Geomatys)
  * @since   0.7
  * @version 0.7
@@ -83,7 +83,7 @@ public class FeatureTypeBuilder {
 
     /**
      * Copy parameters from the given feature type.
-     * 
+     *
      * @param type feature type to copy parameters from.
      */
     public void copy(FeatureType type){
@@ -213,7 +213,7 @@ public class FeatureTypeBuilder {
     /**
      * Define an id operation composed of the given attribute.
      * Generated id prefix will be the name of the featuretype+'.'
-     * 
+     *
      * @param attributeName attribute id used in the id operation
      */
     public void setIdOperation(String attributeName){
@@ -267,7 +267,7 @@ public class FeatureTypeBuilder {
 
     /**
      * Define a default geometry link operation.
-     * 
+     *
      * @param attribute referenced attribute
      */
     public void setDefaultGeometryOperation(String attribute){
@@ -286,7 +286,7 @@ public class FeatureTypeBuilder {
 
     /**
      * Define a default geometry link operation.
-     * 
+     *
      * @param attribute referenced attribute
      */
     public void setDefaultGeometryOperation(GenericName attribute){
@@ -369,7 +369,7 @@ public class FeatureTypeBuilder {
      * Add a new property to the feature type.
      * Property will have a minimum and maximum occurrence of one, no default value
      * and the given {@code CoordinateReferenceSystem} characteristic.
-     * 
+     *
      * @param name property name
      * @param valueClass property value class
      * @param crs property {@code CoordinateReferenceSystem} characteristic
@@ -426,7 +426,7 @@ public class FeatureTypeBuilder {
      * Add a new property to the feature type.
      * Property will have a minimum and maximum occurrence of one and the given
      * {@code CoordinateReferenceSystem} characteristic.
-     * 
+     *
      * @param name property name
      * @param valueClass property value class
      * @param defaultValue property default value
@@ -503,7 +503,7 @@ public class FeatureTypeBuilder {
 
     /**
      * Add a new property to the feature type.
-     * 
+     *
      * @param name property name
      * @param valueClass property value class
      * @param minimumOccurs property minimum number of occurrences
@@ -632,7 +632,7 @@ public class FeatureTypeBuilder {
 
     /**
      * Remove a property from the feature type.
-     * 
+     *
      * @param name property name
      * @return removed property, can be null if property was not found
      */
@@ -660,7 +660,9 @@ public class FeatureTypeBuilder {
                 prefix = getName().tip().toString();
             }
 
-            final Operation att = FeatureOperations.aggregate(ATTRIBUTE_ID, prefix, null,
idSeparator, idAttributes);
+            final Operation att = FeatureOperations.compound(
+                    Collections.singletonMap(AbstractOperation.NAME_KEY, ATTRIBUTE_ID),
+                    idSeparator, prefix, null, idAttributes);
             properties.put(ATTRIBUTE_ID, att);
         }
         //build default geometry property
@@ -670,16 +672,17 @@ public class FeatureTypeBuilder {
             }
             final PropertyType geomAtt = properties.get(defGeomAttribute);
             final CoordinateReferenceSystem crs = AttributeConvention.getCRSCharacteristic(geomAtt);
-            final Operation att = FeatureOperations.link(ATTRIBUTE_DEFAULT_GEOMETRY, geomAtt);
+            final Operation att = FeatureOperations.link(
+                    Collections.singletonMap(AbstractOperation.NAME_KEY, ATTRIBUTE_DEFAULT_GEOMETRY),
geomAtt);
             properties.put(ATTRIBUTE_DEFAULT_GEOMETRY, att);
 
-            final Operation boundAtt = FeatureOperations.bounds(ATTRIBUTE_BOUNDS, crs);
+            final Operation boundAtt = FeatureOperations.bounds(Collections.singletonMap(AbstractOperation.NAME_KEY,
ATTRIBUTE_BOUNDS), crs);
             properties.put(ATTRIBUTE_BOUNDS, boundAtt);
 
         }
 
         verifyOperations();
-        
+
         return new DefaultFeatureType(
                 parameters,
                 isAbstract,
@@ -689,11 +692,11 @@ public class FeatureTypeBuilder {
 
     /**
      * Check operations have the required properties.
-     * 
+     *
      * @throws IllegalArgumentException if some properties are missing for an operation.
      */
     private void verifyOperations() throws IllegalArgumentException{
-        
+
         for(PropertyType pt : properties.values()){
             if(pt instanceof AbstractOperation){
                 final Set<String> dependencies = ((AbstractOperation)pt).getDependencies();
@@ -704,10 +707,10 @@ public class FeatureTypeBuilder {
                     }
                     throw new IllegalArgumentException("Operation "+pt.getName().toString()+"
requiere property "+dep+" but this property is missing.");
                 }
-                
+
             }
         }
-        
+
     }
 
     ////////////////////////////////////////////////////////////////////////////

Modified: 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/BoundsOperationTest.java?rev=1739058&r1=1739057&r2=1739058&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/BoundsOperationTest.java
[UTF-8] Thu Apr 14 11:24:59 2016
@@ -16,7 +16,7 @@
  */
 package org.apache.sis.feature;
 
-import org.apache.sis.internal.feature.FeatureTypeBuilder;
+import java.util.Collections;
 import com.esri.core.geometry.Point;
 import com.esri.core.geometry.Polygon;
 import org.apache.sis.geometry.GeneralEnvelope;
@@ -24,6 +24,7 @@ import org.apache.sis.referencing.Common
 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.*;
@@ -64,7 +65,9 @@ public final strictfp class BoundsOperat
         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(Names.parseGenericName(null,":","bounds"),
CommonCRS.WGS84.geographic()));
+        ftb.addProperty(FeatureOperations.bounds(
+                Collections.singletonMap(AbstractOperation.NAME_KEY, Names.parseGenericName(null,
":", "bounds")),
+                CommonCRS.WGS84.geographic()));
         return ftb.build();
     }
 

Copied: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
(from r1739057, sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AggregateOperationTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java?p2=sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java&p1=sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AggregateOperationTest.java&r1=1739057&r2=1739058&rev=1739058&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/AggregateOperationTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/StringJoinOperationTest.java
[UTF-8] Thu Apr 14 11:24:59 2016
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.feature;
 
+import java.util.Collections;
 import org.apache.sis.internal.feature.FeatureTypeBuilder;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -27,7 +28,7 @@ import org.opengis.feature.PropertyType;
 
 
 /**
- * Tests {@link AggregateOperation}.
+ * Tests {@link StringJoinOperation}.
  *
  * @author  Johann Sorel (Geomatys)
  * @since   0.7
@@ -38,7 +39,7 @@ import org.opengis.feature.PropertyType;
     AbstractOperationTest.class,
     DenseFeatureTest.class
 })
-public final strictfp class AggregateOperationTest extends TestCase {
+public final strictfp class StringJoinOperationTest extends TestCase {
     /**
      * Creates a feature type with an aggregation operation.
      * The feature contains the following properties:
@@ -57,8 +58,9 @@ public final strictfp class AggregateOpe
         ftb.setName("person");
         final PropertyType nameType = ftb.addProperty("name", String.class);
         final PropertyType ageType = ftb.addProperty("age", Integer.class);
-        ftb.addProperty(FeatureOperations.aggregate(Names.parseGenericName(null, ":", 
-                "summary"), "prefix:", ":suffix","/",nameType.getName(), ageType.getName()));
+        ftb.addProperty(FeatureOperations.compound(
+                Collections.singletonMap(AbstractOperation.NAME_KEY, Names.parseGenericName(null,
":", "summary")),
+                "/", "prefix:", ":suffix", nameType.getName(), ageType.getName()));
         return ftb.build();
     }
 
@@ -68,9 +70,9 @@ public final strictfp class AggregateOpe
     private static void run(final AbstractFeature feature) {
 
         //test feature
-        assertEquals("prefix:null/null:suffix", feature.getPropertyValue("summary"));
+        assertEquals("prefix:/:suffix", feature.getPropertyValue("summary"));
         feature.setPropertyValue("name", "marc");
-        assertEquals("prefix:marc/null:suffix", feature.getPropertyValue("summary"));
+        assertEquals("prefix:marc/:suffix", feature.getPropertyValue("summary"));
         feature.setPropertyValue("age", 21);
         assertEquals("prefix:marc/21:suffix", feature.getPropertyValue("summary"));
 

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=1739058&r1=1739057&r2=1739058&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] Thu Apr 14 11:24:59 2016
@@ -44,7 +44,7 @@ import org.junit.BeforeClass;
     org.apache.sis.feature.SingletonAssociationTest.class,
     org.apache.sis.feature.AbstractOperationTest.class,
     org.apache.sis.feature.LinkOperationTest.class,
-    org.apache.sis.feature.AggregateOperationTest.class,
+    org.apache.sis.feature.StringJoinOperationTest.class,
     org.apache.sis.feature.BoundsOperationTest.class,
     org.apache.sis.feature.FeatureFormatTest.class,
     org.apache.sis.feature.FeaturesTest.class,




Mime
View raw message