1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64:
65:
71: public abstract class Expr
72: implements XPathExpression
73: {
74:
75: protected static final Comparator documentOrderComparator =
76: new DocumentOrderComparator();
77:
78: protected static final DecimalFormat decimalFormat =
79: new DecimalFormat("####################################################" +
80: ".####################################################",
81: new DecimalFormatSymbols(Locale.US));
82:
83: public Object evaluate(Object item, QName returnType)
84: throws XPathExpressionException
85: {
86: Object ret = null;
87: Node context = null;
88: if (item instanceof Node)
89: {
90: context = (Node) item;
91: ret = evaluate(context, 1, 1);
92: if (XPathConstants.STRING == returnType &&
93: !(ret instanceof String))
94: {
95: ret = _string(context, ret);
96: }
97: else if (XPathConstants.NUMBER == returnType &&
98: !(ret instanceof Double))
99: {
100: ret = new Double(_number(context, ret));
101: }
102: else if (XPathConstants.BOOLEAN == returnType &&
103: !(ret instanceof Boolean))
104: {
105: ret = _boolean(context, ret) ? Boolean.TRUE : Boolean.FALSE;
106: }
107: else if (XPathConstants.NODE == returnType)
108: {
109: if (ret instanceof Collection)
110: {
111: Collection ns = (Collection) ret;
112: switch (ns.size())
113: {
114: case 0:
115: ret = null;
116: break;
117: case 1:
118: ret = (Node) ns.iterator().next();
119: break;
120: default:
121: throw new XPathExpressionException("multiple nodes in node-set");
122: }
123: }
124: else if (ret != null)
125: {
126: throw new XPathExpressionException("return value is not a node-set");
127: }
128: }
129: else if (XPathConstants.NODESET == returnType)
130: {
131: if (ret != null && !(ret instanceof Collection))
132: {
133: throw new XPathExpressionException("return value is not a node-set");
134: }
135: }
136: }
137: return ret;
138: }
139:
140: public String evaluate(Object item)
141: throws XPathExpressionException
142: {
143: return (String) evaluate(item, XPathConstants.STRING);
144: }
145:
146: public Object evaluate(InputSource source, QName returnType)
147: throws XPathExpressionException
148: {
149: try
150: {
151: DocumentBuilderFactory factory =
152: new gnu.xml.dom.JAXPFactory();
153: DocumentBuilder builder = factory.newDocumentBuilder();
154: Document doc = builder.parse(source);
155: return evaluate(doc, returnType);
156: }
157: catch (ParserConfigurationException e)
158: {
159: throw new XPathExpressionException(e);
160: }
161: catch (SAXException e)
162: {
163: throw new XPathExpressionException(e);
164: }
165: catch (IOException e)
166: {
167: throw new XPathExpressionException(e);
168: }
169: }
170:
171: public String evaluate(InputSource source)
172: throws XPathExpressionException
173: {
174: return (String) evaluate(source, XPathConstants.STRING);
175: }
176:
177: public abstract Object evaluate(Node context, int pos, int len);
178:
179: public abstract Expr clone(Object context);
180:
181: public abstract boolean references(QName var);
182:
183:
184:
185:
197: public static Collection _id(Node context, Object object)
198: {
199: Set ret = new HashSet();
200: if (object instanceof Collection)
201: {
202: Collection nodeSet = (Collection) object;
203: for (Iterator i = nodeSet.iterator(); i.hasNext(); )
204: {
205: String string = stringValue((Node) i.next());
206: ret.addAll(_id (context, string));
207: }
208: }
209: else
210: {
211: Document doc = (context instanceof Document) ? (Document) context :
212: context.getOwnerDocument();
213: String string = _string(context, object);
214: StringTokenizer st = new StringTokenizer(string, " \t\r\n");
215: while (st.hasMoreTokens())
216: {
217: Node element = doc.getElementById(st.nextToken());
218: if (element != null)
219: {
220: ret.add(element);
221: }
222: }
223: }
224: return ret;
225: }
226:
227:
234: public static String _local_name(Node context, Collection nodeSet)
235: {
236: Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
237: firstNode(nodeSet);
238: return node.getLocalName();
239: }
240:
241:
249: public static String _namespace_uri(Node context, Collection nodeSet)
250: {
251: Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
252: firstNode(nodeSet);
253: return node.getNamespaceURI();
254: }
255:
256:
272: public static String _name(Node context, Collection nodeSet)
273: {
274: Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
275: firstNode(nodeSet);
276: switch (node.getNodeType())
277: {
278: case Node.ATTRIBUTE_NODE:
279: case Node.ELEMENT_NODE:
280: case Node.PROCESSING_INSTRUCTION_NODE:
281: return node.getNodeName();
282: default:
283: return "";
284: }
285: }
286:
287:
290: static Node firstNode(Collection nodeSet)
291: {
292: List list = new ArrayList(nodeSet);
293: Collections.sort(list, documentOrderComparator);
294: return (Node) list.get(0);
295: }
296:
297:
298:
299:
302: public static String _string(Node context, Object object)
303: {
304: if (object == null)
305: {
306: return stringValue(context);
307: }
308: if (object instanceof String)
309: {
310: return (String) object;
311: }
312: if (object instanceof Boolean)
313: {
314: return object.toString();
315: }
316: if (object instanceof Double)
317: {
318: double d = ((Double) object).doubleValue();
319: if (Double.isNaN(d))
320: {
321: return "NaN";
322: }
323: else if (d == 0.0d)
324: {
325: return "0";
326: }
327: else if (Double.isInfinite(d))
328: {
329: if (d < 0)
330: {
331: return "-Infinity";
332: }
333: else
334: {
335: return "Infinity";
336: }
337: }
338: else
339: {
340: String ret = decimalFormat.format(d);
341: if (ret.endsWith (".0"))
342: {
343: ret = ret.substring(0, ret.length() - 2);
344: }
345: return ret;
346: }
347: }
348: if (object instanceof Collection)
349: {
350: Collection nodeSet = (Collection) object;
351: if (nodeSet.isEmpty())
352: {
353: return "";
354: }
355: Node node = firstNode(nodeSet);
356: return stringValue(node);
357: }
358: throw new IllegalArgumentException(object.toString());
359: }
360:
361:
362:
363:
366: public static boolean _boolean(Node context, Object object)
367: {
368: if (object instanceof Boolean)
369: {
370: return ((Boolean) object).booleanValue();
371: }
372: if (object instanceof Double)
373: {
374: return ((Double) object).doubleValue() != 0.0;
375: }
376: if (object instanceof String)
377: {
378: return ((String) object).length() != 0;
379: }
380: if (object instanceof Collection)
381: {
382: return ((Collection) object).size() != 0;
383: }
384: return false;
385: }
386:
387:
388:
389:
392: public static double _number(Node context, Object object)
393: {
394: if (object == null)
395: {
396: object = Collections.singleton(context);
397: }
398: if (object instanceof Double)
399: {
400: return ((Double) object).doubleValue();
401: }
402: if (object instanceof Boolean)
403: {
404: return ((Boolean) object).booleanValue() ? 1.0 : 0.0;
405: }
406: if (object instanceof Collection)
407: {
408:
409: object = stringValue((Collection) object);
410: }
411: if (object instanceof String)
412: {
413: String string = ((String) object).trim();
414: try
415: {
416: return Double.parseDouble(string);
417: }
418: catch (NumberFormatException e)
419: {
420: return Double.NaN;
421: }
422: }
423: return Double.NaN;
424: }
425:
426:
429: public static String stringValue(Collection nodeSet)
430: {
431: StringBuffer buf = new StringBuffer();
432: for (Iterator i = nodeSet.iterator(); i.hasNext(); )
433: {
434: buf.append(stringValue((Node) i.next()));
435: }
436: return buf.toString();
437: }
438:
439:
442: public static String stringValue(Node node)
443: {
444: return stringValue(node, false);
445: }
446:
447: static String stringValue(Node node, boolean elementMode)
448: {
449: switch (node.getNodeType())
450: {
451: case Node.DOCUMENT_NODE:
452: case Node.DOCUMENT_FRAGMENT_NODE:
453: case Node.ELEMENT_NODE:
454: StringBuffer buf = new StringBuffer();
455: for (Node ctx = node.getFirstChild(); ctx != null;
456: ctx = ctx.getNextSibling())
457: {
458: buf.append(stringValue(ctx, true));
459: }
460: return buf.toString();
461: case Node.TEXT_NODE:
462: case Node.CDATA_SECTION_NODE:
463: return node.getNodeValue();
464: case Node.ATTRIBUTE_NODE:
465: case Node.PROCESSING_INSTRUCTION_NODE:
466: case Node.COMMENT_NODE:
467: if (!elementMode)
468: {
469: return node.getNodeValue();
470: }
471: default:
472: return "";
473: }
474: }
475:
476: }