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;
033    
034    import java.util.Collection;
035    
036    import org.opengis.feature.type.ComplexType;
037    import org.opengis.feature.type.Name;
038    import org.opengis.filter.expression.Expression;
039    
040    /**
041     * An instance of {@link ComplexType} which is composed of other properties.
042     * <p>
043     * A complex attribute is a container for other properties (attributes +
044     * associations). The value of a complex attribute is a collection of those
045     * contained properties.
046     * </p>
047     * <br/>
048     * <p>
049     * <h3>Property Access</h3>
050     * The {@link #getValue()} method returns a collection of the properties
051     * contained by the complex attribute.
052     *
053     * <pre>
054     *    ComplexAttribute attribute = ...;
055     *
056     *    //loop through all the properties
057     *    for (Property p : attribute.getValue(); ) {
058     *        // do something with the property
059     *    }
060     * </pre>
061     *
062     * <br>
063     * Contained properties can also be fetched by name by {@link Name} with the
064     * {@link #getProperties(Name)} and {@link #getProperties(String)} methods.
065     *
066     * <pre>
067     *    ComplexAttribute attribute = ...;
068     *
069     *    //loop through all the &quot;foo&quot; attributes
070     *    for ( Property p : attribute.getProperties( &quot;foo&quot; ) ) {
071     *        p.getName().getLocalPart() == &quot;foo&quot;;
072     *    }
073     * </pre>
074     *
075     * <br>
076     * Often it is known in advance that a single instance of a particular property
077     * exists. When this is the case the {@link #getProperty(Name)} and
078     * {@link #getProperty(String)} methods can be used to get direct access to the
079     * property.
080     *
081     * <pre>
082     *    ComplexAttribute attribute = ...;
083     *
084     *    //get the single foo attribute
085     *    Property foo = attribute.getProperty( &quot;foo&quot; );
086     * </pre>
087     *
088     * </p>
089     * <br>
090     * <p>
091     * <h3>Xpath and Query Language Access</h3>
092     * The above property access methods perform an exact match on property name
093     * against the name passed in. However, often it is necesary to access
094     * properties via a query language such as xpath.
095     * </p>
096     * <br>
097     * <p>
098     * For instance.the expression <code>"//foo"</code> should return all the
099     * properties named "foo". Or the expression <code>"foo/bar"</code> should
100     * return the "bar" property nested inside of the "foo" property. In these
101     * cases, an {@link Expression} must be used:
102     *
103     * <pre>
104     *   ComplexAttribute attribute = ...;
105     *
106     *   //get the 'foo/bar' property
107     *   FilterFactory factory = ...;
108     *   PropertyName xpath = factory.property( &quot;foo/bar&quot; );
109     *   Property bar = xpath.evaluate( attribute );
110     * </pre>
111     *
112     * </p>
113     *
114     * @author Jody Garnett, Refractions Research
115     * @author Gabriel Roldan, Axios Engineering
116     * @author Justin Deoliveira, The Open Planning Project
117     */
118    public interface ComplexAttribute extends Attribute {
119    
120        /**
121         * Override of {@link Attribute#getType()} which type narrows to
122         * {@link ComplexType}.
123         *
124         * @see Attribute#getType()
125         */
126        ComplexType getType();
127    
128        /**
129         * Sets the contained properties of the complex attribute.
130         * <p>
131         * The <tt>values</tt> should match the structure defined by
132         * <code>getDescriptor()</code>.
133         * </p>
134         */
135        void setValue(Collection<Property> values);
136    
137        /**
138         * Override of {@link Property#getValue()} which returns the collection of
139         * {@link Property} which make up the value of the complex attribute.
140         */
141        Collection<? extends Property> getValue();
142    
143        /**
144         * Returns a subset of the properties of the complex attribute which match
145         * the specified name.
146         * <p>
147         * The <tt>name</tt> parameter is matched against each contained
148         * {@link Property#getName()}, those that are equal are returned.
149         * </p>
150         *
151         * @param name
152         *            The name of the properties to return.
153         *
154         * @return The collection of properties which match the specified name, or
155         *         an empty collection if no such properties match.
156         */
157        Collection<Property> getProperties(Name name);
158    
159        /**
160         * Returns single property of the complex attribute which matches the
161         * specified name.
162         * <p>
163         * Note: This method is a convenience and care should be taken when calling
164         * it if more then a single property matches <tt>name</tt>. In such a
165         * case the first encountered property in which {@link Property#getName()}
166         * is equal to <tt>name</tt> is returned, and no order is guaranteed.
167         * </p>
168         * <p>
169         * This method is a safe convenience for:
170         *
171         * <code>getProperties(name).iterator().next()</code>.
172         *
173         * In the event that no property matches the specified name
174         * <code>null</code> is returned.
175         * </p>
176         *
177         * @param name
178         *            The name of the property to return.
179         *
180         * @return The property matching the specified name, or <code>null</code>.
181         */
182        Property getProperty(Name name);
183    
184        /**
185         * Returns a subset of the properties of the complex attribute which match
186         * the specified name.
187         * <p>
188         * This method is a convenience for {@link #getProperties(Name)} in which
189         * {@link Name#getNamespaceURI()} is <code>null</code>.
190         * </p>
191         * <p>
192         * Note: Special care should be taken when using this method in the case
193         * that two properties with the same local name but different namespace uri
194         * exist. For this reason using {@link #getProperties(Name)} is safer.
195         * </p>
196         *
197         * @param name
198         *            The local name of the properties to return.
199         *
200         * @return The collection of properties which match the specified name, or
201         *         an empty collection if no such properties match.
202         *
203         * @see #getProperties(Name)
204         */
205        Collection<Property> getProperties(String name);
206    
207        /**
208         * Complete collection of properties.
209         * <p>
210         * This method is a convenience method for calling (Collection<Property>) getValue().
211         * </p>
212         * @return The complete collection of properties.
213         */
214        Collection<Property> getProperties();
215    
216        /**
217         * Returns single property of the complex attribute which matches the
218         * specified name.
219         * <p>
220         * This method is a convenience for {@link #getProperty(Name)} in which
221         * {@link Name#getNamespaceURI()} is <code>null</code>.
222         * </p>
223         * <p>
224         * Note: This method is a convenience and care should be taken when calling
225         * it if more then a single property matches <tt>name</tt>. In such a
226         * case the first encountered property in which {@link Property#getName()}
227         * is matches <tt>name</tt> is returned, and no order is guaranteed.
228         * </p>
229         * <p>
230         * Note: Special care should be taken when using this method in the case
231         * that two properties with the same local name but different namespace uri
232         * exist. For this reason using {@link #getProperties(Name)} is safer.
233         * </p>
234         *
235         * @param name
236         *            The local name of the property to return.
237         *
238         * @return The property matching the specified name, or <code>null</code>.
239         */
240        Property getProperty(String name);
241        
242        /**
243         * Check the properties against the constraints provided by their AttributeDescriptors.
244         * <p>
245         * Please note this method checks minOccurs and maxOccurs information; and calls each Attribute.validate
246         * on each entry in turn (in order to check isNillable, binding and restrictions).
247         * @throws IllegalAttributeException If any attribute fails validation
248         */
249        void validate() throws IllegalAttributeException;
250    }