001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2004-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.Set;
021import java.util.Collection;
022import org.opengis.annotation.UML;
023import org.opengis.annotation.Classifier;
024import org.opengis.annotation.Stereotype;
025import org.opengis.util.GenericName;
026
027import static org.opengis.annotation.Obligation.*;
028import static org.opengis.annotation.Specification.ISO_19109;
029
030
031/**
032 * Abstraction of a real-world phenomena.
033 * A {@code FeatureType} instance describes the class of all {@link Feature} instances of that type.
034 *
035 * <div class="note"><b>Analogy with Java reflection</b>:
036 * compared to the Java language, {@code FeatureType} is equivalent to {@link Class} while
037 * {@code Feature} instances are equivalent to {@link Object} instances of that class.</div>
038 *
039 * <h2>Naming</h2>
040 * The feature type {@linkplain #getName() name} is mandatory and should be unique.
041 * Names can be {@linkplain org.opengis.util.ScopedName} for avoiding name collision.
042 *
043 * <h2>Properties and inheritance</h2>
044 * Each feature type can provide descriptions for the following {@linkplain #getProperties(boolean) properties}:
045 *
046 * <ul>
047 *   <li>{@linkplain AttributeType           Attributes}</li>
048 *   <li>{@linkplain FeatureAssociationRole  Associations to other features}</li>
049 *   <li>{@linkplain Operation               Operations}</li>
050 * </ul>
051 *
052 * In addition, a feature type can inherit the properties of one or more other feature types.
053 * Properties defined in the sub-type can override properties of the same name defined in the
054 * {@linkplain #getSuperTypes() super-types}, provided that values of the sub-type property are
055 * assignable to the super-type property.
056 *
057 * <div class="note"><b>Analogy with Java language</b>:
058 * compared to the Java language, the above rule is similar to overriding a method with a more specific return
059 * type (a.k.a. <dfn>covariant return type</dfn>). This is also similar to Java arrays, which are implicitly
060 * <i>covariant</i> (i.e. {@code String[]} can be casted to {@code CharSequence[]}, which is safe for read
061 * operations but not for write operations — the latter may throw {@link ArrayStoreException}).</div>
062 *
063 * @author  Jody Garnett (Refractions Research)
064 * @author  Justin Deoliveira (The Open Planning Project)
065 * @author  Martin Desruisseaux (Geomatys)
066 * @version 3.1
067 * @since   3.1
068 *
069 * @see Feature
070 */
071@Classifier(Stereotype.METACLASS)
072@UML(identifier="FeatureType", specification=ISO_19109)
073public interface FeatureType extends IdentifiedType {
074    /**
075     * Returns the name of this feature type.
076     * For {@code FeatureType}, the name is mandatory.
077     * The feature name is often an instance of {@link org.opengis.util.TypeName}, but this is not mandatory.
078     *
079     * @return the feature type name.
080     */
081    @Override
082    @UML(identifier="name", obligation=MANDATORY, specification=ISO_19109)
083    GenericName getName();
084
085    /**
086     * Returns {@code true} if the feature type acts as an abstract super-type.
087     * Abstract types cannot be {@linkplain #newInstance() instantiated}.
088     *
089     * @return {@code true} if the feature type acts as an abstract super-type.
090     */
091    @UML(identifier="isAbstract", obligation=MANDATORY, specification=ISO_19109)
092    boolean isAbstract();
093
094    /**
095     * Returns {@code true} if this feature type contains only attributes constrained to the [1 … 1] multiplicity,
096     * or operations (no feature association).
097     * Such feature types can be handled as a {@link org.opengis.util.RecordType} instances.
098     *
099     * @return {@code true} if this feature type contains only simple attributes or operations.
100     */
101    boolean isSimple();
102
103    /**
104     * Returns {@code true} if and only if an attribute, operation or association role of the given name exists
105     * in this feature type or in one of its super-types. If this method returns {@code true}, then calls to
106     * <code>{@linkplain #getProperty(String) getProperty}(name)</code> will not throw
107     * {@link PropertyNotFoundException}.
108     *
109     * @param  name  the name of the property to search.
110     * @return whether an attribute, operation or association role exists for the given name.
111     */
112//  boolean hasProperty(String name);
113
114    /**
115     * Returns the attribute, operation or association role for the given name.
116     *
117     * @param  name  the name of the property to search.
118     * @return the property for the given name.
119     * @throws PropertyNotFoundException if the given argument is not a property name of this feature type.
120     *
121     * @see Feature#getProperty(String)
122     */
123    PropertyType getProperty(String name) throws PropertyNotFoundException;
124
125    /**
126     * Returns any feature operation, any feature attribute type and any feature association role that
127     * carries characteristics of a feature type. The returned collection will include the properties
128     * inherited from the {@linkplain #getSuperTypes() super-types} only if {@code includeSuperTypes}
129     * is {@code true}.
130     *
131     * @param  includeSuperTypes {@code true} for including the properties inherited from the super-types,
132     *         or {@code false} for returning only the properties defined explicitly in this type.
133     * @return Feature operation, attribute type and association role that carries characteristics of this
134     *         feature type (not including parent types).
135     */
136    @UML(identifier="carrierOfCharacteristics", obligation=OPTIONAL, specification=ISO_19109)
137    Collection<? extends PropertyType> getProperties(boolean includeSuperTypes);
138
139    /**
140     * Returns the direct parents of this feature type.
141     *
142     * <div class="note"><b>Analogy with Java reflection</b>:
143     * if we compare {@code FeatureType} to {@link Class} in the Java language, then this method is equivalent
144     * to {@link Class#getSuperclass()} except that feature types allow multi-inheritance.</div>
145     *
146     * @return the parents of this feature type, or an empty set if none.
147     */
148    @UML(identifier="superType", obligation=OPTIONAL, specification=ISO_19109)
149    Set<? extends FeatureType> getSuperTypes();
150
151    /**
152     * Returns {@code true} if this type is same or a super-type of the given type.
153     * Implementations should ensure that the following constraints are met:
154     *
155     * <ul>
156     *   <li>If <var>A</var> is assignable from <var>B</var> and <var>B</var> is assignable from <var>C</var>,
157     *       then <var>A</var> is assignable from <var>C</var>.</li>
158     * </ul>
159     *
160     * <div class="note"><b>Analogy with Java reflection</b>:
161     * if we compare {@code FeatureType} to {@link Class} in the Java language, then this method is equivalent
162     * to {@link Class#isAssignableFrom(Class)}.</div>
163     *
164     * @param  type  the type to be checked.
165     * @return {@code true} if instances of the given type can be assigned to association of this type.
166     */
167    boolean isAssignableFrom(FeatureType type);
168
169    /**
170     * Creates a new feature instance of this type.
171     *
172     * <div class="note"><b>Analogy with Java reflection</b>:
173     * if we compare {@code FeatureType} to {@link Class} and {@code Feature} to {@link Object} in the Java language,
174     * then this method is equivalent to {@link Class#newInstance()}.</div>
175     *
176     * @return a new feature instance.
177     * @throws FeatureInstantiationException if this feature type {@linkplain #isAbstract() is abstract}
178     *         or cannot be instantiated for some other reason.
179     * @throws UnsupportedOperationException if this type does not support new instance creation.
180     */
181    Feature newInstance() throws FeatureInstantiationException, UnsupportedOperationException;
182}