sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1752158 [5/6] - in /sis/branches/JDK8/core/sis-feature/src: main/java/org/apache/sis/feature/builder/ main/java/org/apache/sis/internal/feature/ test/java/org/apache/sis/feature/builder/ test/java/org/apache/sis/internal/feature/ test/java...
Date Mon, 11 Jul 2016 13:29:44 GMT
Copied: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java (from r1752157, 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/feature/builder/FeatureTypeBuilder.java?p2=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java&p1=sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureTypeBuilder.java&r1=1752157&r2=1752158&rev=1752158&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/feature/builder/FeatureTypeBuilder.java [UTF-8] Mon Jul 11 13:29:44 2016
@@ -14,30 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.feature;
+package org.apache.sis.feature.builder;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Locale;
 import org.opengis.util.GenericName;
 import org.opengis.util.NameFactory;
 import org.opengis.util.FactoryException;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.feature.AbstractOperation;
-import org.apache.sis.feature.DefaultAssociationRole;
-import org.apache.sis.feature.DefaultAttributeType;
 import org.apache.sis.feature.DefaultFeatureType;
 import org.apache.sis.feature.FeatureOperations;
 import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.feature.AttributeConvention;
 import org.apache.sis.util.CorruptedObjectException;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArraysExt;
-import org.apache.sis.util.Classes;
 
 // Branch-dependent imports
 import java.util.Objects;
@@ -59,13 +54,13 @@ import org.opengis.feature.FeatureAssoci
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.7
+ * @since   0.8
  * @version 0.8
  * @module
  *
  * @see org.apache.sis.parameter.ParameterBuilder
  */
-public class FeatureTypeBuilder extends FeatureElementBuilder {
+public class FeatureTypeBuilder extends TypeBuilder {
     /**
      * The factory to use for creating names.
      */
@@ -74,7 +69,7 @@ public class FeatureTypeBuilder extends
     /**
      * Builders for the properties (attributes, associations or operations) of this feature.
      */
-    private final List<Property> properties;
+    private final List<PropertyTypeBuilder> properties;
 
     /**
      * The parent of the feature to create. By default, new features have no parent.
@@ -102,14 +97,14 @@ public class FeatureTypeBuilder extends
      *
      * @see #setDefaultCardinality(int, int)
      */
-    private int defaultMinimumOccurs;
+    int defaultMinimumOccurs;
 
     /**
      * The default maximum number of property values.
      *
      * @see #setDefaultCardinality(int, int)
      */
-    private int defaultMaximumOccurs;
+    int defaultMaximumOccurs;
 
     /**
      * An optional prefix or suffix to insert before or after the {@linkplain FeatureOperations#compound compound key}
@@ -126,18 +121,18 @@ public class FeatureTypeBuilder extends
     /**
      * Number of attribute that have been flagged as an identifier component.
      *
-     * @see Attribute.Role#IDENTIFIER_COMPONENT
+     * @see AttributeRole#IDENTIFIER_COMPONENT
      * @see AttributeConvention#IDENTIFIER_PROPERTY
      */
-    private int identifierCount;
+    int identifierCount;
 
     /**
      * The default geometry attribute, or {@code null} if none.
      *
-     * @see Attribute.Role#DEFAULT_GEOMETRY
+     * @see AttributeRole#DEFAULT_GEOMETRY
      * @see AttributeConvention#GEOMETRY_PROPERTY
      */
-    private Attribute<?> defaultGeometry;
+    AttributeTypeBuilder<?> defaultGeometry;
 
     /**
      * The object created by this builder, or {@code null} if not yet created.
@@ -184,11 +179,11 @@ public class FeatureTypeBuilder extends
             isAbstract = template.isAbstract();
             superTypes.addAll(template.getSuperTypes());
             for (final PropertyType p : template.getProperties(false)) {
-                final Property builder;
+                final PropertyTypeBuilder builder;
                 if (p instanceof AttributeType<?>) {
-                    builder = new Attribute<>(this, (AttributeType<?>) p);
+                    builder = new AttributeTypeBuilder<>(this, (AttributeType<?>) p);
                 } else if (p instanceof FeatureAssociationRole) {
-                    builder = new Association(this, (FeatureAssociationRole) p);
+                    builder = new AssociationRoleBuilder(this, (FeatureAssociationRole) p);
                 } else {
                     continue;           // Skip unknown types.
                 }
@@ -314,7 +309,7 @@ public class FeatureTypeBuilder extends
     }
 
     /**
-     * Invoked by {@link FeatureElementBuilder} for creating new {@code LocalName} or {@code GenericName} instances.
+     * Invoked by {@link TypeBuilder} for creating new {@code LocalName} or {@code GenericName} instances.
      */
     @Override
     final GenericName name(String scope, final String localPart) {
@@ -361,7 +356,7 @@ public class FeatureTypeBuilder extends
      * @param  maximumOccurs  new default maximum number of property values.
      * @return {@code this} for allowing method calls chaining.
      *
-     * @see Attribute#setCardinality(int, int)
+     * @see AttributeTypeBuilder#setCardinality(int, int)
      */
     public FeatureTypeBuilder setDefaultCardinality(final int minimumOccurs, final int maximumOccurs) {
         if (minimumOccurs < 0 || maximumOccurs < minimumOccurs) {
@@ -376,7 +371,7 @@ public class FeatureTypeBuilder extends
 
     /**
      * Sets the prefix, suffix and delimiter to use when formatting a compound identifier made of two or more attributes.
-     * The delimiter will be used only if at least two attributes have the {@linkplain Attribute.Role#IDENTIFIER_COMPONENT
+     * The delimiter will be used only if at least two attributes have the {@linkplain AttributeRole#IDENTIFIER_COMPONENT
      * identifier component role}.
      *
      * <p>If this method is not invoked, then the default values are the {@code ":"} delimiter and no prefix or suffix.</p>
@@ -386,7 +381,7 @@ public class FeatureTypeBuilder extends
      * @param  suffix     characters to use at the end of the concatenated string, or {@code null} if none.
      * @return {@code this} for allowing method calls chaining.
      *
-     * @see Attribute.Role#IDENTIFIER_COMPONENT
+     * @see AttributeRole#IDENTIFIER_COMPONENT
      * @see FeatureOperations#compound(Map, String, String, String, PropertyType...)
      */
     public FeatureTypeBuilder setIdentifierDelimiters(final String delimiter, final String prefix, final String suffix) {
@@ -401,9 +396,28 @@ public class FeatureTypeBuilder extends
     }
 
     /**
+     * Returns a view of all attributes and associations added to the {@code FeatureType} to build.
+     * The returned list is <cite>live</cite>: changes in this builder are reflected in that list and conversely.
+     * However the returned list allows only {@linkplain List#remove(Object) remove} operations;
+     * new attributes or associations can be added only by calls to one of the {@code addAttribute(…)}
+     * or {@code addAssociation(…)} methods.
+     *
+     * @return a live list over the properties declared to this builder.
+     *
+     * @see #addAttribute(Class)
+     * @see #addAttribute(AttributeType)
+     * @see #addAssociation(FeatureType)
+     * @see #addAssociation(GenericName)
+     * @see #addAssociation(FeatureAssociationRole)
+     */
+    public List<PropertyTypeBuilder> properties() {
+        return new RemoveOnlyList<>(properties);
+    }
+
+    /**
      * Creates a new {@code AttributeType} builder for values of the given class.
      * The default attribute name is the name of the given type, but callers should invoke one
-     * of the {@code Attribute.setName(…)} methods on the returned instance with a better name.
+     * of the {@code AttributeTypeBuilder.setName(…)} methods on the returned instance with a better name.
      *
      * <p>Usage example:</p>
      * {@preformat java
@@ -416,14 +430,16 @@ public class FeatureTypeBuilder extends
      * @param  <V>  the compile-time value of {@code valueClass} argument.
      * @param  valueClass  the class of attribute values (can not be {@code Feature.class}).
      * @return a builder for an {@code AttributeType}.
+     *
+     * @see #properties()
      */
-    public <V> Attribute<V> addAttribute(final Class<V> valueClass) {
+    public <V> AttributeTypeBuilder<V> addAttribute(final Class<V> valueClass) {
         ensureNonNull("valueClass", valueClass);
         if (Feature.class.isAssignableFrom(valueClass)) {
             // We disallow Feature.class because that type shall be handled as association instead than attribute.
             throw new IllegalArgumentException(errors().getString(Errors.Keys.IllegalArgumentValue_2, "valueClass", valueClass));
         }
-        final Attribute<V> property = new Attribute<>(this, valueClass);
+        final AttributeTypeBuilder<V> property = new AttributeTypeBuilder<>(this, valueClass);
         properties.add(property);
         clearCache();
         return property;
@@ -435,10 +451,12 @@ public class FeatureTypeBuilder extends
      * @param  <V>       the compile-time type of values in the {@code template} argument.
      * @param  template  an existing attribute type to use as a template.
      * @return a builder for an {@code AttributeType}, initialized with the values of the given template.
+     *
+     * @see #properties()
      */
-    public <V> Attribute<V> addAttribute(final AttributeType<V> template) {
+    public <V> AttributeTypeBuilder<V> addAttribute(final AttributeType<V> template) {
         ensureNonNull("template", template);
-        final Attribute<V> property = new Attribute<>(this, template);
+        final AttributeTypeBuilder<V> property = new AttributeTypeBuilder<>(this, template);
         properties.add(property);
         clearCache();
         return property;
@@ -447,14 +465,16 @@ public class FeatureTypeBuilder extends
     /**
      * Creates a new {@code FeatureAssociationRole} builder for features of the given type.
      * The default association name is the name of the given type, but callers should invoke one
-     * of the {@code Association.setName(…)} methods on the returned instance with a better name.
+     * of the {@code AssociationRoleBuilder.setName(…)} methods on the returned instance with a better name.
      *
      * @param  type  the type of feature values.
      * @return a builder for a {@code FeatureAssociationRole}.
+     *
+     * @see #properties()
      */
-    public Association addAssociation(final FeatureType type) {
+    public AssociationRoleBuilder addAssociation(final FeatureType type) {
         ensureNonNull("type", type);
-        final Association property = new Association(this, type, type.getName());
+        final AssociationRoleBuilder property = new AssociationRoleBuilder(this, type, type.getName());
         properties.add(property);
         clearCache();
         return property;
@@ -467,10 +487,12 @@ public class FeatureTypeBuilder extends
      *
      * @param  type  the name of the type of feature values.
      * @return a builder for a {@code FeatureAssociationRole}.
+     *
+     * @see #properties()
      */
-    public Association addAssociation(final GenericName type) {
+    public AssociationRoleBuilder addAssociation(final GenericName type) {
         ensureNonNull("type", type);
-        final Association property = new Association(this, null, type);
+        final AssociationRoleBuilder property = new AssociationRoleBuilder(this, null, type);
         properties.add(property);
         clearCache();
         return property;
@@ -482,857 +504,17 @@ public class FeatureTypeBuilder extends
      *
      * @param  template  an existing feature association to use as a template.
      * @return a builder for an {@code FeatureAssociationRole}, initialized with the values of the given template.
+     *
+     * @see #properties()
      */
-    public Association addAssociation(final FeatureAssociationRole template) {
+    public AssociationRoleBuilder addAssociation(final FeatureAssociationRole template) {
         ensureNonNull("template", template);
-        final Association property = new Association(this, template);
+        final AssociationRoleBuilder property = new AssociationRoleBuilder(this, template);
         properties.add(property);
         clearCache();
         return property;
     }
 
-
-
-
-    /**
-     * Describes one property of the {@code FeatureType} to be built by the enclosing {@code FeatureTypeBuilder}.
-     * A different instance of {@code Property} exists for each property to describe. Those instances are created by:
-     *
-     * <ul>
-     *   <li>{@link FeatureTypeBuilder#addAttribute(Class)}</li>
-     *   <li>{@link FeatureTypeBuilder#addAssociation(FeatureType)}</li>
-     *   <li>{@link FeatureTypeBuilder#addAssociation(GenericName)}</li>
-     * </ul>
-     */
-    public static abstract class Property extends FeatureElementBuilder {
-        /**
-         * The feature type builder instance that created this {@code Property} builder.
-         *
-         * <div class="note">We could replace this reference by a non-static {@code Property} class.
-         * But we do not for consistency with {@link Characteristic} and for allowing the inner
-         * {@code Attribute.Role} enumeration.</div>
-         */
-        final FeatureTypeBuilder owner;
-
-        /**
-         * The minimum number of property values.
-         * The default value is 1, unless otherwise specified by {@link #setDefaultCardinality(int, int)}.
-         *
-         * @see #setCardinality(int, int)
-         */
-        int minimumOccurs;
-
-        /**
-         * The maximum number of property values.
-         * The default value is 1, unless otherwise specified by {@link #setDefaultCardinality(int, int)}.
-         *
-         * @see #setCardinality(int, int)
-         */
-        int maximumOccurs;
-
-        /**
-         * The attribute or association created by this builder, or {@code null} if not yet created.
-         * This field must be cleared every time that a setter method is invoked on this builder.
-         */
-        private transient PropertyType property;
-
-        /**
-         * Creates a new {@code PropertyType} builder initialized to the values of an existing property.
-         *
-         * @param owner     the builder of the {@code FeatureType} for which to add this property.
-         * @param template  an existing property to use as a template, or {@code null} if none.
-         */
-        Property(final FeatureTypeBuilder owner, final PropertyType template) {
-            super(template, owner.getLocale());
-            this.owner    = owner;
-            minimumOccurs = owner.defaultMinimumOccurs;
-            maximumOccurs = owner.defaultMaximumOccurs;
-            property      = template;
-        }
-
-        /**
-         * Sets the minimum and maximum number of property values. Those numbers must be equal or greater than zero.
-         *
-         * <p>If this method is not invoked, then the default values are the cardinality specified by the last call
-         * to {@link FeatureTypeBuilder#setDefaultCardinality(int, int)} at the time this instance has been created.
-         * If the later method has not been invoked, then the default cardinality is [1 … 1].</p>
-         *
-         * @param  minimumOccurs  new minimum number of property values.
-         * @param  maximumOccurs  new maximum number of property values.
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @SuppressWarnings("unchecked")
-        public Property setCardinality(final int minimumOccurs, final int maximumOccurs) {
-            if (this.minimumOccurs != minimumOccurs || this.maximumOccurs != maximumOccurs) {
-                if (minimumOccurs < 0 || maximumOccurs < minimumOccurs) {
-                    throw new IllegalArgumentException(errors().getString(Errors.Keys.IllegalRange_2, minimumOccurs, maximumOccurs));
-                }
-                this.minimumOccurs = minimumOccurs;
-                this.maximumOccurs = maximumOccurs;
-                clearCache();
-            }
-            return this;
-        }
-
-        /**
-         * Returns {@code true} if {@link Attribute.Role#IDENTIFIER_COMPONENT} has been associated to this property.
-         */
-        boolean isIdentifier() {
-            return false;
-        }
-
-        /**
-         * Delegates the creation of a new name to the enclosing builder.
-         */
-        @Override
-        final GenericName name(final String scope, final String localPart) {
-            return owner.name(scope, localPart);
-        }
-
-        /**
-         * If the {@code PropertyType} created by the last call to {@link #build()} has been cached,
-         * clears that cache. This method must be invoked every time that a setter method is invoked.
-         */
-        @Override
-        final void clearCache() {
-            property = null;
-            owner.clearCache();
-        }
-
-        /**
-         * Returns the property type from the current setting.
-         * This method may return an existing property if it was already created.
-         */
-        final PropertyType build() {
-            if (property == null) {
-                property = create();
-            }
-            return property;
-        }
-
-        /**
-         * Creates a new property type from the current setting.
-         */
-        abstract PropertyType create();
-    }
-
-
-
-
-    /**
-     * Describes one association from the {@code FeatureType} to be built by the enclosing {@code FeatureTypeBuilder}
-     * to another {@code FeatureType}. A different instance of {@code Association} exists for each feature association
-     * to describe. Those instances are created preferably by {@link FeatureTypeBuilder#addAssociation(FeatureType)},
-     * or in case of cyclic reference by {@link FeatureTypeBuilder#addAssociation(GenericName)}.
-     *
-     * @see FeatureTypeBuilder#addAssociation(FeatureType)
-     * @see FeatureTypeBuilder#addAssociation(GenericName)
-     */
-    public static final class Association extends Property {
-        /**
-         * The target feature type, or {@code null} if unknown.
-         */
-        private final FeatureType type;
-
-        /**
-         * Name of the target feature type (never null).
-         */
-        private final GenericName typeName;
-
-        /**
-         * Creates a new {@code AssociationRole} builder for values of the given type.
-         * The {@code type} argument can be null if unknown, but {@code typeName} is mandatory.
-         *
-         * @param owner  the builder of the {@code FeatureType} for which to add this property.
-         */
-        Association(final FeatureTypeBuilder owner, final FeatureType type, final GenericName typeName) {
-            super(owner, null);
-            this.type     = type;
-            this.typeName = typeName;
-        }
-
-        /**
-         * Creates a new {@code FeatureAssociationRole} builder initialized to the values of an existing association.
-         *
-         * @param owner  the builder of the {@code FeatureType} for which to add this property.
-         */
-        Association(final FeatureTypeBuilder owner, final FeatureAssociationRole template) {
-            super(owner, template);
-            minimumOccurs = template.getMinimumOccurs();
-            maximumOccurs = template.getMaximumOccurs();
-            type          = template.getValueType();
-            typeName      = type.getName();
-        }
-
-        /**
-         * Appends a text inside the value returned by {@link #toString()}, before the closing bracket.
-         */
-        @Override
-        final void toStringInternal(final StringBuilder buffer) {
-            buffer.append(" → ").append(typeName);
-        }
-
-        /**
-         * Returns a default name to use if the user did not specified a name. The first letter will be changed to
-         * lower case (unless the name looks like an acronym) for compliance with Java convention on property names.
-         */
-        @Override
-        final String getDefaultName() {
-            return typeName.tip().toString();
-        }
-
-        /**
-         * Sets the {@code FeatureAssociationRole} name as a generic name.
-         * If another name was defined before this method call, that previous value will be discarded.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Association setName(final GenericName name) {
-            super.setName(name);
-            return this;
-        }
-
-        /**
-         * Sets the {@code FeatureAssociationRole} name as a simple string with the default scope.
-         * The default scope is the value specified by the last call to
-         * {@link FeatureTypeBuilder#setDefaultScope(String)}.
-         * The name will be a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} if no default scope
-         * has been specified, or a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} otherwise.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Association setName(final String localPart) {
-            super.setName(localPart);
-            return this;
-        }
-
-        /**
-         * Sets the {@code FeatureAssociationRole} name as a string in the given scope.
-         * The name will be a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} if the given scope is
-         * {@code null} or empty, or a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} otherwise.
-         * If a {@linkplain FeatureTypeBuilder#setDefaultScope(String) default scope} has been specified, then the
-         * {@code scope} argument overrides it.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Association setName(final String scope, final String localPart) {
-            super.setName(scope, localPart);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Association setDefinition(final CharSequence definition) {
-            super.setDefinition(definition);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Association setDesignation(final CharSequence designation) {
-            super.setDesignation(designation);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Association setDescription(final CharSequence description) {
-            super.setDescription(description);
-            return this;
-        }
-
-        /**
-         * Creates a new property type from the current setting.
-         */
-        @Override
-        final PropertyType create() {
-            if (type != null) {
-                return new DefaultAssociationRole(identification(), type, minimumOccurs, maximumOccurs);
-            } else {
-                return new DefaultAssociationRole(identification(), typeName, minimumOccurs, maximumOccurs);
-            }
-        }
-    }
-
-
-
-
-    /**
-     * Describes one attribute of the {@code FeatureType} to be built by the enclosing {@code FeatureTypeBuilder}.
-     * A different instance of {@code Attribute} exists for each feature attribute to describe.
-     * Those instances are created by {@link FeatureTypeBuilder#addAttribute(Class)}.
-     *
-     * @param <V> the class of property values.
-     *
-     * @see FeatureTypeBuilder#addAttribute(Class)
-     */
-    public static final class Attribute<V> extends Property {
-        /**
-         * The class of property values. Can not be changed after construction
-         * because this value determines the parameterized type {@code <V>}.
-         */
-        private final Class<V> valueClass;
-
-        /**
-         * The default value for the property, or {@code null} if none.
-         */
-        private V defaultValue;
-
-        /**
-         * Whether this attribute will be used in a {@linkplain FeatureOperations#compound compound key} named
-         * {@code "@identifier"}. If only one attribute has this flag and {@link FeatureTypeBuilder#idPrefix} and
-         * {@code isSuffix} are null, then {@code "@identifier"} will be a {@linkplain FeatureOperations#link link}
-         * to {@code idAttributes[0]}.
-         *
-         * @see #addRole(Role)
-         */
-        private boolean isIdentifier;
-
-        /**
-         * Builders for the characteristics associated to the attribute.
-         */
-        private final List<Characteristic<?>> characteristics = new ArrayList<>();
-
-        /**
-         * Creates a new {@code AttributeType} builder for values of the given class.
-         *
-         * @param owner      the builder of the {@code FeatureType} for which to add this property.
-         * @param valueClass the class of property values.
-         */
-        Attribute(final FeatureTypeBuilder owner, final Class<V> valueClass) {
-            super(owner, null);
-            this.valueClass = valueClass;
-        }
-
-        /**
-         * Creates a new {@code AttributeType} builder initialized to the values of an existing attribute.
-         *
-         * @param owner  the builder of the {@code FeatureType} for which to add this property.
-         */
-        Attribute(final FeatureTypeBuilder owner, final AttributeType<V> template) {
-            super(owner, template);
-            minimumOccurs = template.getMinimumOccurs();
-            maximumOccurs = template.getMaximumOccurs();
-            valueClass    = template.getValueClass();
-            defaultValue  = template.getDefaultValue();
-            for (final AttributeType<?> c : template.characteristics().values()) {
-                characteristics.add(new Characteristic<>(this, c));
-            }
-        }
-
-        /**
-         * Returns a default name to use if the user did not specified a name. The first letter will be changed to
-         * lower case (unless the name looks like an acronym) for compliance with Java convention on property names.
-         */
-        @Override
-        final String getDefaultName() {
-            return Classes.getShortName(valueClass);
-        }
-
-        /**
-         * Sets the {@code AttributeType} name as a generic name.
-         * If another name was defined before this method call, that previous value will be discarded.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Attribute<V> setName(final GenericName name) {
-            super.setName(name);
-            return this;
-        }
-
-        /**
-         * Sets the {@code AttributeType} name as a simple string with the default scope.
-         * The default scope is the value specified by the last call to
-         * {@link FeatureTypeBuilder#setDefaultScope(String)}.
-         * The name will be a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} if no default scope
-         * has been specified, or a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} otherwise.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Attribute<V> setName(final String localPart) {
-            super.setName(localPart);
-            return this;
-        }
-
-        /**
-         * Sets the {@code AttributeType} name as a string in the given scope.
-         * The name will be a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} if the given scope is
-         * {@code null} or empty, or a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} otherwise.
-         * If a {@linkplain FeatureTypeBuilder#setDefaultScope(String) default scope} has been specified, then the
-         * {@code scope} argument overrides it.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Attribute<V> setName(final String scope, final String localPart) {
-            super.setName(scope, localPart);
-            return this;
-        }
-
-        /**
-         * Sets the default value for the property.
-         *
-         * @param  value  default property value, or {@code null} if none.
-         * @return {@code this} for allowing method calls chaining.
-         */
-        public Attribute<V> setDefaultValue(final V value) {
-            if (!Objects.equals(defaultValue, value)) {
-                defaultValue = value;
-                clearCache();
-            }
-            return this;
-        }
-
-        /**
-         * Sets an enumeration of valid values for this attribute.
-         *
-         * <p>This is a convenience method for {@link #addCharacteristic(Class)} with a value
-         * of type {@link Set} and a conventional name.</p>
-         *
-         * @param  values valid values.
-         * @return {@code this} for allowing method calls chaining.
-         * @throws UnsupportedOperationException if this property does not support characteristics.
-         *
-         * @see AttributeConvention#VALID_VALUES_CHARACTERISTIC
-         */
-        @SafeVarargs
-        public final Attribute<V> setValidValues(final V... values) {
-            return setCharacteristic(AttributeConvention.VALID_VALUES_CHARACTERISTIC,
-                    Set.class, CollectionsExt.immutableSet(false, values));
-        }
-
-        /**
-         * Sets the maximal length that characterizes the {@link CharSequence} values of this attribute.
-         * While this characteristic can be applied to any kind of attribute, it is meaningful only with
-         * character sequences.
-         *
-         * <p>This is a convenience method for {@link #addCharacteristic(Class)} with a value
-         * of type {@link Integer} and a conventional name.</p>
-         *
-         * @param  length  maximal length of {@link CharSequence} attribute values, or {@code null}.
-         * @return {@code this} for allowing method calls chaining.
-         * @throws UnsupportedOperationException if this property does not support length characteristics.
-         *
-         * @see AttributeConvention#MAXIMAL_LENGTH_CHARACTERISTIC
-         */
-        public Attribute<V> setMaximalLengthCharacteristic(final Integer length) {
-            return setCharacteristic(AttributeConvention.MAXIMAL_LENGTH_CHARACTERISTIC, Integer.class, length);
-        }
-
-        /**
-         * Sets the coordinate reference system that characterizes the values of this attribute.
-         * While this characteristic can be applied to any kind of attribute, it is meaningful
-         * only with georeferenced values like geometries or coverages.
-         *
-         * <p>This is a convenience method for {@link #addCharacteristic(Class)} with a value
-         * of type {@link CoordinateReferenceSystem} and a conventional name.</p>
-         *
-         * @param  crs  coordinate reference system associated to attribute values, or {@code null}.
-         * @return {@code this} for allowing method calls chaining.
-         * @throws UnsupportedOperationException if this property does not support CRS characteristics.
-         *
-         * @see AttributeConvention#CRS_CHARACTERISTIC
-         */
-        public Attribute<V> setCRSCharacteristic(final CoordinateReferenceSystem crs) {
-            return setCharacteristic(AttributeConvention.CRS_CHARACTERISTIC, CoordinateReferenceSystem.class, crs);
-        }
-
-        /**
-         * Implementation of all setter methods for characteristics.
-         *
-         * @throws UnsupportedOperationException if this property does not support characteristics.
-         */
-        private <C> Attribute<V> setCharacteristic(final GenericName name, final Class<C> type, final C value) {
-            for (final Characteristic<?> characteristic : characteristics) {
-                if (name.equals(characteristic.getName())) {
-                    characteristic.set(value);
-                    return this;
-                }
-            }
-            addCharacteristic(type).setDefaultValue(value).setName(name);
-            return this;
-        }
-
-        /**
-         * Adds another attribute type that describes this attribute type.
-         * See <cite>"Attribute characterization"</cite> in {@link DefaultAttributeType} Javadoc for more information.
-         *
-         * <p>Usage example:</p>
-         * {@preformat java
-         *     attribute.addCharacteristic(Unit.class).setName("Unit of measurement").setDefaultValue(SI.CELSIUS);
-         * }
-         *
-         * The default characteristic name is the name of the given type, but callers should invoke one
-         * of the {@code Characteristic.setName(…)} methods on the returned instance with a better name.
-         *
-         * @param  <C>   the compile-time type of {@code type} argument.
-         * @param  type  the class of characteristic values.
-         * @return a builder for a characteristic of this attribute.
-         */
-        public <C> Characteristic<C> addCharacteristic(final Class<C> type) {
-            if (valueClass == Feature.class) {
-                throw new UnsupportedOperationException(errors().getString(Errors.Keys.IllegalOperationForValueClass_1, valueClass));
-            }
-            ensureNonNull("type", type);
-            final Characteristic<C> characteristic = new Characteristic<>(this, type);
-            characteristics.add(characteristic);
-            clearCache();
-            return characteristic;
-        }
-
-        /**
-         * Adds another attribute type that describes this attribute type, using an existing one as a template.
-         * See <cite>"Attribute characterization"</cite> in {@link DefaultAttributeType} Javadoc for more information.
-         *
-         * @param  <C>       the compile-time type of values in the {@code template} argument.
-         * @param  template  an existing attribute type to use as a template.
-         * @return a builder for a characteristic of this attribute, initialized with the values of the given template.
-         */
-        public <C> Characteristic<C> addCharacteristic(final AttributeType<C> template) {
-            ensureNonNull("template", template);
-            final Characteristic<C> characteristic = new Characteristic<>(this, template);
-            characteristics.add(characteristic);
-            clearCache();
-            return characteristic;
-        }
-
-        /**
-         * Roles that can be associated to some attributes for instructing {@code FeatureTypeBuilder}
-         * how to generate pre-defined operations. Those pre-defined operations are:
-         *
-         * <ul>
-         *   <li>A {@linkplain FeatureOperations#compound compound operation} for generating a unique identifier
-         *       from an arbitrary amount of attribute values.</li>
-         *   <li>A {@linkplain FeatureOperations#link link operation} for referencing a geometry to be used as the
-         *       <em>default</em> geometry.</li>
-         *   <li>An {@linkplain FeatureOperations#envelope operation} for computing the bounding box of all geometries
-         *       found in the feature. This operation is automatically added if the feature contains a default geometry.</li>
-         * </ul>
-         *
-         * This enumeration allows user code to specify which feature attribute to use for creating those operations.
-         *
-         * @see Attribute#addRole(Role)
-         */
-        public static enum Role {
-            /**
-             * Attribute value will be part of a unique identifier for the feature instance.
-             * An arbitrary amount of attributes can be flagged as identifier components:
-             *
-             * <ul>
-             *   <li>If no attribute has this role, then no attribute is marked as feature identifier.</li>
-             *   <li>If exactly one attribute has this role, then a synthetic attribute named {@code "@identifier"}
-             *       will be created as a {@linkplain FeatureOperations#link link} to the flagged attribute.</li>
-             *   <li>If more than one attribute have this role, then a synthetic attribute named {@code "@identifier"}
-             *       will be created as a {@linkplain FeatureOperations#compound compound key} made of all flagged
-             *       attributes. The separator character can be modified by a call to
-             *       {@link FeatureTypeBuilder#setIdentifierDelimiters(String, String, String)}</li>
-             * </ul>
-             *
-             * @see FeatureTypeBuilder#setIdentifierDelimiters(String, String, String)
-             */
-            IDENTIFIER_COMPONENT,
-
-            /**
-             * Attribute value will be flagged as the <em>default</em> geometry.
-             * Feature can have an arbitrary amount of geometry attributes,
-             * but only one can be flagged as the default geometry.
-             */
-            DEFAULT_GEOMETRY
-        }
-
-        /**
-         * Flags this attribute as an input of one of the pre-defined operations managed by {@code FeatureTypeBuilder}.
-         *
-         * @param role the role to add to this attribute (shall not be null).
-         */
-        public void addRole(final Role role) {
-            ensureNonNull("role", role);
-            switch (role) {
-                case IDENTIFIER_COMPONENT: {
-                    if (!isIdentifier) {
-                        isIdentifier = true;
-                        owner.identifierCount++;
-                        owner.clearCache();         // The change does not impact this attribute itself.
-                    }
-                    break;
-                }
-                case DEFAULT_GEOMETRY: {
-                    if (owner.defaultGeometry != this) {
-                        if (!Geometries.isKnownType(valueClass)) {
-                            throw new IllegalStateException(errors().getString(Errors.Keys.UnsupportedImplementation_1, valueClass));
-                        }
-                        if (owner.defaultGeometry != null) {
-                            throw new IllegalStateException(errors().getString(Errors.Keys.PropertyAlreadyExists_2,
-                                    owner.getDisplayName(), AttributeConvention.GEOMETRY_PROPERTY));
-                        }
-                        owner.defaultGeometry = this;
-                        owner.clearCache();         // The change does not impact this attribute itself.
-                    }
-                    break;
-                }
-            }
-        }
-
-        /**
-         * Returns {@code true} if {@link Role#IDENTIFIER_COMPONENT} has been associated to this attribute.
-         */
-        @Override
-        boolean isIdentifier() {
-            return isIdentifier;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Attribute<V> setDefinition(final CharSequence definition) {
-            super.setDefinition(definition);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Attribute<V> setDesignation(final CharSequence designation) {
-            super.setDesignation(designation);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Attribute<V> setDescription(final CharSequence description) {
-            super.setDescription(description);
-            return this;
-        }
-
-        /**
-         * Appends a text inside the value returned by {@link #toString()}, before the closing bracket.
-         */
-        @Override
-        final void toStringInternal(final StringBuilder buffer) {
-            buffer.append(" : ").append(Classes.getShortName(valueClass));
-        }
-
-        /**
-         * Creates a new property type from the current setting.
-         */
-        @Override
-        final PropertyType create() {
-            final AttributeType<?>[] chrts = new AttributeType<?>[characteristics.size()];
-            for (int i=0; i<chrts.length; i++) {
-                chrts[i] = characteristics.get(i).build();
-            }
-            return new DefaultAttributeType<>(identification(), valueClass, minimumOccurs, maximumOccurs, defaultValue, chrts);
-        }
-    }
-
-
-
-
-    /**
-     * Describes one characteristic of an {@code AttributeType} to be built by the enclosing {@code FeatureTypeBuilder}.
-     * A different instance of {@code Characteristic} exists for each characteristic to describe.
-     * Those instances are created by:
-     *
-     * <ul>
-     *   <li>{@link Attribute#addCharacteristic(Class)}</li>
-     * </ul>
-     *
-     * @param <V> the class of characteristic values.
-     */
-    public static final class Characteristic<V> extends FeatureElementBuilder {
-        /**
-         * The attribute type builder instance that created this {@code Characteristic} builder.
-         */
-        private final Attribute<?> owner;
-
-        /**
-         * The class of attribute values. Can not be changed after construction
-         * because this value determines the parameterized type {@code <V>}.
-         */
-        private final Class<V> valueClass;
-
-        /**
-         * The default value for the attribute, or {@code null} if none.
-         */
-        private V defaultValue;
-
-        /**
-         * The characteristic created by this builder, or {@code null} if not yet created.
-         * This field must be cleared every time that a setter method is invoked on this builder.
-         */
-        private transient AttributeType<V> characteristic;
-
-        /**
-         * Creates a new characteristic builder for values of the given class.
-         *
-         * @param owner      the builder of the {@code AttributeType} for which to add this property.
-         * @param valueClass the class of characteristic values.
-         */
-        Characteristic(final Attribute<?> owner, final Class<V> valueClass) {
-            super(null, owner.getLocale());
-            this.owner = owner;
-            this.valueClass = valueClass;
-        }
-
-        /**
-         * Creates a new characteristic builder initialized to the values of an existing attribute.
-         *
-         * @param owner  the builder of the {@code AttributeType} for which to add this property.
-         */
-        Characteristic(final Attribute<?> owner, final AttributeType<V> template) {
-            super(template, owner.getLocale());
-            this.owner     = owner;
-            valueClass     = template.getValueClass();
-            defaultValue   = template.getDefaultValue();
-            characteristic = template;
-        }
-
-        /**
-         * If the {@code AttributeType<V>} created by the last call to {@link #build()} has been cached,
-         * clears that cache. This method must be invoked every time that a setter method is invoked.
-         */
-        @Override
-        final void clearCache() {
-            characteristic = null;
-            owner.clearCache();
-        }
-
-        /**
-         * Returns a default name to use if the user did not specified a name. The first letter will be changed to
-         * lower case (unless the name looks like an acronym) for compliance with Java convention on property names.
-         */
-        @Override
-        final String getDefaultName() {
-            return Classes.getShortName(valueClass);
-        }
-
-        /**
-         * Sets the characteristic name as a generic name.
-         * If another name was defined before this method call, that previous value will be discarded.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Characteristic<V> setName(final GenericName name) {
-            super.setName(name);
-            return this;
-        }
-
-        /**
-         * Sets the characteristic name as a simple string with the default scope.
-         * The default scope is the value specified by the last call to
-         * {@link FeatureTypeBuilder#setDefaultScope(String)}.
-         * The name will be a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} if no default scope
-         * has been specified, or a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} otherwise.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Characteristic<V> setName(final String localPart) {
-            super.setName(localPart);
-            return this;
-        }
-
-        /**
-         * Sets the characteristic name as a string in the given scope.
-         * The name will be a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} if the given scope is
-         * {@code null} or empty, or a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} otherwise.
-         * If a {@linkplain FeatureTypeBuilder#setDefaultScope(String) default scope} has been specified, then the
-         * {@code scope} argument overrides it.
-         *
-         * @return {@code this} for allowing method calls chaining.
-         */
-        @Override
-        public Characteristic<V> setName(final String scope, final String localPart) {
-            super.setName(scope, localPart);
-            return this;
-        }
-
-        /**
-         * Delegates the creation of a new name to the enclosing builder.
-         */
-        @Override
-        final GenericName name(final String scope, final String localPart) {
-            return owner.name(scope, localPart);
-        }
-
-        /**
-         * Sets the default value with check of the value class.
-         */
-        final void set(final Object value) {
-            setDefaultValue(valueClass.cast(value));
-        }
-
-        /**
-         * Sets the default value for the characteristic.
-         *
-         * @param  value  characteristic default value, or {@code null} if none.
-         * @return {@code this} for allowing method calls chaining.
-         */
-        public Characteristic<V> setDefaultValue(final V value) {
-            if (!Objects.equals(defaultValue, value)) {
-                defaultValue = value;
-                clearCache();
-            }
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Characteristic<V> setDefinition(final CharSequence definition) {
-            super.setDefinition(definition);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Characteristic<V> setDesignation(final CharSequence designation) {
-            super.setDesignation(designation);
-            return this;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public Characteristic<V> setDescription(final CharSequence description) {
-            super.setDescription(description);
-            return this;
-        }
-
-        /**
-         * Creates a new characteristic from the current setting.
-         */
-        final AttributeType<V> build() {
-            if (characteristic == null) {
-                characteristic = new DefaultAttributeType<>(identification(), valueClass, 0, 1, defaultValue);
-            }
-            return characteristic;
-        }
-    }
-
-
-
-
     /**
      * {@inheritDoc}
      */
@@ -1367,7 +549,7 @@ public class FeatureTypeBuilder extends
      *
      * @return the new feature type.
      * @throws IllegalStateException if the feature type contains incompatible
-     *         {@linkplain Attribute#setCRSCharacteristic CRS characteristics}.
+     *         {@linkplain AttributeTypeBuilder#setCRS CRS characteristics}.
      */
     public FeatureType build() throws IllegalStateException {
         if (feature == null) {
@@ -1397,13 +579,13 @@ public class FeatureTypeBuilder extends
             int propertyCursor = numSynthetic;
             int identifierCursor = 0;
             for (int i=0; i<numSpecified; i++) {
-                final Property     builder = properties.get(i);
+                final PropertyTypeBuilder builder = properties.get(i);
                 final PropertyType instance = builder.build();
                 propertyTypes[propertyCursor] = instance;
                 /*
                  * Collect the attributes to use as identifier components while we loop over all properties.
                  * A NullPointerException or an ArrayIndexOutOfBoundsException in this block would mean that
-                 * identifierCount field has not been updated correctly by an Attribute.addRole(Role) method.
+                 * identifierCount field has not been updated correctly by an addRole(AttributeRole) method.
                  */
                 if (builder.isIdentifier()) {
                     identifierTypes[identifierCursor++] = instance;
@@ -1486,7 +668,7 @@ public class FeatureTypeBuilder extends
         }
         buffer.append(" {");
         separator = System.lineSeparator();
-        for (final Property p : properties) {
+        for (final PropertyTypeBuilder p : properties) {
             p.toString(buffer.append(separator).append("    ").append(p.getClass().getSimpleName()));
         }
         buffer.append(separator).append('}');



Mime
View raw message