All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.expr.FunctionCall Maven / Gradle / Ivy

There is a newer version: 10.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Saxonica Limited.
// 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/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.expr;

import net.sf.saxon.expr.parser.ExpressionTool;
import net.sf.saxon.expr.parser.ExpressionVisitor;
import net.sf.saxon.expr.parser.PathMap;
import net.sf.saxon.expr.parser.PromotionOffer;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.NoDynamicContextException;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.util.FastStringBuffer;
import net.sf.saxon.value.SequenceExtent;

import java.util.Arrays;
import java.util.Iterator;

/**
* Abstract superclass for calls to system-defined and user-defined functions
*/

public abstract class FunctionCall extends Expression {

    /**
     * The name of the function
     */

    private StructuredQName name;

    /**
    * The array of expressions representing the actual parameters
    * to the function call
    */

    protected Expression[] argument;

    /**
     * Set the name of the function being called
     * @param name the name of the function
     */

    public final void setFunctionName(StructuredQName name) {
        this.name = name;
    }

    /**
     * Get the qualified of the function being called
     * @return the qualified name
     */

    public StructuredQName getFunctionName() {
        return name;
    }

    /**
     * Determine the number of actual arguments supplied in the function call
     * @return the arity (the number of arguments)
     */

    public final int getNumberOfArguments() {
        return argument.length;
    }

    /**
     * Method called by the expression parser when all arguments have been supplied
     * @param args the expressions contained in the argument list of the function call
     */

    public void setArguments(Expression[] args) {
        argument = args;
        for (Expression arg : args) {
            adoptChildExpression(arg);
        }
    }

    /**
     * Get the expressions supplied as actual arguments to the function
     * @return the array of expressions supplied in the argument list of the function call
     */

    public Expression[] getArguments() {
        return argument;
    }

    /**
    * Simplify the function call. Default method is to simplify each of the supplied arguments and
    * evaluate the function if all are now known.
     * @param visitor an expression visitor
     */

    /*@NotNull*/
    public Expression simplify(ExpressionVisitor visitor) throws XPathException {
        return simplifyArguments(visitor);
    }

    /**
     * Simplify the arguments of the function.
     * Called from the simplify() method of each function.
     * @return the result of simplifying the arguments of the expression
     * @param visitor an expression visitor
     * @throws net.sf.saxon.trans.XPathException if an error occurs
     */

    protected final Expression simplifyArguments(ExpressionVisitor visitor) throws XPathException {
        for (int i=0; i
     * 

This method is called after all references to functions and variables have been resolved * to the declaration of the function or variable, and after all type checking has been done.

* * @param visitor an expression visitor * @param contextItemType the static type of "." at the point where this expression is invoked. * The parameter is set to null if it is known statically that the context item will be undefined. * If the type of the context item is not known statically, the argument is set to * {@link net.sf.saxon.type.Type#ITEM_TYPE} * @return the original expression, rewritten if appropriate to optimize execution * @throws XPathException if an error is discovered during this phase * (typically a type error) */ /*@NotNull*/ public Expression optimize(ExpressionVisitor visitor, ExpressionVisitor.ContextItemType contextItemType) throws XPathException { boolean fixed = true; for (int i=0; i * A convenience routine for use in subclasses. * @param min the minimum number of arguments allowed * @param max the maximum number of arguments allowed * @return the actual number of arguments * @throws net.sf.saxon.trans.XPathException if the number of arguments is out of range */ protected int checkArgumentCount(int min, int max) throws XPathException { int numArgs = argument.length; String msg = null; if (min==max && numArgs != min) { msg = "Function " + getDisplayName() + " must have " + min + pluralArguments(min); } else if (numArgs < min) { msg = "Function " + getDisplayName() + " must have at least " + min + pluralArguments(min); } else if (numArgs > max) { msg = "Function " + getDisplayName() + " must have no more than " + max + pluralArguments(max); } if (msg != null) { XPathException err = new XPathException(msg, "XPST0017"); err.setIsStaticError(true); err.setLocator(this); throw err; } return numArgs; } /** * Utility routine used in constructing error messages: get the word "argument" or "arguments" * @param num the number of arguments * @return the singular or plural word */ private static String pluralArguments(int num) { if (num==1) return " argument"; return " arguments"; } /** * Get the immediate subexpressions of this expression */ /*@NotNull*/ public Iterator iterateSubExpressions() { // try { return Arrays.asList(argument).iterator(); // } catch (NullPointerException err) { // // typically caused by doing CopyLocationInfo after creating the function // // but before creating its arguments // throw err; // } } /** * Replace one subexpression by a replacement subexpression * @param original the original subexpression * @param replacement the replacement subexpression * @return true if the original subexpression is found */ public boolean replaceSubExpression(Expression original, Expression replacement) { boolean found = false; for (int i=0; i *

The default implementation of this method assumes that an expression does no navigation other than * the navigation done by evaluating its subexpressions, and that the subexpressions are evaluated in the * same context as the containing expression. The method must be overridden for any expression * where these assumptions do not hold. For example, implementations exist for AxisExpression, ParentExpression, * and RootExpression (because they perform navigation), and for the doc(), document(), and collection() * functions because they create a new navigation root. Implementations also exist for PathExpression and * FilterExpression because they have subexpressions that are evaluated in a different context from the * calling expression.

* * @param pathMap the PathMap to which the expression should be added * @param pathMapNodes the node in the PathMap representing the focus at the point where this expression * is called. Set to null if this expression appears at the top level, in which case the expression, if it * is registered in the path map at all, must create a new path map root. * @return the pathMapNode representing the focus established by this expression, in the case where this * expression is the first operand of a path expression or filter expression. For an expression that does * navigation, it represents the end of the arc in the path map that describes the navigation route. For other * expressions, it is the same as the input pathMapNode. */ public PathMap.PathMapNodeSet addExternalFunctionCallToPathMap(PathMap pathMap, PathMap.PathMapNodeSet pathMapNodes) { // Except in the case of system functions, we have no idea where a function call might // navigate, so we assume the worst, and register that the path has unknown dependencies PathMap.PathMapNodeSet result = new PathMap.PathMapNodeSet(); for (Iterator iter = iterateSubExpressions(); iter.hasNext(); ) { Expression child = (Expression)iter.next(); result.addNodeSet(child.addToPathMap(pathMap, pathMapNodes)); } result.setHasUnknownDependencies(); return result; } /** * Get a name identifying the kind of expression, in terms meaningful to a user. * @return a name identifying the kind of expression, in terms meaningful to a user. * The name will always be in the form of a lexical XML QName, and should match the name used * in explain() output displaying the expression. */ public final String getExpressionName() { return getDisplayName(); } /** * Get the name of the function for display in messages * @return the name of the function as a lexical QName */ public final String getDisplayName() { StructuredQName fName = getFunctionName(); return (fName == null ? "(anonymous)" : fName.getDisplayName()); } /** * The toString() method for an expression attempts to give a representation of the expression * in an XPath-like form, but there is no guarantee that the syntax will actually be true XPath. * In the case of XSLT instructions, the toString() method gives an abstracted view of the syntax */ public String toString() { FastStringBuffer buff = new FastStringBuffer(FastStringBuffer.SMALL); StructuredQName fName = getFunctionName(); String f; if (fName == null) { f = "$anonymousFunction"; } else if (fName.isInNamespace(NamespaceConstant.FN)) { f = fName.getLocalPart(); } else { f = fName.getEQName(); } buff.append(f); Iterator iter = iterateSubExpressions(); boolean first = true; while (iter.hasNext()) { buff.append(first ? "(" : ", "); buff.append(iter.next().toString()); first = false; } buff.append(first ? "()" : ")"); return buff.toString(); } /** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. */ public void explain(ExpressionPresenter out) { out.startElement("functionCall"); out.emitAttribute("name", getDisplayName()); for (Expression anArgument : argument) { anArgument.explain(out); } out.endElement(); } /** * Determine whether two expressions are equivalent */ public boolean equals(Object o) { if (!(o instanceof FunctionCall)) { return false; } FunctionCall f = (FunctionCall)o; if (!getFunctionName().equals(f.getFunctionName())) { return false; } if (getNumberOfArguments() != f.getNumberOfArguments()) { return false; } for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy