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: if (nodeSet == null || nodeSet.isEmpty())
237: return "";
238: Node node = firstNode(nodeSet);
239: String ret = node.getLocalName();
240: return (ret == null) ? "" : ret;
241: }
242:
243:
251: public static String _namespace_uri(Node context, Collection nodeSet)
252: {
253: if (nodeSet == null || nodeSet.isEmpty())
254: return "";
255: Node node = firstNode(nodeSet);
256: String ret = node.getNamespaceURI();
257: return (ret == null) ? "" : ret;
258: }
259:
260:
276: public static String _name(Node context, Collection nodeSet)
277: {
278: if (nodeSet == null || nodeSet.isEmpty())
279: return "";
280: Node node = firstNode(nodeSet);
281: String ret = null;
282: switch (node.getNodeType())
283: {
284: case Node.ATTRIBUTE_NODE:
285: case Node.ELEMENT_NODE:
286: case Node.PROCESSING_INSTRUCTION_NODE:
287: ret = node.getNodeName();
288: }
289: return (ret == null) ? "" : ret;
290: }
291:
292:
295: static Node firstNode(Collection nodeSet)
296: {
297: List list = new ArrayList(nodeSet);
298: Collections.sort(list, documentOrderComparator);
299: return (Node) list.get(0);
300: }
301:
302:
303:
304:
307: public static String _string(Node context, Object object)
308: {
309: if (object == null)
310: {
311: return stringValue(context);
312: }
313: if (object instanceof String)
314: {
315: return (String) object;
316: }
317: if (object instanceof Boolean)
318: {
319: return object.toString();
320: }
321: if (object instanceof Double)
322: {
323: double d = ((Double) object).doubleValue();
324: if (Double.isNaN(d))
325: {
326: return "NaN";
327: }
328: else if (d == 0.0d)
329: {
330: return "0";
331: }
332: else if (Double.isInfinite(d))
333: {
334: if (d < 0)
335: {
336: return "-Infinity";
337: }
338: else
339: {
340: return "Infinity";
341: }
342: }
343: else
344: {
345: String ret = decimalFormat.format(d);
346: if (ret.endsWith (".0"))
347: {
348: ret = ret.substring(0, ret.length() - 2);
349: }
350: return ret;
351: }
352: }
353: if (object instanceof Collection)
354: {
355: Collection nodeSet = (Collection) object;
356: if (nodeSet.isEmpty())
357: {
358: return "";
359: }
360: Node node = firstNode(nodeSet);
361: return stringValue(node);
362: }
363: throw new IllegalArgumentException(object.toString());
364: }
365:
366:
367:
368:
371: public static boolean _boolean(Node context, Object object)
372: {
373: if (object instanceof Boolean)
374: {
375: return ((Boolean) object).booleanValue();
376: }
377: if (object instanceof Double)
378: {
379: Double value = (Double) object;
380: if (value.isNaN())
381: return false;
382: return value.doubleValue() != 0.0;
383: }
384: if (object instanceof String)
385: {
386: return ((String) object).length() != 0;
387: }
388: if (object instanceof Collection)
389: {
390: return ((Collection) object).size() != 0;
391: }
392: return false;
393: }
394:
395:
396:
397:
400: public static double _number(Node context, Object object)
401: {
402: if (object == null)
403: {
404: object = Collections.singleton(context);
405: }
406: if (object instanceof Double)
407: {
408: return ((Double) object).doubleValue();
409: }
410: if (object instanceof Boolean)
411: {
412: return ((Boolean) object).booleanValue() ? 1.0 : 0.0;
413: }
414: if (object instanceof Collection)
415: {
416:
417: object = stringValue((Collection) object);
418: }
419: if (object instanceof String)
420: {
421: String string = ((String) object).trim();
422: try
423: {
424: return Double.parseDouble(string);
425: }
426: catch (NumberFormatException e)
427: {
428: return Double.NaN;
429: }
430: }
431: return Double.NaN;
432: }
433:
434:
437: public static String stringValue(Collection nodeSet)
438: {
439: StringBuffer buf = new StringBuffer();
440: for (Iterator i = nodeSet.iterator(); i.hasNext(); )
441: {
442: buf.append(stringValue((Node) i.next()));
443: }
444: return buf.toString();
445: }
446:
447:
450: public static String stringValue(Node node)
451: {
452: return stringValue(node, false);
453: }
454:
455: static String stringValue(Node node, boolean elementMode)
456: {
457: switch (node.getNodeType())
458: {
459: case Node.DOCUMENT_NODE:
460: case Node.DOCUMENT_FRAGMENT_NODE:
461: case Node.ELEMENT_NODE:
462: StringBuffer buf = new StringBuffer();
463: for (Node ctx = node.getFirstChild(); ctx != null;
464: ctx = ctx.getNextSibling())
465: {
466: buf.append(stringValue(ctx, true));
467: }
468: return buf.toString();
469: case Node.TEXT_NODE:
470: case Node.CDATA_SECTION_NODE:
471: return node.getNodeValue();
472: case Node.ATTRIBUTE_NODE:
473: case Node.PROCESSING_INSTRUCTION_NODE:
474: case Node.COMMENT_NODE:
475: if (!elementMode)
476: {
477: return node.getNodeValue();
478: }
479: default:
480: return "";
481: }
482: }
483:
484: static int intValue(Object val)
485: {
486: if (val instanceof Double)
487: {
488: Double d = (Double) val;
489: return d.isNaN() ? 0 : d.intValue();
490: }
491: else
492: return (int) Math.ceil(_number(null, val));
493: }
494:
495: }