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