001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2004-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.util;
033    
034    import java.util.List;
035    import org.opengis.annotation.UML;
036    
037    import static org.opengis.annotation.Obligation.*;
038    import static org.opengis.annotation.Specification.*;
039    
040    
041    /**
042     * A sequence of identifiers rooted within the context of a {@linkplain NameSpace namespace}.
043     * This interface is similar in purpose to {@link javax.naming.Name} from the <cite>Java Naming
044     * and Directory Interface</cite>. All generic names:
045     * <p>
046     * <ul>
047     *   <li>carry an association with their {@linkplain #scope scope} in which they are
048     *       considered local;</li>
049     *   <li>have the ability to provide a {@linkplain #getParsedNames parsed} version of
050     *       themselves.</li>
051     * </ul>
052     * <p>
053     * Names are <em>immutables</em>. They may be {@linkplain #toFullyQualifiedName() fully qualified}
054     * like {@code "org.opengis.util.Record"}, or they may be relative to a {@linkplain #scope scope}
055     * like {@code "util.Record"} in the {@code "org.opengis"} scope. The illustration below shows all
056     * possible constructions for {@code "org.opengis.util.Record"}. They are all instances of
057     * {@link ScopedName} except the last one which is a {@link LocalName}.
058     *
059     * <blockquote><table border="1" cellpadding="15"><tr><td><table border="0" cellspacing="0">
060     *   <tr>
061     *     <td align="right"><b>org</b></td>
062     *     <td><b>.</b></td><td><b>opengis</b></td>
063     *     <td><b>.</b></td><td><b>util</b></td>
064     *     <td><b>.</b></td><td><b>Record</b></td>
065     *     <td width="50"></td>
066     *     <td><b>{@link #scope()}</b></td>
067     *     <td align="right"><b>{@link #getParsedNames()}</b></td>
068     *   </tr>
069     *   <tr align="center">
070     *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">{@linkplain #head() head}</font></td><td></td>
071     *     <td bgcolor="palegoldenrod" colspan="5"><font size="-1">{@linkplain ScopedName#tail() tail}</font></td>
072     *     <td rowspan="2"></td>
073     *     <td rowspan="2" bgcolor="beige" align="left">{@linkplain NameSpace#isGlobal() global}</td>
074     *     <td rowspan="2" bgcolor="beige" align="right">{{@code "org"}, {@code "opengis"}, {@code "util"}, {@code "Record"}}</td>
075     *   </tr>
076     *   <tr align="center">
077     *     <td bgcolor="wheat" colspan="5"><font size="-1">{@linkplain ScopedName#path() path}</font></td><td></td>
078     *     <td bgcolor="wheat" colspan="1"><font size="-1">{@linkplain #tip() tip}</font></td>
079     *   </tr>
080     *
081     *   <tr><td colspan="7" height="15"></td></tr>
082     *   <tr>
083     *     <td align="right">org</td>
084     *     <td>.</td><td><b>opengis</b></td>
085     *     <td><b>.</b></td><td><b>util</b></td>
086     *     <td><b>.</b></td><td><b>Record</b></td>
087     *     <td colspan="3"></td>
088     *   </tr>
089     *   <tr align="center">
090     *     <td bgcolor="palegoldenrod" colspan="1" rowspan="2"><font size="-1">{@linkplain #scope() scope}</font></td><td rowspan="3"></td>
091     *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td><td></td>
092     *     <td bgcolor="palegoldenrod" colspan="3"><font size="-1">tail</font></td>
093     *     <td rowspan="2"></td>
094     *     <td rowspan="2" bgcolor="beige" align="left">{@code "org"}</td>
095     *     <td rowspan="2" bgcolor="beige" align="right">{{@code "opengis"}, {@code "util"}, {@code "Record"}}</td>
096     *   </tr>
097     *   <tr align="center">
098     *     <td bgcolor="wheat" colspan="3"><font size="-1">path</font></td><td></td>
099     *     <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td>
100     *   </tr>
101     *
102     *   <tr><td colspan="7" height="15"></td></tr>
103     *   <tr>
104     *     <td align="right">org</td>
105     *     <td>.</td><td>opengis</td>
106     *     <td>.</td><td><b>util</b></td>
107     *     <td><b>.</b></td><td><b>Record</b></td>
108     *     <td colspan="3"></td>
109     *   </tr>
110     *   <tr align="center">
111     *     <td bgcolor="palegoldenrod" colspan="3" rowspan="2"><font size="-1">scope</font></td><td rowspan="3"></td>
112     *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td><td></td>
113     *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">tail</font></td>
114     *     <td rowspan="2"></td>
115     *     <td rowspan="2" bgcolor="beige" align="left">{@code "org.opengis"}</td>
116     *     <td rowspan="2" bgcolor="beige" align="right">{{@code "util"}, {@code "Record"}}</td>
117     *   </tr>
118     *   <tr align="center">
119     *     <td bgcolor="wheat" colspan="1"><font size="-1">path</font></td><td></td>
120     *     <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td>
121     *   </tr>
122     *
123     *   <tr><td colspan="7" height="15"></td></tr>
124     *   <tr>
125     *     <td align="right">org</td>
126     *     <td>.</td><td>opengis</td>
127     *     <td>.</td><td>util</td>
128     *     <td>.</td><td><b>Record</b></td>
129     *     <td colspan="3"></td>
130     *   </tr>
131     *   <tr align="center">
132     *     <td bgcolor="palegoldenrod" colspan="5" rowspan="2"><font size="-1">scope</font></td><td rowspan="3"></td>
133     *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td>
134     *     <td rowspan="2"></td>
135     *     <td rowspan="2" bgcolor="beige" align="left">{@code "org.opengis.util"}</td>
136     *     <td rowspan="2" bgcolor="beige" align="right">{{@code "Record"}}</td>
137     *   </tr>
138     *   <tr align="center">
139     *     <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td>
140     *   </tr>
141     * </table></td></tr></table></blockquote>
142     * <p>
143     * The {@linkplain Comparable natural ordering} for generic names is implementation dependent.
144     * A recommended practice is to {@linkplain String#compareTo compare lexicographically} each
145     * element in the {@linkplain #getParsedNames() list of parsed names}. Specific attributes of
146     * the name, such as how it treats case, may affect the ordering. In general, two names of
147     * different classes may not be compared.
148     *
149     * @author  Martin Desruisseaux (IRD)
150     * @author  Bryce Nordgren (USDA)
151     * @version 3.0
152     * @since   1.0
153     *
154     * @see javax.naming.Name
155     * @see NameFactory#createGenericName(NameSpace, CharSequence[])
156     * @see NameFactory#parseGenericName(NameSpace, CharSequence)
157     *
158     * @navassoc 1 - - NameSpace
159     */
160    @UML(identifier="GenericName", specification=ISO_19103)
161    public interface GenericName extends Comparable<GenericName> {
162        /**
163         * Returns the scope (name space) in which this name is local. The scope of a name
164         * determines where a name starts. The scope is set on creation and is not modifiable.
165         * <p>
166         * <b>Example</b>:
167         * For a {@linkplain #toFullyQualifiedName() fully qualified name} (a name having a
168         * {@linkplain NameSpace#isGlobal() global namespace}) {@code "org.opengis.util.Record"},
169         * if this instance is the {@code "util.Record"} name, then the scope of this instance
170         * has the {@code "org.opengis"} {@linkplain NameSpace#name() name}.
171         *
172         * @return The scope of this name.
173         *
174         * @since 2.1
175         */
176        @UML(identifier="scope", obligation=MANDATORY, specification=ISO_19103)
177        NameSpace scope();
178    
179        /**
180         * Indicates the number of levels specified by this name. The depth is the {@linkplain List#size() size}
181         * of the list returned by the {@link #getParsedNames()} method. As such it is a derived parameter. For
182         * any {@link LocalName}, it is always one. For a {@link ScopedName} it is some number greater than or
183         * equal to 2.
184         * <p>
185         * This method is similar in purpose to the {@link javax.naming.Name#size() Name.size()}
186         * method from the <cite>Java Naming and Directory Interface</cite>.
187         * <p>
188         * <b>Example</b>:
189         * If {@code this} name is {@code "org.opengis.util.Record"}, then this method shall return
190         * {@code 4}. If this name is {@code "util.Record"} in the {@code "org.opengis"} scope, then
191         * this method shall return {@code 2}.
192         *
193         * @return The depth of this name.
194         *
195         * @since 2.1
196         */
197        @UML(identifier="depth", obligation=MANDATORY, specification=ISO_19103)
198        int depth();
199    
200        /**
201         * Returns the sequence of {@linkplain LocalName local names} making this generic name.
202         * The length of this sequence is the {@linkplain #depth() depth}. It does not include
203         * the {@linkplain #scope() scope}.
204         * <p>
205         * This method is similar in purpose to the {@link javax.naming.Name#getAll() Name.getAll()}
206         * method from the <cite>Java Naming and Directory Interface</cite>.
207         * <p>
208         * <b>Example</b>:
209         * If {@code this} name is {@code "org.opengis.util.Record"}, then this method shall returns a
210         * list containing {@code {"org", "opengis", "util", "Record"}} elements in that iteration order.
211         * If this name is {@code "util.Record"} in scope {@code "org.opengis"}, then this method shall
212         * returns a list containing only {@code {"util", "Record"}} elements.
213         *
214         * @return The local names making this generic name, without the {@linkplain #scope() scope}.
215         *         Shall never be {@code null} neither {@linkplain List#isEmpty empty}.
216         */
217        @UML(identifier="parsedName", obligation=MANDATORY, specification=ISO_19103)
218        List<? extends LocalName> getParsedNames();
219    
220        /**
221         * Returns the first element in the sequence of {@linkplain #getParsedNames() parsed names}.
222         * For any {@link LocalName}, this is always {@code this}.
223         * <p>
224         * This method is similar in purpose to <code>{@linkplain javax.naming.Name#get(int)
225         * Name.get}(0)</code> from the <cite>Java Naming and Directory Interface</cite>.
226         * <p>
227         * <b>Example</b>:
228         * If {@code this} name is {@code "org.opengis.util.Record"} (no matter its
229         * {@linkplain #scope() scope}), then this method shall returns {@code "org"}.
230         *
231         * @return The first element in the list of {@linkplain #getParsedNames() parsed names}.
232         *
233         * @departure generalization
234         *   ISO defines this method in <code>ScopedName</code> only. GeoAPI defines it in the base
235         *   class since <code>LocalName</code> can return a sensible value for it. This reduces the
236         *   need for casts.
237         *
238         * @since 2.2
239         */
240        @UML(identifier="ScopedName.head", obligation=MANDATORY, specification=ISO_19103)
241        LocalName head();
242    
243        /**
244         * Returns the last element in the sequence of {@linkplain #getParsedNames() parsed names}.
245         * For any {@link LocalName}, this is always {@code this}.
246         * <p>
247         * This method is similar in purpose to <code>{@linkplain javax.naming.Name#get(int)
248         * Name.get}(size-1)</code> from the <cite>Java Naming and Directory Interface</cite>.
249         * <p>
250         * <b>Example</b>:
251         * If {@code this} name is {@code "org.opengis.util.Record"} (no matter its
252         * {@linkplain #scope scope}), then this method shall returns {@code "Record"}.
253         *
254         * @return The last element in the list of {@linkplain #getParsedNames() parsed names}.
255         *
256         * @departure easeOfUse
257         *   This method is not part of ISO specification. It does not provide any additional
258         *   information compared to that accessible though the standard methods defined by
259         *   ISO, but provides easier to access frequently requested information.
260         *
261         * @since 2.1
262         */
263        LocalName tip();
264    
265        /**
266         * Returns a view of this name as a fully-qualified name. The {@linkplain #scope() scope}
267         * of a fully qualified name must be {@linkplain NameSpace#isGlobal() global}. If the scope
268         * of this name is already global, then this method shall returns {@code this}.
269         * <p>
270         * <b>Example</b>:
271         * If {@code this} name is {@code "util.Record"} ({@linkplain #depth() depth} of two) and its
272         * {@linkplain #scope() scope} has the {@code "org.opengis"} {@linkplain NameSpace#name() name},
273         * then the fully qualified name shall be {@code "org.opengis.util.Record"}.
274         *
275         * @return The fully-qualified name (never {@code null}).
276         *
277         * @departure easeOfUse
278         *   This method is not part of ISO specification. It does not provide any additional
279         *   information compared to that accessible though the standard methods defined by
280         *   ISO, but provides easier to access frequently requested information.
281         *
282         * @since 2.1
283         */
284        GenericName toFullyQualifiedName();
285    
286        /**
287         * Returns this name expanded with the specified scope. One may represent this operation
288         * as a concatenation of the specified {@code scope} with {@code this}. In pseudo-code,
289         * the following relationships must hold (the last one is specific to {@link ScopedName}):
290         * <p>
291         * <ul>
292         *   <li><code>push(</code><var>foo</var><code> : LocalName).{@linkplain #head()}</code>
293         *       &nbsp;&nbsp; {@linkplain Object#equals equals} &nbsp;&nbsp; <var>foo</var></li>
294         *
295         *   <li><code>push(</code><var>foo</var><code> : LocalName).{@linkplain ScopedName#tail() tail()}</code>
296         *       &nbsp;&nbsp; {@linkplain Object#equals equals} &nbsp;&nbsp; <var>this</var></li>
297         *
298         *   <li><code>push(</code><var>foo</var><code> : GenericName).{@linkplain #scope()}</code>
299         *       &nbsp;&nbsp; {@linkplain Object#equals equals} &nbsp;&nbsp; <var>foo</var>.{@link #scope()}</li>
300         *
301         *   <li><code>push(</code><var>foo</var><code> : GenericName).{@linkplain #getParsedNames()}</code>
302         *       &nbsp;&nbsp; {@linkplain List#equals equals} &nbsp;&nbsp; <var>foo</var>.<code>getParsedNames().{@linkplain
303         *       List#addAll addAll}(</code><var>this</var>.<code>getParsedNames())</code></li>
304         * </ul>
305         * <p>
306         * This method is similar in purpose to <code>{@linkplain javax.naming.Name#addAll(int,javax.naming.Name)
307         * Name.addAll}(0,name)</code> from the <cite>Java Naming and Directory Interface</cite>.
308         * <p>
309         * <b>Example</b>:
310         * If {@code this} name is {@code "util.Record"} and the given {@code scope} argument is
311         * {@code "org.opengis"}, then {@code this.push(scope)} shall returns
312         * {@code "org.opengis.util.Record"}.
313         *
314         * @param scope The name to use as prefix.
315         * @return A concatenation of the given scope with this name.
316         *
317         * @since 2.1
318         */
319        @UML(identifier="push", obligation=MANDATORY, specification=ISO_19103)
320        ScopedName push(GenericName scope);
321    
322        /**
323         * Returns a string representation of this generic name. This string representation is
324         * local-independent. It contains all elements listed by {@link #getParsedNames()} separated
325         * by a namespace-dependent character (usually {@code :} or {@code /}). This rule implies
326         * that the result may or may not be fully qualified. Special cases:
327         * <p>
328         * <ul>
329         *   <li><code>{@linkplain #toFullyQualifiedName()}.toString()</code> is guaranteed to
330         *       contains the {@linkplain #scope() scope} (if any).</li>
331         *   <li><code>{@linkplain #tip()}.toString()</code> is guaranteed to <strong>not</strong>
332         *       contains any scope.</li>
333         * </ul>
334         *
335         * @return A local-independent string representation of this name.
336         *
337         * @departure easeOfUse
338         *   This method is not part of ISO specification. It does not provide any additional
339         *   information compared to that accessible though the standard methods defined by
340         *   ISO, but provides easier to access frequently requested information.
341         */
342        @Override
343        String toString();
344    
345        /**
346         * Returns a local-dependent string representation of this generic name. This string
347         * is similar to the one returned by {@link #toString()} except that each element has
348         * been localized in the {@linkplain InternationalString#toString(java.util.Locale)
349         * specified locale}. If no international string is available, then this method shall
350         * returns an implementation mapping to {@link #toString()} for all locales.
351         * <p>
352         * <b>Example</b>:
353         * An implementation may want to localize the {@code "My Documents"} directory name
354         * into {@code "Mes Documents"} on French installation of Windows operating system.
355         *
356         * @return A localizable string representation of this name.
357         *
358         * @departure extension
359         *   This method is not part of the ISO specification. It has been added to provide
360         *   a way to localize the name.
361         */
362        InternationalString toInternationalString();
363    }