package org.basex.api.jaxp;
import java.io.IOException;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import org.basex.api.dom.BXNList;
import org.basex.core.BaseXException;
import org.basex.core.Context;
import org.basex.core.cmd.CreateDB;
import org.basex.data.Data;
import org.basex.data.Nodes;
import org.basex.data.Result;
import org.basex.io.out.ArrayOutput;
import org.basex.io.serial.Serializer;
import org.basex.query.QueryException;
import org.basex.query.QueryProcessor;
import org.basex.query.item.DBNode;
import org.xml.sax.InputSource;
/**
* This class provides an API for standalone XPath processing.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class BXPathExpression implements XPathExpression {
/** Query context. */
private final Context context = new Context();
/** Query context. */
private final QueryProcessor xproc;
/**
* Constructor.
* @param qu query
*/
BXPathExpression(final String qu) {
xproc = new QueryProcessor(qu, context);
}
@Override
public String evaluate(final Object item) throws XPathExpressionException {
return evaluate(item, XPathConstants.STRING).toString();
}
@Override
public String evaluate(final InputSource is) throws XPathExpressionException {
return evaluate(is, XPathConstants.STRING).toString();
}
@Override
public Object evaluate(final Object item, final QName res)
throws XPathExpressionException {
return finish(execute(), res);
}
@Override
public Object evaluate(final InputSource is, final QName res)
throws XPathExpressionException {
try {
new CreateDB(is.getSystemId()).execute(context);
return finish(execute(), res);
} catch(final BaseXException ex) {
throw new XPathExpressionException(ex.getMessage());
}
}
/**
* Executes the current query.
* @return result
* @throws XPathExpressionException xpath exception
*/
private Result execute() throws XPathExpressionException {
try {
return xproc.execute();
} catch(final QueryException ex) {
throw new XPathExpressionException(ex);
}
}
/**
* Finishes the query result.
* @param item input
* @param res result type
* @return result
* @throws XPathExpressionException xpath exception
*/
private static Object finish(final Result item, final QName res)
throws XPathExpressionException {
final Nodes nodes = item instanceof Nodes ? (Nodes) item : null;
if(res == XPathConstants.NODESET || res == XPathConstants.NODE) {
if(nodes == null) throw new XPathExpressionException(
"Result can't be cast to a nodeset");
if(nodes.size() == 0) return null;
final Data data = nodes.data;
return res == XPathConstants.NODESET ? new BXNList(nodes) :
new DBNode(data, nodes.list[0]).toJava();
}
try {
final ArrayOutput ao = new ArrayOutput();
final Serializer ser = Serializer.get(ao);
item.serialize(ser);
ser.close();
final String val = ao.toString();
if(res == XPathConstants.NUMBER) return Double.valueOf(val);
if(res == XPathConstants.STRING) return val;
if(res == XPathConstants.BOOLEAN) return Boolean.valueOf(val);
throw new XPathExpressionException("Invalid type: " + res);
} catch(final IOException ex) {
throw new XPathExpressionException(ex);
}
}
}