package lux.functions; import java.util.Iterator; import lux.Evaluator; import lux.query.parser.LuxQueryParser; import net.sf.saxon.dom.NodeOverNodeInfo; import net.sf.saxon.expr.Expression; import net.sf.saxon.expr.StaticContext; import net.sf.saxon.expr.instruct.SavedNamespaceContext; import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.lib.NamespaceConstant; import net.sf.saxon.om.Item; import net.sf.saxon.om.NamespaceResolver; import net.sf.saxon.om.NodeInfo; import net.sf.saxon.trans.XPathException; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.xml.ParserException; import org.apache.lucene.search.Query; import org.w3c.dom.Element; public abstract class NamespaceAwareFunctionCall extends ExtensionFunctionCall { private NamespaceResolver namespaceResolver; public NamespaceResolver getNamespaceResolver() { return namespaceResolver; } @Override public void supplyStaticContext (StaticContext context, int locationId, Expression[] arguments) { namespaceResolver = context.getNamespaceResolver(); if (!(namespaceResolver instanceof SavedNamespaceContext)) { namespaceResolver = new SavedNamespaceContext(namespaceResolver); } } @Override public void copyLocalData (ExtensionFunctionCall destination) { ((NamespaceAwareFunctionCall) destination).namespaceResolver = namespaceResolver; } protected Query parseQuery(Item queryArg, Evaluator eval) throws XPathException { if (queryArg instanceof NodeInfo) { NodeInfo queryNodeInfo = (NodeInfo) queryArg; NodeOverNodeInfo queryDocument = NodeOverNodeInfo.wrap(queryNodeInfo); if (queryDocument instanceof Element) { try { return eval.getXmlQueryParser().getQuery((Element) queryDocument); } catch (ParserException e) { throw new XPathException ("Failed to parse xml query : " + e.getMessage(), e); } } // maybe it was a text node? } // parse the string value using the Lux query parser LuxQueryParser luxQueryParser = eval.getLuxQueryParser(); // declare all of the in-scope namespace bindings Iterator<String> prefixes = namespaceResolver.iteratePrefixes(); while (prefixes.hasNext()) { String prefix = prefixes.next(); String nsURI = namespaceResolver.getURIForPrefix(prefix, false); if (! NamespaceConstant.isReservedInQuery(nsURI)) { luxQueryParser.bindNamespacePrefix(prefix, nsURI); } } try { return luxQueryParser.parse(queryArg.getStringValue()); } catch (ParseException e) { throw new XPathException (e.getMessage(), e); } } }