Initial revision

From-SVN: r102074
This commit is contained in:
Tom Tromey
2005-07-16 00:30:23 +00:00
parent 6f4434b39b
commit f911ba985a
4557 changed files with 1000262 additions and 0 deletions
@@ -0,0 +1,87 @@
/* AndExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Logical and.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class AndExpr
extends Expr
{
final Expr lhs;
final Expr rhs;
public AndExpr(Expr lhs, Expr rhs)
{
this.lhs = lhs;
this.rhs = rhs;
}
public Object evaluate(Node context, int pos, int len)
{
Object left = lhs.evaluate(context, pos, len);
if (!_boolean(context, left))
{
return Boolean.FALSE;
}
Object right = rhs.evaluate(context, pos, len);
return _boolean(context, right) ? Boolean.TRUE : Boolean.FALSE;
}
public Expr clone(Object context)
{
return new AndExpr(lhs.clone(context), rhs.clone(context));
}
public boolean references(QName var)
{
return (lhs.references(var) || rhs.references(var));
}
public String toString()
{
return lhs + " and " + rhs;
}
}
@@ -0,0 +1,154 @@
/* ArithmeticExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Binary arithmetic expression.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class ArithmeticExpr
extends Expr
{
static final int ADD = 0;
static final int SUBTRACT = 1;
static final int MULTIPLY = 2;
static final int DIVIDE = 3;
static final int MODULO = 4;
final Expr lhs;
final Expr rhs;
final int op;
ArithmeticExpr(Expr lhs, Expr rhs, int op)
{
this.lhs = lhs;
this.rhs = rhs;
switch (op)
{
case ADD:
case SUBTRACT:
case MULTIPLY:
case DIVIDE:
case MODULO:
this.op = op;
break;
default:
throw new IllegalArgumentException();
}
}
public Object evaluate(Node context, int pos, int len)
{
Object left = lhs.evaluate(context, pos, len);
Object right = rhs.evaluate(context, pos, len);
double ln = _number(context, left);
double rn = _number(context, right);
switch (op)
{
case ADD:
return new Double(ln + rn);
case SUBTRACT:
return new Double(ln - rn);
case MULTIPLY:
return new Double(ln * rn);
case DIVIDE:
if (rn == 0.0d || rn == -0.0d)
{
return new Double(ln < 0.0d ?
Double.NEGATIVE_INFINITY :
Double.POSITIVE_INFINITY);
}
return new Double(ln / rn);
case MODULO:
if (rn == 0.0d || rn == -0.0d)
{
return new Double(ln < 0.0d ?
Double.NEGATIVE_INFINITY :
Double.POSITIVE_INFINITY);
}
return new Double(ln % rn);
default:
throw new IllegalStateException();
}
}
public Expr clone(Object context)
{
return new ArithmeticExpr(lhs.clone(context), rhs.clone(context), op);
}
public boolean references(QName var)
{
return (lhs.references(var) || rhs.references(var));
}
public String toString()
{
StringBuffer buf = new StringBuffer();
buf.append(lhs);
buf.append(' ');
switch (op)
{
case ADD:
buf.append('+');
break;
case SUBTRACT:
buf.append('-');
break;
case MULTIPLY:
buf.append('*');
break;
case DIVIDE:
buf.append("div");
break;
case MODULO:
buf.append("mod");
break;
}
buf.append(' ');
buf.append(rhs);
return buf.toString();
}
}
@@ -0,0 +1,95 @@
/* BooleanFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>boolean</code> function converts its argument to a boolean as
* follows:
* <ul>
* <li>a number is true if and only if it is neither positive or negative
* zero nor NaN</li>
* <li>a node-set is true if and only if it is non-empty</li>
* <li>a string is true if and only if its length is non-zero</li>
* <li>an object of a type other than the four basic types is converted to a
* boolean in a way that is dependent on that type</li>
* </ul>
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class BooleanFunction
extends Expr
{
final Expr arg;
BooleanFunction(List args)
{
this((Expr) args.get(0));
}
BooleanFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
return _boolean(context, val) ? Boolean.TRUE : Boolean.FALSE;
}
public Expr clone(Object context)
{
return new BooleanFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "boolean(" + arg + ")";
}
}
@@ -0,0 +1,89 @@
/* CeilingFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>ceiling</code> function returns the smallest (closest to
* negative infinity) number that is not less than the argument and that
* is an integer.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class CeilingFunction
extends Expr
{
final Expr arg;
CeilingFunction(List args)
{
this((Expr) args.get(0));
}
CeilingFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
double n = _number(context, val);
return new Double(Math.ceil(n));
}
public Expr clone(Object context)
{
return new CeilingFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "ceiling(" + arg + ")";
}
}
@@ -0,0 +1,113 @@
/* ConcatFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>concat</code> function returns the concatenation of its arguments.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class ConcatFunction
extends Expr
{
final List args;
ConcatFunction(List args)
{
this.args = args;
}
public Object evaluate(Node context, int pos, int len)
{
StringBuffer buf = new StringBuffer();
for (Iterator i = args.iterator(); i.hasNext(); )
{
Expr arg = (Expr) i.next();
Object val = arg.evaluate(context, pos, len);
buf.append(_string(context, val));
}
return buf.toString();
}
public Expr clone(Object context)
{
int len = args.size();
List args2 = new ArrayList(len);
for (int i = 0; i < len; i++)
{
args2.add(((Expr) args.get(i)).clone(context));
}
return new ConcatFunction(args2);
}
public boolean references(QName var)
{
for (Iterator i = args.iterator(); i.hasNext(); )
{
if (((Expr) i.next()).references(var))
{
return true;
}
}
return false;
}
public String toString()
{
StringBuffer buf = new StringBuffer("concat(");
int len = args.size();
for (int i = 0; i < len; i++)
{
if (i > 0)
{
buf.append(',');
}
buf.append(args.get(i));
}
buf.append(')');
return buf.toString();
}
}
@@ -0,0 +1,98 @@
/* Constant.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Constant value (string literal or number).
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class Constant
extends Expr
{
final Object value;
public Constant(Object value)
{
this.value = value;
}
public Object evaluate(Node context, int pos, int len)
{
return value;
}
public Expr clone(Object context)
{
return new Constant(value);
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
String ret = value.toString();
if (value instanceof String)
{
if (ret.indexOf('\'') == -1)
{
return '\'' + ret + '\'';
}
else
{
return '"' + ret + '"';
}
}
if (value instanceof Double)
{
if (ret.endsWith(".0"))
{
ret = ret.substring(0, ret.length() - 2);
}
}
return ret;
}
}
@@ -0,0 +1,92 @@
/* ContainsFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>contains</code> function returns true if the first argument
* string contains the second argument string, and otherwise returns false.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class ContainsFunction
extends Expr
{
final Expr arg1;
final Expr arg2;
ContainsFunction(List args)
{
this((Expr) args.get(0), (Expr) args.get(1));
}
ContainsFunction(Expr arg1, Expr arg2)
{
this.arg1 = arg1;
this.arg2 = arg2;
}
public Object evaluate(Node context, int pos, int len)
{
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
String s1 = _string(context, val1);
String s2 = _string(context, val2);
return (s1.indexOf(s2) != -1) ? Boolean.TRUE : Boolean.FALSE;
}
public Expr clone(Object context)
{
return new ContainsFunction(arg1.clone(context), arg2.clone(context));
}
public boolean references(QName var)
{
return (arg1.references(var) || arg2.references(var));
}
public String toString()
{
return "contains(" + arg1 + "," + arg2 + ")";
}
}
@@ -0,0 +1,88 @@
/* CountFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>count</code> function returns the number of nodes in the
* argument node-set.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class CountFunction
extends Expr
{
final Expr arg;
CountFunction(List args)
{
this((Expr) args.get(0));
}
CountFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
return new Double((double) ((Collection) val).size());
}
public Expr clone(Object context)
{
return new CountFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "count(" + arg + ")";
}
}
@@ -0,0 +1,63 @@
/* DocumentOrderComparator.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Comparator;
import org.w3c.dom.Node;
/**
* Sorts nodes into document order.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class DocumentOrderComparator
implements Comparator
{
public int compare(Object o1, Object o2)
{
if (o1 instanceof Node && o2 instanceof Node)
{
Node n1 = (Node)o1;
Node n2 = (Node)o2;
return (int) n1.compareDocumentPosition(n2);
}
return 0;
}
}
@@ -0,0 +1,268 @@
/* EqualityExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.Iterator;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Boolean equality expression.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class EqualityExpr
extends Expr
{
final Expr lhs;
final Expr rhs;
final boolean invert;
EqualityExpr(Expr lhs, Expr rhs, boolean invert)
{
this.lhs = lhs;
this.rhs = rhs;
this.invert = invert;
}
public Object evaluate(Node context, int pos, int len)
{
boolean val = evaluateImpl(context, pos, len);
if (invert)
{
return val ? Boolean.FALSE : Boolean.TRUE;
}
else
{
return val ? Boolean.TRUE : Boolean.FALSE;
}
}
private boolean evaluateImpl(Node context, int pos, int len)
{
Object left = lhs.evaluate(context, pos, len);
Object right = rhs.evaluate(context, pos, len);
/*
* If both objects to be compared are node-sets, then the comparison
* will be true if and only if there is a node in the first node-set and
* a node in the second node-set such that the result of performing the
* comparison on the string-values of the two nodes is true.
*/
boolean flns = left instanceof Collection;
boolean frns = right instanceof Collection;
if (flns && frns)
{
Collection lns = (Collection) left;
Collection rns = (Collection) right;
if (lns.isEmpty())
{
return false;
}
boolean all = true;
for (Iterator i = lns.iterator(); i.hasNext(); )
{
Node ltest = (Node) i.next();
for (Iterator j = rns.iterator(); j.hasNext(); )
{
Node rtest = (Node) j.next();
if (ltest == rtest || ltest.equals(rtest))
{
// much shorter
if (!invert)
{
return true;
}
}
else if (stringValue(ltest).equals(stringValue(rtest)))
{
if (!invert)
{
return true;
}
}
else
{
all = false;
}
}
}
return all;
}
/*
* If one object to be compared is a node-set and the other is a number,
* then the comparison will be true if and only if there is a node in
* the node-set such that the result of performing the comparison on the
* number to be compared and on the result of converting the
* string-value of that node to a number using the number function is
* true.
*/
boolean fln = left instanceof Double;
boolean frn = right instanceof Double;
if ((flns && frn) || (frns && fln))
{
Collection ns = flns ? (Collection) left : (Collection) right;
double n = fln ? ((Double) left).doubleValue() :
((Double) right).doubleValue();
boolean all = true;
for (Iterator i = ns.iterator(); i.hasNext(); )
{
Node test = (Node) i.next();
double nn = _number(context, stringValue(test));
if (nn == n)
{
if (!invert)
{
return true;
}
}
else
{
all = false;
}
}
return invert ? all : false;
}
/*
* If one object to be compared is a node-set and the other is a
* string, then the comparison will be true if and only if there is a
* node in the node-set such that the result of performing the
* comparison on the string-value of the node and the other string is
* true.
*/
boolean fls = left instanceof String;
boolean frs = right instanceof String;
if ((flns && frs) || (frns && fls))
{
Collection ns = flns ? (Collection) left : (Collection) right;
String s = fls ? (String) left : (String) right;
boolean all = true;
for (Iterator i = ns.iterator(); i.hasNext(); )
{
Node test = (Node) i.next();
if (stringValue(test).equals(s))
{
if (!invert)
{
return true;
}
}
else
{
all = false;
}
}
return invert ? all : false;
}
/*
* If one object to be compared is a node-set and the other is a
* boolean, then the comparison will be true if and only if the result
* of performing the comparison on the boolean and on the result of
* converting the node-set to a boolean using the boolean function is
* true.
*/
boolean flb = left instanceof Boolean;
boolean frb = right instanceof Boolean;
if ((flns && frb) || (frns && flb))
{
Collection ns = flns ? (Collection) left : (Collection) right;
boolean b = flb ? ((Boolean) left).booleanValue() :
((Boolean) right).booleanValue();
return _boolean(context, ns) == b;
}
/*
* If at least one object to be compared is a boolean, then each object
* to be compared is converted to a boolean as if by applying the
* boolean function.
*/
if (flb || frb)
{
boolean lb = flb ? ((Boolean) left).booleanValue() :
_boolean(context, left);
boolean rb = frb ? ((Boolean) right).booleanValue() :
_boolean(context, right);
return lb == rb;
}
/*
* Otherwise, if at least one object to be compared is
* a number, then each object to be compared is converted to a number as
* if by applying the number function.
*/
if (fln || frn)
{
double ln = fln ? ((Double) left).doubleValue() :
_number(context, left);
double rn = frn ? ((Double) right).doubleValue() :
_number(context, right);
return ln == rn;
}
/*
* Otherwise, both objects to be
* compared are converted to strings as if by applying the string
* function.
*/
String ls = fls ? (String) left : _string(context, left);
String rs = frs ? (String) right : _string(context, right);
return ls.equals(rs);
}
public Expr clone(Object context)
{
return new EqualityExpr(lhs.clone(context), rhs.clone(context), invert);
}
public boolean references(QName var)
{
return (lhs.references(var) || rhs.references(var));
}
public String toString()
{
if (invert)
{
return lhs + " != " + rhs;
}
else
{
return lhs + " = " + rhs;
}
}
}
+476
View File
@@ -0,0 +1,476 @@
/* Expr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* An XPath expression.
* This can be evaluated in the context of a node to produce a result.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public abstract class Expr
implements XPathExpression
{
protected static final Comparator documentOrderComparator =
new DocumentOrderComparator();
protected static final DecimalFormat decimalFormat =
new DecimalFormat("####################################################" +
".####################################################",
new DecimalFormatSymbols(Locale.US));
public Object evaluate(Object item, QName returnType)
throws XPathExpressionException
{
Object ret = null;
Node context = null;
if (item instanceof Node)
{
context = (Node) item;
ret = evaluate(context, 1, 1);
if (XPathConstants.STRING == returnType &&
!(ret instanceof String))
{
ret = _string(context, ret);
}
else if (XPathConstants.NUMBER == returnType &&
!(ret instanceof Double))
{
ret = new Double(_number(context, ret));
}
else if (XPathConstants.BOOLEAN == returnType &&
!(ret instanceof Boolean))
{
ret = _boolean(context, ret) ? Boolean.TRUE : Boolean.FALSE;
}
else if (XPathConstants.NODE == returnType)
{
if (ret instanceof Collection)
{
Collection ns = (Collection) ret;
switch (ns.size())
{
case 0:
ret = null;
break;
case 1:
ret = (Node) ns.iterator().next();
break;
default:
throw new XPathExpressionException("multiple nodes in node-set");
}
}
else if (ret != null)
{
throw new XPathExpressionException("return value is not a node-set");
}
}
else if (XPathConstants.NODESET == returnType)
{
if (ret != null && !(ret instanceof Collection))
{
throw new XPathExpressionException("return value is not a node-set");
}
}
}
return ret;
}
public String evaluate(Object item)
throws XPathExpressionException
{
return (String) evaluate(item, XPathConstants.STRING);
}
public Object evaluate(InputSource source, QName returnType)
throws XPathExpressionException
{
try
{
DocumentBuilderFactory factory =
new gnu.xml.dom.JAXPFactory();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(source);
return evaluate(doc, returnType);
}
catch (ParserConfigurationException e)
{
throw new XPathExpressionException(e);
}
catch (SAXException e)
{
throw new XPathExpressionException(e);
}
catch (IOException e)
{
throw new XPathExpressionException(e);
}
}
public String evaluate(InputSource source)
throws XPathExpressionException
{
return (String) evaluate(source, XPathConstants.STRING);
}
public abstract Object evaluate(Node context, int pos, int len);
public abstract Expr clone(Object context);
public abstract boolean references(QName var);
/* -- 4.1 Node Set Functions -- */
/**
* The id function selects elements by their unique ID.
* When the argument to id is of type node-set, then the result is
* the union of the result of applying id to the string-value of each of
* the nodes in the argument node-set. When the argument to id is of any
* other type, the argument is converted to a string as if by a call to
* the string function; the string is split into a whitespace-separated
* list of tokens (whitespace is any sequence of characters matching the
* production S); the result is a node-set containing the elements in the
* same document as the context node that have a unique ID equal to any of
* the tokens in the list.
*/
public static Collection _id(Node context, Object object)
{
Set ret = new HashSet();
if (object instanceof Collection)
{
Collection nodeSet = (Collection) object;
for (Iterator i = nodeSet.iterator(); i.hasNext(); )
{
String string = stringValue((Node) i.next());
ret.addAll(_id (context, string));
}
}
else
{
Document doc = (context instanceof Document) ? (Document) context :
context.getOwnerDocument();
String string = _string(context, object);
StringTokenizer st = new StringTokenizer(string, " \t\r\n");
while (st.hasMoreTokens())
{
Node element = doc.getElementById(st.nextToken());
if (element != null)
{
ret.add(element);
}
}
}
return ret;
}
/**
* The local-name function returns the local part of the expanded-name of
* the node in the argument node-set that is first in document order. If
* the argument node-set is empty or the first node has no expanded-name,
* an empty string is returned. If the argument is omitted, it defaults to
* a node-set with the context node as its only member.
*/
public static String _local_name(Node context, Collection nodeSet)
{
Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
firstNode(nodeSet);
return node.getLocalName();
}
/**
* The namespace-uri function returns the namespace URI of the
* expanded-name of the node in the argument node-set that is first in
* document order. If the argument node-set is empty, the first node has
* no expanded-name, or the namespace URI of the expanded-name is null, an
* empty string is returned. If the argument is omitted, it defaults to a
* node-set with the context node as its only member.
*/
public static String _namespace_uri(Node context, Collection nodeSet)
{
Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
firstNode(nodeSet);
return node.getNamespaceURI();
}
/**
* The name function returns a string containing a QName representing the
* expanded-name of the node in the argument node-set that is first in
* document order. The QName must represent the expanded-name with respect
* to the namespace declarations in effect on the node whose expanded-name
* is being represented. Typically, this will be the QName that occurred
* in the XML source. This need not be the case if there are namespace
* declarations in effect on the node that associate multiple prefixes
* with the same namespace. However, an implementation may include
* information about the original prefix in its representation of nodes;
* in this case, an implementation can ensure that the returned string is
* always the same as the QName used in the XML source. If the argument
* node-set is empty or the first node has no expanded-name, an empty
* string is returned. If the argument it omitted, it defaults to a
* node-set with the context node as its only member.
*/
public static String _name(Node context, Collection nodeSet)
{
Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
firstNode(nodeSet);
switch (node.getNodeType())
{
case Node.ATTRIBUTE_NODE:
case Node.ELEMENT_NODE:
case Node.PROCESSING_INSTRUCTION_NODE:
return node.getNodeName();
default:
return "";
}
}
/**
* Returns the first node in the set in document order.
*/
static Node firstNode(Collection nodeSet)
{
List list = new ArrayList(nodeSet);
Collections.sort(list, documentOrderComparator);
return (Node) list.get(0);
}
/* -- 4.2 String Functions -- */
/**
* Implementation of the XPath <code>string</code> function.
*/
public static String _string(Node context, Object object)
{
if (object == null)
{
return stringValue(context);
}
if (object instanceof String)
{
return (String) object;
}
if (object instanceof Boolean)
{
return object.toString();
}
if (object instanceof Double)
{
double d = ((Double) object).doubleValue();
if (Double.isNaN(d))
{
return "NaN";
}
else if (d == 0.0d)
{
return "0";
}
else if (Double.isInfinite(d))
{
if (d < 0)
{
return "-Infinity";
}
else
{
return "Infinity";
}
}
else
{
String ret = decimalFormat.format(d);
if (ret.endsWith (".0"))
{
ret = ret.substring(0, ret.length() - 2);
}
return ret;
}
}
if (object instanceof Collection)
{
Collection nodeSet = (Collection) object;
if (nodeSet.isEmpty())
{
return "";
}
Node node = firstNode(nodeSet);
return stringValue(node);
}
throw new IllegalArgumentException(object.toString());
}
/* -- 4.3 Boolean Functions -- */
/**
* Implementation of the XPath <code>boolean</code> function.
*/
public static boolean _boolean(Node context, Object object)
{
if (object instanceof Boolean)
{
return ((Boolean) object).booleanValue();
}
if (object instanceof Double)
{
return ((Double) object).doubleValue() != 0.0;
}
if (object instanceof String)
{
return ((String) object).length() != 0;
}
if (object instanceof Collection)
{
return ((Collection) object).size() != 0;
}
return false; // TODO user defined types
}
/* -- 4.4 Number Functions -- */
/**
* Implementation of the XPath <code>number</code> function.
*/
public static double _number(Node context, Object object)
{
if (object == null)
{
object = Collections.singleton(context);
}
if (object instanceof Double)
{
return ((Double) object).doubleValue();
}
if (object instanceof Boolean)
{
return ((Boolean) object).booleanValue() ? 1.0 : 0.0;
}
if (object instanceof Collection)
{
// Convert node-set to string
object = stringValue((Collection) object);
}
if (object instanceof String)
{
String string = ((String) object).trim();
try
{
return Double.parseDouble(string);
}
catch (NumberFormatException e)
{
return Double.NaN;
}
}
return Double.NaN; // TODO user-defined types
}
/**
* Computes the XPath string-value of the specified node-set.
*/
public static String stringValue(Collection nodeSet)
{
StringBuffer buf = new StringBuffer();
for (Iterator i = nodeSet.iterator(); i.hasNext(); )
{
buf.append(stringValue((Node) i.next()));
}
return buf.toString();
}
/**
* Computes the XPath string-value of the specified node.
*/
public static String stringValue(Node node)
{
return stringValue(node, false);
}
static String stringValue(Node node, boolean elementMode)
{
switch (node.getNodeType())
{
case Node.DOCUMENT_NODE: // 5.1 Root Node
case Node.DOCUMENT_FRAGMENT_NODE:
case Node.ELEMENT_NODE: // 5.2 Element Nodes
StringBuffer buf = new StringBuffer();
for (Node ctx = node.getFirstChild(); ctx != null;
ctx = ctx.getNextSibling())
{
buf.append(stringValue(ctx, true));
}
return buf.toString();
case Node.TEXT_NODE: // 5.7 Text Nodes
case Node.CDATA_SECTION_NODE:
return node.getNodeValue();
case Node.ATTRIBUTE_NODE: // 5.3 Attribute Nodes
case Node.PROCESSING_INSTRUCTION_NODE: // 5.5 Processing Instruction
case Node.COMMENT_NODE: // 5.6 Comment Nodes
if (!elementMode)
{
return node.getNodeValue();
}
default:
return "";
}
}
}
@@ -0,0 +1,72 @@
/* FalseFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>false</code> function returns false.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class FalseFunction
extends Expr
{
public Object evaluate(Node context, int pos, int len)
{
return Boolean.FALSE;
}
public Expr clone(Object context)
{
return new FalseFunction();
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
return "false()";
}
}
@@ -0,0 +1,89 @@
/* FloorFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>floor</code> function returns the largest (closest to positive
* infinity) number that is not greater than the argument and that is an
* integer.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class FloorFunction
extends Expr
{
final Expr arg;
FloorFunction(List args)
{
this((Expr) args.get(0));
}
FloorFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
double n = _number(context, val);
return new Double(Math.floor(n));
}
public Expr clone(Object context)
{
return new FloorFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "floor(" + arg + ")";
}
}
@@ -0,0 +1,57 @@
/* Function.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
/**
* Interface to be implemented by external functions that need to receive
* parameter values.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public interface Function
{
/**
* Sets the list of expressions to evaluate as parameter values.
*/
void setArguments(List args);
}
@@ -0,0 +1,163 @@
/* FunctionCall.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathFunction;
import javax.xml.xpath.XPathFunctionException;
import javax.xml.xpath.XPathFunctionResolver;
import org.w3c.dom.Node;
/**
* Executes an XPath core or extension function.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class FunctionCall
extends Expr
{
final XPathFunctionResolver resolver;
final String name;
final List args;
public FunctionCall(XPathFunctionResolver resolver, String name)
{
this(resolver, name, Collections.EMPTY_LIST);
}
public FunctionCall(XPathFunctionResolver resolver, String name, List args)
{
this.resolver = resolver;
this.name = name;
this.args = args;
}
public Object evaluate(Node context, int pos, int len)
{
if (resolver != null)
{
QName qname = QName.valueOf(name);
int arity = args.size();
XPathFunction function = resolver.resolveFunction(qname, arity);
if (function != null)
{
//System.err.println("Calling "+toString()+" with "+values);
if (function instanceof Expr)
{
if (function instanceof Function)
{
((Function) function).setArguments(args);
}
return ((Expr) function).evaluate(context, pos, len);
}
else
{
List values = new ArrayList(arity);
for (int i = 0; i < arity; i++)
{
Expr arg = (Expr) args.get(i);
values.add(arg.evaluate(context, pos, len));
}
try
{
return function.evaluate(values);
}
catch (XPathFunctionException e)
{
e.printStackTrace(System.err); // FIXME
throw new RuntimeException(e.getMessage(), e);
}
}
}
}
throw new IllegalArgumentException("Invalid function call: " +
toString());
}
public Expr clone(Object context)
{
int len = args.size();
List args2 = new ArrayList(len);
for (int i = 0; i < len; i++)
{
args2.add(((Expr) args.get(i)).clone(context));
}
XPathFunctionResolver r = resolver;
if (context instanceof XPathFunctionResolver)
{
r = (XPathFunctionResolver) context;
}
return new FunctionCall(r, name, args2);
}
public boolean references(QName var)
{
for (Iterator i = args.iterator(); i.hasNext(); )
{
if (((Expr) i.next()).references(var))
{
return true;
}
}
return false;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
buf.append(name);
buf.append('(');
int len = args.size();
for (int i = 0; i < len; i++)
{
if (i > 0)
{
buf.append(',');
}
buf.append(args.get(i));
}
buf.append(')');
return buf.toString();
}
}
@@ -0,0 +1,102 @@
/* IdFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>id</code> function selects elements by their unique ID.
* When the argument to id is of type node-set, then the result is
* the union of the result of applying id to the string-value of each of the
* nodes in the argument node-set. When the argument to id is of any other
* type, the argument is converted to a string as if by a call to the string
* function; the string is split into a whitespace-separated list of tokens
* (whitespace is any sequence of characters matching the production S); the
* result is a node-set containing the elements in the same document as the
* context node that have a unique ID equal to any of the tokens in the
* list.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class IdFunction
extends Pattern
{
final Expr arg;
IdFunction(List args)
{
this((Expr) args.get(0));
}
public IdFunction(Expr arg)
{
this.arg = arg;
}
public boolean matches(Node context)
{
Object ret = evaluate(context, 1, 1);
return !((Collection) ret).isEmpty();
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
return _id(context, val);
}
public Expr clone(Object context)
{
return new IdFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "id(" + arg + ")";
}
}
@@ -0,0 +1,116 @@
/* LangFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* The <code>lang</code> function returns true or false depending on whether
* the language of the context node as specified by xml:lang attributes is
* the same as or is a sublanguage of the language specified by the argument
* string. The language of the context node is determined by the value of
* the xml:lang attribute on the context node, or, if the context node has
* no xml:lang attribute, by the value of the xml:lang attribute on the
* nearest ancestor of the context node that has an xml:lang attribute. If
* there is no such attribute, then lang returns false. If there is such an
* attribute, then lang returns true if the attribute value is equal to the
* argument ignoring case, or if there is some suffix starting with - such
* that the attribute value is equal to the argument ignoring that suffix of
* the attribute value and ignoring case.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class LangFunction
extends Expr
{
final Expr arg;
LangFunction(List args)
{
this((Expr) args.get(0));
}
LangFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
String lang = _string(context, val);
String clang = getLang(context);
while (clang == null && context != null)
{
context = context.getParentNode();
clang = getLang(context);
}
boolean ret = (clang == null) ? false :
clang.toLowerCase().startsWith(lang.toLowerCase());
return ret ? Boolean.TRUE : Boolean.FALSE;
}
String getLang(Node node)
{
if (node.getNodeType() == Node.ELEMENT_NODE)
{
return ((Element) node).getAttribute("xml:lang");
}
return null;
}
public Expr clone(Object context)
{
return new IdFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "lang(" + arg + ")";
}
}
@@ -0,0 +1,73 @@
/* LastFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>last</code> function returns a number equal to the context
* size from the expression evaluation context.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class LastFunction
extends Expr
{
public Object evaluate(Node context, int pos, int len)
{
return new Double((double) len);
}
public Expr clone(Object context)
{
return new LastFunction();
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
return "last()";
}
}
@@ -0,0 +1,93 @@
/* LocalNameFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>local-name</code> function returns the local part of the
* expanded-name of the node in the argument node-set that is first in
* document order.
* If the argument node-set is empty or the first node has no expanded-name,
* an empty string is returned. If the argument is omitted, it defaults to a
* node-set with the context node as its only member.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class LocalNameFunction
extends Expr
{
final Expr arg;
LocalNameFunction(List args)
{
this(args.size() > 0 ? (Expr) args.get(0) : null);
}
LocalNameFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
return _local_name(context, (Collection) val);
}
public Expr clone(Object context)
{
return new LocalNameFunction((arg == null) ? null :
arg.clone(context));
}
public boolean references(QName var)
{
return (arg == null) ? false : arg.references(var);
}
public String toString()
{
return (arg == null) ? "local-name()" : "local-name(" + arg + ")";
}
}
@@ -0,0 +1,101 @@
/* NameFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>name</code> function returns a string containing a QName
* representing the expanded-name of the node in the argument node-set that
* is first in document order. The QName must represent the expanded-name
* with respect to the namespace declarations in effect on the node whose
* expanded-name is being represented. Typically, this will be the QName
* that occurred in the XML source. This need not be the case if there are
* namespace declarations in effect on the node that associate multiple
* prefixes with the same namespace. However, an implementation may include
* information about the original prefix in its representation of nodes; in
* this case, an implementation can ensure that the returned string is
* always the same as the QName used in the XML source. If the argument
* node-set is empty or the first node has no expanded-name, an empty string
* is returned. If the argument it omitted, it defaults to a node-set with
* the context node as its only member.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class NameFunction
extends Expr
{
final Expr arg;
NameFunction(List args)
{
this(args.size() > 0 ? (Expr) args.get(0) : null);
}
NameFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
return _name(context, (Collection) val);
}
public Expr clone(Object context)
{
return new NameFunction((arg == null) ? null :
arg.clone(context));
}
public boolean references(QName var)
{
return (arg == null) ? false : arg.references(var);
}
public String toString()
{
return (arg == null) ? "name()" : "name(" + arg + ")";
}
}
@@ -0,0 +1,142 @@
/* NameTest.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Tests whether a node has the specified name.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class NameTest
extends Test
{
final QName qName;
final boolean anyLocalName;
final boolean any;
public NameTest(QName qName, boolean anyLocalName, boolean any)
{
this.anyLocalName = anyLocalName;
this.any = any;
this.qName = qName;
}
public boolean matchesAny()
{
return any;
}
public boolean matchesAnyLocalName()
{
return anyLocalName;
}
public boolean matches(Node node, int pos, int len)
{
switch (node.getNodeType())
{
case Node.ATTRIBUTE_NODE:
// Do not match namespace attributes
String uri = node.getNamespaceURI();
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getPrefix()) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getNodeName()))
{
return false;
}
// Fall through
case Node.ELEMENT_NODE:
break;
default:
return false;
}
if (any)
{
return true;
}
String uri = qName.getNamespaceURI();
String nodeUri = node.getNamespaceURI();
String nodeLocalName = node.getLocalName();
if (nodeLocalName != null && !equal(uri, nodeUri))
{
return false;
}
if (anyLocalName)
{
return true;
}
String localName = qName.getLocalPart();
if (nodeLocalName != null)
{
nodeLocalName = node.getNodeName();
}
return (localName.equals(nodeLocalName));
}
final boolean equal(String s1, String s2)
{
return (((s1 == null || s1.length() == 0) &&
(s2 == null || s2.length() == 0)) ||
s1 != null && s1.equals(s2));
}
public Test clone(Object context)
{
return new NameTest(qName, anyLocalName, any);
}
public boolean references(QName var)
{
return false;
}
public String toString ()
{
if (any)
{
return "*";
}
return qName.toString();
}
}
@@ -0,0 +1,128 @@
/* NamespaceTest.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Tests whether a namespace attribute has the specified name.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class NamespaceTest
extends Test
{
final QName qName;
final boolean anyLocalName;
final boolean any;
public NamespaceTest(QName qName, boolean anyLocalName, boolean any)
{
this.anyLocalName = anyLocalName;
this.any = any;
this.qName = qName;
}
public boolean matchesAny()
{
return any;
}
public boolean matchesAnyLocalName()
{
return anyLocalName;
}
public boolean matches(Node node, int pos, int len)
{
switch (node.getNodeType())
{
case Node.ATTRIBUTE_NODE:
// Only match namespace attributes
String uri = node.getNamespaceURI();
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getPrefix()) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getNodeName()))
{
break;
}
// Fall through
default:
// Only process namespace attributes
return false;
}
if (any)
{
return true;
}
if (anyLocalName)
{
return true;
}
String localName = qName.getLocalPart();
String nodeLocalName = node.getLocalName();
if (nodeLocalName == null)
{
nodeLocalName = node.getNodeName();
}
return (localName.equals(nodeLocalName));
}
public Test clone(Object context)
{
return new NamespaceTest(qName, anyLocalName, any);
}
public boolean references(QName var)
{
return false;
}
public String toString ()
{
if (any)
{
return "*";
}
return qName.toString();
}
}
@@ -0,0 +1,93 @@
/* NamespaceUriFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>namespace-uri</code> function returns the namespace URI of the
* expanded-name of the node in the argument node-set that is first in
* document order. If the argument node-set is empty, the first node has no
* expanded-name, or the namespace URI of the expanded-name is null, an
* empty string is returned. If the argument is omitted, it defaults to a
* node-set with the context node as its only member.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class NamespaceUriFunction
extends Expr
{
final Expr arg;
NamespaceUriFunction(List args)
{
this(args.size() > 0 ? (Expr) args.get(0) : null);
}
NamespaceUriFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
return _namespace_uri(context, (Collection) val);
}
public Expr clone(Object context)
{
return new NamespaceUriFunction((arg == null) ? null :
arg.clone(context));
}
public boolean references(QName var)
{
return (arg == null) ? false : arg.references(var);
}
public String toString()
{
return (arg == null) ? "namespace-uri()" : "namespace-uri(" + arg + ")";
}
}
@@ -0,0 +1,81 @@
/* NegativeExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Unary negative.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class NegativeExpr
extends Expr
{
final Expr expr;
NegativeExpr(Expr expr)
{
this.expr = expr;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = expr.evaluate(context, pos, len);
double n = _number(context, val);
return new Double(-n);
}
public Expr clone(Object context)
{
return new NegativeExpr(expr.clone(context));
}
public boolean references(QName var)
{
return expr.references(var);
}
public String toString()
{
return "-" + expr;
}
}
@@ -0,0 +1,136 @@
/* NodeTypeTest.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Tests whether a node is of a given type.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class NodeTypeTest
extends Test
{
final short type;
final String data;
public NodeTypeTest(short type)
{
this(type, null);
}
public NodeTypeTest(short type, String data)
{
this.type = type;
this.data = data;
}
public short getNodeType()
{
return type;
}
public String getData()
{
return data;
}
public boolean matches(Node node, int pos, int len)
{
short nodeType = node.getNodeType();
switch (nodeType)
{
case Node.ELEMENT_NODE:
case Node.ATTRIBUTE_NODE:
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
case Node.COMMENT_NODE:
case Node.PROCESSING_INSTRUCTION_NODE:
if (type > 0)
{
if (nodeType != type)
{
return false;
}
if (data != null && !data.equals(node.getNodeValue()))
{
return false;
}
}
return true;
default:
// Not part of XPath data model
return false;
}
}
public Test clone(Object context)
{
return new NodeTypeTest(type, data);
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
switch (type)
{
case 0:
return "node()";
case Node.TEXT_NODE:
return "text()";
case Node.COMMENT_NODE:
return "comment()";
case Node.PROCESSING_INSTRUCTION_NODE:
if (data != null)
{
return "processing-instruction('" + data + "')";
}
return "processing-instruction()";
default:
throw new IllegalStateException();
}
}
}
@@ -0,0 +1,105 @@
/* NormalizeSpaceFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>normalize-space</code> function returns the argument string
* with whitespace normalized by stripping leading and trailing whitespace
* and replacing sequences of whitespace characters by a single space.
* Whitespace characters are the same as those allowed by the S production
* in XML. If the argument is omitted, it defaults to the context node
* converted to a string, in other words the string-value of the context
* node.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class NormalizeSpaceFunction
extends Expr
{
final Expr arg;
NormalizeSpaceFunction(List args)
{
this((Expr) args.get(0));
}
NormalizeSpaceFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
String s = _string(context, val);
StringTokenizer st = new StringTokenizer(s, " \t\r\n");
StringBuffer buf = new StringBuffer();
if (st.hasMoreTokens())
{
buf.append(st.nextToken());
while (st.hasMoreTokens())
{
buf.append(' ');
buf.append(st.nextToken());
}
}
return buf.toString();
}
public Expr clone(Object context)
{
return new NormalizeSpaceFunction(arg.clone(context));
}
public boolean references(QName var)
{
return (arg == null) ? false : arg.references(var);
}
public String toString()
{
return (arg == null) ? "normalize-space()" : "normalize-space(" + arg + ")";
}
}
@@ -0,0 +1,87 @@
/* NotFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>not</code> function returns true if its argument is false,
* and false otherwise.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class NotFunction
extends Expr
{
final Expr arg;
NotFunction(List args)
{
this((Expr) args.get(0));
}
NotFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
return _boolean(context, val) ? Boolean.FALSE : Boolean.TRUE;
}
public Expr clone(Object context)
{
return new NotFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "not(" + arg + ")";
}
}
@@ -0,0 +1,102 @@
/* NumberFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>number</code> function converts its argument to a number as
* follows:
* <ul>
* <li>a string that consists of optional whitespace followed by an optional
* minus sign followed by a Number followed by whitespace is converted to
* the IEEE 754 number that is nearest (according to the IEEE 754
* round-to-nearest rule) to the mathematical value represented by the
* string; any other string is converted to NaN</li>
* <li>boolean true is converted to 1; boolean false is converted to 0</li>
* <li>a node-set is first converted to a string as if by a call to the
* string function and then converted in the same way as a string
* argument</li>
* <li>an object of a type other than the four basic types is converted to a
* number in a way that is dependent on that type</li>
* </ul>
* If the argument is omitted, it defaults to a node-set with the context
* node as its only member.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class NumberFunction
extends Expr
{
final Expr arg;
NumberFunction(List args)
{
this(args.size() > 0 ? (Expr) args.get(0) : null);
}
NumberFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
return new Double(_number(context, val));
}
public Expr clone(Object context)
{
return new NumberFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "number(" + arg + ")";
}
}
@@ -0,0 +1,87 @@
/* OrExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Logical or.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class OrExpr
extends Expr
{
final Expr lhs;
final Expr rhs;
public OrExpr(Expr lhs, Expr rhs)
{
this.lhs = lhs;
this.rhs = rhs;
}
public Object evaluate(Node context, int pos, int len)
{
Object left = lhs.evaluate(context, pos, len);
if (_boolean(context, left))
{
return Boolean.TRUE;
}
Object right = rhs.evaluate(context, pos, len);
return _boolean(context, right) ? Boolean.TRUE : Boolean.FALSE;
}
public Expr clone(Object context)
{
return new OrExpr(lhs.clone(context), rhs.clone(context));
}
public boolean references(QName var)
{
return (lhs.references(var) || rhs.references(var));
}
public String toString()
{
return lhs + " or " + rhs;
}
}
@@ -0,0 +1,90 @@
/* ParenthesizedExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Simple subexpression.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class ParenthesizedExpr
extends Expr
{
final Expr expr;
ParenthesizedExpr(Expr expr)
{
this.expr = expr;
}
public Object evaluate(Node context, int pos, int len)
{
Object ret = expr.evaluate(context, pos, len);
if (ret instanceof Collection)
{
List list = new ArrayList((Collection) ret);
Collections.sort(list, documentOrderComparator);
ret = list;
}
return ret;
}
public Expr clone(Object context)
{
return new ParenthesizedExpr(expr.clone(context));
}
public boolean references(QName var)
{
return expr.references(var);
}
public String toString()
{
return "(" + expr + ")";
}
}
+54
View File
@@ -0,0 +1,54 @@
/* Path.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import org.w3c.dom.Node;
/**
* An XPath path component expression.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
abstract class Path
extends Pattern
{
abstract Collection evaluate(Node context, Collection nodeSet);
}
@@ -0,0 +1,54 @@
/* Pattern.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import org.w3c.dom.Node;
/**
* Interface implemented by expressions that can form part of XSL patterns.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public abstract class Pattern
extends Expr
{
public abstract boolean matches(Node context);
}
@@ -0,0 +1,73 @@
/* PositionFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>position</code> function returns a number equal to the context
* position from the expression evaluation context.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class PositionFunction
extends Expr
{
public Object evaluate(Node context, int pos, int len)
{
return new Double((double) pos);
}
public Expr clone(Object context)
{
return new PositionFunction();
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
return "position()";
}
}
@@ -0,0 +1,85 @@
/* Predicate.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Tests whether an expression matches against a given context node.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
class Predicate
extends Test
{
final Expr expr;
Predicate(Expr expr)
{
this.expr = expr;
}
public boolean matches(Node node, int pos, int len)
{
Object ret = expr.evaluate(node, pos, len);
if (ret instanceof Double)
{
// Same as [position() = x]
return ((Double) ret).intValue() == pos;
}
return Expr._boolean(node, expr.evaluate(node, pos, len));
}
public Test clone(Object context)
{
return new Predicate(expr.clone(context));
}
public boolean references(QName var)
{
return expr.references(var);
}
public String toString()
{
return "[" + expr + "]";
}
}
@@ -0,0 +1,107 @@
/* RelationalExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* Numerical comparison expression.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class RelationalExpr
extends Expr
{
final Expr lhs;
final Expr rhs;
final boolean lt;
final boolean eq;
RelationalExpr(Expr lhs, Expr rhs, boolean lt, boolean eq)
{
this.lhs = lhs;
this.rhs = rhs;
this.lt = lt;
this.eq = eq;
}
public Object evaluate(Node context, int pos, int len)
{
Object left = lhs.evaluate(context, pos, len);
Object right = rhs.evaluate(context, pos, len);
double ln = _number(context, left);
double rn = _number(context, right);
if (eq && ln == rn)
{
return Boolean.TRUE;
}
if (lt)
{
if (ln < rn || Double.isInfinite(rn))
{
return Boolean.TRUE;
}
}
else
{
if (ln > rn || Double.isInfinite(ln))
{
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
public Expr clone(Object context)
{
return new RelationalExpr(lhs.clone(context), rhs.clone(context), lt, eq);
}
public boolean references(QName var)
{
return (lhs.references(var) || rhs.references(var));
}
public String toString()
{
return lhs + " " + (lt ? "<" : ">") + (eq ? "=" : "") + " " + rhs;
}
}
+87
View File
@@ -0,0 +1,87 @@
/* Root.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.Collections;
import javax.xml.namespace.QName;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* Expression that evaluates to the document root.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class Root
extends Path
{
public boolean matches(Node node)
{
return (node.getNodeType() == Node.DOCUMENT_NODE);
}
public Object evaluate(Node context, int pos, int len)
{
return evaluate(context, Collections.EMPTY_SET);
}
Collection evaluate(Node context, Collection ns)
{
Document doc = (context instanceof Document) ? (Document) context :
context.getOwnerDocument();
return Collections.singleton(doc);
}
public Expr clone(Object context)
{
return new Root();
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
return "/";
}
}
@@ -0,0 +1,96 @@
/* RoundFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>round</code> function returns the number that is closest to the
* argument and that is an integer. If there are two such numbers, then the
* one that is closest to positive infinity is returned. If the argument is
* NaN, then NaN is returned. If the argument is positive infinity, then
* positive infinity is returned. If the argument is negative infinity, then
* negative infinity is returned. If the argument is positive zero, then
* positive zero is returned. If the argument is negative zero, then
* negative zero is returned. If the argument is less than zero, but greater
* than or equal to -0.5, then negative zero is returned.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class RoundFunction
extends Expr
{
final Expr arg;
RoundFunction(List args)
{
this((Expr) args.get(0));
}
RoundFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
double n = _number(context, val);
return (Double.isNaN(n) || Double.isInfinite(n)) ?
new Double(n) : new Double(Math.round(n));
}
public Expr clone(Object context)
{
return new RoundFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "round(" + arg + ")";
}
}
@@ -0,0 +1,519 @@
/* Selector.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import org.w3c.dom.Attr;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* A single component of a location path.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class Selector
extends Path
{
public static final int ANCESTOR = 0;
public static final int ANCESTOR_OR_SELF = 1;
public static final int ATTRIBUTE = 2;
public static final int CHILD = 3;
public static final int DESCENDANT = 4;
public static final int DESCENDANT_OR_SELF = 5;
public static final int FOLLOWING = 6;
public static final int FOLLOWING_SIBLING = 7;
public static final int NAMESPACE = 8;
public static final int PARENT = 9;
public static final int PRECEDING = 10;
public static final int PRECEDING_SIBLING = 11;
public static final int SELF = 12;
/**
* Axis to select nodes in.
*/
final int axis;
/**
* List of tests to perform on candidates.
*/
final Test[] tests;
public Selector(int axis, List tests)
{
this.axis = axis;
this.tests = new Test[tests.size()];
tests.toArray(this.tests);
if (axis == NAMESPACE &&
this.tests.length > 0 &&
this.tests[0] instanceof NameTest)
{
NameTest nt = (NameTest) this.tests[0];
this.tests[0] = new NamespaceTest(nt.qName, nt.anyLocalName, nt.any);
}
}
/**
* Returns the list of tests to perform on candidates.
*/
public Test[] getTests()
{
return tests;
}
public boolean matches(Node context)
{
short nodeType = context.getNodeType();
switch (axis)
{
case CHILD:
if (nodeType == Node.ATTRIBUTE_NODE)
{
return false;
}
break;
case ATTRIBUTE:
case NAMESPACE:
if (nodeType != Node.ATTRIBUTE_NODE)
{
return false;
}
break;
case DESCENDANT_OR_SELF:
return true;
default:
return false;
}
int tlen = tests.length;
if (tlen > 0)
{
int pos = getContextPosition(context);
int len = getContextSize(context);
for (int j = 0; j < tlen && len > 0; j++)
{
Test test = tests[j];
if (!test.matches(context, pos, len))
{
return false;
}
}
}
return true;
}
private int getContextPosition(Node ctx)
{
int pos = 1;
for (ctx = ctx.getPreviousSibling(); ctx != null;
ctx = ctx.getPreviousSibling())
{
pos++;
}
return pos;
}
private int getContextSize(Node ctx)
{
if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
{
Node parent = ((Attr) ctx).getOwnerElement();
return parent.getAttributes().getLength();
}
Node parent = ctx.getParentNode();
if (parent != null)
{
return parent.getChildNodes().getLength();
}
return 1;
}
public Object evaluate(Node context, int pos, int len)
{
Set acc = new LinkedHashSet();
addCandidates(context, acc);
List candidates = new ArrayList(acc);
//Collections.sort(candidates, documentOrderComparator);
List ret = filterCandidates(candidates, false);
return ret;
}
Collection evaluate(Node context, Collection ns)
{
Set acc = new LinkedHashSet();
for (Iterator i = ns.iterator(); i.hasNext(); )
{
addCandidates((Node) i.next(), acc);
}
List candidates = new ArrayList(acc);
//Collections.sort(candidates, documentOrderComparator);
List ret = filterCandidates(candidates, true);
return ret;
}
/**
* Filter the given list of candidates according to the node tests.
*/
List filterCandidates(List candidates, boolean cascade)
{
int len = candidates.size();
int tlen = tests.length;
if (tlen > 0 && len > 0)
{
// Present the result of each successful generation to the next test
for (int j = 0; j < tlen && len > 0; j++)
{
Test test = tests[j];
List successful = new ArrayList(len);
for (int i = 0; i < len; i++)
{
Node node = (Node) candidates.get(i);
if (cascade)
{
// Documents and DocumentFragments should be considered
// if part of a location path where the axis involves
// the SELF concept
short nodeType = node.getNodeType();
if ((nodeType == Node.DOCUMENT_NODE ||
nodeType == Node.DOCUMENT_FRAGMENT_NODE) &&
(axis == DESCENDANT_OR_SELF ||
axis == ANCESTOR_OR_SELF ||
axis == SELF) &&
(tests.length == 1 &&
tests[0] instanceof NodeTypeTest &&
((NodeTypeTest) tests[0]).type == (short) 0))
{
successful.add(node);
continue;
}
}
if (test.matches(node, i + 1, len))
{
successful.add(node);
}
/*
System.err.println("Testing "+node);
int p = getContextPosition(node);
int l = getContextSize(node);
if (test.matches(node, p, l))
{
successful.add(node);
}*/
}
candidates = successful;
len = candidates.size();
}
}
return candidates;
}
void addCandidates(Node context, Collection candidates)
{
// Build list of candidates
switch (axis)
{
case CHILD:
addChildNodes(context, candidates, false);
break;
case DESCENDANT:
addChildNodes(context, candidates, true);
break;
case DESCENDANT_OR_SELF:
candidates.add (context);
addChildNodes(context, candidates, true);
break;
case PARENT:
addParentNode(context, candidates, false);
break;
case ANCESTOR:
addParentNode(context, candidates, true);
break;
case ANCESTOR_OR_SELF:
candidates.add(context);
addParentNode(context, candidates, true);
break;
case FOLLOWING_SIBLING:
addFollowingNodes(context, candidates, false);
break;
case PRECEDING_SIBLING:
addPrecedingNodes(context, candidates, false);
break;
case FOLLOWING:
addFollowingNodes(context, candidates, true);
break;
case PRECEDING:
addPrecedingNodes(context, candidates, true);
break;
case ATTRIBUTE:
addAttributes(context, candidates);
break;
case NAMESPACE:
addNamespaceAttributes(context, candidates);
break;
case SELF:
candidates.add(context);
break;
}
}
void addChildNodes(Node context, Collection acc, boolean recurse)
{
Node child = context.getFirstChild();
while (child != null)
{
acc.add(child);
if (recurse)
{
addChildNodes(child, acc, recurse);
}
child = child.getNextSibling();
}
}
void addParentNode(Node context, Collection acc, boolean recurse)
{
Node parent = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
((Attr) context).getOwnerElement() : context.getParentNode();
if (parent != null)
{
acc.add(parent);
if (recurse)
{
addParentNode(parent, acc, recurse);
}
}
}
void addFollowingNodes(Node context, Collection acc, boolean recurse)
{
Node cur = context.getNextSibling();
while (cur != null)
{
acc.add(cur);
if (recurse)
{
addChildNodes(cur, acc, true);
}
cur = cur.getNextSibling();
}
if (recurse)
{
context = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
((Attr) context).getOwnerElement() : context.getParentNode();
if (context != null)
{
addFollowingNodes(context, acc, recurse);
}
}
}
void addPrecedingNodes(Node context, Collection acc, boolean recurse)
{
Node cur = context.getPreviousSibling();
while (cur != null)
{
acc.add(cur);
if (recurse)
{
addChildNodes(cur, acc, true);
}
cur = cur.getPreviousSibling();
}
if (recurse)
{
context = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
((Attr) context).getOwnerElement() : context.getParentNode();
if (context != null)
{
addPrecedingNodes(context, acc, recurse);
}
}
}
void addAttributes(Node context, Collection acc)
{
NamedNodeMap attrs = context.getAttributes();
if (attrs != null)
{
int attrLen = attrs.getLength();
for (int i = 0; i < attrLen; i++)
{
Node attr = attrs.item(i);
if (!isNamespaceAttribute(attr))
{
acc.add(attr);
}
}
}
}
void addNamespaceAttributes(Node context, Collection acc)
{
NamedNodeMap attrs = context.getAttributes();
if (attrs != null)
{
int attrLen = attrs.getLength();
for (int i = 0; i < attrLen; i++)
{
Node attr = attrs.item(i);
if (isNamespaceAttribute(attr))
{
acc.add(attr);
}
}
}
}
final boolean isNamespaceAttribute(Node node)
{
String uri = node.getNamespaceURI();
return (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getPrefix()) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getNodeName()));
}
public Expr clone(Object context)
{
int len = tests.length;
List tests2 = new ArrayList(len);
for (int i = 0; i < len; i++)
{
tests2.add(tests[i].clone(context));
}
return new Selector(axis, tests2);
}
public boolean references(QName var)
{
for (int i = 0; i < tests.length; i++)
{
if (tests[i].references(var))
{
return true;
}
}
return false;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
switch (axis)
{
case ANCESTOR:
buf.append("ancestor::");
break;
case ANCESTOR_OR_SELF:
buf.append("ancestor-or-self::");
break;
case ATTRIBUTE:
if (tests.length == 0 ||
(tests[0] instanceof NameTest))
{
buf.append('@');
}
else
{
buf.append("attribute::");
}
break;
case CHILD:
//buf.append("child::");
break;
case DESCENDANT:
buf.append("descendant::");
break;
case DESCENDANT_OR_SELF:
buf.append("descendant-or-self::");
break;
case FOLLOWING:
buf.append("following::");
break;
case FOLLOWING_SIBLING:
buf.append("following-sibling::");
break;
case NAMESPACE:
buf.append("namespace::");
break;
case PARENT:
if (tests.length == 0 ||
(tests[0] instanceof NodeTypeTest &&
((NodeTypeTest) tests[0]).type == 0))
{
return "..";
}
buf.append("parent::");
break;
case PRECEDING:
buf.append("preceding::");
break;
case PRECEDING_SIBLING:
buf.append("preceding-sibling::");
break;
case SELF:
if (tests.length == 0 ||
(tests[0] instanceof NodeTypeTest &&
((NodeTypeTest) tests[0]).type == 0))
{
return ".";
}
buf.append("self::");
break;
}
if (tests.length == 0)
{
buf.append('*');
}
else
{
for (int i = 0; i < tests.length; i++)
{
buf.append(tests[i]);
}
}
return buf.toString();
}
}
@@ -0,0 +1,92 @@
/* StartsWithFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>starts-with</code> function returns true if the first argument
* string starts with the second argument string, and otherwise returns false.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class StartsWithFunction
extends Expr
{
final Expr arg1;
final Expr arg2;
StartsWithFunction(List args)
{
this((Expr) args.get(0), (Expr) args.get(1));
}
StartsWithFunction(Expr arg1, Expr arg2)
{
this.arg1 = arg1;
this.arg2 = arg2;
}
public Object evaluate(Node context, int pos, int len)
{
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
String s1 = _string(context, val1);
String s2 = _string(context, val2);
return s1.startsWith(s2) ? Boolean.TRUE : Boolean.FALSE;
}
public Expr clone(Object context)
{
return new StartsWithFunction(arg1.clone(context), arg2.clone(context));
}
public boolean references(QName var)
{
return (arg1.references(var) || arg2.references(var));
}
public String toString()
{
return "starts-with(" + arg1 + "," + arg2 + ")";
}
}
+253
View File
@@ -0,0 +1,253 @@
/* Steps.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
import javax.xml.namespace.QName;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
/**
* A list of transitions between components in a location path.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class Steps
extends Path
{
final LinkedList path;
public Steps()
{
this(new LinkedList());
}
Steps(LinkedList path)
{
this.path = path;
}
public boolean matches(Node context)
{
// Right to left
return matches(context, path.size() - 1);
}
boolean matches(Node context, int pos)
{
Pattern right = (Pattern) path.get(pos);
if (!right.matches(context))
{
return false;
}
if (pos > 0)
{
Pattern left = (Pattern) path.get(pos - 1);
Iterator j = possibleContexts(right, context).iterator();
while (j.hasNext())
{
Node candidate = (Node) j.next();
if (left.matches(candidate) &&
matches(candidate, pos - 1))
{
return true;
}
// keep going, there may be another candidate
}
return false;
}
return true;
}
/**
* Essentially the reverse of Selector.addCandidates.
* The idea is to determine possible context nodes for a match.
*/
Collection possibleContexts(Pattern pattern, Node context)
{
if (pattern instanceof Selector)
{
Selector s = (Selector) pattern;
Collection candidates = new LinkedHashSet();
switch (s.axis)
{
case Selector.PARENT:
s.addChildNodes(context, candidates, false);
break;
case Selector.ANCESTOR:
s.addChildNodes(context, candidates, true);
break;
case Selector.ANCESTOR_OR_SELF:
candidates.add (context);
s.addChildNodes(context, candidates, true);
break;
case Selector.CHILD:
s.addParentNode(context, candidates, false);
break;
case Selector.DESCENDANT:
s.addParentNode(context, candidates, true);
break;
case Selector.DESCENDANT_OR_SELF:
candidates.add(context);
s.addParentNode(context, candidates, true);
break;
case Selector.PRECEDING_SIBLING:
s.addFollowingNodes(context, candidates, false);
break;
case Selector.FOLLOWING_SIBLING:
s.addPrecedingNodes(context, candidates, false);
break;
case Selector.PRECEDING:
s.addFollowingNodes(context, candidates, true);
break;
case Selector.FOLLOWING:
s.addPrecedingNodes(context, candidates, true);
break;
case Selector.ATTRIBUTE:
case Selector.NAMESPACE:
if (context.getNodeType() == Node.ATTRIBUTE_NODE)
{
candidates.add(((Attr) context).getOwnerElement());
}
break;
case Selector.SELF:
candidates.add(context);
break;
}
return candidates;
}
return Collections.EMPTY_SET;
}
public Object evaluate(Node context, int pos, int len)
{
//System.err.println(toString()+" evaluate");
// Left to right
Iterator i = path.iterator();
Expr lhs = (Expr) i.next();
Object val = lhs.evaluate(context, pos, len);
//System.err.println("\tevaluate "+lhs+" = "+val);
while (val instanceof Collection && i.hasNext())
{
Path rhs = (Path) i.next();
val = rhs.evaluate(context, (Collection) val);
//System.err.println("\tevaluate "+rhs+" = "+val);
}
return val;
}
Collection evaluate(Node context, Collection ns)
{
// Left to right
Iterator i = path.iterator();
Expr lhs = (Expr) i.next();
if (lhs instanceof Path)
{
ns = ((Path) lhs).evaluate(context, ns);
}
else
{
Set acc = new LinkedHashSet();
int pos = 1, len = ns.size();
for (Iterator j = ns.iterator(); j.hasNext(); )
{
Node node = (Node) j.next();
Object ret = lhs.evaluate(node, pos++, len);
if (ret instanceof Collection)
{
acc.addAll((Collection) ret);
}
}
ns = acc;
}
while (i.hasNext())
{
Path rhs = (Path) i.next();
ns = rhs.evaluate(context, ns);
}
return ns;
}
public Expr clone(Object context)
{
int len = path.size();
LinkedList path2 = new LinkedList();
for (int i = 0; i < len; i++)
{
path2.add(((Expr) path.get(i)).clone(context));
}
return new Steps(path2);
}
public boolean references(QName var)
{
for (Iterator i = path.iterator(); i.hasNext(); )
{
if (((Expr) i.next()).references(var))
{
return true;
}
}
return false;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
Iterator i = path.iterator();
Expr expr = (Expr) i.next();
if (!(expr instanceof Root))
{
buf.append(expr);
}
while (i.hasNext())
{
expr = (Expr) i.next();
buf.append('/');
buf.append(expr);
}
return buf.toString();
}
}
@@ -0,0 +1,119 @@
/* StringFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>string function converts an object to a string as follows:
* <ul>
* <li>A node-set is converted to a string by returning the string-value of
* the node in the node-set that is first in document order. If the node-set
* is empty, an empty string is returned.</li>
* <li>A number is converted to a string as follows
* <ul>
* <li>NaN is converted to the string NaN</li>
* <li>positive zero is converted to the string 0</li>
* <li>negative zero is converted to the string 0</li>
* <li>positive infinity is converted to the string Infinity</li>
* <li>negative infinity is converted to the string -Infinity</li>
* <li>if the number is an integer, the number is represented in decimal
* form as a Number with no decimal point and no leading zeros, preceded by
* a minus sign (-) if the number is negative</li>
* <li>otherwise, the number is represented in decimal form as a Number
* including a decimal point with at least one digit before the decimal
* point and at least one digit after the decimal point, preceded by a minus
* sign (-) if the number is negative; there must be no leading zeros before
* the decimal point apart possibly from the one required digit immediately
* before the decimal point; beyond the one required digit after the decimal
* point there must be as many, but only as many, more digits as are needed
* to uniquely distinguish the number from all other IEEE 754 numeric
* values.</li>
* </ul>
* </li>
* <li>The boolean false value is converted to the string false. The boolean
* true value is converted to the string true.</li>
* <li>An object of a type other than the four basic types is converted to a
* string in a way that is dependent on that type.</li>
* </ul>
* If the argument is omitted, it defaults to a node-set with the context
* node as its only member.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class StringFunction
extends Expr
{
final Expr arg;
StringFunction(List args)
{
this(args.size() > 0 ? (Expr) args.get(0) : null);
}
StringFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
return _string(context, val);
}
public Expr clone(Object context)
{
return new StringFunction((arg == null) ? null :
arg.clone(context));
}
public boolean references(QName var)
{
return (arg == null) ? false : arg.references(var);
}
public String toString()
{
return (arg == null) ? "string()" : "string(" + arg + ")";
}
}
@@ -0,0 +1,91 @@
/* StringLengthFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>string-length</code> function returns the number of characters
* in the string.
* If the argument is omitted, it defaults to the context node converted to
* a string, in other words the string-value of the context node.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class StringLengthFunction
extends Expr
{
final Expr arg;
StringLengthFunction(List args)
{
this(args.isEmpty() ? null : (Expr) args.get(0));
}
StringLengthFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
String s = _string(context, val);
return new Double((double) s.length());
}
public Expr clone(Object context)
{
return new StringLengthFunction((arg == null) ? null :
arg.clone(context));
}
public boolean references(QName var)
{
return (arg == null) ? false : arg.references(var);
}
public String toString()
{
return (arg == null) ? "string-length()" : "string-length(" + arg + ")";
}
}
@@ -0,0 +1,98 @@
/* SubstringAfterFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>substring-after</code> function returns the substring of the
* first argument string that follows the first occurrence of the second
* argument string in the first argument string, or the empty string if the
* first argument string does not contain the second argument string. For
* example, substring-after("1999/04/01","/") returns 04/01, and
* substring-after("1999/04/01","19") returns 99/04/01.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class SubstringAfterFunction
extends Expr
{
final Expr arg1;
final Expr arg2;
SubstringAfterFunction(List args)
{
this((Expr) args.get(0), (Expr) args.get(1));
}
SubstringAfterFunction(Expr arg1, Expr arg2)
{
this.arg1 = arg1;
this.arg2 = arg2;
}
public Object evaluate(Node context, int pos, int len)
{
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
String s1 = _string(context, val1);
String s2 = _string(context, val2);
int index = s1.indexOf(s2);
return (index == -1) ? "" : s1.substring(index + s2.length());
}
public Expr clone(Object context)
{
return new SubstringAfterFunction(arg1.clone(context),
arg2.clone(context));
}
public boolean references(QName var)
{
return (arg1.references(var) || arg2.references(var));
}
public String toString()
{
return "substring-after(" + arg1 + "," + arg2 + ")";
}
}
@@ -0,0 +1,97 @@
/* SubstringBeforeFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>substring-before</code> function returns the substring of the
* first argument string that precedes the first occurrence of the second
* argument string in the first argument string, or the empty string if the
* first argument string does not contain the second argument string. For
* example, substring-before("1999/04/01","/") returns 1999.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class SubstringBeforeFunction
extends Expr
{
final Expr arg1;
final Expr arg2;
SubstringBeforeFunction(List args)
{
this((Expr) args.get(0), (Expr) args.get(1));
}
SubstringBeforeFunction(Expr arg1, Expr arg2)
{
this.arg1 = arg1;
this.arg2 = arg2;
}
public Object evaluate(Node context, int pos, int len)
{
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
String s1 = _string(context, val1);
String s2 = _string(context, val2);
int index = s1.indexOf(s2);
return (index == -1) ? "" : s1.substring(0, index);
}
public Expr clone(Object context)
{
return new SubstringBeforeFunction(arg1.clone(context),
arg2.clone(context));
}
public boolean references(QName var)
{
return (arg1.references(var) || arg2.references(var));
}
public String toString()
{
return "substring-before(" + arg1 + "," + arg2 + ")";
}
}
@@ -0,0 +1,129 @@
/* SubstringFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The substring function returns the substring of the first argument
* starting at the position specified in the second argument with length
* specified in the third argument. For example, substring("12345",2,3)
* returns "234". If the third argument is not specified, it returns the
* substring starting at the position specified in the second argument and
* continuing to the end of the string. For example, substring("12345",2)
* returns "2345".
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class SubstringFunction
extends Expr
{
final Expr arg1;
final Expr arg2;
final Expr arg3;
SubstringFunction(List args)
{
this((Expr) args.get(0), (Expr) args.get(1),
(args.size() > 2) ? (Expr) args.get(2) : null);
}
SubstringFunction(Expr arg1, Expr arg2, Expr arg3)
{
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
public Object evaluate(Node context, int pos, int len)
{
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
String s = _string(context, val1);
int p = (val2 instanceof Double) ?
((Double) val2).intValue() :
(int) Math.round(_number(context, val2));
p--;
if (p < 0)
{
p = 0;
}
int l = s.length() - p;
if (l <= 0)
{
return "";
}
if (arg3 != null)
{
Object val3 = arg3.evaluate(context, pos, len);
int v3 = (val3 instanceof Double) ?
((Double) val3).intValue() :
(int) Math.round(_number(context, val3));
if (v3 < l)
{
l = v3;
}
}
return s.substring(p, p + l);
}
public Expr clone(Object context)
{
return new SubstringFunction(arg1.clone(context), arg2.clone(context),
(arg3 == null) ? null : arg3.clone(context));
}
public boolean references(QName var)
{
return (arg1.references(var) || arg2.references(var) ||
(arg3 == null) ? false : arg3.references(var));
}
public String toString()
{
return (arg3 == null) ? "substring(" + arg1 + "," + arg2 + ")" :
"substring(" + arg1 + "," + arg2 + "," + arg3 + ")";
}
}
@@ -0,0 +1,100 @@
/* SumFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>sum</code> function returns the sum, for each node in the
* argument node-set, of the result of converting the string-values of the
* node to a number.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class SumFunction
extends Expr
{
final Expr arg;
SumFunction(List args)
{
this((Expr) args.get(0));
}
SumFunction(Expr arg)
{
this.arg = arg;
}
public Object evaluate(Node context, int pos, int len)
{
Object val = arg.evaluate(context, pos, len);
double sum = 0.0d;
if (val instanceof Collection)
{
for (Iterator i = ((Collection) val).iterator(); i.hasNext(); )
{
Node node = (Node) i.next();
String s = stringValue(node);
sum += _number(context, s);
}
}
return new Double(sum);
}
public Expr clone(Object context)
{
return new SumFunction(arg.clone(context));
}
public boolean references(QName var)
{
return arg.references(var);
}
public String toString()
{
return "sum(" + arg + ")";
}
}
+58
View File
@@ -0,0 +1,58 @@
/* Test.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* A test that can be performed on a node to determine whether to include it
* in a selection.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public abstract class Test
{
public abstract boolean matches(Node node, int pos, int len);
public abstract Test clone(Object context);
public abstract boolean references(QName var);
}
@@ -0,0 +1,133 @@
/* TranslateFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>translate</code> function returns the first argument string
* with occurrences of characters in the second argument string replaced by
* the character at the corresponding position in the third argument string.
* For example, translate("bar","abc","ABC") returns the string BAr. If
* there is a character in the second argument string with no character at a
* corresponding position in the third argument string (because the second
* argument string is longer than the third argument string), then
* occurrences of that character in the first argument string are removed.
* For example, translate("--aaa--","abc-","ABC") returns "AAA". If a
* character occurs more than once in the second argument string, then the
* first occurrence determines the replacement character. If the third
* argument string is longer than the second argument string, then excess
* characters are ignored.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class TranslateFunction
extends Expr
{
final Expr arg1;
final Expr arg2;
final Expr arg3;
TranslateFunction(List args)
{
this((Expr) args.get(0), (Expr) args.get(1), (Expr) args.get(2));
}
TranslateFunction(Expr arg1, Expr arg2, Expr arg3)
{
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
public Object evaluate(Node context, int pos, int len)
{
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
Object val3 = arg3.evaluate(context, pos, len);
String string = _string(context, val1);
String search = _string(context, val2);
String replace = _string(context, val3);
StringBuffer buf = new StringBuffer();
int l1 = string.length();
int l2 = search.length();
int l3 = replace.length();
for (int i = 0; i < l1; i++)
{
char c = string.charAt(i);
boolean replaced = false;
for (int j = 0; j < l2; j++)
{
if (c == search.charAt(j))
{
if (j < l3)
{
buf.append(replace.charAt(j));
}
replaced = true;
}
}
if (!replaced)
{
buf.append(c);
}
}
return new String(buf);
}
public Expr clone(Object context)
{
return new TranslateFunction(arg1.clone(context), arg2.clone(context),
arg3.clone(context));
}
public boolean references(QName var)
{
return (arg1.references(var) || arg2.references(var) ||
arg3.references(var));
}
public String toString()
{
return "translate(" + arg1 + "," + arg2 + "," + arg3 + ")";
}
}
@@ -0,0 +1,72 @@
/* TrueFunction.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The <code>true</code> function returns true.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
final class TrueFunction
extends Expr
{
public Object evaluate(Node context, int pos, int len)
{
return Boolean.TRUE;
}
public Expr clone(Object context)
{
return new TrueFunction();
}
public boolean references(QName var)
{
return false;
}
public String toString()
{
return "true()";
}
}
@@ -0,0 +1,108 @@
/* UnionExpr.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
/**
* The union of two node-sets.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public final class UnionExpr
extends Pattern
{
final Expr lhs;
final Expr rhs;
public UnionExpr(Expr lhs, Expr rhs)
{
this.lhs = lhs;
this.rhs = rhs;
}
public boolean matches(Node context)
{
if (lhs instanceof Pattern && rhs instanceof Pattern)
{
return ((Pattern) lhs).matches(context) ||
((Pattern) rhs).matches(context);
}
return false;
}
public Object evaluate(Node context, int pos, int len)
{
Object left = lhs.evaluate(context, pos, len);
Object right = rhs.evaluate(context, pos, len);
if (left instanceof Collection && right instanceof Collection)
{
Set set = new HashSet();
set.addAll ((Collection) left);
set.addAll ((Collection) right);
List list = new ArrayList(set);
Collections.sort(list, documentOrderComparator);
return list;
}
return Collections.EMPTY_SET;
}
public Expr clone(Object context)
{
return new UnionExpr(lhs.clone(context), rhs.clone(context));
}
public boolean references(QName var)
{
return (lhs.references(var) || rhs.references(var));
}
public String toString()
{
return lhs + " | " + rhs;
}
}
@@ -0,0 +1,100 @@
/* VariableReference.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathVariableResolver;
import org.w3c.dom.Node;
import gnu.xml.transform.Bindings;
public class VariableReference
extends Expr
{
final XPathVariableResolver resolver;
final QName name;
public VariableReference(XPathVariableResolver resolver, QName name)
{
this.resolver = resolver;
this.name = name;
}
public Object evaluate(Node context, int pos, int len)
{
if (resolver != null)
{
if (resolver instanceof Bindings)
{
// Needs context to operate properly
return ((Bindings) resolver).get(name, context, pos, len);
}
return resolver.resolveVariable(name);
}
throw new IllegalStateException("no variable resolver");
}
public Expr clone(Object context)
{
XPathVariableResolver r = resolver;
if (context instanceof XPathVariableResolver)
{
r = (XPathVariableResolver) context;
}
return new VariableReference(r, name);
}
public boolean references(QName var)
{
return name.equals(var);
}
public String toString()
{
StringBuffer buf = new StringBuffer("$");
String prefix = name.getPrefix();
if (prefix != null && !"".equals(prefix))
{
buf.append(prefix);
buf.append(':');
}
buf.append(name.getLocalPart());
return buf.toString();
}
}
@@ -0,0 +1,90 @@
/* XPathFactoryImpl.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
/**
* GNU XPath factory implementation.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class XPathFactoryImpl
extends XPathFactory
{
XPathVariableResolver variableResolver;
XPathFunctionResolver functionResolver;
public boolean isObjectModelSupported(String objectModel)
{
return XPathFactory.DEFAULT_OBJECT_MODEL_URI.equals(objectModel);
}
public void setFeature(String name, boolean value)
throws XPathFactoryConfigurationException
{
throw new XPathFactoryConfigurationException(name);
}
public boolean getFeature(String name)
throws XPathFactoryConfigurationException
{
throw new XPathFactoryConfigurationException(name);
}
public void setXPathVariableResolver(XPathVariableResolver resolver)
{
variableResolver = resolver;
}
public void setXPathFunctionResolver(XPathFunctionResolver resolver)
{
functionResolver = resolver;
}
public XPath newXPath()
{
return new XPathImpl(null, variableResolver, functionResolver);
}
}
@@ -0,0 +1,164 @@
/* XPathImpl.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.io.IOException;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
import org.xml.sax.InputSource;
/**
* JAXP XPath implementation.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class XPathImpl
implements XPath
{
XPathParser parser;
NamespaceContext namespaceContext;
XPathVariableResolver variableResolver;
XPathFunctionResolver functionResolver;
XPathImpl(NamespaceContext namespaceContext,
XPathVariableResolver variableResolver,
XPathFunctionResolver functionResolver)
{
parser = new XPathParser();
this.namespaceContext = namespaceContext;
this.variableResolver = variableResolver;
this.functionResolver = functionResolver;
reset();
}
public void reset()
{
parser.namespaceContext = namespaceContext;
parser.variableResolver = variableResolver;
parser.functionResolver = functionResolver;
}
public void setXPathVariableResolver(XPathVariableResolver resolver)
{
parser.variableResolver = resolver;
}
public XPathVariableResolver getXPathVariableResolver()
{
return parser.variableResolver;
}
public void setXPathFunctionResolver(XPathFunctionResolver resolver)
{
parser.functionResolver = resolver;
}
public XPathFunctionResolver getXPathFunctionResolver()
{
return parser.functionResolver;
}
public void setNamespaceContext(NamespaceContext nsContext)
{
parser.namespaceContext = nsContext;
}
public NamespaceContext getNamespaceContext()
{
return parser.namespaceContext;
}
public XPathExpression compile(String expression)
throws XPathExpressionException
{
XPathTokenizer tokenizer = new XPathTokenizer(expression);
try
{
return (Expr) parser.yyparse(tokenizer);
}
catch (IOException e)
{
throw new XPathExpressionException(e);
}
catch (XPathParser.yyException e)
{
throw new XPathExpressionException(expression);
}
}
public Object evaluate(String expression,
Object item,
QName returnType)
throws XPathExpressionException
{
XPathExpression expr = compile(expression);
return expr.evaluate(item, returnType);
}
public String evaluate(String expression,
Object item)
throws XPathExpressionException
{
XPathExpression expr = compile(expression);
return expr.evaluate(item);
}
public Object evaluate(String expression,
InputSource source,
QName returnType)
throws XPathExpressionException
{
XPathExpression expr = compile(expression);
return expr.evaluate(source, returnType);
}
public String evaluate(String expression,
InputSource source)
throws XPathExpressionException
{
XPathExpression expr = compile(expression);
return expr.evaluate(source);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,784 @@
%{
/*
* XPathParser.java
* Copyright (C) 2004 The Free Software Foundation
*
* This file is part of GNU JAXP, a library.
*
* GNU JAXP is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GNU JAXP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obliged to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package gnu.xml.xpath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
import org.w3c.dom.Node;
/**
* An XPath 1.0 parser.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class XPathParser
{
NamespaceContext namespaceContext;
XPathVariableResolver variableResolver;
XPathFunctionResolver functionResolver;
QName getQName(String name)
{
QName qName = QName.valueOf(name);
if (namespaceContext != null)
{
String prefix = qName.getPrefix();
String uri = qName.getNamespaceURI();
if (prefix != null && (uri == null || uri.length() == 0))
{
uri = namespaceContext.getNamespaceURI(prefix);
String localName = qName.getLocalPart();
qName = new QName(uri, localName, prefix);
}
}
return qName;
}
Expr lookupFunction(String name, List args)
{
int arity = args.size();
if ("position".equals(name) && arity == 0)
{
return new PositionFunction();
}
else if ("last".equals(name) && arity == 0)
{
return new LastFunction();
}
else if ("string".equals(name) && (arity == 1 || arity == 0))
{
return new StringFunction(args);
}
else if ("number".equals(name) && (arity == 1 || arity == 0))
{
return new NumberFunction(args);
}
else if ("boolean".equals(name) && arity == 1)
{
return new BooleanFunction(args);
}
else if ("count".equals(name) && arity == 1)
{
return new CountFunction(args);
}
else if ("not".equals(name) && arity == 1)
{
return new NotFunction(args);
}
else if ("id".equals(name) && arity == 1)
{
return new IdFunction(args);
}
else if ("concat".equals(name) && arity > 1)
{
return new ConcatFunction(args);
}
else if ("true".equals(name) && arity == 0)
{
return new TrueFunction();
}
else if ("false".equals(name) && arity == 0)
{
return new FalseFunction();
}
else if ("name".equals(name) && (arity == 1 || arity == 0))
{
return new NameFunction(args);
}
else if ("local-name".equals(name) && (arity == 1 || arity == 0))
{
return new LocalNameFunction(args);
}
else if ("namespace-uri".equals(name) && (arity == 1 || arity == 0))
{
return new NamespaceUriFunction(args);
}
else if ("starts-with".equals(name) && arity == 2)
{
return new StartsWithFunction(args);
}
else if ("contains".equals(name) && arity == 2)
{
return new ContainsFunction(args);
}
else if ("string-length".equals(name) && (arity == 1 || arity == 0))
{
return new StringLengthFunction(args);
}
else if ("translate".equals(name) && arity == 3)
{
return new TranslateFunction(args);
}
else if ("normalize-space".equals(name) && (arity == 1 || arity == 0))
{
return new NormalizeSpaceFunction(args);
}
else if ("substring".equals(name) && (arity == 2 || arity == 3))
{
return new SubstringFunction(args);
}
else if ("substring-before".equals(name) && arity == 2)
{
return new SubstringBeforeFunction(args);
}
else if ("substring-after".equals(name) && arity == 2)
{
return new SubstringAfterFunction(args);
}
else if ("lang".equals(name) && arity == 1)
{
return new LangFunction(args);
}
else if ("sum".equals(name) && arity == 1)
{
return new SumFunction(args);
}
else if ("floor".equals(name) && arity == 1)
{
return new FloorFunction(args);
}
else if ("ceiling".equals(name) && arity == 1)
{
return new CeilingFunction(args);
}
else if ("round".equals(name) && arity == 1)
{
return new RoundFunction(args);
}
else if (functionResolver != null)
{
QName qName = QName.valueOf(name);
Object function = functionResolver.resolveFunction(qName, arity);
if (function != null &&
function instanceof Function &&
function instanceof Expr)
{
Function f = (Function) function;
f.setArguments(args);
return (Expr) function;
}
}
return new FunctionCall(functionResolver, name, args);
}
%}
%token LITERAL
%token DIGITS
%token NAME
%token LP // '('
%token RP // ')'
%token LB // '['
%token RB // ']'
%token COMMA // ','
%token PIPE // '|'
%token SLASH // '/'
%token DOUBLE_SLASH // '//'
%token EQ // '='
%token NE // '!='
%token GT // '>'
%token LT // '<'
%token GTE // '>='
%token LTE // '<='
%token PLUS // '+'
%token MINUS // '-'
%token AT // '@'
%token STAR // '*'
%token DOLLAR // '$'
%token COLON // ':'
%token DOUBLE_COLON // '::'
%token DOT // '.'
%token DOUBLE_DOT // '..'
%token ANCESTOR
%token ANCESTOR_OR_SELF
%token ATTRIBUTE
%token CHILD
%token DESCENDANT
%token DESCENDANT_OR_SELF
%token FOLLOWING
%token FOLLOWING_SIBLING
%token NAMESPACE
%token PARENT
%token PRECEDING
%token PRECEDING_SIBLING
%token SELF
%token DIV
%token MOD
%token OR
%token AND
%token COMMENT
%token PROCESSING_INSTRUCTION
%token TEXT
%token NODE
%right UNARY
%start expr
%%
expr:
or_expr
;
location_path:
relative_location_path
| absolute_location_path
;
absolute_location_path:
SLASH
{
$$ = new Root();
}
| SLASH relative_location_path
{
Steps steps;
if ($2 instanceof Steps)
{
steps = (Steps) $2;
}
else
{
steps = new Steps();
steps.path.addFirst($2);
}
steps.path.addFirst(new Root());
$$ = steps;
//$$ = new Step(new Root(), (Path) $2);
}
| DOUBLE_SLASH relative_location_path
{
Test nt = new NodeTypeTest((short) 0);
Selector s = new Selector(Selector.DESCENDANT_OR_SELF,
Collections.singletonList (nt));
Steps steps;
if ($2 instanceof Steps)
{
steps = (Steps) $2;
}
else
{
steps = new Steps();
steps.path.addFirst($2);
}
steps.path.addFirst(s);
steps.path.addFirst(new Root());
$$ = steps;
//Step step = new Step(s, (Path) $2);
//$$ = new Step(new Root(), step);
}
;
relative_location_path:
step
| relative_location_path SLASH step
{
Steps steps;
if ($1 instanceof Steps)
{
steps = (Steps) $1;
}
else
{
steps = new Steps();
steps.path.addFirst($1);
}
steps.path.addLast($3);
$$ = steps;
//$$ = new Step((Expr) $1, (Path) $3);
}
| relative_location_path DOUBLE_SLASH step
{
Test nt = new NodeTypeTest((short) 0);
Selector s = new Selector(Selector.DESCENDANT_OR_SELF,
Collections.singletonList (nt));
Steps steps;
if ($1 instanceof Steps)
{
steps = (Steps) $1;
}
else
{
steps = new Steps();
steps.path.addFirst($1);
}
steps.path.addLast(s);
steps.path.addLast($3);
$$ = steps;
//Step step = new Step(s, (Path) $3);
//$$ = new Step((Expr) $1, step);
}
;
step:
step_node_test
{
$$ = new Selector (Selector.CHILD, (List) $1);
}
| AT step_node_test
{
$$ = new Selector (Selector.ATTRIBUTE, (List) $2);
}
| axis_name DOUBLE_COLON step_node_test
{
$$ = new Selector (((Integer) $1).intValue (), (List) $3);
}
| DOT
{
$$ = new Selector (Selector.SELF, Collections.EMPTY_LIST);
}
| DOUBLE_DOT
{
$$ = new Selector (Selector.PARENT, Collections.EMPTY_LIST);
}
;
step_node_test:
node_test
{
List list = new ArrayList();
list.add($1);
$$ = list;
}
| step_node_test predicate
{
List list = (List)$1;
list.add($2);
$$ = list;
}
;
/*predicate_list:
predicate
{
List list = new ArrayList ();
list.add ($1);
$$ = list;
}
| predicate predicate_list
{
List list = (List) $3;
list.add (0, $1);
$$ = list;
}
;*/
axis_name:
ANCESTOR
{
$$ = new Integer(Selector.ANCESTOR);
}
| ANCESTOR_OR_SELF
{
$$ = new Integer(Selector.ANCESTOR_OR_SELF);
}
| ATTRIBUTE
{
$$ = new Integer(Selector.ATTRIBUTE);
}
| CHILD
{
$$ = new Integer(Selector.CHILD);
}
| DESCENDANT
{
$$ = new Integer(Selector.DESCENDANT);
}
| DESCENDANT_OR_SELF
{
$$ = new Integer(Selector.DESCENDANT_OR_SELF);
}
| FOLLOWING
{
$$ = new Integer(Selector.FOLLOWING);
}
| FOLLOWING_SIBLING
{
$$ = new Integer(Selector.FOLLOWING_SIBLING);
}
| NAMESPACE
{
$$ = new Integer(Selector.NAMESPACE);
}
| PARENT
{
$$ = new Integer(Selector.PARENT);
}
| PRECEDING
{
$$ = new Integer(Selector.PRECEDING);
}
| PRECEDING_SIBLING
{
$$ = new Integer(Selector.PRECEDING_SIBLING);
}
| SELF
{
$$ = new Integer(Selector.SELF);
}
;
node_test:
name_test
/*| PROCESSING_INSTRUCTION LP LITERAL RP*/
| PROCESSING_INSTRUCTION LITERAL RP
{
$$ = new NodeTypeTest(Node.PROCESSING_INSTRUCTION_NODE, (String) $2);
}
/*| node_type LP RP*/
| node_type RP
{
$$ = new NodeTypeTest(((Short) $1).shortValue());
}
;
predicate:
LB expr RB
{
$$ = new Predicate((Expr) $2);
}
;
primary_expr:
variable_reference
| LP expr RP
{
$$ = new ParenthesizedExpr((Expr) $2);
}
| LITERAL
{
$$ = new Constant($1);
}
| number
{
$$ = new Constant($1);
}
| function_call
;
function_call:
function_name LP RP
{
$$ = lookupFunction((String) $1, Collections.EMPTY_LIST);
}
| function_name LP argument_list RP
{
$$ = lookupFunction((String) $1, (List) $3);
}
;
argument_list:
expr
{
List list = new ArrayList();
list.add($1);
$$ = list;
}
| expr COMMA argument_list
{
List list = (List) $3;
list.add(0, $1);
$$ = list;
}
;
union_expr:
path_expr
| union_expr PIPE path_expr
{
$$ = new UnionExpr((Expr) $1, (Expr) $3);
}
;
path_expr:
location_path
| filter_expr
| filter_expr SLASH relative_location_path
{
Steps steps;
if ($3 instanceof Steps)
{
steps = (Steps) $3;
}
else
{
steps = new Steps();
steps.path.addFirst($3);
}
steps.path.addFirst($1);
$$ = steps;
//$$ = new Step ((Expr) $1, (Path) $3);
}
| filter_expr DOUBLE_SLASH relative_location_path
{
Test nt = new NodeTypeTest((short) 0);
Selector s = new Selector(Selector.DESCENDANT_OR_SELF,
Collections.singletonList(nt));
Steps steps;
if ($3 instanceof Steps)
{
steps = (Steps) $3;
}
else
{
steps = new Steps();
steps.path.addFirst($3);
}
steps.path.addFirst(s);
steps.path.addFirst($1);
$$ = steps;
//Step step = new Step (s, (Path) $3);
//$$ = new Step ((Expr) $1, step);
}
;
filter_expr:
primary_expr
| filter_expr predicate
{
Predicate filter = (Predicate) $2;
Selector s = new Selector(Selector.SELF,
Collections.singletonList(filter));
Steps steps;
if ($1 instanceof Steps)
{
steps = (Steps) $1;
}
else
{
steps = new Steps();
steps.path.addFirst($1);
}
steps.path.addLast(s);
$$ = steps;
//$$ = new Step ((Expr) $1, s);
}
;
or_expr:
and_expr
| or_expr OR and_expr
{
$$ = new OrExpr((Expr) $1, (Expr) $3);
}
;
and_expr:
equality_expr
| and_expr AND equality_expr
{
$$ = new AndExpr((Expr) $1, (Expr) $3);
}
;
equality_expr:
relational_expr
| equality_expr EQ relational_expr
{
$$ = new EqualityExpr((Expr) $1, (Expr) $3, false);
}
| equality_expr NE relational_expr
{
$$ = new EqualityExpr((Expr) $1, (Expr) $3, true);
}
;
relational_expr:
additive_expr
| relational_expr LT additive_expr
{
$$ = new RelationalExpr((Expr) $1, (Expr) $3, true, false);
}
| relational_expr GT additive_expr
{
$$ = new RelationalExpr((Expr) $1, (Expr) $3, false, false);
}
| relational_expr LTE additive_expr
{
$$ = new RelationalExpr((Expr) $1, (Expr) $3, true, true);
}
| relational_expr GTE additive_expr
{
$$ = new RelationalExpr((Expr) $1, (Expr) $3, false, true);
}
;
additive_expr:
multiplicative_expr
| additive_expr PLUS multiplicative_expr
{
$$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.ADD);
}
| additive_expr MINUS multiplicative_expr
{
$$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.SUBTRACT);
}
;
multiplicative_expr:
unary_expr
| multiplicative_expr STAR unary_expr
{
$$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.MULTIPLY);
}
| multiplicative_expr DIV unary_expr
{
$$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.DIVIDE);
}
| multiplicative_expr MOD unary_expr
{
$$ = new ArithmeticExpr((Expr) $1, (Expr) $3, ArithmeticExpr.MODULO);
}
;
unary_expr:
union_expr
| MINUS unary_expr %prec UNARY
{
$$ = new NegativeExpr((Expr) $2);
}
;
number:
DIGITS
{
$$ = new Double((String) $1 + ".0");
}
| DIGITS DOT
{
$$ = new Double((String) $1 + ".0");
}
| DIGITS DOT DIGITS
{
$$ = new Double((String) $1 + "." + (String) $3);
}
| DOT DIGITS
{
$$ = new Double("0." + (String) $2);
}
;
function_name:
qname
/* | node_type
{
switch (((Short) $1).shortValue ())
{
case Node.COMMENT_NODE:
$$ = "comment";
break;
case Node.TEXT_NODE:
$$ = "text";
break;
case Node.PROCESSING_INSTRUCTION_NODE:
$$ = "processing-instruction";
break;
default:
$$ = "node";
break;
}
}*/
;
variable_reference:
DOLLAR qname
{
String name = (String) $2;
$$ = new VariableReference(variableResolver, getQName(name));
}
;
name_test:
STAR
{
$$ = new NameTest(null, true, true);
}
| NAME COLON STAR
{
QName qName = getQName((String) $1);
$$ = new NameTest(qName, true, false);
}
| qname
{
QName qName = getQName((String) $1);
$$ = new NameTest(qName, false, false);
}
;
qname:
NAME
| NAME COLON NAME
{
$$ = (String) $1 + ':' + (String) $3;
}
;
node_type:
COMMENT
{
$$ = new Short(Node.COMMENT_NODE);
}
| TEXT
{
$$ = new Short(Node.TEXT_NODE);
}
| PROCESSING_INSTRUCTION
{
$$ = new Short(Node.PROCESSING_INSTRUCTION_NODE);
}
| NODE
{
$$ = new Short((short) 0);
}
;
%%
}
@@ -0,0 +1,592 @@
/* XPathTokenizer.java --
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.xml.xpath;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Map;
import java.util.TreeMap;
/*import antlr.Token;
import antlr.TokenStream;
import antlr.TokenStreamException;
import antlr.TokenStreamIOException;*/
/**
* XPath 1.0 expression tokenizer.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class XPathTokenizer
implements XPathParser.yyInput
//implements TokenStream
{
static class XPathToken
//extends Token
{
int type;
String val;
XPathToken (int type)
{
this (type, null);
}
XPathToken (int type, String val)
{
//super (type);
this.type = type;
this.val = val;
}
public String getText ()
{
return val;
}
public String toString ()
{
return val;
}
}
static final Map keywords = new TreeMap ();
static
{
keywords.put ("ancestor", new Integer (XPathParser.ANCESTOR));
keywords.put ("ancestor-or-self", new Integer (XPathParser.ANCESTOR_OR_SELF));
keywords.put ("attribute", new Integer (XPathParser.ATTRIBUTE));
keywords.put ("child", new Integer (XPathParser.CHILD));
keywords.put ("descendant", new Integer (XPathParser.DESCENDANT));
keywords.put ("descendant-or-self", new Integer (XPathParser.DESCENDANT_OR_SELF));
keywords.put ("following", new Integer (XPathParser.FOLLOWING));
keywords.put ("following-sibling", new Integer (XPathParser.FOLLOWING_SIBLING));
keywords.put ("namespace", new Integer (XPathParser.NAMESPACE));
keywords.put ("parent", new Integer (XPathParser.PARENT));
keywords.put ("preceding", new Integer (XPathParser.PRECEDING));
keywords.put ("preceding-sibling", new Integer (XPathParser.PRECEDING_SIBLING));
keywords.put ("self", new Integer (XPathParser.SELF));
keywords.put ("div", new Integer (XPathParser.DIV));
keywords.put ("mod", new Integer (XPathParser.MOD));
keywords.put ("or", new Integer (XPathParser.OR));
keywords.put ("and", new Integer (XPathParser.AND));
keywords.put ("comment", new Integer (XPathParser.COMMENT));
keywords.put ("processing-instruction", new Integer (XPathParser.PROCESSING_INSTRUCTION));
keywords.put ("text", new Integer (XPathParser.TEXT));
keywords.put ("node", new Integer (XPathParser.NODE));
}
Reader in;
XPathToken token;
XPathToken lastToken;
public XPathTokenizer (String expr)
{
this (new StringReader (expr));
}
XPathTokenizer (Reader in)
{
this.in = in.markSupported () ? in : new BufferedReader (in);
}
/* Begin ANTLR specific *
public Token nextToken ()
throws TokenStreamException
{
try
{
if (!advance ())
{
throw new TokenStreamException ("eof");
}
token ();
return token;
}
catch (IOException e)
{
throw new TokenStreamIOException (e);
}
}
* End ANTLR specific */
public boolean advance ()
throws IOException
{
lastToken = token;
int c = in.read ();
switch (c)
{
case -1: // eof
return false;
case 0x20:
case 0x09:
case 0x0d:
case 0x0a: // skip whitespace
return advance ();
case 0x22: // "
case 0x27: // '
token = consume_literal (c);
break;
case 0x28: // (
token = new XPathToken (XPathParser.LP);
break;
case 0x29: // )
token = new XPathToken (XPathParser.RP);
break;
case 0x5b: // [
token = new XPathToken (XPathParser.LB);
break;
case 0x5d: // ]
token = new XPathToken (XPathParser.RB);
break;
case 0x2c: // ,
token = new XPathToken (XPathParser.COMMA);
break;
case 0x7c: // |
token = new XPathToken (XPathParser.PIPE);
break;
case 0x2f: // /
in.mark (1);
int d1 = in.read ();
if (d1 == 0x2f)
{
token = new XPathToken (XPathParser.DOUBLE_SLASH);
}
else
{
in.reset ();
token = new XPathToken (XPathParser.SLASH);
}
break;
case 0x3d: // =
token = new XPathToken (XPathParser.EQ);
break;
case 0x21: // !
in.mark (1);
int d2 = in.read ();
if (d2 == 0x3d) // =
{
token = new XPathToken (XPathParser.NE);
}
else
{
in.reset ();
token = new XPathToken (XPathParser.yyErrorCode);
}
break;
case 0x3e: // >
in.mark (1);
int d3 = in.read ();
if (d3 == 0x3d) // =
{
token = new XPathToken (XPathParser.GTE);
}
else
{
in.reset ();
token = new XPathToken (XPathParser.GT);
}
break;
case 0x3c: // <
in.mark (1);
int d4 = in.read ();
if (d4 == 0x3d) // =
{
token = new XPathToken (XPathParser.LTE);
}
else
{
in.reset ();
token = new XPathToken (XPathParser.LT);
}
break;
case 0x2b: // +
token = new XPathToken (XPathParser.PLUS);
break;
case 0x2d: // -
token = new XPathToken (XPathParser.MINUS);
break;
case 0x40: // @
token = new XPathToken (XPathParser.AT);
break;
case 0x2a: // *
token = new XPathToken (XPathParser.STAR);
break;
case 0x24: // $
token = new XPathToken (XPathParser.DOLLAR);
break;
case 0x3a: // :
in.mark (1);
int d5 = in.read ();
if (d5 == 0x3a)
{
token = new XPathToken (XPathParser.DOUBLE_COLON);
}
else
{
in.reset ();
token = new XPathToken (XPathParser.COLON);
}
break;
case 0x2e: // .
in.mark (1);
int d6 = in.read ();
if (d6 == 0x2e)
{
token = new XPathToken (XPathParser.DOUBLE_DOT);
}
else
{
in.reset ();
token = new XPathToken (XPathParser.DOT);
}
break;
default:
if (c >= 0x30 && c <= 0x39)
{
token = consume_digits (c);
}
else if (c == 0x5f || Character.isLetter ((char) c))
{
token = consume_name (c);
}
else
{
token = new XPathToken (XPathParser.yyErrorCode);
}
}
return true;
}
public int token ()
{
return token.type;
}
public Object value ()
{
return token.val;
}
XPathToken consume_literal (int delimiter)
throws IOException
{
StringBuffer buf = new StringBuffer ();
while (true)
{
int c = in.read ();
if (c == -1)
{
return new XPathToken (XPathParser.yyErrorCode);
}
else if (c == delimiter)
{
return new XPathToken (XPathParser.LITERAL, buf.toString ());
}
else
{
buf.append ((char) c);
}
}
}
XPathToken consume_digits (int c)
throws IOException
{
StringBuffer buf = new StringBuffer ();
buf.append ((char) c);
while (true)
{
in.mark (1);
c = in.read ();
if (c >= 0x30 && c <= 0x39)
{
buf.append ((char) c);
}
else
{
in.reset ();
return new XPathToken (XPathParser.DIGITS, buf.toString ());
}
}
}
XPathToken consume_name (int c)
throws IOException
{
StringBuffer buf = new StringBuffer ();
buf.append ((char) c);
while (true)
{
in.mark (1);
c = in.read ();
if (isNameChar (c))
{
buf.append ((char) c);
}
else
{
in.reset ();
String name = buf.toString ();
Integer keyword = (Integer) keywords.get (name);
if (keyword == null)
{
return new XPathToken (XPathParser.NAME, name);
}
else
{
int val = keyword.intValue ();
switch (val)
{
case XPathParser.NODE:
case XPathParser.COMMENT:
case XPathParser.TEXT:
case XPathParser.PROCESSING_INSTRUCTION:
// Consume subsequent (
in.mark (1);
do
{
c = in.read ();
}
while (c == 0x20 || c == 0x09);
if (c != 0x28)
{
in.reset ();
return new XPathToken (XPathParser.NAME, name);
}
break;
case XPathParser.CHILD:
case XPathParser.PARENT:
case XPathParser.SELF:
case XPathParser.DESCENDANT:
case XPathParser.ANCESTOR:
case XPathParser.DESCENDANT_OR_SELF:
case XPathParser.ANCESTOR_OR_SELF:
case XPathParser.ATTRIBUTE:
case XPathParser.NAMESPACE:
case XPathParser.FOLLOWING:
case XPathParser.FOLLOWING_SIBLING:
case XPathParser.PRECEDING:
case XPathParser.PRECEDING_SIBLING:
// Check that this is an axis specifier
in.mark(1);
do
{
c = in.read();
}
while (c == 0x20 || c == 0x09);
if (c == 0x3a)
{
c = in.read();
if (c == 0x3a)
{
in.reset();
return new XPathToken(val);
}
}
in.reset();
return new XPathToken(XPathParser.NAME, name);
case XPathParser.DIV:
case XPathParser.MOD:
// May be a name
if (lastToken == null)
{
return new XPathToken(XPathParser.NAME, name);
}
switch (lastToken.type)
{
case XPathParser.LP:
case XPathParser.LB:
case XPathParser.COMMA:
case XPathParser.PIPE:
case XPathParser.EQ:
case XPathParser.NE:
case XPathParser.GT:
case XPathParser.LT:
case XPathParser.GTE:
case XPathParser.LTE:
case XPathParser.PLUS:
case XPathParser.MINUS:
case XPathParser.STAR:
case XPathParser.AT:
case XPathParser.DOLLAR:
case XPathParser.COLON:
case XPathParser.DOUBLE_COLON:
case XPathParser.DIV:
case XPathParser.MOD:
case XPathParser.OR:
case XPathParser.AND:
case XPathParser.SLASH:
return new XPathToken(XPathParser.NAME, name);
}
break;
}
return new XPathToken (val);
}
}
}
}
boolean isNameChar (int c)
{
/* Name */
return (c == 0x5f
|| c == 0x2d
|| c == 0x2e
|| (c >= 0x30 && c <= 0x39)
/* CombiningChar */
|| (c >= 0x0300 && c <= 0x0345)
|| (c >= 0x0360 && c <= 0x0361)
|| (c >= 0x0483 && c <= 0x0486)
|| (c >= 0x0591 && c <= 0x05A1)
|| (c >= 0x05A3 && c <= 0x05B9)
|| (c >= 0x05BB && c <= 0x05BD)
|| c == 0x05BF
|| (c >= 0x05C1 && c <= 0x05C2)
|| c == 0x05C4
|| (c >= 0x064B && c <= 0x0652)
|| c == 0x0670
|| (c >= 0x06D6 && c <= 0x06DC)
|| (c >= 0x06DD && c <= 0x06DF)
|| (c >= 0x06E0 && c <= 0x06E4)
|| (c >= 0x06E7 && c <= 0x06E8)
|| (c >= 0x06EA && c <= 0x06ED)
|| (c >= 0x0901 && c <= 0x0903)
|| c == 0x093C
|| (c >= 0x093E && c <= 0x094C)
|| c == 0x094D
|| (c >= 0x0951 && c <= 0x0954)
|| (c >= 0x0962 && c <= 0x0963)
|| (c >= 0x0981 && c <= 0x0983)
|| c == 0x09BC
|| c == 0x09BE
|| c == 0x09BF
|| (c >= 0x09C0 && c <= 0x09C4)
|| (c >= 0x09C7 && c <= 0x09C8)
|| (c >= 0x09CB && c <= 0x09CD)
|| c == 0x09D7
|| (c >= 0x09E2 && c <= 0x09E3)
|| c == 0x0A02
|| c == 0x0A3C
|| c == 0x0A3E
|| c == 0x0A3F
|| (c >= 0x0A40 && c <= 0x0A42)
|| (c >= 0x0A47 && c <= 0x0A48)
|| (c >= 0x0A4B && c <= 0x0A4D)
|| (c >= 0x0A70 && c <= 0x0A71)
|| (c >= 0x0A81 && c <= 0x0A83)
|| c == 0x0ABC
|| (c >= 0x0ABE && c <= 0x0AC5)
|| (c >= 0x0AC7 && c <= 0x0AC9)
|| (c >= 0x0ACB && c <= 0x0ACD)
|| (c >= 0x0B01 && c <= 0x0B03)
|| c == 0x0B3C
|| (c >= 0x0B3E && c <= 0x0B43)
|| (c >= 0x0B47 && c <= 0x0B48)
|| (c >= 0x0B4B && c <= 0x0B4D)
|| (c >= 0x0B56 && c <= 0x0B57)
|| (c >= 0x0B82 && c <= 0x0B83)
|| (c >= 0x0BBE && c <= 0x0BC2)
|| (c >= 0x0BC6 && c <= 0x0BC8)
|| (c >= 0x0BCA && c <= 0x0BCD)
|| c == 0x0BD7
|| (c >= 0x0C01 && c <= 0x0C03)
|| (c >= 0x0C3E && c <= 0x0C44)
|| (c >= 0x0C46 && c <= 0x0C48)
|| (c >= 0x0C4A && c <= 0x0C4D)
|| (c >= 0x0C55 && c <= 0x0C56)
|| (c >= 0x0C82 && c <= 0x0C83)
|| (c >= 0x0CBE && c <= 0x0CC4)
|| (c >= 0x0CC6 && c <= 0x0CC8)
|| (c >= 0x0CCA && c <= 0x0CCD)
|| (c >= 0x0CD5 && c <= 0x0CD6)
|| (c >= 0x0D02 && c <= 0x0D03)
|| (c >= 0x0D3E && c <= 0x0D43)
|| (c >= 0x0D46 && c <= 0x0D48)
|| (c >= 0x0D4A && c <= 0x0D4D)
|| c == 0x0D57
|| c == 0x0E31
|| (c >= 0x0E34 && c <= 0x0E3A)
|| (c >= 0x0E47 && c <= 0x0E4E)
|| c == 0x0EB1
|| (c >= 0x0EB4 && c <= 0x0EB9)
|| (c >= 0x0EBB && c <= 0x0EBC)
|| (c >= 0x0EC8 && c <= 0x0ECD)
|| (c >= 0x0F18 && c <= 0x0F19)
|| c == 0x0F35
|| c == 0x0F37
|| c == 0x0F39
|| c == 0x0F3E
|| c == 0x0F3F
|| (c >= 0x0F71 && c <= 0x0F84)
|| (c >= 0x0F86 && c <= 0x0F8B)
|| (c >= 0x0F90 && c <= 0x0F95)
|| c == 0x0F97
|| (c >= 0x0F99 && c <= 0x0FAD)
|| (c >= 0x0FB1 && c <= 0x0FB7)
|| c == 0x0FB9
|| (c >= 0x20D0 && c <= 0x20DC)
|| c == 0x20E1
|| (c >= 0x302A && c <= 0x302F)
|| c == 0x3099
|| c == 0x309A
/* Extender */
|| c == 0x00B7
|| c == 0x02D0
|| c == 0x02D1
|| c == 0x0387
|| c == 0x0640
|| c == 0x0E46
|| c == 0x0EC6
|| c == 0x3005
|| (c >= 0x3031 && c <= 0x3035)
|| (c >= 0x309D && c <= 0x309E)
|| (c >= 0x30FC && c <= 0x30FE)
/* Name */
|| Character.isLetter ((char) c));
}
}