package lux.xpath;
import lux.index.FieldRole;
import lux.xml.QName;
import lux.xml.ValueType;
public class FunCall extends AbstractExpression {
public static final String LUX_NAMESPACE = lux.Evaluator.LUX_NAMESPACE;
private final QName name;
private final ValueType returnType;
public FunCall (QName name, ValueType returnType, AbstractExpression ... arguments) {
super (Type.FUNCTION_CALL);
this.name = name;
setSubs (arguments);
this.returnType = returnType;
}
public void setArguments (AbstractExpression ... args) {
setSubs (args);
}
@Override
public void toString(StringBuilder buf) {
buf.append (name);
buf.append ('(');
if (subs.length == 1) {
buf.append (subs[0]);
}
else if (subs.length > 1) {
subs[0].toString(buf);
}
for (int i = 1; i < subs.length; i++) {
buf.append (',');
subs[i].toString(buf);
}
buf.append (')');
}
public QName getName() {
return name;
}
/**
* @return 100; the outer precedence.
*/
@Override public int getPrecedence () {
return 100;
}
public static final QName LUX_SEARCH = new QName (LUX_NAMESPACE, "search", "lux");
public static final QName LUX_COUNT = new QName (LUX_NAMESPACE, "count", "lux");
public static final QName LUX_EXISTS = new QName (LUX_NAMESPACE, "exists", "lux");
public static final QName LUX_KEY = new QName (LUX_NAMESPACE, "key", "lux");
public static final QName LUX_FIELD_VALUES = new QName (LUX_NAMESPACE, "field-values", "lux");
public static final String FN_NAMESPACE = "http://www.w3.org/2005/xpath-functions";
public static final QName FN_ROOT = new QName (FN_NAMESPACE, "root", "fn");
public static final QName FN_LAST = new QName (FN_NAMESPACE, "last", "fn");
public static final QName FN_DATA = new QName (FN_NAMESPACE, "data", "fn");
public static final QName FN_UNORDERED = new QName (FN_NAMESPACE, "unordered", "fn");
public static final QName FN_SUBSEQUENCE = new QName (FN_NAMESPACE, "subsequence", "fn");
public static final QName FN_COUNT = new QName (FN_NAMESPACE, "count", "fn");
public static final QName FN_EXISTS = new QName (FN_NAMESPACE, "exists", "fn");
public static final QName FN_NOT = new QName (FN_NAMESPACE, "not", "fn");
public static final QName FN_EMPTY = new QName (FN_NAMESPACE, "empty", "fn");
public static final QName FN_COLLECTION = new QName (FN_NAMESPACE, "collection", "fn");
public static final QName FN_STRING_JOIN = new QName (FN_NAMESPACE, "string-join", "fn");
public static final QName FN_CONTAINS = new QName(FN_NAMESPACE, "contains", "fn");
public static final QName FN_MIN = new QName(FN_NAMESPACE, "min", "fn");
public static final QName FN_MAX = new QName(FN_NAMESPACE, "max", "fn");
public static final String LOCAL_NAMESPACE = "http://www.w3.org/2005/xquery-local-functions";
public static final String XS_NAMESPACE = "http://www.w3.org/2001/XMLSchema";
// represent last() in Subsequence(foo, last()); ie foo[last()].
public static final FunCall LastExpression = new FunCall (FN_LAST, ValueType.VALUE);
@Override
public AbstractExpression accept(ExpressionVisitor visitor) {
super.acceptSubs(visitor);
return visitor.visit(this);
}
public ValueType getReturnType() {
return returnType;
}
@Override
public boolean isDocumentOrdered () {
if (returnType.isAtomic) {
return false;
}
if (name.getNamespaceURI().equals(LUX_NAMESPACE)) {
if (name.getLocalPart().equals("search")) {
// if we are returning results ordered by docid, that is document ordered already
if (getSubs().length > 1) {
AbstractExpression sortExpr = getSubs()[1];
if (sortExpr instanceof LiteralExpression) {
if (((LiteralExpression)sortExpr).getValue().equals (FieldRole.LUX_DOCID)) {
return true;
}
}
}
// ordered some other way
return false;
}
}
if (name.getNamespaceURI().equals(FN_NAMESPACE)) {
if (name.getLocalPart().equals ("reverse") || name.getLocalPart().equals("unordered")) {
return false;
}
if (name.getLocalPart().equals("root")) {
return false;
}
return super.isDocumentOrdered();
}
return false;
}
/**
* @return for "transparent" functions that return their argument, like
* data() and typecasts, the argument's rightmost subexpression (last
* context step) is returned. For other functions, the function
* expression itself is returned.
*/
@Override
public AbstractExpression getLastContextStep () {
if (name.getNamespaceURI().equals(XS_NAMESPACE) ||
(name.getNamespaceURI().equals(FN_NAMESPACE) &&
name.getLocalPart().equals("data"))) {
return subs[0].getLastContextStep();
}
return this;
}
@Override
public AbstractExpression getRoot () {
if (name.equals(LUX_SEARCH)) {
return this;
}
if (name.equals(FN_UNORDERED) || name.equals(FN_SUBSEQUENCE)) {
return getSubs()[0].getRoot();
}
return null;
}
@Override
public boolean propEquals (AbstractExpression other) {
return name.equals(((FunCall) other).name) &&
returnType.equals(((FunCall) other).returnType);
}
@Override
public int equivHash () {
return 43 + returnType.ordinal() + name.hashCode();
}
@Override
public boolean isRestrictive () {
return (name.equals(FunCall.FN_ROOT) || name.equals(FunCall.FN_DATA) || name.equals(FunCall.FN_EXISTS));
}
}
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */