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

net.sf.saxon.query.XQueryFunction Maven / Gradle / Ivy

package net.sf.saxon.query;

import net.sf.saxon.Configuration;
import net.sf.saxon.event.LocationProvider;
import net.sf.saxon.expr.*;
import net.sf.saxon.functions.ExecutableFunctionLibrary;
import net.sf.saxon.instruct.*;
import net.sf.saxon.om.*;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trace.InstructionInfo;
import net.sf.saxon.trace.Location;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class XQueryFunction implements InstructionInfo, Container, Declaration {
    private StructuredQName functionName;
    private List arguments;              // A list of UserFunctionParameter objects
    private SequenceType resultType;
    private Expression body = null;
    private List references = new ArrayList(10);
    private int lineNumber;
    private int columnNumber;
    private String systemId;
    private Executable executable;
    private UserFunction compiledFunction = null;
    private boolean memoFunction;
    private NamespaceResolver namespaceResolver;
    private StaticContext staticContext;

    /**
     * Create an XQuery function
     */

    public XQueryFunction() {
        arguments = new ArrayList(8);
    }

    /**
     * Set the name of the function
     * @param name the name of the function as a StructuredQName object
     */

    protected void setFunctionName(StructuredQName name) {
        functionName = name;
    }

    /**
     * Set the arguments of the function
     * @param arguments a list of the arguments of the function, as a list whose
     * members are instances of {@link UserFunctionParameter}
     */

//    protected void setArgumentList(List arguments) {
//        this.arguments = arguments;
//    }

    /**
     * Add an argument to the list of arguments
     * @param argument the formal declaration of the argument to be added
     */

    protected void addArgument(UserFunctionParameter argument) {
        arguments.add(argument);
    }

    /**
     * Set the required result type of the function
     * @param resultType the declared result type of the function
     */

    protected void setResultType(SequenceType resultType) {
        this.resultType = resultType;
    }

    /**
     * Set the body of the function
     * @param body the expression forming the body of the function
     */

    protected void setBody(Expression body) {
        this.body = body;
        if (body != null) {
            body.setContainer(this);
        }
    }

    /**
     * Get the body of the function
     * @return the expression making up the body of the function
     */

    public Expression getBody() {
        return body;
    }

    /**
     * Set the system ID of the module containing the function
     * @param systemId the system ID (= base URI) of the module containing the function
     */

    protected void setSystemId(String systemId) {
        this.systemId = systemId;
    }

    /**
     * Set the line number of the function declaration within its module
     * @param line the line number of the function declaration
     */

    protected void setLineNumber(int line) {
        lineNumber = line;
    }

    /**
     * Set the column number of the function declaration
     * @param column the column number of the function declaration
     */

    protected void setColumnNumber(int column) {
        columnNumber = column;
    }

    /**
     * Get the name of the function as a structured QName
     * @return the name of the function as a structured QName
     */

    public StructuredQName getFunctionName() {
        return functionName;
    }

    /**
     * Get the name of the function for display in error messages
     * @return the name of the function as a lexical QName
     */

    public String getDisplayName() {
        return functionName.getDisplayName();
    }

    /**
     * Get an identifying key for this function, which incorporates the URI and local part of the
     * function name plus the arity
     * @return an identifying key
     */

    public String getIdentificationKey() {
        return functionName.getClarkName() + '/' + arguments.size();
    }

    /**
     * Construct what the identification key would be for a function with given URI, local name, and arity
     * @param uri the URI part of the function name
     * @param localName the local part of the function name
     * @param arity the number of arguments in the function
     * @return an identifying key
     */

    public static String getIdentificationKey(String uri, String localName, int arity) {
        FastStringBuffer sb = new FastStringBuffer(uri.length() + localName.length() + 8);
        sb.append('{');
        sb.append(uri);
        sb.append('}');
        sb.append(localName);
        sb.append('/');
        sb.append(arity+"");
        return sb.toString();
    }

    /**
     * Construct what the identification key would be for a function with given URI, local name, and arity
     * @param qName the name of the function
     * @param arity the number of arguments
     * @return an identifying key
     */

    public static String getIdentificationKey(StructuredQName qName, int arity) {
        String uri = qName.getNamespaceURI();
        String localName = qName.getLocalName();
        FastStringBuffer sb = new FastStringBuffer(uri.length() + localName.length() + 8);
        sb.append('{');
        sb.append(uri);
        sb.append('}');
        sb.append(localName);
        sb.append('/');
        sb.append(arity+"");
        return sb.toString();
    }

    /**
     * Get the result type of the function
     * @return the declared result type
     */

    public SequenceType getResultType() {
        return resultType;
    }

    /**
     * Set the executable in which this function is contained
     * @param exec the executable
     */

    public void setExecutable(Executable exec) {
        executable = exec;
    }

    /**
     * Get the executable in which this function is contained
     * @return the executable
     */

    public Executable getExecutable() {
        return executable;
    }

    /**
     * Get the LocationProvider allowing location identifiers to be resolved.
     * @return the location provider
     */

    public LocationProvider getLocationProvider() {
        return executable.getLocationMap();
    }

    /**
     * Set the static context for this function
     * @param env the static context for the module in which the function is declared
     */

    public void setStaticContext(StaticContext env) {
        staticContext = env;
    }

    /**
     * Get the static context for this function
     * @return the static context for the module in which the function is declared
     */

    public StaticContext getStaticContext() {
        return staticContext;
    }

    /**
     * Get the declared types of the arguments of this function
     * @return an array, holding the types of the arguments in order
     */

    public SequenceType[] getArgumentTypes() {
        SequenceType[] types = new SequenceType[arguments.size()];
        for (int i=0; i 0, tailCalls > 1);
            body = new TailCallLoop(compiledFunction);
        }

        body.setContainer(this);
        compiledFunction.setBody(body);
        compiledFunction.computeEvaluationMode();
        ExpressionTool.allocateSlots(body, arity, compiledFunction.getStackFrameMap());
    }

    /**
     * Fix up references to this function
     * @param env the static context
     */

    public void fixupReferences(StaticContext env) throws XPathException {
        Iterator iter = references.iterator();
        while (iter.hasNext()) {
            UserFunctionCall ufc = (UserFunctionCall)iter.next();
            ufc.setFunction(compiledFunction);
            ufc.computeArgumentEvaluationModes();
        }
    }

    /**
     * Type-check references to this function
     * @param visitor the expression visitor
     */

    public void checkReferences(ExpressionVisitor visitor) throws XPathException {
        Iterator iter = references.iterator();
        while (iter.hasNext()) {
            UserFunctionCall ufc = (UserFunctionCall)iter.next();
            ufc.checkFunctionCall(compiledFunction, visitor);
            ufc.computeArgumentEvaluationModes();
        }

        // clear the list of references, so that more can be added in another module
        references = new ArrayList(0);

    }

    /**
     * Produce diagnostic output showing the compiled and optimized expression tree for a function
     * @param out the destination to be used
     */
    public void explain(ExpressionPresenter out) {
        out.startElement("declareFunction");
        out.emitAttribute("name", functionName.getDisplayName());
        out.emitAttribute("tailRecursive", (compiledFunction.isTailRecursive() ? "true" : "false"));
        body.explain(out);
        out.endElement();
    }

    /**
     * Get the callable compiled function contained within this XQueryFunction definition.
     * @return the compiled function object
     */

    public UserFunction getUserFunction() {
        return compiledFunction;
    }

    /**
     * Get the type of construct. This will be a constant in
     * class {@link Location}.
     */

    public int getConstructType() {
        return StandardNames.XSL_FUNCTION;
    }

    /**
     * Get a description of the instruction for use in error messages. For an XSLT instruction this
     * will be the display name
     */

//    public String getDescription(NamePool pool) {
//        return "declare function";
//    }

    /**
     * Get a name identifying the object of the expression, for example a function name, template name,
     * variable name, key name, element name, etc. This is used only where the name is known statically.
     * @param pool the name pool (not used in this implementation)
     */

    public StructuredQName getObjectName(NamePool pool) {
        return functionName;
    }

    /**
     * Get the system identifier (URI) of the source module containing
     * the instruction. This will generally be an absolute URI. If the system
     * identifier is not known, the method may return null. In some cases, for example
     * where XML external entities are used, the correct system identifier is not
     * always retained.
     */

    public String getSystemId() {
        return systemId;
    }

    /**
     * Get the line number of the instruction in the source stylesheet module.
     * If this is not known, or if the instruction is an artificial one that does
     * not relate to anything in the source code, the value returned may be -1.
     */

    public int getLineNumber() {
        return lineNumber;
    }

    /**
     * Return the public identifier for the current document event.
     * @return A string containing the public identifier, or
     *         null if none is available.
     * @see #getSystemId
     */
    public String getPublicId() {
        return null;
    }

    /**
     * Return the column number
     * @return The column number, or -1 if none is available.
     * @see #getLineNumber
     */

    public int getColumnNumber() {
        return -1;
    }

    public String getSystemId(long locationId) {
        return getSystemId();
    }

    public int getLineNumber(long locationId) {
        return getLineNumber();
    }

    /**
     * Get the namespace context of the instruction. This will not always be available, in which
     * case the method returns null.
     */

    public NamespaceResolver getNamespaceResolver() {
        return namespaceResolver;
    }

    /**
     * Get the value of a particular property of the instruction. Properties
     * of XSLT instructions are generally known by the name of the stylesheet attribute
     * that defines them.
     * @param name The name of the required property
     * @return  The value of the requested property, or null if the property is not available
     */

    public Object getProperty(String name) {
        if ("name".equals(name)) {
            return functionName.getDisplayName();
        } else if ("as".equals(name)) {
            return resultType.toString();
        } else {
            return null;
        }
    }

    /**
     * Get an iterator over all the properties available. The values returned by the iterator
     * will be of type String, and each string can be supplied as input to the getProperty()
     * method to retrieve the value of the property.
     */

    public Iterator getProperties() {
        return new PairIterator("name", "as");
    }

    /**
     * Get the host language (XSLT, XQuery, XPath) used to implement the code in this container
     * @return typically {@link net.sf.saxon.Configuration#XSLT} or {@link net.sf.saxon.Configuration#XQUERY}
     */

    public int getHostLanguage() {
        return Configuration.XQUERY;
    }

    /**
      * 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;
         if (body == original) {
             body = replacement;
             found = true;
         }
                 return found;
    }


}


//
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the
// License at http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is: all this file.
//
// The Initial Developer of the Original Code is Michael H. Kay
//
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
//
// Contributor(s): none
//




© 2015 - 2024 Weber Informatics LLC | Privacy Policy