/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2011, Open Source Geospatial Foundation (OSGeo) * (C) 2003-2005, Open Geospatial Consortium Inc. * * All Rights Reserved. http://www.opengis.org/legal/ */ package org.opengis.util; import java.util.List; import org.opengis.annotation.UML; import org.opengis.annotation.Extension; import static org.opengis.annotation.Obligation.*; import static org.opengis.annotation.Specification.*; /** * A sequence of identifiers rooted within the context of a {@linkplain NameSpace namespace}. * This interface is similar in purpose to {@link javax.naming.Name} from the <cite>Java Naming * and Directory Interface</cite>. All generic names: * <p> * <ul> * <li>carry an association with their {@linkplain #scope scope} in which they are * considered local;</li> * <li>have the ability to provide a {@linkplain #getParsedNames parsed} version of * themselves.</li> * </ul> * <p> * Names are <em>immutables</em>. They may be {@linkplain #toFullyQualifiedName fully qualified} * like {@code "org.opengis.util.Record"}, or they may be relative to a {@linkplain #scope scope} * like {@code "util.Record"} in the {@code "org.opengis"} scope. The illustration below shows all * possible constructions for {@code "org.opengis.util.Record"}. * * <blockquote><table border="1" cellpadding="15"><tr><td><table border="0" cellspacing="0"> * <tr> * <th align="right">org</th> * <th>.</th><th>opengis</th> * <th>.</th><th>util</th> * <th>.</th><th>Record</th> * <th width="50"></th> * <th>{@link #scope}</th> * <th>{@link #getParsedNames}</th> * </tr> * * <tr align="center"> * <td bgcolor="palegoldenrod" colspan="1"><font size="-1">{@linkplain #head head}</font></td><td></td> * <td bgcolor="palegoldenrod" colspan="5"><font size="-1">{@linkplain ScopedName#tail tail}</font></td> * <td rowspan="3"></td> * <td rowspan="3" bgcolor="beige" align="left">{@linkplain NameSpace#isGlobal global}</td> * <td rowspan="3" bgcolor="beige" align="right">{@literal {"org", "opengis", "util", "Record"}}</td> * </tr> * <tr align="center"> * <td bgcolor="wheat" colspan="5"><font size="-1">{@linkplain ScopedName#path path}</font></td><td></td> * <td bgcolor="wheat" colspan="1"><font size="-1">{@linkplain #tip tip}</font></td> * </tr> * <tr align="center"> * <td bgcolor="burlywood" colspan="7">{@linkplain ScopedName}</td> * </tr> * * <tr><td colspan="7" height="3"></td></tr> * <tr align="center"> * <td bgcolor="palegoldenrod" colspan="1" rowspan="3"><font size="-1">{@linkplain #scope scope}</font></td><td rowspan="3"></td> * <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td><td></td> * <td bgcolor="palegoldenrod" colspan="3"><font size="-1">tail</font></td> * <td rowspan="3"></td> * <td rowspan="3" bgcolor="beige" align="left">{@literal "org"}</td> * <td rowspan="3" bgcolor="beige" align="right">{@literal {"opengis", "util", "Record"}}</td> * </tr> * <tr align="center"> * <td bgcolor="wheat" colspan="3"><font size="-1">path</font></td><td></td> * <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td> * </tr> * <tr align="center"> * <td bgcolor="burlywood" colspan="5">ScopedName</td> * </tr> * * <tr><td colspan="7" height="3"></td></tr> * <tr align="center"> * <td bgcolor="palegoldenrod" colspan="3" rowspan="3"><font size="-1">scope</font></td><td rowspan="3"></td> * <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td><td></td> * <td bgcolor="palegoldenrod" colspan="1"><font size="-1">tail</font></td> * <td rowspan="3"></td> * <td rowspan="3" bgcolor="beige" align="left">{@literal "org.opengis"}</td> * <td rowspan="3" bgcolor="beige" align="right">{@literal {"util", "Record"}}</td> * </tr> * <tr align="center"> * <td bgcolor="wheat" colspan="1"><font size="-1">path</font></td><td></td> * <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td> * </tr> * <tr align="center"> * <td bgcolor="burlywood" colspan="3">ScopedName</td> * </tr> * * <tr><td colspan="7" height="3"></td></tr> * <tr align="center"> * <td bgcolor="palegoldenrod" colspan="5" rowspan="3"><font size="-1">scope</font></td><td rowspan="3"></td> * <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td> * <td rowspan="3"></td> * <td rowspan="3" bgcolor="beige" align="left">{@literal "org.opengis.util"}</td> * <td rowspan="3" bgcolor="beige" align="right">{@literal {"Record"}}</td> * </tr> * <tr align="center"> * <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td> * </tr> * <tr align="center"> * <td bgcolor="burlywood" colspan="1">{@linkplain LocalName}</td> * </tr> * </table></td></tr></table></blockquote> * <p> * The {@linkplain Comparable natural ordering} for generic names is implementation dependent. * A recommended practice is to {@linkplain String#compareTo compare lexicographically} each * element in the {@linkplain #getParsedNames list of parsed names}. Specific attributes of * the name, such as how it treats case, may affect the ordering. In general, two names of * different classes may not be compared. * * @author Martin Desruisseaux (IRD) * @author Bryce Nordgren (USDA) * @since GeoAPI 1.0 * * @see javax.naming.Name * * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/modules/library/opengis/src/main/java/org/opengis/util/GenericName.java $ */ @UML(identifier="GenericName", specification=ISO_19103) public interface GenericName extends Comparable<GenericName> { /** * Returns the scope (name space) in which this name is local. The scope is set on creation * and is not modifiable. The scope of a name determines where a name starts. * <p> * <b>Example</b>: * For a {@linkplain #toFullyQualifiedName fully qualified name} (a name having a * {@linkplain NameSpace#isGlobal global namespace}) {@code "org.opengis.util.Record"}, * if this instance is the name {@code "util.Record"}, then the scope of this instance * has the {@linkplain NameSpace#name name} {@code "org.opengis"}. * * @return The scope of this name. * * @since GeoAPI 2.1 */ @UML(identifier="scope", obligation=MANDATORY, specification=ISO_19103) NameSpace scope(); /** * Indicates the number of levels specified by this name. The depth is the {@linkplain List#size size} * of the list returned by the {@link #getParsedNames} method. As such it is a derived parameter. For * any {@link LocalName}, it is always one. For a {@link ScopedName} it is some number greater than or * equal to 2. * <p> * This method is similar in purpose to {@link javax.naming.Name#size()} * from the <cite>Java Naming and Directory Interface</cite>. * <p> * <b>Example</b>: * If {@code this} name is {@code "org.opengis.util.Record"}, then this method shall returns * {@code 4}. If this name is {@code "util.Record"} in scope {@code "org.opengis"}, then this * method shall returns {@code 2}. * * @return The depth of this name. * * @since GeoAPI 2.1 */ @UML(identifier="depth", obligation=MANDATORY, specification=ISO_19103) int depth(); /** * Returns the sequence of {@linkplain LocalName local names} making this generic name. * The length of this sequence is the {@linkplain #depth depth}. It does not include the * {@linkplain #scope scope}. * <p> * This method is similar in purpose to {@link javax.naming.Name#getAll()} * from the <cite>Java Naming and Directory Interface</cite>. * <p> * <b>Example</b>: * If {@code this} name is {@code "org.opengis.util.Record"}, then this method shall returns a * list containing {@code {"org", "opengis", "util", "Record"}} elements in that iteration order. * If this name is {@code "util.Record"} in scope {@code "org.opengis"}, then this method shall * returns a list containing only {@code {"util", "Record"}} elements. * * @return The local names making this generic name, without the {@linkplain #scope scope}. * Shall never be {@code null} neither {@linkplain List#isEmpty empty}. */ @UML(identifier="parsedName", obligation=MANDATORY, specification=ISO_19103) List<? extends LocalName> getParsedNames(); /** * Returns the first element in the sequence of {@linkplain #getParsedNames parsed names}. * For any {@link LocalName}, this is always {@code this}. * <p> * This method is similar in purpose to <code>{@linkplain javax.naming.Name#get(int) * Name.get}(0)</code> from the <cite>Java Naming and Directory Interface</cite>. * <p> * <b>Example</b>: * If {@code this} name is {@code "org.opengis.util.Record"} (no matter its * {@linkplain #scope scope}), then this method shall returns {@code "org"}. * * @return The first element in the list of {@linkplain #getParsedNames parsed names}. * * @since GeoAPI 2.2 */ @UML(identifier="ScopedName.head", obligation=MANDATORY, specification=ISO_19103) LocalName head(); /** * Returns the last element in the sequence of {@linkplain #getParsedNames parsed names}. * For any {@link LocalName}, this is always {@code this}. * <p> * This method is similar in purpose to <code>{@linkplain javax.naming.Name#get(int) * Name.get}(size-1)</code> from the <cite>Java Naming and Directory Interface</cite>. * <p> * <b>Example</b>: * If {@code this} name is {@code "org.opengis.util.Record"} (no matter its * {@linkplain #scope scope}), then this method shall returns {@code "Record"}. * * @return The last element in the list of {@linkplain #getParsedNames parsed names}. * * @since GeoAPI 2.1 */ @Extension LocalName tip(); /** * @deprecated Renamed as {@link #tip}. * * @return The last element in the list of {@linkplain #getParsedNames parsed names}. */ @Extension @Deprecated LocalName name(); /** * Returns a view of this name as a fully-qualified name. The {@linkplain #scope scope} * of a fully qualified name must be {@linkplain NameSpace#isGlobal global}. If the scope * of this name is already global, then this method shall returns {@code this}. * <p> * <b>Example</b>: * If {@code this} name is {@code "util.Record"} ({@linkplain #depth depth} of two) and its * {@linkplain #scope scope} has the {@linkplain NameSpace#name name} {@code "org.opengis"}, * then the fully qualified name shall be {@code "org.opengis.util.Record"}. * * @return The fully-qualified name (never {@code null}). * * @since GeoAPI 2.1 */ @Extension GenericName toFullyQualifiedName(); /** * Returns this name expanded with the specified scope. One may represent this operation * as a concatenation of the specified {@code scope} with {@code this}. In pseudo-code, * the following relationships must hold (the last one is specific to {@link ScopedName}): * <p> * <ul> * <li><code>push(</code><var>foo</var><code> : LocalName).{@linkplain #head}</code> * {@linkplain #equals equals} <var>foo</var></li> * * <li><code>push(</code><var>foo</var><code> : LocalName).{@linkplain ScopedName#tail tail()}</code> * {@linkplain #equals equals} <var>this</var></li> * * <li><code>push(</code><var>foo</var><code> : GenericName).{@linkplain #scope}</code> * {@linkplain #equals equals} <var>foo</var>.{@link #scope()}</li> * * <li><code>push(</code><var>foo</var><code> : GenericName).{@linkplain #getParsedNames}</code> * {@linkplain List#equals equals} <var>foo</var>.<code>getParsedNames().{@linkplain * List#addAll addAll}(</code><var>this</var>.<code>getParsedNames())</code></li> * </ul> * <p> * This method is similar in purpose to <code>{@linkplain javax.naming.Name#addAll(int,javax.naming.Name) * Name.addAll}(0,name)</code> from the <cite>Java Naming and Directory Interface</cite>. * <p> * <b>Example</b>: * If {@code this} name is {@code "util.Record"} and the given {@code scope} argument is * {@code "org.opengis"}, then {@code this.push(scope)} shall returns * {@code "org.opengis.util.Record"}. * * @param scope The name to use as prefix. * @return A concatenation of the given name with this name. * * @since GeoAPI 2.1 */ @UML(identifier="push", obligation=MANDATORY, specification=ISO_19103) ScopedName push(GenericName scope); /** * Returns a string representation of this generic name. This string representation is * local-independant. It contains all elements listed by {@link #getParsedNames} separated * by a namespace-dependant character (usually {@code :} or {@code /}). This rule implies * that the result may or may not be fully qualified. Special cases: * <p> * <ul> * <li><code>{@linkplain #toFullyQualifiedName}.toString()</code> is garanteed to * contains the {@linkplain #scope scope} (if any).</li> * <li><code>{@linkplain #name}.toString()</code> is garanteed to <strong>not</strong> * contains any scope.</li> * </ul> * * @return A local-independant string representation of this name. */ /// @Override @Extension String toString(); /** * Returns a local-dependent string representation of this generic name. This string * is similar to the one returned by {@link #toString} except that each element has * been localized in the {@linkplain InternationalString#toString(java.util.Locale) * specified locale}. If no international string is available, then this method shall * returns an implementation mapping to {@link #toString} for all locales. * <p> * <b>Example</b>: * An implementation may want to localize the {@code "My Documents"} directory name * into {@code "Mes Documents"} on French installation of Windows operating system. * * @return A localizable string representation of this name. */ @Extension InternationalString toInternationalString(); }