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 020 021/** 022 * An instance of a {@link FeatureType} containing values for a real-world phenomena. 023 * Each feature instance can provide values for the following properties: 024 * 025 * <ul> 026 * <li>{@linkplain Attribute Attributes}, which may be {@linkplain DynamicAttribute dynamic}</li> 027 * <li>{@linkplain FeatureAssociation Associations to other features}</li> 028 * <li>{@linkplain Operation Operations}</li> 029 * </ul> 030 * 031 * {@code Feature} can be instantiated by calls to {@link FeatureType#newInstance()}. 032 * 033 * <h2>Simple features</h2> 034 * A feature is said “simple” if it complies to all the following conditions: 035 * <ul> 036 * <li>the feature allows only attributes and operations (no associations),</li> 037 * <li>the multiplicity of all attributes is constrained to [1 … 1].</li> 038 * </ul> 039 * 040 * <h2>Moving features</h2> 041 * A feature is a moving feature if it complies to at least one of the following conditions: 042 * <ul> 043 * <li>the feature contains {@linkplain DynamicAttribute dynamic attributes},</li> 044 * <li>the geometry value of an {@linkplain Attribute attribute} is a trajectory.</li> 045 * </ul> 046 * 047 * @author Jody Garnett (Refractions Research, Inc.) 048 * @author Justin Deoliveira (The Open Planning Project) 049 * @author Martin Desruisseaux (Geomatys) 050 * @version 3.1 051 * @since 3.1 052 * 053 * @see FeatureType 054 */ 055public interface Feature { 056 /** 057 * Returns information about the feature (name, characteristics, <i>etc.</i>). 058 * 059 * @return information about the feature. 060 */ 061 FeatureType getType(); 062 063 /** 064 * Returns the property (attribute, feature association or operation result) of the given name. 065 * If the property type is a parameterless {@link Operation}, then this method may return 066 * the result of {@linkplain Operation#apply executing} the operation on this feature, 067 * at implementation choice. 068 * 069 * <h4>Performance note</h4> 070 * This method returns the property <em>instance</em>. If only the property <em>value</em> is desired, 071 * then {@link #getPropertyValue(String)} is preferred because it gives to implementations a chance to 072 * avoid the creation of {@link Attribute} or {@link FeatureAssociation} instances. 073 * 074 * @param name the property name. 075 * @return the property of the given name (never {@code null}). 076 * @throws PropertyNotFoundException if the given argument is not a property name of this feature. 077 * 078 * @see #getPropertyValue(String) 079 * @see FeatureType#getProperty(String) 080 */ 081 Property getProperty(String name) throws PropertyNotFoundException; 082 083 /** 084 * Sets the property (attribute or feature association). 085 * The given property shall comply to the following conditions: 086 * 087 * <ul> 088 * <li>It must be non-null.</li> 089 * <li>Its {@linkplain Property#getName() name} shall be the name of the property to set in this feature.</li> 090 * <li>Its type shall be the same instance as the {@linkplain FeatureType#getProperty(String) property type} 091 * defined by the feature type for the above name. In other words, the following condition shall hold:</li> 092 * </ul> 093 * 094 * {@snippet lang="java" : 095 * assert property.getType() == getType().getProperty(property.getName()); 096 * } 097 * 098 * <h4>Usage note</h4> 099 * This method is useful for storing non-default {@code Attribute} or {@code Association} implementations in 100 * this feature. When default implementations are sufficient, the {@link #setPropertyValue(String, Object)} 101 * method is preferred. 102 * 103 * @param property the property to set. 104 * @throws PropertyNotFoundException if the name of the given property is not a property name of this feature. 105 * @throws InvalidPropertyValueException if the value of the given property is not valid. 106 * @throws IllegalArgumentException if the property cannot be set for another reason 107 * (e.g. a library may accept only some specific property instances). 108 * 109 * @see #setPropertyValue(String, Object) 110 */ 111 void setProperty(Property property) throws IllegalArgumentException; 112 113 /** 114 * Returns the value for the property of the given name. 115 * This convenience method is equivalent to invoking {@link #getProperty(String)} for the given name, 116 * then to perform one of the following actions depending on the property type and the multiplicity: 117 * 118 * <table class="ogc"> 119 * <caption>Class of returned value</caption> 120 * <tr><th>Property type</th> <th>max. occurs</th> <th>Method invoked</th> <th>Return type</th></tr> 121 * <tr><td>{@link AttributeType}</td> <td>0 or 1</td> <td>{@link Attribute#getValue()}</td> <td>{@link Object}</td></tr> 122 * <tr><td>{@code AttributeType}</td> <td>2 or more</td> <td>{@link Attribute#getValues()}</td> <td>{@code Collection<?>}</td></tr> 123 * <tr><td>{@link FeatureAssociationRole}</td> <td>0 or 1</td> <td>{@link FeatureAssociation#getValue()}</td> <td>{@link Feature}</td></tr> 124 * <tr><td>{@code FeatureAssociationRole}</td> <td>2 or more</td> <td>{@link FeatureAssociation#getValues()}</td> <td>{@code Collection<Feature>}</td></tr> 125 * </table> 126 * 127 * <h4>Note on occurrences</h4> 128 * “max. occurs” is the {@linkplain AttributeType#getMaximumOccurs() maximum number of occurrences} 129 * and does not depend on the actual number of values. If an attribute allows more than one value, 130 * then this method will always return a collection for that attribute even if the collection is empty. 131 * 132 * @param name the property name. 133 * @return value of the specified property, 134 * or the {@linkplain AttributeType#getDefaultValue() default value} (which may be {@code null}} if none. 135 * @throws PropertyNotFoundException if the given argument is not an attribute or association name of this feature. 136 * 137 * @see Attribute#getValue() 138 * @see FeatureAssociation#getValue() 139 */ 140 Object getPropertyValue(String name) throws PropertyNotFoundException; 141 142 /** 143 * Sets the value for the property of the given name. 144 * 145 * <h4>Note on validation</h4> 146 * The verifications performed by this method is implementation dependent. 147 * For performance reasons, an implementation may verify only the most basic constraints 148 * and offer another method for performing more extensive validation. 149 * Implementations should document their validation process. 150 * 151 * @param name the property name. 152 * @param value the new value for the specified property (may be {@code null}). 153 * @throws PropertyNotFoundException if the given name is not an attribute or association name of this feature. 154 * @throws ClassCastException if the value is not assignable to the expected value class. 155 * @throws InvalidPropertyValueException if the given value is not valid for a reason other than its type. 156 * 157 * @see Attribute#setValue(Object) 158 * @see FeatureAssociation#setValue(Feature) 159 */ 160 void setPropertyValue(final String name, final Object value) throws IllegalArgumentException; 161 162 /** 163 * Returns the value for the property of the given name if that property exists, or a fallback value otherwise. 164 * This method is equivalent to the following code, but potentially more efficient when the property does not exist: 165 * 166 * {@snippet lang="java" : 167 * try { 168 * return getPropertyValue(name); 169 * } catch (PropertyNotFoundException ignore) { 170 * return missingPropertyFallback 171 * }} 172 * 173 * Note that if a property of the given name exists but has no value, then this method returns 174 * the {@linkplain AttributeType#getDefaultValue() default value} (which may be {@code null}). 175 * <i>Property without value</i> is not equivalent to <i>non-existent property</i>. 176 * 177 * @param name the property name. 178 * @param missingPropertyFallback the (potentially {@code null}) value to return 179 * if no attribute or association of the given name exists. 180 * @return value or default value of the specified property, or {@code missingPropertyFallback} 181 * if no attribute or association of that name exists. This value may be {@code null}. 182 */ 183 Object getValueOrFallback(String name, Object missingPropertyFallback); 184}