KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > value > QNameValue


1 package net.sf.saxon.value;
2
3 import net.sf.saxon.Configuration;
4 import net.sf.saxon.ConversionContext;
5 import net.sf.saxon.expr.XPathContext;
6 import net.sf.saxon.expr.StaticContext;
7 import net.sf.saxon.functions.Component;
8 import net.sf.saxon.om.NamePool;
9 import net.sf.saxon.om.XMLChar;
10 import net.sf.saxon.om.Name;
11 import net.sf.saxon.om.QNameException;
12 import net.sf.saxon.style.StandardNames;
13 import net.sf.saxon.trans.DynamicError;
14 import net.sf.saxon.trans.XPathException;
15 import net.sf.saxon.trans.StaticError;
16 import net.sf.saxon.type.*;
17
18 import java.lang.reflect.Constructor JavaDoc;
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20
21
22 /**
23  * A QName value. This implements the so-called "triples proposal", in which the prefix is retained as
24  * part of the value. The prefix is not used in any operation on a QName other than conversion of the
25  * QName to a string.
26  */

27
28 public class QNameValue extends AtomicValue {
29
30     private String JavaDoc prefix; // "" for the default prefix
31
private String JavaDoc uri; // "" for the null namespace
32
private String JavaDoc localPart;
33
34     // Note: an alternative design was considered in which the QName was represented by a NamePool and a
35
// nameCode. This caused difficulties because there is not always enough context information available
36
// when creating a QName to locate the NamePool.
37

38     /**
39      * Constructor
40      * @param namePool The name pool containing the specified name code
41      * @param nameCode The name code identifying this name in the name pool
42      */

43
44     public QNameValue(NamePool namePool, int nameCode) {
45         prefix = namePool.getPrefix(nameCode);
46         uri = namePool.getURI(nameCode);
47         localPart = namePool.getLocalName(nameCode);
48     }
49
50     /**
51      * Constructor. This constructor validates that the local part is a valid NCName.
52      * @param prefix The prefix part of the QName (not used in comparisons). Use null or "" to represent the
53      * default prefix.
54      * @param uri The namespace part of the QName. Use null or "" to represent the null namespace.
55      * @param localName The local part of the QName
56      */

57
58     public QNameValue(String JavaDoc prefix, String JavaDoc uri, String JavaDoc localName) throws XPathException {
59         if (!XMLChar.isValidNCName(localName)) {
60             DynamicError err = new DynamicError("Malformed local name in QName: '" + localName + '\'');
61             err.setErrorCode("FORG0001");
62             throw err;
63         }
64         this.prefix = (prefix==null ? "" : prefix);
65         this.uri = (uri==null ? "" : uri);
66         this.localPart = localName;
67     }
68
69     /**
70      * Create a QName value (possibly a DerivedAtomicValue derived from QName) from
71      * a string literal, given a namespace context
72      * @param operand the input string
73      * @param targetType the type required: QName, or a type derived from QName or NOTATION
74      * @param env the static context, including the namespace context
75      * @return the value after conversion
76      * @throws XPathException if the name is lexically invalid or uses an undeclared prefix
77      */

78
79     public static AtomicValue castToQName(StringValue operand, AtomicType targetType, StaticContext env)
80             throws XPathException {
81         try {
82             CharSequence JavaDoc arg = operand.getStringValueCS();
83             String JavaDoc parts[] = Name.getQNameParts(arg);
84             String JavaDoc uri;
85             if ("".equals(parts[0])) {
86                 uri = "";
87             } else {
88                 uri = env.getURIForPrefix(parts[0]);
89                 if (uri==null) {
90                     StaticError e = new StaticError("Prefix '" + parts[0] + "' has not been declared");
91                     throw e;
92                 }
93             }
94             if (targetType.getFingerprint() == StandardNames.XS_QNAME) {
95                 return new QNameValue(parts[0], uri, parts[1]);
96             } else if (Type.isSubType(targetType, Type.QNAME_TYPE)) {
97                 QNameValue q = new QNameValue(parts[0], uri, parts[1]);
98                 AtomicValue av = targetType.makeDerivedValue(q, arg, true);
99                 if (av instanceof ValidationErrorValue) {
100                     throw ((ValidationErrorValue)av).getException();
101                 }
102                 return av;
103             } else {
104                 NotationValue n = new NotationValue(parts[0], uri, parts[1]);
105                 AtomicValue av = targetType.makeDerivedValue(n, arg, true);
106                 if (av instanceof ValidationErrorValue) {
107                     throw ((ValidationErrorValue)av).getException();
108                 }
109                 return av;
110             }
111         } catch (QNameException err) {
112             StaticError e = new StaticError(err);
113             throw e;
114         }
115     }
116
117
118     /**
119      * Get the string value as a String. Returns the QName as a lexical QName, retaining the original
120      * prefix if available.
121      */

122
123     public String JavaDoc getStringValue() {
124         if ("".equals(prefix)) {
125             return localPart;
126         } else {
127             return prefix + ':' + localPart;
128         }
129     }
130
131     /**
132      * Get the value as a JAXP QName
133      */

134
135 // public QName getQName() {
136
// return new QName(uri, localPart, prefix);
137
// }
138

139     /**
140      * Get the name in Clark notation, that is {uri}local
141      */

142
143     public String JavaDoc getClarkName() {
144         if ("".equals(uri)) {
145             return localPart;
146         } else {
147             return '{' + uri + '}' + localPart;
148         }
149     }
150
151     /**
152      * Get the local part
153      */

154
155     public String JavaDoc getLocalName() {
156         return localPart;
157     }
158
159     /**
160      * Get the namespace part (null means no namespace)
161      */

162
163     public String JavaDoc getNamespaceURI() {
164         return ("".equals(uri) ? null : uri);
165     }
166
167     /**
168      * Get the prefix
169      */

170
171     public String JavaDoc getPrefix() {
172         return prefix;
173     }
174
175     /**
176      * Allocate a nameCode for this QName in the NamePool
177      * @param pool the NamePool to be used
178      * @return the allocated nameCode
179      */

180
181     public int allocateNameCode(NamePool pool) {
182         return pool.allocate(prefix, uri, localPart);
183     }
184
185     /**
186      * Get a component. Returns a zero-length string if the namespace-uri component is
187      * requested and is not present.
188      * @param part either Component.LOCALNAME or Component.NAMESPACE indicating which
189      * component of the value is required
190      * @return either the local name or the namespace URI, in each case as a StringValue
191      */

192
193     public AtomicValue getComponent(int part) {
194         if (part == Component.LOCALNAME) {
195             return RestrictedStringValue.makeRestrictedString(
196                     localPart, StandardNames.XS_NCNAME, false);
197         } else if (part == Component.NAMESPACE) {
198             return new AnyURIValue(uri);
199         } else if (part == Component.PREFIX) {
200             return RestrictedStringValue.makeRestrictedString(
201                     prefix, StandardNames.XS_NCNAME, false);
202         } else {
203             throw new UnsupportedOperationException JavaDoc("Component of QName must be URI, Local Name, or Prefix");
204         }
205     }
206
207     /**
208      * Convert to target data type
209      * @param requiredType an integer identifying the required atomic type
210      * @param conversion
211      * @return an AtomicValue, a value of the required type; or an ErrorValue
212      */

213
214     public AtomicValue convertPrimitive(BuiltInAtomicType requiredType, boolean validate, ConversionContext conversion) {
215         switch (requiredType.getPrimitiveType()) {
216             case Type.ATOMIC:
217             case Type.ITEM:
218             case Type.QNAME:
219                 return this;
220             case Type.STRING:
221                 return new StringValue(getStringValue());
222             case Type.UNTYPED_ATOMIC:
223                 return new UntypedAtomicValue(getStringValue());
224             default:
225                 ValidationException err = new ValidationException("Cannot convert QName to " +
226                         requiredType.getDisplayName());
227                 //err.setXPathContext(context);
228
err.setErrorCode("FORG0001");
229                 return new ValidationErrorValue(err);
230         }
231     }
232
233     /**
234      * Return the type of the expression
235      * @return Type.QNAME (always)
236      */

237
238     public ItemType getItemType() {
239         return Type.QNAME_TYPE;
240     }
241
242
243     /**
244      * Determine if two QName values are equal. This comparison ignores the prefix part
245      * of the value.
246      * @throws ClassCastException if they are not comparable
247      * @throws IllegalStateException if the two QNames are in different name pools
248      */

249
250     public boolean equals(Object JavaDoc other) {
251         QNameValue val = (QNameValue) other;
252         return localPart.equals(val.localPart) && uri.equals(val.uri);
253     }
254
255     public int hashCode() {
256         return localPart.hashCode() ^ uri.hashCode();
257     }
258
259
260     /**
261      * Convert to Java object (for passing to external functions)
262      */

263
264     public Object JavaDoc convertToJava(Class JavaDoc target, XPathContext context) throws XPathException {
265         if (target.isAssignableFrom(QNameValue.class)) {
266             return this;
267         } else if (target.getClass().getName().equals("javax.xml.namespace.QName")) {
268             // TODO: rewrite this under JDK 1.5
269
return makeQName(context.getController().getConfiguration());
270         } else {
271             Object JavaDoc o = super.convertToJava(target, context);
272             if (o == null) {
273                 throw new DynamicError("Conversion of QName to " + target.getName() +
274                         " is not supported");
275             }
276             return o;
277         }
278     }
279
280     /**
281      * The toString() method returns the name in the form QName("uri", "local")
282      * @return the name in in the form QName("uri", "local")
283      */

284
285     public String JavaDoc toString() {
286         return "QName(\"" + uri + "\", \"" + localPart + "\")";
287     }
288
289     /**
290      * Temporary method to construct a javax.xml.namespace.QName without actually mentioning it
291      * by name
292      */

293
294     public Object JavaDoc makeQName(Configuration config) {
295         try {
296             Class JavaDoc qnameClass = config.getClass("javax.xml.namespace.QName", false, null);
297             Class JavaDoc[] argTypes = {String JavaDoc.class, String JavaDoc.class, String JavaDoc.class};
298             Constructor JavaDoc constructor = qnameClass.getConstructor(argTypes);
299             String JavaDoc[] argValues = {uri, localPart, prefix};
300             Object JavaDoc result = constructor.newInstance(argValues);
301             return result;
302         } catch (XPathException e) {
303             return null;
304         } catch (NoSuchMethodException JavaDoc e) {
305             return null;
306         } catch (InstantiationException JavaDoc e) {
307             return null;
308         } catch (IllegalAccessException JavaDoc e) {
309             return null;
310         } catch (InvocationTargetException JavaDoc e) {
311             return null;
312         }
313
314     }
315
316 // public static void main(String[] args) throws Exception {
317
// QName q = (QName)new QNameValue("a", "b", "c").makeQName();
318
// QNameValue v = Value.makeQNameValue(q);
319
// System.err.println(q);
320
// System.err.println(v);
321
// }
322

323 }
324
325 //
326
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
327
// you may not use this file except in compliance with the License. You may obtain a copy of the
328
// License at http://www.mozilla.org/MPL/
329
//
330
// Software distributed under the License is distributed on an "AS IS" basis,
331
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
332
// See the License for the specific language governing rights and limitations under the License.
333
//
334
// The Original Code is: all this file.
335
//
336
// The Initial Developer of the Original Code is Michael H. Kay
337
//
338
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
339
//
340
// Contributor(s): none.
341
//
342

343
Popular Tags