| /******************************************************************************* |
| * 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 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; |
| |
| import java.math.BigInteger; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| /** |
| * 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; |
| } |
| } |