blob: c31e1f96bef4212dcd34fc2e404ecab59e42eb95 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2009 Andrea Bittau, University College London, and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrea Bittau - initial API and implementation from the PsychoPath XPath 2.0
*******************************************************************************/
package org.eclipse.wst.xml.xpath2.processor.internal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.wst.xml.xpath2.processor.StaticContext;
import org.eclipse.wst.xml.xpath2.processor.ast.XPath;
import org.eclipse.wst.xml.xpath2.processor.function.FnFunctionLibrary;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.AddExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.AndExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.AnyKindTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.AttributeTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.AxisStep;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.BinExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.CastExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.CastableExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.CmpExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.CntxItemExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.CommentTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.DecimalLiteral;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.DivExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.DocumentTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.DoubleLiteral;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ElementTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ExceptExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.Expr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.FilterExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ForExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ForwardStep;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.FunctionCall;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.IDivExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.IfExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.InstOfExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.IntegerLiteral;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.IntersectExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ItemType;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.MinusExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ModExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.MulExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.NameTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.NodeTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.OrExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.PITest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ParExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.PipeExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.PlusExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.PrimaryExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.QuantifiedExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.RangeExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.ReverseStep;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.SchemaAttrTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.SchemaElemTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.SequenceType;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.SingleType;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.Step;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.StepExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.StringLiteral;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.SubExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.TextTest;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.TreatAsExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.UnExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.UnionExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.VarExprPair;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.VarRef;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.XPathExpr;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.XPathNode;
import org.eclipse.wst.xml.xpath2.processor.internal.ast.XPathVisitor;
import org.eclipse.wst.xml.xpath2.processor.internal.function.OpFunctionLibrary;
import org.eclipse.wst.xml.xpath2.processor.internal.types.QName;
/**
* Normalizer that uses XPathVisitor.
*/
// XXX currently not supported anymore!
public class Normalizer implements XPathVisitor {
private StaticContext _sc;
/**
* Static Context is set to sc
*
* @param sc
* is the StaticContext.
*/
public Normalizer(StaticContext sc) {
_sc = sc;
}
/**
* Returns the normalized tree
*
* @param xp
* is the xpath expression.
* @return the xpath expressions.
*/
public Object visit(XPath xp) {
Collection exprs = new ArrayList();
for (Iterator i = xp.iterator(); i.hasNext();) {
Expr e = (Expr) i.next();
Expr n = (Expr) e.accept(this);
exprs.add(n);
}
return new XPath(exprs);
}
private void printVarExprPairs(Iterator i) {
while (i.hasNext()) {
VarExprPair pair = (VarExprPair) i.next();
QName var = pair.varname();
Expr e = pair.expr();
e.accept(this);
}
}
// does a for and a quantified expression
// takes the iterator for var expr paris
private void doForExpr(Iterator iter, Expr expr) {
Collection vars = new ArrayList();
// go through expression and cache variables
while (iter.hasNext()) {
VarExprPair pair = (VarExprPair) iter.next();
QName var = pair.varname();
Expr e = pair.expr();
// XXX this is wrong!
// need to define new scope, and reference "inner scope"
// [shadow outer vars]
/*
* if(_sc.variable_exists(var)) report_error(new
* StaticNameError("Variable " + var.string() +
* " already defined"));
*/
// ok we can cheat here cuz we only care about variable
// "presence" not its specific instance / value so we
// can fakely shadow without creating explicit scopes
// if variable already exists.... then leave it there...
// [we do not need to create a new instance and delete
// it at the end]
// we only need to if variable does not exist
// XXX: i fink this is all wrong
vars.add(var);
e.accept(this);
}
// add variables to scope
for (Iterator i = vars.iterator(); i.hasNext();) {
QName var = (QName) i.next();
}
// do the bounded expression
expr.accept(this);
// remove variables
}
/**
*
* @param fex
* is the For expression.
* @return fex expression.
*/
public Object visit(ForExpr fex) {
ForExpr last = fex;
Expr ret = fex.expr();
int depth = 0;
for (Iterator i = fex.iterator(); i.hasNext();) {
VarExprPair ve = (VarExprPair) i.next();
// ok we got nested fors...
if (depth > 0) {
Collection pairs = new ArrayList();
pairs.add(ve);
ForExpr fe = new ForExpr(pairs, ret);
last.set_expr(fe);
last = fe;
}
depth++;
}
// normalize return value, and set it to the last for expr
ret.accept(this);
// get rid of the pairs in the parent (original) for
if (depth > 1)
fex.truncate_pairs();
return fex;
}
/**
*
* @param qex
* is the Quantified expression.
* @return qex expression.
*/
// XXX: code duplication
public Object visit(QuantifiedExpr qex) {
QuantifiedExpr last = qex;
Expr ret = qex.expr();
int depth = 0;
for (Iterator i = qex.iterator(); i.hasNext();) {
VarExprPair ve = (VarExprPair) i.next();
// ok we got nested fors...
if (depth > 0) {
Collection pairs = new ArrayList();
pairs.add(ve);
QuantifiedExpr qe = new QuantifiedExpr(qex.type(), pairs, ret);
last.set_expr(qe);
last = qe;
}
depth++;
}
// normalize return value, and set it to the last for expr
ret.accept(this);
// get rid of the pairs in the parent (original) for
if (depth > 1)
qex.truncate_pairs();
return qex;
}
private void printExprs(Iterator i) {
while (i.hasNext()) {
Expr e = (Expr) i.next();
e.accept(this);
}
}
/**
*
* @param ifex
* is the 'if' expression.
* @return ifex expression.
*/
public Object visit(IfExpr ifex) {
printExprs(ifex.iterator());
ifex.then_clause().accept(this);
ifex.else_clause().accept(this);
return ifex;
}
/**
* @param name
* of binary expression.
* @param e
* is the binary expression.
*/
public void printBinExpr(String name, BinExpr e) {
e.left().accept(this);
e.right().accept(this);
}
private BinExpr make_logic_expr(BinExpr e) {
Collection normalized = normalize_bin_args(e);
XPathNode nor_arr[] = new XPathNode[2];
int j = 0;
for (Iterator i = normalized.iterator(); i.hasNext();) {
nor_arr[j] = (XPathNode) i.next();
j++;
}
Collection args = new ArrayList();
args.add(nor_arr[0]);
e.set_left(make_function(new QName("fn", "boolean",
FnFunctionLibrary.XPATH_FUNCTIONS_NS), args));
args.clear();
args.add(nor_arr[1]);
e.set_right(make_function(new QName("fn", "boolean",
FnFunctionLibrary.XPATH_FUNCTIONS_NS), args));
return e;
}
/**
* @param orex
* is the 'or' expression.
* @return make logic expr(orex).
*/
public Object visit(OrExpr orex) {
return make_logic_expr(orex);
}
/**
* @param andex
* is the 'and' expression.
* @return make logic expr(andex).
*/
public Object visit(AndExpr andex) {
return make_logic_expr(andex);
}
/**
* @param cmpex
* is the compare expression.
* @return cmpex.
*/
public Object visit(CmpExpr cmpex) {
switch (cmpex.type()) {
case CmpExpr.EQ:
return make_CmpOp(cmpex, new QName("fs", "eq",
OpFunctionLibrary.XPATH_OP_NS));
case CmpExpr.NE:
return make_CmpOp(cmpex, new QName("fs", "ne",
OpFunctionLibrary.XPATH_OP_NS));
case CmpExpr.LT:
return make_CmpOp(cmpex, new QName("fs", "lt",
OpFunctionLibrary.XPATH_OP_NS));
case CmpExpr.GT:
return make_CmpOp(cmpex, new QName("fs", "gt",
OpFunctionLibrary.XPATH_OP_NS));
case CmpExpr.LE:
return make_CmpOp(cmpex, new QName("fs", "le",
OpFunctionLibrary.XPATH_OP_NS));
case CmpExpr.GE:
return make_CmpOp(cmpex, new QName("fs", "ge",
OpFunctionLibrary.XPATH_OP_NS));
// XXX don't have functs!
case CmpExpr.IS:
return make_function(new QName("op", "node-equal"),
normalize_bin_args(cmpex));
case CmpExpr.LESS_LESS:
return make_function(new QName("op", "node-before"),
normalize_bin_args(cmpex));
case CmpExpr.GREATER_GREATER:
return make_function(new QName("op", "node-after"),
normalize_bin_args(cmpex));
}
printBinExpr("CMP" + cmpex.type(), cmpex);
return cmpex;
}
private Collection normalize_bin_args(BinExpr e) {
Collection args = new ArrayList();
XPathNode left = (XPathNode) e.left().accept(this);
XPathNode right = (XPathNode) e.right().accept(this);
args.add(left);
args.add(right);
return args;
}
/**
* @param rex
* is the range expression.
* @return a new function.
*/
public Object visit(RangeExpr rex) {
Collection args = normalize_bin_args(rex);
return make_function(new QName("op", "to",
OpFunctionLibrary.XPATH_OP_NS), args);
}
private XPathExpr make_xpathexpr(PrimaryExpr pex) {
FilterExpr fe = new FilterExpr(pex, new ArrayList());
return new XPathExpr(0, fe);
}
private XPathExpr make_int_lit(int i) {
IntegerLiteral il = new IntegerLiteral(BigInteger.valueOf(i));
return make_xpathexpr(il);
}
private XPathExpr make_string_lit(String s) {
StringLiteral sl = new StringLiteral(s);
return make_xpathexpr(sl);
}
private XPathExpr make_convert_operand(XPathExpr arg1, XPathExpr arg2) {
Collection args = new ArrayList();
args.add(arg1);
args.add(arg2);
return make_function(new QName("fs", "convert-operand",
OpFunctionLibrary.XPATH_OP_NS), args);
}
private XPathExpr make_double_lit(double d) {
DoubleLiteral dl = new DoubleLiteral(d);
return make_xpathexpr(dl);
}
// fs:fname( fs:convert-operand( fn:data(ARG1), 1.0E0 ),
// fs:convert-operand( fn:data(ARG2), 1.0E0 )
// )
private XPathExpr make_convert_binop(BinExpr e, XPathExpr convarg,
QName name) {
Collection args = normalize_bin_args(e);
XPathExpr args_arr[] = new XPathExpr[2];
int j = 0;
for (Iterator i = args.iterator(); i.hasNext();) {
args_arr[j] = (XPathExpr) i.next();
j++;
}
Collection argsfname = new ArrayList();
for (j = 0; j < 2; j++) {
XPathExpr arg = make_convert_operand(args_arr[j], convarg);
argsfname.add(arg);
}
return make_function(name, argsfname);
}
private XPathExpr make_ArithOp(BinExpr e, QName name) {
return make_convert_binop(e, make_double_lit(1.0), name);
}
// fs:fname( fs:convert_operand( fn:data(ARG1), "string"),
// fs:convert_operand( fn:data(ARG2), "string")
// )
private XPathExpr make_CmpOp(BinExpr e, QName name) {
return make_convert_binop(e, make_string_lit("string"), name);
}
/**
* @param addex
* is the add expression.
* @return a new function.
*/
public Object visit(AddExpr addex) {
return make_ArithOp(addex, new QName("fs", "plus",
OpFunctionLibrary.XPATH_OP_NS));
}
/**
* @param subex
* is the sub expression.
* @return a new function.
*/
public Object visit(SubExpr subex) {
return make_ArithOp(subex, new QName("fs", "minus",
OpFunctionLibrary.XPATH_OP_NS));
}
/**
* @param mulex
* is the multiply expression.
* @return a new function.
*/
public Object visit(MulExpr mulex) {
return make_ArithOp(mulex, new QName("fs", "times",
OpFunctionLibrary.XPATH_OP_NS));
}
/**
* @param mulex
* is the division expression.
* @return a new function.
*/
public Object visit(DivExpr mulex) {
return make_ArithOp(mulex, new QName("fs", "div",
OpFunctionLibrary.XPATH_OP_NS));
}
/**
* @param mulex
* is the integer division expression that always returns an
* integer.
* @return a new function.
*/
// XXX: integer cast!
public Object visit(IDivExpr mulex) {
return make_ArithOp(mulex, new QName("fs", "idiv",
OpFunctionLibrary.XPATH_OP_NS));
}
/**
* @param mulex
* is the mod expression.
* @return a new function.
*/
public Object visit(ModExpr mulex) {
return make_ArithOp(mulex, new QName("fs", "mod",
OpFunctionLibrary.XPATH_OP_NS));
}
/**
* @param unex
* is the union expression.
* @return a new function.
*/
public Object visit(UnionExpr unex) {
Collection args = normalize_bin_args(unex);
return make_function(new QName("op", "union",
OpFunctionLibrary.XPATH_OP_NS), args);
}
/**
* @param pipex
* is the pipe expression.
* @return a new function.
*/
public Object visit(PipeExpr pipex) {
Collection args = normalize_bin_args(pipex);
return make_function(new QName("op", "union",
OpFunctionLibrary.XPATH_OP_NS), args);
}
/**
* @param iexpr
* is the intersect expression.
* @return a new function.
*/
public Object visit(IntersectExpr iexpr) {
Collection args = normalize_bin_args(iexpr);
return make_function(new QName("op", "intersect",
OpFunctionLibrary.XPATH_OP_NS), args);
}
/**
* @param eexpr
* is the except expression.
* @return a new function.
*/
public Object visit(ExceptExpr eexpr) {
Collection args = normalize_bin_args(eexpr);
return make_function(new QName("op", "except",
OpFunctionLibrary.XPATH_OP_NS), args);
}
/**
* @param ioexp
* is the instance of expression.
* @return a ioexp.
*/
public Object visit(InstOfExpr ioexp) {
printBinExpr("INSTANCEOF", ioexp);
return ioexp;
}
/**
* @param taexp
* is the treat as expression.
* @return a taexp.
*/
public Object visit(TreatAsExpr taexp) {
printBinExpr("TREATAS", taexp);
return taexp;
}
/**
* @param cexp
* is the castable expression.
* @return cexp.
*/
public Object visit(CastableExpr cexp) {
printBinExpr("CASTABLE", cexp);
return cexp;
}
/**
* @param cexp
* is the cast expression.
* @return cexp.
*/
public Object visit(CastExpr cexp) {
printBinExpr("CAST", cexp);
return cexp;
}
/**
* @param name
* is the name.
* @param e
* is the Un Expression.
*/
public void printUnExpr(String name, UnExpr e) {
e.arg().accept(this);
}
/**
* @param e
* is the minus expression.
* @return new sub expression
*/
public Object visit(MinusExpr e) {
SubExpr se = new SubExpr(make_int_lit(0), e.arg());
return se.accept(this);
}
/**
* @param e
* is the plus expression.
* @return new add expression
*/
public Object visit(PlusExpr e) {
AddExpr ae = new AddExpr(make_int_lit(0), e.arg());
return ae.accept(this);
}
private XPathExpr make_function(QName name, Collection args) {
FunctionCall fc = new FunctionCall(name, args);
FilterExpr fe = new FilterExpr(fc, new ArrayList());
return new XPathExpr(0, fe);
}
private XPathExpr make_root_self_node() {
// self::node()
Step self_node = new ForwardStep(ForwardStep.SELF, new AnyKindTest());
StepExpr self_node_expr = new AxisStep(self_node, new ArrayList());
XPathExpr self_node_xpath = new XPathExpr(0, self_node_expr);
// fn:root(self::node())
Collection args = new ArrayList();
args.add(self_node_xpath);
XPathExpr xpe = make_function(new QName("fn", "root",
FnFunctionLibrary.XPATH_FUNCTIONS_NS), args);
return xpe;
}
private XPathExpr make_descendant_or_self() {
Step desc_self_node = new ForwardStep(ForwardStep.DESCENDANT_OR_SELF,
new AnyKindTest());
StepExpr se = new AxisStep(desc_self_node, new ArrayList());
return new XPathExpr(0, se);
}
/**
* @param e
* is the xpath expression.
* @return result.
*/
public Object visit(XPathExpr e) {
XPathExpr xp = e;
int depth = 0; // indicates how many / we traversed
XPathExpr result = e;
while (xp != null) {
int slashes = xp.slashes();
StepExpr se = xp.expr();
if (slashes == 1) {
// this is a single slash and nothing else...
if (se == null)
return make_root_self_node();
// /RelativePathExpr
if (depth == 0) {
XPathExpr xpe = make_root_self_node();
xpe.set_next(e);
result = xpe;
}
}
if (slashes == 2) {
// //RelativePathExpr
if (depth == 0) {
XPathExpr desc = make_descendant_or_self();
desc.set_slashes(1);
e.set_slashes(1);
desc.set_next(e);
XPathExpr root_self = make_root_self_node();
root_self.set_next(desc);
return root_self;
}
}
if (se != null)
se.accept(this);
XPathExpr next = xp.next();
// peek if the next guy will have 2 slashes...
if (next != null) {
// StepExpr//StepExpr
if (next.slashes() == 2) {
// create the node to stick between the
// slashes
XPathExpr desc = make_descendant_or_self();
desc.set_slashes(1);
// current node / desc / next
xp.set_next(desc);
desc.set_next(next);
next.set_slashes(1);
}
}
xp = next;
depth++;
}
return result;
}
/**
* @param e
* is the forward step.
* @return e
*/
// XXX: normalzie!
public Object visit(ForwardStep e) {
int axis = e.axis();
switch (axis) {
case ForwardStep.AT_SYM:
e.set_axis(ForwardStep.ATTRIBUTE);
break;
case ForwardStep.NONE:
e.set_axis(ForwardStep.CHILD);
break;
}
e.node_test().accept(this);
return e;
}
/**
* @param e
* is the reverse step.
* @return e
*/
public Object visit(ReverseStep e) {
if (e.axis() == ReverseStep.DOTDOT) {
NodeTest nt = new AnyKindTest();
Step s = new ReverseStep(ReverseStep.PARENT, nt);
return s;
}
NodeTest nt = e.node_test();
if (nt != null)
nt.accept(this);
return e;
}
/**
* @param e
* is the Name test.
* @return e
*/
public Object visit(NameTest e) {
String prefix = e.name().prefix();
// XXX: is this correct ?
// i.e. if there is no prefix... its ok.. else it must exist
if (prefix == null)
return null;
return e;
}
/**
* @param e
* is the veriable reference.
* @return e
*/
public Object visit(VarRef e) {
return e;
}
/**
* @param e
* is the string literal.
* @return e
*/
public Object visit(StringLiteral e) {
return e;
}
/**
* @param e
* is the integer literal.
* @return e
*/
public Object visit(IntegerLiteral e) {
return e;
}
/**
* @param e
* is the double literal.
* @return e
*/
public Object visit(DoubleLiteral e) {
return e;
}
/**
* @param e
* is the decimal literal.
* @return e
*/
public Object visit(DecimalLiteral e) {
return e;
}
/**
* @param e
* is the par expression.
* @return e
*/
public Object visit(ParExpr e) {
printExprs(e.iterator());
return e;
}
/**
* @param e
* is the Cntx Item Expression.
* @return new function
*/
public Object visit(CntxItemExpr e) {
return new VarRef(new QName("fs", "dot"));
}
/**
* @param e
* is the fucntion call.
* @return e
*/
// XXX: how do we normalize ?
public Object visit(FunctionCall e) {
printExprs(e.iterator());
return e;
}
/**
* @param e
* is the single type.
* @return e
*/
public Object visit(SingleType e) {
return e;
}
/**
* @param e
* is the sequence type.
* @return e
*/
public Object visit(SequenceType e) {
ItemType it = e.item_type();
if (it != null)
it.accept(this);
return e;
}
/**
* @param e
* is the item type.
* @return e
*/
public Object visit(ItemType e) {
switch (e.type()) {
case ItemType.ITEM:
break;
case ItemType.QNAME:
break;
case ItemType.KINDTEST:
e.kind_test().accept(this);
break;
}
return e;
}
/**
* @param e
* is the any kind test.
* @return e
*/
public Object visit(AnyKindTest e) {
return e;
}
/**
* @param e
* is the document test.
* @return e
*/
public Object visit(DocumentTest e) {
switch (e.type()) {
case DocumentTest.ELEMENT:
e.elem_test().accept(this);
break;
case DocumentTest.SCHEMA_ELEMENT:
e.schema_elem_test().accept(this);
break;
}
return e;
}
/**
* @param e
* is the text test.
* @return e
*/
public Object visit(TextTest e) {
return e;
}
/**
* @param e
* is the common test.
* @return e
*/
public Object visit(CommentTest e) {
return e;
}
/**
* @param e
* is the PI test.
* @return e
*/
public Object visit(PITest e) {
String arg = e.arg();
if (arg == null)
arg = "";
return e;
}
/**
* @param e
* is the attribute test.
* @return e
*/
// XXX NO CHECK ?
public Object visit(AttributeTest e) {
return e;
}
/**
* @param e
* is the schema attribute test.
* @return e
*/
public Object visit(SchemaAttrTest e) {
return e;
}
/**
* @param e
* is the element test.
* @return e
*/
// XXX NO SEMANTIC CHECK?!
public Object visit(ElementTest e) {
return e;
}
/**
* @param e
* is the schema element test.
* @return e
*/
public Object visit(SchemaElemTest e) {
return e;
}
private void printCollExprs(Iterator i) {
while (i.hasNext()) {
Collection exprs = (Collection) i.next();
printExprs(exprs.iterator());
}
}
/**
* @param e
* is the axis step.
* @return e
*/
public Object visit(AxisStep e) {
Step s = (Step) e.step().accept(this);
e.set_step(s);
printCollExprs(e.iterator());
return e;
}
/**
* @param e
* is the filter expression.
* @return e
*/
public Object visit(FilterExpr e) {
PrimaryExpr pe = (PrimaryExpr) e.primary().accept(this);
e.set_primary(pe);
printCollExprs(e.iterator());
return e;
}
}