blob: 3f754969c9166ca27b73b49424b86fafe8a3479a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2011 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
* Jesper Steen Moller - bug 340933 - Migrate to new XPath2 API
* Jesper Steen Moller - bug 343804 - Updated API information
* Lukasz Wycisk - bug 361802 - Default variable namespace Ð no namespace
*
*******************************************************************************/
package org.eclipse.wst.xml.xpath2.processor;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.xml.XMLConstants;
import org.eclipse.wst.xml.xpath2.api.Function;
import org.eclipse.wst.xml.xpath2.processor.ast.XPath;
import org.eclipse.wst.xml.xpath2.processor.internal.ReverseAxis;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticAttrNameError;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticContextAdapter;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticElemNameError;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticFunctNameError;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticNameError;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticNsNameError;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticTypeNameError;
import org.eclipse.wst.xml.xpath2.processor.internal.StaticVarNameError;
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.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.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.types.QName;
import org.eclipse.wst.xml.xpath2.processor.internal.types.SimpleAtomicItemTypeImpl;
import org.eclipse.wst.xml.xpath2.processor.internal.types.builtin.BuiltinTypeDefinition;
import org.eclipse.wst.xml.xpath2.processor.internal.types.builtin.BuiltinTypeLibrary;
/**
* This class resolves static names.
*/
public class StaticNameResolver implements XPathVisitor, StaticChecker {
static class DummyError extends Error {
/**
*
*/
private static final long serialVersionUID = 3898564402981741950L;
}
private org.eclipse.wst.xml.xpath2.api.StaticContext _sc;
private StaticNameError _err;
private Set<javax.xml.namespace.QName> _resolvedFunctions = new HashSet<javax.xml.namespace.QName>();
private Set<String> _axes = new HashSet<String>();
private Set<javax.xml.namespace.QName> _freeVariables = new HashSet<javax.xml.namespace.QName>();
/**
* Constructor for static name resolver
*
* @param sc
* is the static context.
* @since 2.0
*/
public StaticNameResolver(final org.eclipse.wst.xml.xpath2.processor.StaticContext sc) {
_sc = new StaticContextAdapter(sc);
_err = null;
}
/**
* @since 2.0
*/
public StaticNameResolver(org.eclipse.wst.xml.xpath2.api.StaticContext context) {
_sc = context;
_err = null;
}
class VariableScope {
public VariableScope(QName name, org.eclipse.wst.xml.xpath2.api.typesystem.ItemType typeDef, VariableScope nextScope) {
this.name = name;
this.typeDef = typeDef;
this.nextScope = nextScope;
}
final public QName name;
final public org.eclipse.wst.xml.xpath2.api.typesystem.ItemType typeDef;
final public VariableScope nextScope;
}
/**
* @since 2.0
*/
public Set<String> getAxes() {
return _axes;
}
/**
* @since 2.0
*/
public Set<javax.xml.namespace.QName> getFreeVariables() {
return _freeVariables;
}
/**
* @since 2.0
*/
public Set<javax.xml.namespace.QName> getResolvedFunctions() {
return _resolvedFunctions;
}
private VariableScope _innerScope = null;
private boolean _rootUsed;
private org.eclipse.wst.xml.xpath2.api.typesystem.ItemType getVariableType(QName name) {
VariableScope scope = _innerScope;
while (scope != null) {
if (name.equals(scope.name)) return scope.typeDef;
scope = scope.nextScope;
}
return _sc.getInScopeVariables().getVariableType(name.asQName());
}
private boolean isVariableCaptured(QName name) {
VariableScope scope = _innerScope;
while (scope != null) {
if (name.equals(scope.name)) return true;
scope = scope.nextScope;
}
return false;
}
private boolean isVariableInScope(QName name) {
return isVariableCaptured(name) || _sc.getInScopeVariables().isVariablePresent(name.asQName());
}
private void popScope() {
if (_innerScope == null) throw new IllegalStateException("Unmatched scope pop");
_innerScope = _innerScope.nextScope;
}
private void pushScope(QName var, BuiltinTypeDefinition xsAnytype) {
_innerScope = new VariableScope(var, new SimpleAtomicItemTypeImpl(xsAnytype), _innerScope);
}
private boolean expandQName(QName name, String def, boolean allowWildcards) {
String prefix = name.prefix();
if ("*".equals(prefix)) {
if (! allowWildcards)
return false;
name.set_namespace("*");
return true;
}
if (prefix == null || XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
name.set_namespace(def);
return true;
}
// At this point, we know we have a non-null prefix, so look it up
String namespaceURI = _sc.getNamespaceContext().getNamespaceURI(prefix);
if (XMLConstants.NULL_NS_URI.equals(namespaceURI))
return false;
name.set_namespace(namespaceURI);
return true;
}
private boolean expandItemQName(QName name) {
return expandQName(name, _sc.getDefaultNamespace(), true);
}
private boolean expandVarQName(QName name) {
return expandQName(name, null, false);
}
/**
* Expands a qname and uses the default function namespace if unprefixed.
*
* @param name
* qname to expand.
* @return true on success.
*/
private boolean expandFunctionQName(QName name) {
return expandQName(name, _sc.getDefaultFunctionNamespace(), false);
}
/**
* Expands a qname and uses the default type/element namespace if
* unprefixed.
*
* @param name
* qname to expand.
* @return true on success.
*/
private boolean expandItemTypeQName(QName name) {
return expandQName(name, _sc.getDefaultNamespace(), false);
}
// the problem is that visistor interface does not throw exceptions...
// so we get around it ;D
private void reportError(StaticNameError err) {
_err = err;
throw new DummyError();
}
private void reportBadPrefix(String prefix) {
reportError(StaticNsNameError.unknown_prefix(prefix));
}
/**
* Check the XPath node.
*
* @param node
* is the XPath node to check.
* @throws StaticError
* static error.
*/
public void check(XPathNode node) throws StaticError {
try {
node.accept(this);
} catch (DummyError e) {
throw _err;
}
}
/**
* Validate an XPath by visiting all the nodes.
*
* @param xp
* is the XPath.
* @return null.
*/
public Object visit(XPath xp) {
for (Iterator i = xp.iterator(); i.hasNext();) {
Expr e = (Expr) i.next();
e.accept(this);
}
return null;
}
// does a for and a quantified expression
// takes the iterator for var expr paris
private void doForExpr(Iterator iter, Expr expr) {
int scopes = 0;
// add variables to scope and check the binding sequence
while (iter.hasNext()) {
VarExprPair pair = (VarExprPair) iter.next();
QName var = pair.varname();
if (!expandVarQName(var))
reportBadPrefix(var.prefix());
Expr e = pair.expr();
e.accept(this);
pushScope(var, BuiltinTypeLibrary.XS_ANYTYPE);
scopes++;
}
expr.accept(this);
// kill the scopes
for (int i = 0; i < scopes; i++)
popScope();
}
/**
* Validate a for expression.
*
* @param fex
* is the for expression.
* @return null.
*/
public Object visit(ForExpr fex) {
doForExpr(fex.iterator(), fex.expr());
return null;
}
/**
* Validate a quantified expression.
*
* @param qex
* is the quantified expression.
* @return null.
*/
public Object visit(QuantifiedExpr qex) {
// lets cheat
doForExpr(qex.iterator(), qex.expr());
return null;
}
private void visitExprs(Iterator i) {
while (i.hasNext()) {
Expr e = (Expr) i.next();
e.accept(this);
}
}
/**
* Validate an if expression.
*
* @param ifex
* is the if expression.
* @return null.
*/
public Object visit(IfExpr ifex) {
visitExprs(ifex.iterator());
ifex.then_clause().accept(this);
ifex.else_clause().accept(this);
return null;
}
/**
* Validate a binary expression by checking its left and right children.
*
* @param name
* is the name of the binary expression.
* @param e
* is the expression itself.
*/
public void printBinExpr(String name, BinExpr e) {
e.left().accept(this);
e.right().accept(this);
}
/**
* Validate an OR expression.
*
* @param orex
* is the expression.
* @return null.
*/
public Object visit(OrExpr orex) {
printBinExpr("OR", orex);
return null;
}
/**
* Validate an AND expression.
*
* @param andex
* is the expression.
* @return null.
*/
public Object visit(AndExpr andex) {
printBinExpr("AND", andex);
return null;
}
/**
* Validate a comparison expression.
*
* @param cmpex
* is the expression.
* @return null.
*/
public Object visit(CmpExpr cmpex) {
printBinExpr("CMP" + cmpex.type(), cmpex);
return null;
}
/**
* Validate a range expression.
*
* @param rex
* is the expression.
* @return null.
*/
public Object visit(RangeExpr rex) {
printBinExpr("RANGE", rex);
return null;
}
/**
* Validate an additon expression.
*
* @param addex
* is the expression.
* @return null.
*/
public Object visit(AddExpr addex) {
printBinExpr("ADD", addex);
return null;
}
/**
* Validate a subtraction expression.
*
* @param subex
* is the expression.
* @return null.
*/
public Object visit(SubExpr subex) {
printBinExpr("SUB", subex);
return null;
}
/**
* Validate a multiplication expression.
*
* @param mulex
* is the expression.
* @return null.
*/
public Object visit(MulExpr mulex) {
printBinExpr("MUL", mulex);
return null;
}
/**
* Validate a division expression.
*
* @param mulex
* is the expression.
* @return null.
*/
public Object visit(DivExpr mulex) {
printBinExpr("DIV", mulex);
return null;
}
/**
* Validate an integer divison expression.
*
* @param mulex
* is the expression.
* @return null.
*/
public Object visit(IDivExpr mulex) {
printBinExpr("IDIV", mulex);
return null;
}
/**
* Validate a mod expression.
*
* @param mulex
* is the expression.
* @return null.
*/
public Object visit(ModExpr mulex) {
printBinExpr("MOD", mulex);
return null;
}
/**
* Validate a union expression.
*
* @param unex
* is the expression.
* @return null.
*/
public Object visit(UnionExpr unex) {
printBinExpr("UNION", unex);
return null;
}
/**
* Validate a piped expression.
*
* @param pipex
* is the expression.
* @return null.
*/
public Object visit(PipeExpr pipex) {
printBinExpr("PIPE", pipex);
return null;
}
/**
* Validate an intersection expression.
*
* @param iexpr
* is the expression.
* @return null.
*/
public Object visit(IntersectExpr iexpr) {
printBinExpr("INTERSECT", iexpr);
return null;
}
/**
* Validate an except expression.
*
* @param eexpr
* is the expression.
* @return null.
*/
public Object visit(ExceptExpr eexpr) {
printBinExpr("INT_EXCEPT", eexpr);
return null;
}
/**
* Validate an 'instance of' expression.
*
* @param ioexp
* is the expression.
* @return null.
*/
public Object visit(InstOfExpr ioexp) {
printBinExpr("INSTANCEOF", ioexp);
return null;
}
/**
* Validate a 'treat as' expression.
*
* @param taexp
* is the expression.
* @return null.
*/
public Object visit(TreatAsExpr taexp) {
printBinExpr("TREATAS", taexp);
return null;
}
/**
* Validate a castable expression.
*
* @param cexp
* is the expression.
* @return null.
*/
public Object visit(CastableExpr cexp) {
printBinExpr("CASTABLE", cexp);
return null;
}
/**
* Validate a cast expression.
*
* @param cexp
* is the expression.
* @return null.
*/
public Object visit(CastExpr cexp) {
printBinExpr("CAST", cexp);
SingleType st = (SingleType) cexp.right();
QName type = st.type();
javax.xml.namespace.QName qName = type.asQName();
Function f = _sc.resolveFunction(qName, 1);
if (f == null)
reportError(new StaticFunctNameError("Type does not exist: "
+ type.toString()));
cexp.set_function(f);
_resolvedFunctions.add(qName);
return null;
}
/**
* Validate a unary expression by checking its one child.
*
* @param name
* is the name of the expression.
* @param e
* is the expression itself.
*/
public void printUnExpr(String name, UnExpr e) {
e.arg().accept(this);
}
/**
* Validate a minus expression.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(MinusExpr e) {
printUnExpr("MINUS", e);
return null;
}
/**
* Validate a plus expression.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(PlusExpr e) {
printUnExpr("PLUS", e);
return null;
}
/**
* Validate an xpath expression.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(XPathExpr e) {
XPathExpr xp = e;
boolean firstStep = true;
while (xp != null) {
if (firstStep && xp.slashes() != 0)
_rootUsed = true;
firstStep = false;
StepExpr se = xp.expr();
if (se != null)
se.accept(this);
xp = xp.next();
}
return null;
}
/**
* Validate a forward step.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(ForwardStep e) {
e.node_test().accept(this);
_axes.add(e.iterator().name());
return null;
}
/**
* Validate a reverse step.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(ReverseStep e) {
NodeTest nt = e.node_test();
if (nt != null)
nt.accept(this);
ReverseAxis iterator = e.iterator();
if (iterator != null)
_axes.add(iterator.name());
return null;
}
/**
* Validate a name test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(NameTest e) {
QName name = e.name();
if (!expandItemQName(name))
reportBadPrefix(name.prefix());
return null;
}
/**
* Validate a variable reference.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(VarRef e) {
QName var = e.name();
if (!expandVarQName(var))
reportBadPrefix(var.prefix());
if (! isVariableInScope(var))
reportError(new StaticNameError(StaticNameError.NAME_NOT_FOUND));
if (getVariableType(var) == null)
reportError(new StaticNameError(StaticNameError.NAME_NOT_FOUND));
// The variable is good. If it was not captured, it must be referring to an external var
if (! isVariableCaptured(var)) _freeVariables.add(var.asQName());
return null;
}
/**
* Validate a string literal.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(StringLiteral e) {
return null;
}
/**
* Validate an integer literal.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(IntegerLiteral e) {
return null;
}
/**
* Validate a double literal.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(DoubleLiteral e) {
return null;
}
/**
* Validate a decimal literal.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(DecimalLiteral e) {
return null;
}
/**
* Validate a parenthesized expression.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(ParExpr e) {
visitExprs(e.iterator());
return null;
}
/**
* Validate a context item expression.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(CntxItemExpr e) {
return null;
}
/**
* Validate a function call.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(FunctionCall e) {
QName name = e.name();
if (!expandFunctionQName(name))
reportBadPrefix(name.prefix());
javax.xml.namespace.QName qName = name.asQName();
Function f = _sc.resolveFunction(qName, e.arity());
if (f == null)
reportError(new StaticFunctNameError("Function does not exist: "
+ name.string() + " arity: " + e.arity()));
e.set_function(f);
_resolvedFunctions.add(qName);
visitExprs(e.iterator());
return null;
}
/**
* Validate a single type.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(SingleType e) {
QName type = e.type();
if (!expandItemTypeQName(type))
reportBadPrefix(type.prefix());
return null;
}
/**
* Validate a sequence type.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(SequenceType e) {
ItemType it = e.item_type();
if (it != null)
it.accept(this);
return null;
}
/**
* Validate an item type.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(ItemType e) {
switch (e.type()) {
case ItemType.ITEM:
break;
case ItemType.QNAME:
QName type = e.qname();
if (!expandItemTypeQName(type))
reportBadPrefix(type.prefix());
if (BuiltinTypeLibrary.BUILTIN_TYPES.lookupType(e.qname().namespace(), e.qname().local()) == null) {
if (_sc.getTypeModel() == null || _sc.getTypeModel().lookupType(e.qname().namespace(), e.qname().local()) == null)
reportError(new StaticTypeNameError("Type not defined: "
+ e.qname().string()));
}
break;
case ItemType.KINDTEST:
e.kind_test().accept(this);
break;
}
return null;
}
/**
* Validate an any kind test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(AnyKindTest e) {
return null;
}
/**
* Validate a document test.
*
* @param e
* is the expression.
* @return null.
*/
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 null;
}
/**
* Validate a text test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(TextTest e) {
return null;
}
/**
* Validate a comment test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(CommentTest e) {
return null;
}
/**
* Validate a processing instructing test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(PITest e) {
String arg = e.arg();
if (arg == null)
arg = "";
return null;
}
/**
* Validate an attribute test.
*
* @param e
* is the expression.
* @return null.
*/
// XXX NO CHECK ?
public Object visit(AttributeTest e) {
QName name = e.name();
if (name != null) {
if (!expandItemQName(name))
reportBadPrefix(name.prefix());
}
name = e.type();
if (name != null) {
if (!expandItemTypeQName(name))
reportBadPrefix(name.prefix());
}
return null;
}
/**
* Validate a schema attribute test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(SchemaAttrTest e) {
QName name = e.arg();
if (!expandItemQName(name))
reportBadPrefix(name.prefix());
if (_sc.getTypeModel().lookupAttributeDeclaration(name.namespace(), name.local()) == null)
reportError(new StaticAttrNameError("Attribute not decleared: "
+ name.string()));
return null;
}
/**
* Validate an element test.
*
* @param e
* is the expression.
* @return null.
*/
// XXX NO SEMANTIC CHECK?!
public Object visit(ElementTest e) {
if (e.name() != null) {
if (!expandItemTypeQName(e.name()))
reportBadPrefix(e.name().prefix());
}
if (e.type() != null) {
if (!expandItemTypeQName(e.type()))
reportBadPrefix(e.type().prefix());
}
return null;
}
/**
* Validate a schema element test.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(SchemaElemTest e) {
QName elem = e.name();
if (!expandItemQName(elem))
reportBadPrefix(elem.prefix());
if (_sc.getTypeModel().lookupElementDeclaration(elem.namespace(), elem.local()) == null)
reportError(new StaticElemNameError("Element not declared: "
+ elem.string()));
return null;
}
private void visitCollExprs(Iterator i) {
while (i.hasNext()) {
Collection exprs = (Collection) i.next();
visitExprs(exprs.iterator());
}
}
/**
* Validate an axis step.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(AxisStep e) {
e.step().accept(this);
visitCollExprs(e.iterator());
return null;
}
/**
* Validate a filter expression.
*
* @param e
* is the expression.
* @return null.
*/
public Object visit(FilterExpr e) {
e.primary().accept(this);
visitCollExprs(e.iterator());
return null;
}
/**
* @since 2.0
*/
public boolean isRootUsed() {
return _rootUsed;
}
}