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