001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2004-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.util;
019
020import java.util.List;
021import org.opengis.annotation.UML;
022
023import static org.opengis.annotation.Obligation.*;
024import static org.opengis.annotation.Specification.*;
025
026
027/**
028 * A composite of a {@code LocalName} (as head) for locating another name space,
029 * and a {@code GenericName} (as tail) valid in that name space.
030 * For example, if this name is {@code "org.opengis.util.Record"},
031 * then the {@linkplain #head() head} and {@linkplain #tail() tail} components are as below.
032 * The {@linkplain #path() path} and {@linkplain #tip()} are also shown for completeness:
033 *
034 * <blockquote>
035 * <div style="display:grid; grid-template-columns:3em 1ch 4.5em 1ch 2em 1ch 4em; text-align:center">
036 *   <div style="grid-row:1;grid-column:1">org</div>     <div style="grid-row:1;grid-column:2">.</div>
037 *   <div style="grid-row:1;grid-column:3">opengis</div> <div style="grid-row:1;grid-column:4">.</div>
038 *   <div style="grid-row:1;grid-column:5">util</div>    <div style="grid-row:1;grid-column:6">.</div>
039 *   <div style="grid-row:1;grid-column:7">Record</div>
040 *   <div style="grid-row:2;grid-column:1;   background:palegoldenrod">{@linkplain #head() head}</div>
041 *   <div style="grid-row:2;grid-column:3/8; background:palegoldenrod; background:palegoldenrod">{@linkplain #tail() tail}</div>
042 *   <div style="grid-row:3;grid-column:1/6; background:palegoldenrod; background:wheat">{@linkplain #path() path}</div>
043 *   <div style="grid-row:3;grid-column:7;   background:palegoldenrod; background:wheat">{@linkplain #tip() tip}</div>
044 * </div>
045 * </blockquote>
046 *
047 * This definition allows for iteration.
048 * The tail may be either a {@link LocalName} or another {@code ScopedName}.
049 * If it is a scoped name, then another another step towards a remote local name is taken.
050 * In this way, a scoped name may represent an arbitrarily distant local name simply by the number of times
051 * the {@link #tail()} method evaluates to a {@code ScopedName} before finally terminating on a {@link LocalName}.
052 *
053 * <p>It may be seen that {@code ScopedName} is the means by which fully-qualified names are expressed.
054 * However, a {@code ScopedName} is not, in itself, what is commonly thought of as a <i>fully qualified</i> name.
055 * The {@code ScopedName} type is one link in the chain, not the entire chain.
056 * A scoped name is a fully qualified name only if its {@linkplain #scope() scope}
057 * {@linkplain NameSpace#isGlobal() is global}.</p>
058 *
059 * @author  Martin Desruisseaux (IRD)
060 * @author  Bryce Nordgren (USDA)
061 * @version 3.0
062 * @since   2.0
063 */
064@UML(identifier="ScopedName", specification=ISO_19103)
065public interface ScopedName extends GenericName {
066    /**
067     * Returns the first element in the sequence of {@linkplain #getParsedNames() parsed names}.
068     * The head element must exists in the same {@linkplain NameSpace name space} than this
069     * scoped name. In other words, the following relationship must holds:
070     *
071     * <ul>
072     *   <li><code>head().scope()</code>
073     *       &nbsp;&nbsp; {@linkplain Object#equals(Object) equals} &nbsp;&nbsp;
074     *       <code>this.{@linkplain #scope() scope()}</code></li>
075     * </ul>
076     *
077     * <p>In the {@link GenericName GenericName} javadoc,
078     * the heads are the blue elements in the <var>head</var>.<var>tail</var> column.</p>
079     *
080     * <div class="note"><b>Example:</b>
081     * if {@code this} name is {@code "org.opengis.util.Record"}, then this method shall returns {@code "org"}.</div>
082     *
083     * <div class="note"><b>Analogy:</b>
084     * this method is similar in purpose to:
085     * <ul>
086     *   <li><code>{@linkplain java.nio.file.Path#getName(int) Path.getName}(0)</code> from Java I/O;</li>
087     *   <li><code>{@linkplain javax.naming.Name#get(int) Name.get}(0)</code>
088     *       from the <cite>Java Naming and Directory Interface</cite>.</li>
089     * </ul></div>
090     *
091     * @return the first element in the list of {@linkplain #getParsedNames() parsed names}.
092     */
093    @Override
094    @UML(identifier="head", obligation=MANDATORY, specification=ISO_19103)
095    LocalName head();
096
097    /**
098     * Returns every elements in the sequence of {@linkplain #getParsedNames() parsed names} except for
099     * the {@linkplain #head() head}. In other words, the following relationship must holds:
100     *
101     * <ul>
102     *   <li><code>tail().getParsedNames()</code>
103     *   &nbsp;&nbsp; {@linkplain List#equals(Object) equals} &nbsp;&nbsp;
104     *   <code>this.{@linkplain #getParsedNames getParsedNames()}.sublist(1, {@linkplain #depth depth})</code></li>
105     * </ul>
106     *
107     * <p>In the {@link GenericName GenericName} javadoc,
108     * the tails are the yellow elements in the <var>head</var>.<var>tail</var> column.</p>
109     *
110     * <div class="note"><b>Analogy:</b>
111     * this method is similar in purpose to <code>{@link javax.naming.Name#getSuffix(int) Name.getSuffix}(1)</code>
112     * from the <cite>Java Naming and Directory Interface</cite>.
113     * </div>
114     *
115     * @return all elements except the first one in the in the list of {@linkplain #getParsedNames() parsed names}.
116     */
117    @UML(identifier="tail", obligation=MANDATORY, specification=ISO_19103)
118    GenericName tail();
119
120    /**
121     * Returns every elements in the sequence {@linkplain #getParsedNames() parsed names} except for
122     * the {@linkplain #tip() tip}. In other words, the following relationship must holds:
123     *
124     * <ul>
125     *   <li><code>tip().getParsedNames()</code>
126     *   &nbsp;&nbsp; {@linkplain List#equals(Object) equals} &nbsp;&nbsp;
127     *   <code>this.{@linkplain #getParsedNames() getParsedNames()}.sublist(0, {@linkplain #depth() depth}-1)</code></li>
128     * </ul>
129     *
130     * <p>In the {@link GenericName GenericName} javadoc,
131     * the paths are the blue elements in the <var>path</var>.<var>tip</var> column.</p>
132     *
133     * <div class="note"><b>Analogy:</b>
134     * this method is similar in purpose to:
135     * <ul>
136     *   <li>the {@link java.io.File#getParentFile() File.getParentFile()} or
137     *       {@link java.nio.file.Path#getParent() Path.getParent()} from Java I/O;</li>
138     *   <li><code>{@link javax.naming.Name#getPrefix(int) Name.getPrefix}(size-1)</code>
139     *       from the <cite>Java Naming and Directory Interface</cite>.</li>
140     * </ul></div>
141     *
142     * @return all elements except the last one in the in the list of {@linkplain #getParsedNames() parsed names}.
143     *
144     * @departure easeOfUse
145     *   This method is not part of ISO specification. It has been added in GeoAPI as a
146     *   complement of the ISO {@code tail()} method.
147     */
148    GenericName path();
149
150    /**
151     * Returns the last element in the sequence of {@linkplain #getParsedNames() parsed names}.
152     *
153     * <p>In the {@link GenericName GenericName} javadoc,
154     * the tips are the yellow elements in the <var>path</var>.<var>tip</var> column.</p>
155     *
156     * <div class="note"><b>Analogy:</b>
157     * this method is similar in purpose to:
158     * <ul>
159     *   <li>the {@link java.io.File#getName() File.getName()} or
160     *       {@link java.nio.file.Path#getFileName() Path.getFileName()} method in Java I/O;</li>
161     *   <li><code>{@linkplain javax.naming.Name#get(int) Name.get}(size-1)</code>
162     *       from the <cite>Java Naming and Directory Interface</cite>.</li>
163     * </ul></div>
164     *
165     * @return the last element in the list of {@linkplain #getParsedNames() parsed names}.
166     */
167    @Override
168    LocalName tip();
169
170    /**
171     * Returns a locale-independent string representation of this scoped name.
172     * This method encapsulates the domain logic which formats the {@linkplain #getParsedNames() parsed names}
173     * into a legal string representation of the name. There will be variants on this theme.
174     * XML aficionados may require URIs. For Java classes, a dotted notation is more appropriate,
175     * for C/C++, a double-colon, for directories, a forward or reverse slash,
176     * and for {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem <abbr>CRS</abbr>},
177     * it will depend on the mode of expression: <abbr>URN</abbr> or {@code Authority:Identifier} notation.
178     *
179     * <div class="note"><b>Analogy:</b>
180     * this method is similar in purpose to the {@link java.io.File#toString() File.toString()}
181     * or {@link java.nio.file.Path#toString() Path.toString()} method in Java I/O.
182     * </div>
183     */
184    @Override
185    @UML(identifier="scopedName", obligation=MANDATORY, specification=ISO_19103)
186    String toString();
187}