001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2004, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * This package contains documentation from OpenGIS specifications.
018: * OpenGIS consortium's work is fully acknowledged here.
019: */
020: package org.geotools.util;
021:
022: // J2SE dependencies
023: import java.util.Arrays;
024: import java.util.List;
025: import java.util.Locale;
026:
027: // OpenGIS dependencies
028: import org.opengis.util.GenericName;
029: import org.opengis.util.InternationalString;
030: import org.opengis.util.LocalName;
031: import org.opengis.util.NameSpace;
032:
033: // Geotools dependencies
034: import org.geotools.resources.Utilities;
035:
036: /**
037: * Fully qualified identifier for an object.
038: * A {@code ScopedName} contains a {@link LocalName} as
039: * {@linkplain #asLocalName head} and a {@linkplain GenericName},
040: * which may be a {@link LocalName} or an other {@link org.opengis.util.ScopedName},
041: * as {@linkplain #getScope tail}.
042: *
043: * @since 2.1
044: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/util/ScopedName.java $
045: * @version $Id: ScopedName.java 22443 2006-10-27 20:47:22Z desruisseaux $
046: * @author Martin Desruisseaux
047: *
048: * @see NameFactory
049: */
050: public class ScopedName extends org.geotools.util.GenericName implements
051: org.opengis.util.ScopedName {
052: /**
053: * Serial number for interoperability with different versions.
054: */
055: private static final long serialVersionUID = -7664125655784137729L;
056:
057: /**
058: * The scope of this variable (also know as the "tail").
059: */
060: private final GenericName scope;
061:
062: /**
063: * The separator character.
064: */
065: private final char separator;
066:
067: /**
068: * The head as a local name.
069: */
070: private final LocalName name;
071:
072: /**
073: * The list of parsed names. Will be constructed only when first needed.
074: */
075: private transient List parsedNames;
076:
077: /**
078: * Constructs a scoped name from the specified international string.
079: * If the specified name is an {@link InternationalString}, then the
080: * <code>{@linkplain InternationalString#toString(Locale) toString}(null)</code>
081: * method will be used in order to fetch an unlocalized name. Otherwise, the
082: * <code>{@linkplain CharSequence#toString toString}()</code> method will be used.
083: *
084: * @param scope The scope (or "tail") of the variable.
085: * @param name The head (never {@code null}).
086: */
087: public ScopedName(final GenericName scope, final CharSequence name) {
088: this (scope, DEFAULT_SEPARATOR, name);
089: }
090:
091: /**
092: * Constructs a scoped name from the specified international string.
093: * If the specified name is an {@link InternationalString}, then the
094: * <code>{@linkplain InternationalString#toString(Locale) toString}(null)</code>
095: * method will be used in order to fetch an unlocalized name. Otherwise, the
096: * <code>{@linkplain CharSequence#toString toString}()</code> method will be used.
097: *
098: * @param scope The scope (or "tail") of the variable.
099: * @param separator The separator character (usually <code>':'</code> or <code>'/'</code>).
100: * @param name The head (never {@code null}).
101: */
102: public ScopedName(final GenericName scope, final char separator,
103: final CharSequence name) {
104: AbstractInternationalString.ensureNonNull("scope", scope);
105: AbstractInternationalString.ensureNonNull("name", name);
106: this .scope = scope;
107: this .separator = separator;
108: this .name = new org.geotools.util.LocalName(this , name);
109: }
110:
111: /**
112: * Returns the head of this scoped name. This is the first elements in the sequence of
113: * {@linkplain #getParsedNames parsed names}. The head element must exists in the same
114: * {@linkplain NameSpace name space} than this scoped name. In other words, the following
115: * relationship must holds:
116: * <p>
117: * <ul>
118: * <li><code>head().scope() == this.{@linkplain #scope scope()}</code></li>
119: * </ul>
120: *
121: * @since 2.3
122: *
123: * @todo Not yet implemented.
124: */
125: public LocalName head() {
126: throw new UnsupportedOperationException("Not yet implemented.");
127: }
128:
129: /**
130: * Returns the tail of this scoped name. The returned name contains every elements of the
131: * {@linkplain #getParsedNames parsed names list} except for the first one, which is the
132: * {@linkplain #head head}. In other words, the following relationship must holds:
133: * <p>
134: * <ul>
135: * <li><code>tail().getParsedNames() == this.{@linkplain #getParsedNames getParsedNames()}.sublist(1,end)</code></li>
136: * </ul>
137: * <p>
138: * <strong>Note:</strong> This condition can be understood in terms of the Java
139: * {@link java.util.List#equals equals} method instead of the Java identity
140: * comparator {@code ==}.
141: *
142: * @since 2.3
143: *
144: * @todo Not yet implemented.
145: */
146: public GenericName tail() {
147: throw new UnsupportedOperationException("Not yet implemented.");
148: }
149:
150: /**
151: * Returns a name which contains every element of the
152: * {@linkplain #getParsedNames parsed names list} except for the last element.
153: *
154: * @see java.io.File#getPath
155: *
156: * @since 2.3
157: *
158: * @todo Not yet implemented.
159: */
160: public GenericName path() {
161: throw new UnsupportedOperationException("Not yet implemented.");
162: }
163:
164: /**
165: * Returns the last element in the sequence of {@linkplain #getParsedNames parsed names}.
166: *
167: * @see java.io.File#getName
168: *
169: * @since 2.3
170: *
171: * @todo Not yet implemented.
172: */
173: public LocalName name() {
174: throw new UnsupportedOperationException("Not yet implemented.");
175: }
176:
177: /**
178: * Returns the scope (name space) in which this name is local. The scope is set on creation
179: * and is not modifiable. The scope of a name determines where a name "starts". For instance,
180: * if a name has a {@linkplain #depth depth} of two ({@code "util.GenericName"}) and is
181: * associated with a {@linkplain NameSpace name space} having the name {@code "org.opengis"},
182: * then the fully qualified name would be {@code "org.opengis.util.GenericName"}.
183: *
184: * @since 2.3
185: *
186: * @todo Not yet implemented.
187: */
188: public NameSpace scope() {
189: return null;
190: // throw new UnsupportedOperationException("Not yet implemented.");
191: }
192:
193: /**
194: * Returns the scope of this name.
195: *
196: * @deprecated Replaced by {@link #scope()}.
197: */
198: public GenericName getScope() {
199: return scope;
200: }
201:
202: /**
203: * Returns the depth of this name within the namespace hierarchy. This indicates the number
204: * of levels specified by this name. For any {@link LocalName}, it is always one. For a
205: * {@link ScopedName} it is some number greater than or equal to 2.
206: * <p>
207: * The depth is the length of the list returned by the {@link #getParsedNames} method.
208: * As such it is a derived parameter.
209: *
210: * @since 2.3
211: *
212: * @todo Not yet implemented.
213: */
214: public int depth() {
215: throw new UnsupportedOperationException("Not yet implemented.");
216: }
217:
218: /**
219: * Returns the separator character.
220: */
221: public char getSeparator() {
222: return separator;
223: }
224:
225: /**
226: * Returns a view of this object as a scoped name. Since this object is already
227: * a scoped name, this method always returns {@code this}.
228: *
229: * @deprecated Replaced by {@link #toFullyQualifiedName}.
230: */
231: public org.opengis.util.ScopedName asScopedName() {
232: return this ;
233: }
234:
235: /**
236: * Returns a view of this object as a local name. This is the last element in the
237: * sequence of {@linkplain #getParsedNames parsed names}. The local name returned
238: * by this method will still have the same {@linkplain LocalName#getScope scope}
239: * than this scoped name. Note however that the string returned by
240: * {@link LocalName#toString} will differs.
241: *
242: * @deprecated Replaced by {@link #name}.
243: */
244: public LocalName asLocalName() {
245: return name;
246: }
247:
248: /**
249: * Returns the sequence of local name for this {@linkplain GenericName generic name}.
250: */
251: public List getParsedNames() {
252: if (parsedNames == null) {
253: final List parents = scope.getParsedNames();
254: final int size = parents.size();
255: GenericName[] names = new GenericName[size + 1];
256: names = (GenericName[]) parents.toArray(names);
257: names[size] = name;
258: parsedNames = Arrays.asList(names);
259: }
260: return parsedNames;
261: }
262:
263: /**
264: * Returns a view of this name as a fully-qualified name. The {@linkplain #scope scope}
265: * of a fully qualified name must be {@linkplain NameSpace#isGlobal global}. This method
266: * never returns {@code null}.
267: *
268: * @since 2.3
269: *
270: * @todo Not yet implemented.
271: */
272: public GenericName toFullyQualifiedName() {
273: throw new UnsupportedOperationException("Not yet implemented.");
274: }
275:
276: /**
277: * Returns this name expanded with the specified scope. One may represent this operation
278: * as a concatenation of the specified {@code name} with {@code this}. In pseudo-code,
279: * the following relationships must hold:
280: * <p>
281: * <ul>
282: * <li><code>push(<var>name</var>).getParsedList() ==
283: * <var>name</var>.getParsedList().addAll({@linkplain #getParsedNames()})</code></li>
284: * <li><code>push(<var>name</var>).scope() == <var>name</var>.{@linkplain #scope()}</code></li>
285: * <li><code>push({@linkplain ScopedName#head head()}).{@linkplain ScopedName#tail tail()} == this</code></li>
286: * </ul>
287: * <p>
288: * <strong>Note:</strong> Those conditions can be understood in terms of the Java
289: * {@link Object#equals equals} method instead of the Java identity comparator {@code ==}.
290: *
291: * @since 2.3
292: *
293: * @todo Not yet implemented.
294: */
295: public org.opengis.util.ScopedName push(GenericName scope) {
296: throw new UnsupportedOperationException("Not yet implemented.");
297: }
298:
299: /**
300: * Compares this scoped name with the specified object for equality.
301: */
302: public boolean equals(final Object object) {
303: if (object == this ) {
304: return true;
305: }
306: if (object != null && object.getClass().equals(getClass())) {
307: final ScopedName that = (ScopedName) object;
308: return Utilities.equals(this .name, that.name);
309: // No need to checks the scope, since the LocalName implementation
310: // should checks it.
311: }
312: return false;
313: }
314:
315: /**
316: * Returns a hash code value for this generic name.
317: */
318: public int hashCode() {
319: return (int) serialVersionUID ^ name.hashCode()
320: ^ scope.hashCode();
321: }
322: }
|