KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > service > namespace > QName


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.service.namespace;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.Collection JavaDoc;
21
22 /**
23  * <code>QName</code> represents the qualified name of a Repository item. Each
24  * QName consists of a local name qualified by a namespace.
25  * <p>
26  * The {@link org.alfresco.service.namespace.QNamePattern QNamePattern} is implemented
27  * to allow instances of this class to be used for direct pattern matching where
28  * required on interfaces.
29  *
30  * @author David Caruana
31  *
32  */

33 public final class QName implements QNamePattern, Serializable JavaDoc, Cloneable JavaDoc
34 {
35     private static final long serialVersionUID = 3977016258204348976L;
36
37     private String JavaDoc namespaceURI; // never null
38
private String JavaDoc localName; // never null
39
private int hashCode;
40     private String JavaDoc prefix;
41
42     public static final char NAMESPACE_PREFIX = ':';
43     public static final char NAMESPACE_BEGIN = '{';
44     public static final char NAMESPACE_END = '}';
45     public static final int MAX_LENGTH = 100;
46
47     
48     /**
49      * Create a QName
50      *
51      * @param namespaceURI the qualifying namespace (maybe null or empty string)
52      * @param localName the qualified name
53      * @return the QName
54      */

55     public static QName createQName(String JavaDoc namespaceURI, String JavaDoc localName)
56         throws InvalidQNameException
57     {
58         if (localName == null || localName.length() == 0)
59         {
60             throw new InvalidQNameException("A QName must consist of a local name");
61         }
62         return new QName(namespaceURI, localName, null);
63     }
64
65
66     /**
67      * Create a QName
68      *
69      * @param prefix namespace prefix (maybe null or empty string)
70      * @param localName local name
71      * @param prefixResolver lookup to resolve mappings between prefix and namespace
72      * @return the QName
73      */

74     public static QName createQName(String JavaDoc prefix, String JavaDoc localName, NamespacePrefixResolver prefixResolver)
75         throws InvalidQNameException, NamespaceException
76     {
77         // Validate Arguments
78
if (localName == null || localName.length() == 0)
79         {
80             throw new InvalidQNameException("A QName must consist of a local name");
81         }
82         if (prefixResolver == null)
83         {
84             throw new IllegalArgumentException JavaDoc("A Prefix Resolver must be specified");
85         }
86         if (prefix == null)
87         {
88             prefix = NamespaceService.DEFAULT_PREFIX;
89         }
90         
91         // Calculate namespace URI and create QName
92
String JavaDoc uri = prefixResolver.getNamespaceURI(prefix);
93         if (uri == null)
94         {
95             throw new NamespaceException("Namespace prefix " + prefix + " is not mapped to a namespace URI");
96         }
97         return new QName(uri, localName, prefix);
98     }
99
100
101     /**
102      * Create a QName
103      *
104      * @param qname qualified name of the following format <code>prefix:localName</code>
105      * @param prefixResolver lookup to resolve mappings between prefix and namespace
106      * @return the QName
107      */

108     public static QName createQName(String JavaDoc qname, NamespacePrefixResolver prefixResolver)
109         throws InvalidQNameException, NamespaceException
110     {
111         QName name = null;
112         if (qname != null)
113         {
114             int colonIndex = qname.indexOf(NAMESPACE_PREFIX);
115             String JavaDoc prefix = (colonIndex == -1) ? NamespaceService.DEFAULT_PREFIX : qname.substring(0, colonIndex);
116             String JavaDoc localName = (colonIndex == -1) ? qname : qname.substring(colonIndex +1);
117             name = createQName(prefix, localName, prefixResolver);
118         }
119         return name;
120     }
121
122
123     /**
124      * Create a QName from its internal string representation of the following format:
125      *
126      * <code>{namespaceURI}localName</code>
127      *
128      * @param qname the string representation of the QName
129      * @return the QName
130      * @throws IllegalArgumentException
131      * @throws InvalidQNameException
132      */

133     public static QName createQName(String JavaDoc qname)
134         throws InvalidQNameException
135     {
136         if (qname == null || qname.length() == 0)
137         {
138             throw new InvalidQNameException("Argument qname is mandatory");
139         }
140
141         String JavaDoc namespaceURI = null;
142         String JavaDoc localName = null;
143
144         // Parse namespace
145
int namespaceBegin = qname.indexOf(NAMESPACE_BEGIN);
146         int namespaceEnd = -1;
147         if (namespaceBegin != -1)
148         {
149             if (namespaceBegin != 0)
150             {
151                 throw new InvalidQNameException("QName '" + qname + "' must start with a namespaceURI");
152             }
153             namespaceEnd = qname.indexOf(NAMESPACE_END, namespaceBegin + 1);
154             if (namespaceEnd == -1)
155             {
156                 throw new InvalidQNameException("QName '" + qname + "' is missing the closing namespace " + NAMESPACE_END + " token");
157             }
158             namespaceURI = qname.substring(namespaceBegin + 1, namespaceEnd);
159         }
160
161         // Parse name
162
localName = qname.substring(namespaceEnd + 1);
163         if (localName == null || localName.length() == 0)
164         {
165             throw new InvalidQNameException("QName '" + qname + "' must consist of a local name");
166         }
167
168         // Construct QName
169
return new QName(namespaceURI, localName, null);
170     }
171
172
173     /**
174      * Create a valid local name from the specified name
175      *
176      * @param name name to create valid local name from
177      * @return valid local name
178      */

179     public static String JavaDoc createValidLocalName(String JavaDoc name)
180     {
181         // Validate length
182
if (name == null || name.length() == 0)
183         {
184             throw new IllegalArgumentException JavaDoc("Local name cannot be null or empty.");
185         }
186         if (name.length() > MAX_LENGTH)
187         {
188             name = name.substring(0, MAX_LENGTH);
189         }
190
191         return name;
192     }
193     
194     
195     /**
196      * Create a QName
197      *
198      * @param qname qualified name of the following format <code>prefix:localName</code>
199      * @return string array where index 0 => prefix and index 1 => local name
200      */

201     public static String JavaDoc[] splitPrefixedQName(String JavaDoc qname)
202         throws InvalidQNameException, NamespaceException
203     {
204         if (qname != null)
205         {
206             int colonIndex = qname.indexOf(NAMESPACE_PREFIX);
207             String JavaDoc prefix = (colonIndex == -1) ? NamespaceService.DEFAULT_PREFIX : qname.substring(0, colonIndex);
208             String JavaDoc localName = (colonIndex == -1) ? qname : qname.substring(colonIndex +1);
209             return new String JavaDoc[] { prefix, localName };
210         }
211         return null;
212     }
213
214     
215     /**
216      * Construct QName
217      *
218      * @param namespace qualifying namespace (maybe null or empty string)
219      * @param name qualified name
220      * @param prefix prefix (maybe null or empty string)
221      */

222     private QName(String JavaDoc namespace, String JavaDoc name, String JavaDoc prefix)
223     {
224         this.namespaceURI = (namespace == null) ? NamespaceService.DEFAULT_URI : namespace;
225         this.prefix = prefix;
226         this.localName = name;
227         this.hashCode = 0;
228     }
229
230     @Override JavaDoc
231     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc
232     {
233         return super.clone();
234     }
235
236     /**
237      * Gets the name
238      *
239      * @return the name
240      */

241     public String JavaDoc getLocalName()
242     {
243         return this.localName;
244     }
245
246
247     /**
248      * Gets the namespace
249      *
250      * @return the namespace (empty string when not specified, but never null)
251      */

252     public String JavaDoc getNamespaceURI()
253     {
254         return this.namespaceURI;
255     }
256
257
258     /**
259      * Gets a prefix resolved version of this QName
260      *
261      * @param resolver namespace prefix resolver
262      * @return QName with prefix resolved
263      */

264     public QName getPrefixedQName(NamespacePrefixResolver resolver)
265     {
266         Collection JavaDoc<String JavaDoc> prefixes = resolver.getPrefixes(namespaceURI);
267         if (prefixes.size() == 0)
268         {
269             throw new NamespaceException("A namespace prefix is not registered for uri " + namespaceURI);
270         }
271         String JavaDoc resolvedPrefix = prefixes.iterator().next();
272         if (prefix != null && prefix.equals(resolvedPrefix))
273         {
274             return this;
275         }
276         return new QName(namespaceURI, localName, resolvedPrefix);
277     }
278     
279     
280     /**
281      * Two QNames are equal only when both their name and namespace match.
282      *
283      * Note: The prefix is ignored during the comparison.
284      */

285     public boolean equals(Object JavaDoc object)
286     {
287         if (this == object)
288         {
289             return true;
290         }
291         else if (object == null)
292         {
293             return false;
294         }
295         if (object instanceof QName)
296         {
297             QName other = (QName) object;
298             // namespaceURI and localname are not allowed to be null
299
return (this.namespaceURI.equals(other.namespaceURI) &&
300                     this.localName.equals(other.localName));
301         }
302         else
303         {
304             return false;
305         }
306     }
307
308     /**
309      * Performs a direct comparison between qnames.
310      *
311      * @see #equals(Object)
312      */

313     public boolean isMatch(QName qname)
314     {
315         return this.equals(qname);
316     }
317
318     /**
319      * Calculate hashCode. Follows pattern used by String where hashCode is
320      * cached (QName is immutable).
321      */

322     public int hashCode()
323     {
324         if (this.hashCode == 0)
325         {
326             // the hashcode assignment is atomic - it is only an integer
327
this.hashCode = ((37 * localName.hashCode()) + namespaceURI.hashCode());
328         }
329         return this.hashCode;
330     }
331
332
333     /**
334      * Render string representation of QName using format:
335      *
336      * <code>{namespace}name</code>
337      *
338      * @return the string representation
339      */

340     public String JavaDoc toString()
341     {
342         return NAMESPACE_BEGIN + namespaceURI + NAMESPACE_END + localName;
343     }
344
345     
346     /**
347      * Render string representation of QName using format:
348      *
349      * <code>prefix:name</code>
350      *
351      * @return the string representation
352      */

353     public String JavaDoc toPrefixString()
354     {
355         return (prefix == null) ? localName : prefix + NAMESPACE_PREFIX + localName;
356     }
357
358
359     /**
360      * Render string representation of QName using format:
361      *
362      * <code>prefix:name</code>
363      *
364      * according to namespace prefix mappings of specified namespace resolver.
365      *
366      * @param prefixResolver namespace prefix resolver
367      *
368      * @return the string representation
369      */

370     public String JavaDoc toPrefixString(NamespacePrefixResolver prefixResolver)
371     {
372         Collection JavaDoc<String JavaDoc> prefixes = prefixResolver.getPrefixes(namespaceURI);
373         if (prefixes.size() == 0)
374         {
375             throw new NamespaceException("A namespace prefix is not registered for uri " + namespaceURI);
376         }
377         String JavaDoc prefix = prefixes.iterator().next();
378         if (prefix.equals(NamespaceService.DEFAULT_PREFIX))
379         {
380             return localName;
381         }
382         else
383         {
384             return prefix + NAMESPACE_PREFIX + localName;
385         }
386     }
387
388
389     /**
390      * Creates a QName representation for the given String. If the String has no namespace the Alfresco namespace is
391      * added. If the String has a prefix an attempt to resolve the prefix to the full URI will be made.
392      *
393      * @param str The string to convert
394      * @return A QName representation of the given string
395      */

396     public static QName resolveToQName(NamespacePrefixResolver prefixResolver, String JavaDoc str)
397     {
398         QName qname = null;
399
400         if (str == null && str.length() == 0)
401         {
402             throw new IllegalArgumentException JavaDoc("str parameter is mandatory");
403         }
404
405         if (str.charAt(0) == (NAMESPACE_BEGIN))
406         {
407             // create QName directly
408
qname = createQName(str);
409         }
410         else if (str.indexOf(NAMESPACE_PREFIX) != -1)
411         {
412             // extract the prefix and try and resolve using the
413
// namespace service
414
int end = str.indexOf(NAMESPACE_PREFIX);
415             String JavaDoc prefix = str.substring(0, end);
416             String JavaDoc localName = str.substring(end + 1);
417             String JavaDoc uri = prefixResolver.getNamespaceURI(prefix);
418
419             if (uri != null)
420             {
421                 qname = createQName(uri, localName);
422             }
423         }
424         else
425         {
426             // there's no namespace so prefix with Alfresco's Content Model
427
qname = createQName(NamespaceService.CONTENT_MODEL_1_0_URI, str);
428         }
429
430         return qname;
431     }
432
433
434     /**
435      * Creates a string representation of a QName for the given string. If the given string already has a namespace,
436      * either a URL or a prefix, nothing the given string is returned. If it does not have a namespace the Alfresco
437      * namespace is added.
438      *
439      * @param str
440      * The string to convert
441      *
442      * @return A QName String representation of the given string
443      */

444     public static String JavaDoc resolveToQNameString(NamespacePrefixResolver prefixResolver, String JavaDoc str)
445     {
446         String JavaDoc result = str;
447
448         if (str == null && str.length() == 0)
449         {
450             throw new IllegalArgumentException JavaDoc("str parameter is mandatory");
451         }
452
453         if (str.charAt(0) != NAMESPACE_BEGIN && str.indexOf(NAMESPACE_PREFIX) != -1)
454         {
455             // get the prefix and resolve to the uri
456
int end = str.indexOf(NAMESPACE_PREFIX);
457             String JavaDoc prefix = str.substring(0, end);
458             String JavaDoc localName = str.substring(end + 1);
459             String JavaDoc uri = prefixResolver.getNamespaceURI(prefix);
460
461             if (uri != null)
462             {
463                 result = new StringBuilder JavaDoc(64).append(NAMESPACE_BEGIN).append(uri).append(NAMESPACE_END).append(
464                         localName).toString();
465             }
466         }
467         else if (str.charAt(0) != NAMESPACE_BEGIN)
468         {
469             // there's no namespace so prefix with Alfresco's Content Model
470
result = new StringBuilder JavaDoc(64).append(NAMESPACE_BEGIN).append(NamespaceService.CONTENT_MODEL_1_0_URI)
471                     .append(NAMESPACE_END).append(str).toString();
472         }
473
474         return result;
475     }
476 }
477
Popular Tags