OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [gnu/] [xml/] [xpath/] [Expr.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Expr.java --
2
   Copyright (C) 2004 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package gnu.xml.xpath;
39
 
40
import java.io.IOException;
41
import java.text.DecimalFormat;
42
import java.text.DecimalFormatSymbols;
43
import java.util.ArrayList;
44
import java.util.Collection;
45
import java.util.Collections;
46
import java.util.Comparator;
47
import java.util.HashSet;
48
import java.util.Iterator;
49
import java.util.List;
50
import java.util.Locale;
51
import java.util.Set;
52
import java.util.StringTokenizer;
53
import javax.xml.namespace.QName;
54
import javax.xml.parsers.DocumentBuilder;
55
import javax.xml.parsers.DocumentBuilderFactory;
56
import javax.xml.parsers.ParserConfigurationException;
57
import javax.xml.xpath.XPathConstants;
58
import javax.xml.xpath.XPathExpression;
59
import javax.xml.xpath.XPathExpressionException;
60
import org.w3c.dom.Document;
61
import org.w3c.dom.Node;
62
import org.xml.sax.InputSource;
63
import org.xml.sax.SAXException;
64
 
65
/**
66
 * An XPath expression.
67
 * This can be evaluated in the context of a node to produce a result.
68
 *
69
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
70
 */
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
  /* -- 4.1 Node Set Functions -- */
184
 
185
  /**
186
   * The id function selects elements by their unique ID.
187
   * When the argument to id is of type node-set, then the result is
188
   * the union of the result of applying id to the string-value of each of
189
   * the nodes in the argument node-set. When the argument to id is of any
190
   * other type, the argument is converted to a string as if by a call to
191
   * the string function; the string is split into a whitespace-separated
192
   * list of tokens (whitespace is any sequence of characters matching the
193
   * production S); the result is a node-set containing the elements in the
194
   * same document as the context node that have a unique ID equal to any of
195
   * the tokens in the list.
196
   */
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
  /**
228
   * The local-name function returns the local part of the expanded-name of
229
   * the node in the argument node-set that is first in document order. If
230
   * the argument node-set is empty or the first node has no expanded-name,
231
   * an empty string is returned. If the argument is omitted, it defaults to
232
   * a node-set with the context node as its only member.
233
   */
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
  /**
242
   * The namespace-uri function returns the namespace URI of the
243
   * expanded-name of the node in the argument node-set that is first in
244
   * document order. If the argument node-set is empty, the first node has
245
   * no expanded-name, or the namespace URI of the expanded-name is null, an
246
   * empty string is returned. If the argument is omitted, it defaults to a
247
   * node-set with the context node as its only member.
248
   */
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
  /**
257
   * The name function returns a string containing a QName representing the
258
   * expanded-name of the node in the argument node-set that is first in
259
   * document order. The QName must represent the expanded-name with respect
260
   * to the namespace declarations in effect on the node whose expanded-name
261
   * is being represented. Typically, this will be the QName that occurred
262
   * in the XML source. This need not be the case if there are namespace
263
   * declarations in effect on the node that associate multiple prefixes
264
   * with the same namespace. However, an implementation may include
265
   * information about the original prefix in its representation of nodes;
266
   * in this case, an implementation can ensure that the returned string is
267
   * always the same as the QName used in the XML source. If the argument
268
   * node-set is empty or the first node has no expanded-name, an empty
269
   * string is returned. If the argument it omitted, it defaults to a
270
   * node-set with the context node as its only member.
271
   */
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
  /**
288
   * Returns the first node in the set in document order.
289
   */
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
  /* -- 4.2 String Functions -- */
298
 
299
  /**
300
   * Implementation of the XPath <code>string</code> function.
301
   */
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
  /* -- 4.3 Boolean Functions -- */
362
 
363
  /**
364
   * Implementation of the XPath <code>boolean</code> function.
365
   */
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; // TODO user defined types
385
  }
386
 
387
  /* -- 4.4 Number Functions -- */
388
 
389
  /**
390
   * Implementation of the XPath <code>number</code> function.
391
   */
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
        // Convert node-set to string
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; // TODO user-defined types
424
  }
425
 
426
  /**
427
   * Computes the XPath string-value of the specified node-set.
428
   */
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
  /**
440
   * Computes the XPath string-value of the specified node.
441
   */
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: // 5.1 Root Node
452
      case Node.DOCUMENT_FRAGMENT_NODE:
453
      case Node.ELEMENT_NODE: // 5.2 Element Nodes
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: // 5.7 Text Nodes
462
      case Node.CDATA_SECTION_NODE:
463
        return node.getNodeValue();
464
      case Node.ATTRIBUTE_NODE: // 5.3 Attribute Nodes
465
      case Node.PROCESSING_INSTRUCTION_NODE: // 5.5 Processing Instruction
466
      case Node.COMMENT_NODE: // 5.6 Comment Nodes
467
        if (!elementMode)
468
          {
469
            return node.getNodeValue();
470
          }
471
      default:
472
        return "";
473
      }
474
  }
475
 
476
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.