001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2006-2012 Open Geospatial Consortium, Inc.
006     *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007     *
008     *    Permission to use, copy, and modify this software and its documentation, with
009     *    or without modification, for any purpose and without fee or royalty is hereby
010     *    granted, provided that you include the following on ALL copies of the software
011     *    and documentation or portions thereof, including modifications, that you make:
012     *
013     *    1. The full text of this NOTICE in a location viewable to users of the
014     *       redistributed or derivative work.
015     *    2. Notice of any changes or modifications to the OGC files, including the
016     *       date changes were made.
017     *
018     *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019     *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020     *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021     *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022     *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023     *
024     *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025     *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026     *
027     *    The name and trademarks of copyright holders may NOT be used in advertising or
028     *    publicity pertaining to the software without specific, written prior permission.
029     *    Title to copyright in this software and any associated documentation will at all
030     *    times remain with copyright holders.
031     */
032    package org.opengis.feature.type;
033    
034    import java.util.List;
035    import java.util.Map;
036    
037    import org.opengis.feature.Property;
038    import org.opengis.filter.Filter;
039    import org.opengis.util.InternationalString;
040    
041    /**
042     * The type of a Property.
043     * <p>
044     * A property type defines information about the value of a property. This
045     * includes:
046     * <ul>
047     *   <li>java class of the value of the property ((also known as the property "binding")
048     *   <li>any restrictions on the value of the property
049     *   <li>a description of the property
050     *   <li>if the type is abstract or not
051     * </ul>
052     * </p>
053     * <br/>
054     * <p>
055     *  <h3>Binding</h3>
056     *  The {@link #getBinding()} method returns the java class of which the value
057     *  of the property is an instance of.
058     *  <pre>
059     *   Property property = ...;
060     *   property.getType().getBinding().isAssignableFrom(property.getValue().getClass());
061     *  </pre>
062     * </p>
063     * <p>
064     * <h3>Restrictions</h3>
065     * The {@link #getRestrictions()} method returns a set of {@link Filter} objects
066     * which define additional restrictions on the value of the property.
067     * <pre>
068     *   Property property = ...;
069     *   for ( Filter restriction : property.getType().getRestrictions() ) {
070     *       restriction.evaluate( property ) == true;
071     *   }
072     * </pre>
073     * </p>
074     * <p>
075     * <h3>Inheritance</h3>
076     * A property type may extend from another property type. When this occurs any
077     * restrictions defined by the parent type are inherited by the child type. The
078     * binding declared by the super type may or may not be a super class of the
079     * binding declared by the child type.
080     * </p>
081     * <p>
082     * <h3>Abstract Types</h3>
083     * A property type may be abstract similar to how a java class can be abstract.
084     * Such property types are usually not referenced directly by a descriptor, but
085     * usually are the parent type of a non-abstract property type.
086     * </p>
087     * <p>
088     *  <h3>Example</h3>
089     *  Property, PropertyDescriptor, and PropertyType are very similar to concepts
090     *  encountered in xml schema. Consider the following xml schema:
091     *  <pre>
092     *    &lt; simpleType name="number"/>
093     *
094     *    &lt; simpleType name="integer"/>
095     *
096     *    &lt; complexType name="myComplexType"/>
097     *      &lt;element name="foo" type="integer"/>
098     *    &lt;/complexType>
099     *  </pre>
100     *  <br>
101     *  In the above, "number", "integer", and "myComplexType" all map to PropertyType.
102     *  While "foo" maps to a PropertyDescriptor. Consider a complex attribute which is
103     *  of type "myComplexType:
104     *  <pre>
105     *  ComplexAttribute complexAttribute = ...;
106     *  ComplexType complexType = complexAttribute.getType();
107     *
108     *  complexType.getName().getLocalPart() == "myComplexType";
109     *
110     *  //the property descriptor
111     *  PropertyDescriptor propertyDescriptor = complexType.getProperty( "foo" );
112     *  propertyDescriptor.getName().getLocalPart() == "foo";
113     *
114     *  //the property type
115     *  PropertyType propertyType = propertyDescriptor.getType();
116     *  propertyType.getName().getLocalPart() == "integer";
117     *  propertyType.getBinding() == Integer.class;
118     *  propertyType.getSuper().getName().getLocalPart() == "number";
119     *  propertyType.getSuper().getBinding() == Number.class;
120     *
121     *  //the property
122     *  Property property = complexAttribute.getProperty( "foo" );
123     *  property.getDescriptor() == propertyDescriptor;
124     *  property.getType() == propertyType;
125     *  property.getName().getLocalPart() == "foo";
126     *  property.getValue() instanceof Integer;
127     *  </pre>
128     * </p>
129    
130     * @author Jody Garnett, Refractions Research, Inc.
131     * @author Justin Deoliveira, The Open Planning Project
132     */
133    public interface PropertyType {
134        /**
135         * The name of the property type.
136         * <p>
137         * Note that this is not the same name as {@link Property#getName()}, which
138         * is the name of the instance of the type, not the type itself.
139         * </p>
140         * <p>
141         * The returned name is a qualified name made up of two parts. The first
142         * a namespace uri ({@link Name#getNamespaceURI()}, and the second a local
143         * part ({@link Name#getLocalPart()}.
144         * </p>
145         * <p>
146         * This value is never <code>null</code>.
147         * </p>
148         * @return The name of the property type.
149         */
150        Name getName();
151    
152        /**
153         * The java class that values of properties of the property type are bound
154         * to.
155         * <p>
156         * This value is never <code>null</code>.
157         * </p>
158         * @return The binding of the property type.
159         */
160        Class<?> getBinding();
161    
162        /**
163         * The parent type of the property type.
164         * <p>
165         * This method returns <code>null</code> if no super type is defined.
166         * </p>
167         * <p>
168         * The super type may contain additional restrictions to be considered against
169         * properties of the the property type.
170         * </p>
171         *
172         * @return The parent or super type, or <code>null</code>.
173         */
174        PropertyType getSuper();
175    
176        /**
177         * Flag indicating if the type is abstract or not.
178         *
179         * @return <code>true</code> if the type is abstract, otherwise <code>false</code>.
180         */
181        boolean isAbstract();
182    
183        /**
184         * List of restrictions used define valid values for properties of this
185         * property type.
186         * <p>
187         * Each restriction is a {@link Filter} object in which the property is
188         * passed through. If {@link Filter#evaluate(Object)} returns <code>true</code>
189         * the restriction is met. If <code>false</code> is returned then the
190         * restriction has not been met and the property should be considered invalid.
191         * Remember to check getSuper().getRestrictions() as well.
192         * <p>
193         * This method returns an empty set in the case of no restrictions and should
194         * not return <code>null</code>.
195         * </p>
196         * @return List<Restriction> used to validate allowable values.
197         */
198        List<Filter> getRestrictions();
199    
200        /**
201         * Human readable description of this property type.
202         *
203         * @return Human readable description of this property type.
204         */
205        InternationalString getDescription();
206    
207        /**
208         * A map of "user data" which enables applications to store "application-specific"
209         * information against a property type.
210         * <p>
211         * As an example, consider an application that builds a PropertyType from an
212         * xml schema. A useful bit of information to attach to the PropertyType is
213         * the original schema itself, in whatever construct it might be stored in:
214         * <pre>
215         * <code>
216         * XSDComplexTypeDefinition complexTypeDef = ...;
217         * PropertyType type = buildPropertyType( complexTypeDef );
218         *
219         * type.getUserData().put( XSDComplexTypeDefintion.class, complexTypeDef );
220         * </code>
221         * </pre>
222         * </p>
223         *
224         * @return A map of user data.
225         */
226        Map<Object,Object> getUserData();
227    
228        /**
229         * Equality based on property {@link #getName()}.
230         * </p>
231         *
232         * @return <code>true</code> if other is a PropertyType with the same name
233         */
234        @Override    
235        boolean equals(Object other);
236    
237        /**
238         * Hash code override based on {@link #getName()}.
239         *
240         * @return getName().hashCode()
241         */
242        @Override
243        int hashCode();
244    }