001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2006-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.feature;
019
020import java.util.Map;
021import java.util.Collections;
022import org.opengis.annotation.UML;
023import org.opengis.annotation.Stereotype;
024import org.opengis.annotation.Classifier;
025import org.opengis.util.GenericName;
026
027import static org.opengis.annotation.Obligation.*;
028import static org.opengis.annotation.Specification.ISO_19109;
029
030
031/**
032 * Definition of an attribute in a feature type.
033 * The name of attribute type is mandatory. The name {@linkplain org.opengis.util.GenericName#scope() scope}
034 * is typically the name of the {@linkplain FeatureType feature type} containing this attribute, but this is
035 * not mandatory. The scope could also be defined by the ontology for example.
036 *
037 * <div class="note"><b>Note:</b>
038 * compared to the Java language, {@code AttributeType} is equivalent to {@link java.lang.reflect.Field}
039 * while {@code FeatureType} is equivalent to {@link Class}.</div>
040 *
041 * <h2>Value type</h2>
042 * Attributes can be used for both spatial and non-spatial properties.
043 * Some examples are:
044 *
045 * <table class="ogc">
046 *   <caption>Attribute value type examples</caption>
047 *   <tr><th>Attribute name</th>      <th>Value type</th></tr>
048 *   <tr><td>Building shape</td>      <td>{@link org.opengis.geometry.Geometry}</td></tr>
049 *   <tr><td>Building owner</td>      <td>{@link org.opengis.metadata.citation.Responsibility}</td></tr>
050 *   <tr><td>Horizontal accuracy</td> <td>{@link org.opengis.metadata.quality.PositionalAccuracy}</td></tr>
051 * </table>
052 *
053 * <h2>Attribute characterization</h2>
054 * An {@code Attribute} can be characterized by other attributes. For example, an attribute that carries a measurement
055 * (e.g. air temperature) may have another attribute that holds the measurement accuracy (e.g. ±0.1°C).
056 * Such accuracy can be stored as a <i>characteristic</i> of the measurement attribute.
057 *
058 * <p>The {@link #characteristics()} method in this {@code AttributeType} interface returns a description of all
059 * characteristics that attributes of this type may have. The actual characteristics values can be stored on a
060 * record-by-record basis in the {@link Attribute#characteristics()} map.
061 * However, in the common case of characteristics having a constant value for all records in a dataset,
062 * the constant can be given by the characteristic {@linkplain #getDefaultValue() default value} and
063 * {@code Attribute.characteristics()} may return an empty map (at implementation choice).</p>
064 *
065 * @param <V> the type of attribute values. If the attribute supports multi-occurrences,
066 *            then this is the type of elements (not the collection type).
067 *
068 * @author  Jody Garnett (Refractions Research)
069 * @author  Justin Deoliveira (The Open Planning Project)
070 * @author  Martin Desruisseaux (Geomatys)
071 * @version 3.1
072 * @since   3.1
073 *
074 * @see Attribute
075 * @see DynamicAttributeType
076 */
077@Classifier(Stereotype.METACLASS)
078@UML(identifier="AttributeType", specification=ISO_19109)
079public interface AttributeType<V> extends PropertyType {
080    /**
081     * Returns the name of this attribute type.
082     * For {@code AttributeType}, the name is mandatory.
083     *
084     * @return the attribute type name.
085     */
086    @Override
087    @UML(identifier="name", obligation=MANDATORY, specification=ISO_19109)
088    GenericName getName();
089
090    /**
091     * Returns the type of attribute values.
092     *
093     * @return the type of attribute values.
094     */
095    @UML(identifier="valueType", obligation=MANDATORY, specification=ISO_19109)
096    Class<V> getValueClass();
097
098    /*
099     * ISO 19109 properties omitted for now:
100     *
101     *   - valueDomain : CharacterString
102     *
103     * Rational: a CharacterString is hardly programmatically usable. A Range would be better but too specific.
104     * We could follow the GeoAPI path and define a "restrictions : Filter" property. That would be more generic,
105     * but we are probably better to wait for Filter to be made submitted to a GeoAPI release.
106     */
107
108    /**
109     * Returns the minimum number of attribute values.
110     * The returned value is greater than or equal to zero.
111     *
112     * <p>To be valid, an {@code Attribute} instance of this {@code AttributeType} shall have at least
113     * this minimum number of elements in its {@link Attribute#getValues() collection of values}.</p>
114     *
115     * @return the minimum number of attribute values.
116     */
117    @UML(identifier="cardinality", obligation=MANDATORY, specification=ISO_19109)
118    int getMinimumOccurs();
119
120    /**
121     * Returns the maximum number of attribute values.
122     * The returned value is greater than or equal to the {@link #getMinimumOccurs()} value.
123     * If there is no maximum, then this method returns {@link Integer#MAX_VALUE}.
124     *
125     * <p>To be valid, an {@code Attribute} instance of this {@code AttributeType} shall have no more than
126     * this maximum number of elements in its {@link Attribute#getValues() collection of values}.</p>
127     *
128     * @return the maximum number of attribute values, or {@link Integer#MAX_VALUE} if none.
129     */
130    @UML(identifier="cardinality", obligation=MANDATORY, specification=ISO_19109)
131    int getMaximumOccurs();
132
133    /**
134     * Returns the default value for the attribute.
135     * This value is used when an attribute is created and no value for it is specified.
136     *
137     * @return the default value for the attribute, or {@code null} if none.
138     */
139    V getDefaultValue();
140
141    /**
142     * Other attribute types that describe this attribute type.
143     * See <cite>Attribute characterization</cite> in class Javadoc for more information.
144     *
145     * <div class="note"><b>Example:</b>
146     * an attribute that carries a measurement (e.g. air temperature) may have another attribute
147     * that holds the measurement accuracy.</div>
148     *
149     * The characteristics are enumerated in the {@linkplain Map#values() map values}.
150     * The {@linkplain Map#keySet() map keys} are the {@code String} representations of
151     * characteristics {@linkplain #getName() name}, for more convenient lookups.
152     *
153     * @return other attribute types that describe this attribute type, or an empty map if none.
154     *
155     * @see Attribute#characteristics()
156     */
157    @UML(identifier="characterizeBy", obligation=OPTIONAL, specification=ISO_19109)
158    default Map<String,AttributeType<?>> characteristics() {
159        return Collections.emptyMap();
160    }
161    /*
162     * Note: ISO 19109 also defines the following member
163     * for traversing the association in the opposite way:
164     *
165     *   - characterize the attribute type that is described by this attribute type.
166     *
167     * This member has been omitted for now.
168     */
169
170    /**
171     * Creates a new attribute instance of this type initialized to the {@linkplain #getDefaultValue() default value}.
172     *
173     * @return a new attribute instance.
174     * @throws UnsupportedOperationException if this type does not support new instance creation.
175     */
176    Attribute<V> newInstance() throws UnsupportedOperationException;
177}