Package client.net.sf.saxon.ce.functions

Source Code of client.net.sf.saxon.ce.functions.SystemFunction

package client.net.sf.saxon.ce.functions;

import client.net.sf.saxon.ce.expr.*;
import client.net.sf.saxon.ce.lib.NamespaceConstant;
import client.net.sf.saxon.ce.om.StructuredQName;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.type.AnyItemType;
import client.net.sf.saxon.ce.type.ItemType;
import client.net.sf.saxon.ce.type.TypeHierarchy;
import client.net.sf.saxon.ce.value.SequenceType;


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

public abstract class SystemFunction extends FunctionCall {

    /**
     * Make a system function call (one in the standard function namespace).
     * @param name The local name of the function.
     * @param arguments the arguments to the function call
     * @return a FunctionCall that implements this function, if it
     * exists, or null if the function is unknown.
     */

    public static FunctionCall makeSystemFunction(String name, Expression[] arguments) {
        StandardFunction.Entry entry = StandardFunction.getFunction(name, arguments.length);
        if (entry==null) {
            return null;
        }
        SystemFunction f = entry.skeleton.newInstance();
        f.setDetails(entry);
        f.setFunctionName(new StructuredQName("", NamespaceConstant.FN, name));
        f.setArguments(arguments);
        return f;
    }


    private StandardFunction.Entry details;
    protected int operation;

    /**
     * Set the details of this type of function
     * @param entry information giving details of the function signature
    */

    public void setDetails(StandardFunction.Entry entry) {
        details = entry;
    }

    /**
     * Get the details of the function signature
     * @return information about the function signature
    */

    public StandardFunction.Entry getDetails() {
        return details;
    }

    /**
    * Method called during static type checking
    */

    public void checkArguments(ExpressionVisitor visitor) throws XPathException {
        checkArgumentCount(details.minArguments, details.maxArguments, visitor);
        for (int i=0; i<argument.length; i++) {
            checkArgument(i, visitor);
        }
    }

    /**
     * Perform static type checking on an argument to a function call, and add
     * type conversion logic where necessary.
     * @param arg argument number, zero-based
     * @param visitor an expression visitor
    */

    private void checkArgument(int arg, ExpressionVisitor visitor) throws XPathException {
        RoleLocator role = new RoleLocator(RoleLocator.FUNCTION,
                getFunctionName(), arg);
        //role.setSourceLocator(this);
        role.setErrorCode(getErrorCodeForTypeErrors());
        argument[arg] = TypeChecker.staticTypeCheck(
                                argument[arg],
                                getRequiredType(arg),
                                visitor.getStaticContext().isInBackwardsCompatibleMode(),
                                role, visitor);
    }


    /**
     * Copy an expression. This makes a deep copy.
     *
     * @return the copy of the original expression
     */

    public abstract SystemFunction newInstance();

    /**
     * Return the error code to be used for type errors. This is overridden for functions
     * such as exactly-one(), one-or-more(), ...
     * @return the error code to be used for type errors in the function call. Normally XPTY0004,
     * but different codes are used for functions such as exactly-one()
     */

    public String getErrorCodeForTypeErrors() {
        return "XPTY0004";
    }

    /**
     * Get the required type of the nth argument
     * @param arg the number of the argument whose type is requested, zero-based
     * @return the required type of the argument as defined in the function signature
    */

    protected SequenceType getRequiredType(int arg) {
        if (details == null) {
            return SequenceType.ANY_SEQUENCE;
        }
        return details.argumentTypes[arg];
        // this is overridden for concat()
    }

    /**
    * Determine the item type of the value returned by the function
     * @param th the type hierarchy cache
     */

    public ItemType getItemType(TypeHierarchy th) {
        ItemType type = details.resultType.getPrimaryType();
        if (details.sameItemTypeAsFirstArgument) {
            if (argument.length > 0) {
                return argument[0].getItemType(th);
            } else {
                return AnyItemType.getInstance();
                // if there is no first argument, an error will be reported
            }
        } else {
            return type;
        }
    }

    /**
    * Determine the cardinality of the function.
    */

    public int computeCardinality() {
        return details.resultType.getCardinality();
    }

    /**
     * Determine the special properties of this expression. The general rule
     * is that a system function call is non-creative if its return type is
     * atomic, or if all its arguments are non-creative. This is overridden
     * for the generate-id() function, which is considered creative if
     * its operand is creative (because the result depends on the
     * identity of the operand)
     */

    public int computeSpecialProperties() {
        int p = super.computeSpecialProperties();
        if (details == null) {
            return p;
        }
        if (details.resultType.getPrimaryType().isAtomicType()) {
            return p | StaticProperty.NON_CREATIVE;
        }
        for (int i=0; i<argument.length; i++) {
            if ((argument[i].getSpecialProperties() & StaticProperty.NON_CREATIVE) == 0) {
                // the argument is creative
                return p;
            }
        }
        return p | StaticProperty.NON_CREATIVE;
    }

    /**
    * Set "." as the default value for the first and only argument. Called from subclasses.
    */

    protected final void useContextItemAsDefault() {
        if (argument.length==0) {
            argument = new Expression[1];
            argument[0] = new ContextItemExpression();
            ExpressionTool.copyLocationInfo(this, argument[0]);
            resetLocalStaticProperties();
        }
        // Note that the extra argument is added before type-checking takes place. The
        // type-checking will add any necessary checks to ensure that the context item
        // is a node, in cases where this is required.
    }

    /**
    * Add an implicit argument referring to the context document. Called by functions such as
    * id() and key() that take the context document as an implicit argument
     * @param pos the position of the argument whose default value is ".", zero-based
     * @param augmentedName the name to be used for the function call with its extra argument.
     * There are some cases where user function calls cannot supply the argument directly (notably
     * unparsed-entity-uri() and unparsed-entity-public-id()) and in these cases a synthesized
     * function name is used for the new function call.
    */

    protected final void addContextDocumentArgument(int pos, String augmentedName)
    throws XPathException {
        if (argument.length > pos) {
            return;
            // this can happen during optimization, if the extra argument is already present
        }
        if (argument.length != pos) {
            throw new XPathException("Too few arguments in call to " + augmentedName + "() function");
        }
        Expression[] newArgs = new Expression[pos+1];
        System.arraycopy(argument, 0, newArgs, 0, argument.length);
        RootExpression rootExpression = new RootExpression();
        ExpressionTool.copyLocationInfo(this, rootExpression);
        newArgs[pos] = rootExpression;
        argument = newArgs;
        setDetails(StandardFunction.getFunction(augmentedName, newArgs.length));
    }

}

// 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.
TOP

Related Classes of client.net.sf.saxon.ce.functions.SystemFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.