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 * {@linkplain Object#equals equals} <var>foo</var></li>
297 *
298 * <li><code>push(</code><var>foo</var><code> : LocalName).{@linkplain ScopedName#tail() tail()}</code>
299 * {@linkplain Object#equals equals} <var>this</var></li>
300 *
301 * <li><code>push(</code><var>foo</var><code> : GenericName).{@linkplain #scope()}</code>
302 * {@linkplain Object#equals equals} <var>foo</var>.{@link #scope()}</li>
303 *
304 * <li><code>push(</code><var>foo</var><code> : GenericName).{@linkplain #getParsedNames()}</code>
305 * {@linkplain List#equals equals} <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 }