/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.feature.builder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Objects;
import java.lang.reflect.Array;
import org.opengis.util.GenericName;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.feature.DefaultAttributeType;
import org.apache.sis.feature.FeatureOperations;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.util.SetOfUnknownSize;
import org.apache.sis.internal.util.AbstractIterator;
import org.apache.sis.internal.feature.AttributeConvention;
import org.apache.sis.internal.feature.Geometries;
import org.apache.sis.internal.feature.Resources;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.Classes;
import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.UnconvertibleObjectException;

// Branch-dependent imports
import org.opengis.feature.AttributeType;


/**
 * Describes one {@code AttributeType} which will be part of the feature type to be built by
 * a {@code FeatureTypeBuilder}. An attribute can be for example a city name, a temperature
 * (together with its units of measurement and uncertainty if desired) or a geometric shape.
 * Attribute types contain the following information:
 *
 * <ul>
 *   <li>the name        — a unique name which can be defined within a scope (or namespace).</li>
 *   <li>the definition  — a concise definition of the element.</li>
 *   <li>the designation — a natural language designator for the element for user interfaces.</li>
 *   <li>the description — information beyond that required for concise definition of the element.</li>
 *   <li>the value class — often {@link String}, {@link Float} or {@link com.esri.core.geometry.Geometry}.
 *       Must be specified at {@linkplain FeatureTypeBuilder#addAttribute(Class) construction time}.</li>
 *   <li>a default value — to be used when an attribute instance does not provide an explicit value.</li>
 *   <li>characteristics — for example the units of measurement for all attributes of the same type.</li>
 *   <li>multiplicity    — the minimum and maximum occurrences of attribute values.</li>
 * </ul>
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.8
 *
 * @param <V>  the class of attribute values.
 *
 * @see FeatureTypeBuilder#addAttribute(Class)
 * @see org.apache.sis.feature.DefaultAttributeType
 *
 * @since 0.8
 * @module
 */
public final class AttributeTypeBuilder<V> extends PropertyTypeBuilder {
    /**
     * 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;

    /**
     * Whether this attribute will be used in a {@linkplain FeatureOperations#compound compound key} named
     * {@code "sis:identifier"}. If only one attribute has this flag and {@link FeatureTypeBuilder#idPrefix} and
     * {@code isSuffix} are null, then {@code "sis:identifier"} will be a {@linkplain FeatureOperations#link link}
     * to {@code idAttributes[0]}.
     *
     * @see #addRole(AttributeRole)
     */
    private boolean isIdentifier;

    /**
     * Builders for the characteristics associated to the attribute.
     */
    final List<CharacteristicTypeBuilder<?>> characteristics;

    /**
     * The attribute type 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> property;

    /**
     * Creates a new builder initialized to the values of the given builder.
     * This constructor is for {@link #setValueClass(Class)} implementation only.
     *
     * @throws UnconvertibleObjectException if the default value can not be converted to the given class.
     */
    private AttributeTypeBuilder(final AttributeTypeBuilder<?> builder, final Class<V> valueClass)
            throws UnconvertibleObjectException
    {
        super(builder);
        this.valueClass = valueClass;
        defaultValue = ObjectConverters.convert(builder.defaultValue, valueClass);
        isIdentifier = builder.isIdentifier;
        characteristics = builder.characteristics;
    }

    /**
     * Creates a new {@code AttributeType} builder for values of the given class.
     *
     * @param owner       the builder of the {@code FeatureType} for which to add the attribute.
     * @param valueClass  the class of attribute values.
     */
    AttributeTypeBuilder(final FeatureTypeBuilder owner, final Class<V> valueClass) {
        super(owner);
        this.valueClass = valueClass;
        characteristics = new ArrayList<>();
    }

    /**
     * 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 the attribute.
     */
    AttributeTypeBuilder(final FeatureTypeBuilder owner, final AttributeType<V> template) {
        super(owner);
        property      = template;
        minimumOccurs = template.getMinimumOccurs();
        maximumOccurs = template.getMaximumOccurs();
        valueClass    = template.getValueClass();
        defaultValue  = template.getDefaultValue();
        final Map<String, AttributeType<?>> tc = template.characteristics();
        characteristics = new ArrayList<>(tc.size());
        for (final AttributeType<?> c : tc.values()) {
            characteristics.add(new CharacteristicTypeBuilder<>(this, c));
        }
        initialize(template);
    }

    /**
     * If the {@code AttributeType} 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;
        super.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 attribute 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 AttributeTypeBuilder<V> setName(final GenericName name) {
        super.setName(name);
        return this;
    }

    /**
     * Sets the {@code AttributeType} name as a simple string (local name).
     * The namespace will be the value specified by the last call to {@link FeatureTypeBuilder#setNameSpace(CharSequence)},
     * but that namespace will not be visible in the {@linkplain org.apache.sis.util.iso.DefaultLocalName#toString()
     * string representation} unless the {@linkplain org.apache.sis.util.iso.DefaultLocalName#toFullyQualifiedName()
     * fully qualified name} is requested.
     *
     * <p>This convenience method creates a {@link org.opengis.util.LocalName} instance from
     * the given {@code CharSequence}, then delegates to {@link #setName(GenericName)}.</p>
     *
     * @return {@code this} for allowing method calls chaining.
     */
    @Override
    public AttributeTypeBuilder<V> setName(final CharSequence localPart) {
        super.setName(localPart);
        return this;
    }

    /**
     * Sets the {@code AttributeType} name as a string in the given scope.
     * The {@code components} array must contain at least one element.
     * The last component (the {@linkplain org.apache.sis.util.iso.DefaultScopedName#tip() tip}) will be sufficient
     * in many cases for calls to the {@link org.apache.sis.feature.AbstractFeature#getProperty(String)} method.
     * The other elements before the last one are optional and can be used for resolving ambiguity.
     * They will be visible as the name {@linkplain org.apache.sis.util.iso.DefaultScopedName#path() path}.
     *
     * <div class="note"><b>Example:</b>
     * a call to {@code setName("A", "B", "C")} will create a "A:B:C" name.
     * An attribute built with this name can be obtained from a feature by a call to {@code feature.getProperty("C")}
     * if there is no ambiguity, or otherwise by a call to {@code feature.getProperty("B:C")} (if non-ambiguous) or
     * {@code feature.getProperty("A:B:C")}.</div>
     *
     * In addition to the path specified by the {@code components} array, the name may also contain
     * a namespace specified by the last call to {@link FeatureTypeBuilder#setNameSpace(CharSequence)}.
     * But contrarily to the specified components, the namespace will not be visible in the name
     * {@linkplain org.apache.sis.util.iso.DefaultScopedName#toString() string representation} unless the
     * {@linkplain org.apache.sis.util.iso.DefaultScopedName#toFullyQualifiedName() fully qualified name} is requested.
     *
     * <p>This convenience method creates a {@link org.opengis.util.LocalName} or {@link org.opengis.util.ScopedName}
     * instance depending on whether the {@code names} array contains exactly 1 element or more than 1 element, then
     * delegates to {@link #setName(GenericName)}.</p>
     *
     * @return {@code this} for allowing method calls chaining.
     */
    @Override
    public AttributeTypeBuilder<V> setName(final CharSequence... components) {
        super.setName(components);
        return this;
    }

    /**
     * Sets the minimum number of attribute values. If the given number is greater than the
     * {@linkplain #getMaximumOccurs() maximal number} of attribute values, than the maximum
     * is also set to that value.
     *
     * @param  occurs  the new minimum number of attribute values.
     * @return {@code this} for allowing method calls chaining.
     */
    @Override
    public AttributeTypeBuilder<V> setMinimumOccurs(final int occurs) {
        super.setMinimumOccurs(occurs);
        return this;
    }

    /**
     * Sets the maximum number of attribute values. If the given number is less than the
     * {@linkplain #getMinimumOccurs() minimal number} of attribute values, than the minimum
     * is also set to that value. {@link Integer#MAX_VALUE} means that there is no maximum.
     *
     * @param  occurs  the new maximum number of attribute values.
     * @return {@code this} for allowing method calls chaining.
     */
    @Override
    public AttributeTypeBuilder<V> setMaximumOccurs(final int occurs) {
        super.setMaximumOccurs(occurs);
        return this;
    }

    /**
     * Returns the class of attribute values.
     *
     * @return the class of attribute values.
     *
     * @see #setValueClass(Class)
     */
    public Class<V> getValueClass() {
        return valueClass;
    }

    /**
     * Sets the class of attribute values. Callers <strong>must</strong> use the builder returned by this method
     * instead of {@code this} builder after this method call, since the returned builder may be a new instance.
     *
     * @param  <N>   the compile-time value of the {@code type} argument.
     * @param  type  the new class of attribute values.
     * @return the attribute builder — <em>not necessarily this instance.</em>
     * @throws UnconvertibleObjectException if the {@linkplain #getDefaultValue() default value}
     *         can not be converted to the given {@code <N>} class.
     *
     * @see #getValueClass()
     */
    @SuppressWarnings("unchecked")
    public <N> AttributeTypeBuilder<N> setValueClass(final Class<N> type) throws UnconvertibleObjectException {
        final FeatureTypeBuilder owner = owner();
        ensureNonNull("type", type);
        if (type == valueClass) {
            return (AttributeTypeBuilder<N>) this;
        }
        final AttributeTypeBuilder<N> newb = new AttributeTypeBuilder<>(this, type);
        for (final CharacteristicTypeBuilder<?> c : characteristics) {
            c.owner(newb);
        }
        owner.replace(this, newb);
        dispose();
        return newb;
    }

    /**
     * Returns the default value for the attribute, or {@code null} if none.
     *
     * @return the default attribute value, or {@code null} if none.
     *
     * @see #setDefaultValue(Object)
     */
    public V getDefaultValue() {
        return defaultValue;
    }

    /**
     * Sets the default value for the attribute.
     *
     * @param  value  default attribute value, or {@code null} if none.
     * @return {@code this} for allowing method calls chaining.
     *
     * @see #getDefaultValue()
     */
    public AttributeTypeBuilder<V> setDefaultValue(final V value) {
        if (!Objects.equals(defaultValue, value)) {
            defaultValue = value;
            clearCache();
        }
        return this;
    }

    /**
     * Returns an enumeration of valid values for the attribute, or an empty array if none.
     * This convenience method returns the value of the characteristic set by {@link #setValidValues(Object...)}.
     *
     * @return valid values for the attribute, or an empty array if none.
     */
    @SuppressWarnings("unchecked")
    public V[] getValidValues() {
        final Collection<?> c = CollectionsExt.nonNull((Collection<?>)
                getCharacteristic(AttributeConvention.VALID_VALUES_CHARACTERISTIC));
        final V[] values = (V[]) Array.newInstance(valueClass, c.size());
        int index = 0;
        for (final Object value : c) {
            values[index++] = (V) value;        // ArrayStoreException if 'value' is not the expected type.
        }
        return values;
    }

    /**
     * Sets an enumeration of valid values for the 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.
     *
     * @see #characteristics()
     * @see AttributeConvention#VALID_VALUES_CHARACTERISTIC
     */
    @SafeVarargs
    public final AttributeTypeBuilder<V> setValidValues(final V... values) {
        return setCharacteristic(AttributeConvention.VALID_VALUES_CHARACTERISTIC,
                Set.class, CollectionsExt.immutableSet(false, values));
    }

    /**
     * Returns the maximal length that characterizes the {@link CharSequence} values of this attribute.
     * This convenience method returns the value of the characteristic set by {@link #setMaximalLength(Integer)}.
     *
     * @return the maximal length of {@link CharSequence} attribute values, or {@code null}.
     */
    public Integer getMaximalLength() {
        return (Integer) getCharacteristic(AttributeConvention.MAXIMAL_LENGTH_CHARACTERISTIC);
    }

    /**
     * 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.
     *
     * @see #characteristics()
     * @see AttributeConvention#MAXIMAL_LENGTH_CHARACTERISTIC
     */
    public AttributeTypeBuilder<V> setMaximalLength(final Integer length) {
        return setCharacteristic(AttributeConvention.MAXIMAL_LENGTH_CHARACTERISTIC, Integer.class, length);
    }

    /**
     * Returns the coordinate reference system associated to attribute values.
     * This convenience method returns the value of the characteristic set by {@link #setCRS(CoordinateReferenceSystem)}.
     *
     * @return the coordinate reference system associated to attribute values, or {@code null}.
     */
    public CoordinateReferenceSystem getCRS() {
        return (CoordinateReferenceSystem) getCharacteristic(AttributeConvention.CRS_CHARACTERISTIC);
    }

    /**
     * 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.
     *
     * @see #characteristics()
     * @see AttributeConvention#CRS_CHARACTERISTIC
     */
    public AttributeTypeBuilder<V> setCRS(final CoordinateReferenceSystem crs) {
        return setCharacteristic(AttributeConvention.CRS_CHARACTERISTIC, CoordinateReferenceSystem.class, crs);
    }

    /**
     * Implementation of all getter methods for characteristics.
     */
    private Object getCharacteristic(final GenericName name) {
        for (final CharacteristicTypeBuilder<?> characteristic : characteristics) {
            if (name.equals(characteristic.getName())) {
                return characteristic.getDefaultValue();
            }
        }
        return null;
    }

    /**
     * Implementation of all setter methods for characteristics.
     */
    private <C> AttributeTypeBuilder<V> setCharacteristic(final GenericName name, final Class<C> type, final C value) {
        for (final CharacteristicTypeBuilder<?> characteristic : characteristics) {
            if (name.equals(characteristic.getName())) {
                characteristic.set(value);
                clearCache();
                return this;
            }
        }
        addCharacteristic(type).setDefaultValue(value).setName(name);
        return this;
    }

    /**
     * Returns the builder for the characteristic of the given name. The given name does not need to contains
     * all elements of a {@link org.opengis.util.ScopedName}; it is okay to specify only the tip (for example
     * {@code "myName"} instead of {@code "myScope:myName"}) provided that ignoring the name head does not
     * create ambiguity.
     *
     * @param  name   name of the characteristic to search.
     * @return characteristic of the given name, or {@code null} if none.
     * @throws IllegalArgumentException if the given name is ambiguous.
     *
     * @see #characteristics()
     */
    public CharacteristicTypeBuilder<?> getCharacteristic(final String name) {
        return forName(characteristics, name, true);
    }

    /**
     * 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(Units.CELSIUS);
     * }
     *
     * The default characteristic name is the name of the given type, but callers should invoke one
     * of the {@code CharacteristicTypeBuilder.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.
     *
     * @see #characteristics()
     */
    public <C> CharacteristicTypeBuilder<C> addCharacteristic(final Class<C> type) {
        ensureNonNull("type", type);
        final CharacteristicTypeBuilder<C> characteristic = new CharacteristicTypeBuilder<>(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.
     *
     * @see #characteristics()
     */
    public <C> CharacteristicTypeBuilder<C> addCharacteristic(final AttributeType<C> template) {
        ensureNonNull("template", template);
        final CharacteristicTypeBuilder<C> characteristic = new CharacteristicTypeBuilder<>(this, template);
        characteristics.add(characteristic);
        clearCache();
        return characteristic;
    }

    /**
     * Returns a view of all characteristics added to the {@code AttributeType} 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 characteristics can be added only by calls to one of the {@code set/addCharacteristic(…)} methods.
     *
     * @return a live list over the characteristics declared to this builder.
     *
     * @see #getCharacteristic(String)
     * @see #addCharacteristic(Class)
     * @see #addCharacteristic(AttributeType)
     * @see #setValidValues(Object...)
     * @see #setCRS(CoordinateReferenceSystem)
     */
    public List<CharacteristicTypeBuilder<?>> characteristics() {
        return new RemoveOnlyList<>(characteristics);
    }

    /**
     * Returns the roles that the attribute play in the pre-defined operations managed by {@code AttributeTypeBuilder}.
     * The set returned by this method is <cite>live</cite>: additions or removal on that set are reflected back on
     * this builder, and conversely.
     *
     * @return the roles that the attribute play in the pre-defined operations managed by {@code AttributeTypeBuilder}.
     */
    public Set<AttributeRole> roles() {
        return new SetOfUnknownSize<AttributeRole>() {
            @Override public Iterator<AttributeRole> iterator() {return new RoleIter();}
            @Override public boolean add(AttributeRole role)    {return addRole(role);}
        };
    }

    /**
     * The iterator returned by the {@link AttributeTypeBuilder#roles()} set.
     */
    private final class RoleIter extends AbstractIterator<AttributeRole> {
        /**
         * Index of the next {@code AttributeRole} to return.
         */
        private int index;

        /**
         * Prepares the next {@code AttributeRole} on which to iterate and returns
         * {@code true} if such {@code AttributeRole} has been found.
         */
        @Override
        @SuppressWarnings("fallthrough")
        public boolean hasNext() {
            if (next == null) {
                switch (index) {
                    case 0: {
                        if (isIdentifier) {
                            next = AttributeRole.IDENTIFIER_COMPONENT;
                            break;
                        }
                        index++;        // Fall through for testing the case for next 'index' value.
                    }
                    case 1: {
                        if (owner().defaultGeometry == AttributeTypeBuilder.this) {
                            next = AttributeRole.DEFAULT_GEOMETRY;
                            break;
                        }
                        index++;        // Fall through for testing the case for next 'index' value.
                    }
                    default: {
                        return false;
                    }
                }
                index++;
            }
            return true;
        }

        /**
         * Removes the element returned by the last {@link #next()} method.
         */
        @Override
        public void remove() {
            switch (index) {
                case 1: isIdentifier = false; break;
                case 2: owner().defaultGeometry = null; break;
                default: throw new IllegalStateException();
            }
        }
    }

    /**
     * Flags this attribute as an input of one of the pre-defined operations managed by {@code AttributeTypeBuilder}.
     * Invoking this method is equivalent to invoking <code>{@linkplain #roles()}.add(role)</code>.
     *
     * @param  role the role to add to the attribute (shall not be null).
     * @return {@code true} if the given role has been added to the attribute.
     */
    public boolean addRole(final AttributeRole role) {
        final FeatureTypeBuilder owner = owner();
        ensureNonNull("role", role);
        switch (role) {
            case IDENTIFIER_COMPONENT: {
                if (!isIdentifier) {
                    isIdentifier = true;
                    owner.identifierCount++;
                    owner.clearCache();         // The change does not impact this attribute itself.
                    return true;
                }
                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(resources().getString(Resources.Keys.PropertyAlreadyExists_2,
                                owner.getDisplayName(), AttributeConvention.GEOMETRY_PROPERTY));
                    }
                    owner.defaultGeometry = this;
                    owner.clearCache();         // The change does not impact this attribute itself.
                    return true;
                }
                break;
            }
        }
        return false;
    }

    /**
     * Returns {@code true} if {@link AttributeRole#IDENTIFIER_COMPONENT} has been associated to this attribute.
     */
    @Override
    boolean isIdentifier() {
        return isIdentifier;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeTypeBuilder<V> setDefinition(final CharSequence definition) {
        super.setDefinition(definition);
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeTypeBuilder<V> setDesignation(final CharSequence designation) {
        super.setDesignation(designation);
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeTypeBuilder<V> setDescription(final CharSequence description) {
        super.setDescription(description);
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeTypeBuilder<V> setDeprecated(final boolean deprecated) {
        super.setDeprecated(deprecated);
        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));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void remove() {
        if (isIdentifier) {
            isIdentifier = false;
            owner().identifierCount--;      // Owner should never be null since we set 'isIdentifier' to false.
        }
        super.remove();
    }

    /**
     * Builds the attribute type from the information specified to this builder.
     * If a type has already been built and this builder state has not changed since the type creation,
     * then the previously created {@code AttributeType} instance is returned.
     *
     * <div class="note"><b>Example:</b>
     * the following lines of code add a "name" attribute to a "City" feature, then get the corresponding
     * {@code AttributeType<String>} instance. If no setter method is invoked on the builder of the "name"
     * attribute after those lines, then the {@code name} variable below will reference the same instance
     * than the "name" attribute in the {@code city} type.
     *
     * {@preformat java
     *   FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("City");
     *   AttributeType<String> name = builder.addAttribute(String.class).setName("name").build();
     *   FeatureType city = builder.build();
     *
     *   assert city.getProperty("name") == name : "AttributeType instance should be the same.";
     * }
     *
     * Note that {@code city.getProperty("name")} returns {@code AttributeType<?>},
     * i.e. the {@linkplain #getValueClass() value class} is lost at compile-time.
     * By comparison, this {@code build()} method has a more accurate return type.
     * </div>
     *
     * @return the attribute type.
     */
    @Override
    public AttributeType<V> build() {
        if (property == null) {
            final AttributeType<?>[] chrts = new AttributeType<?>[characteristics.size()];
            for (int i=0; i<chrts.length; i++) {
                chrts[i] = characteristics.get(i).build();
            }
            property = new DefaultAttributeType<>(identification(), valueClass, minimumOccurs, maximumOccurs, defaultValue, chrts);
        }
        return property;
    }
}
