Package client.net.sf.saxon.ce.expr.instruct

Source Code of client.net.sf.saxon.ce.expr.instruct.ElementCreator

package client.net.sf.saxon.ce.expr.instruct;

import client.net.sf.saxon.ce.Controller;
import client.net.sf.saxon.ce.event.*;
import client.net.sf.saxon.ce.expr.Expression;
import client.net.sf.saxon.ce.expr.StaticProperty;
import client.net.sf.saxon.ce.expr.XPathContext;
import client.net.sf.saxon.ce.om.Item;
import client.net.sf.saxon.ce.om.NodeInfo;
import client.net.sf.saxon.ce.pattern.NodeKindTest;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.type.ItemType;
import client.net.sf.saxon.ce.type.TypeHierarchy;


/**
* An instruction that creates an element node. There are two subtypes, FixedElement
* for use where the name is known statically, and Element where it is computed
* dynamically. To allow use in both XSLT and XQuery, the class acts both as an
* Instruction and as an Expression.
*/

public abstract class ElementCreator extends ParentNodeConstructor {

    /**
     * The inheritNamespaces flag indicates that the namespace nodes on the element created by this instruction
     * are to be inherited (copied) on the children of this element. That is, if this flag is false, the child
     * elements must carry a namespace undeclaration for all the namespaces on the parent, unless they are
     * redeclared in some way.
     */

    protected boolean inheritNamespaces = true;

    /**
     * Construct an ElementCreator. Exists for the benefit of subclasses.
     */

    public ElementCreator() { }

    /**
     * Get the item type of the value returned by this instruction
     * @return the item type
     * @param th the type hierarchy cache
     */

    public ItemType getItemType(TypeHierarchy th) {
        return NodeKindTest.ELEMENT;
    }

    /**
     * Get the static properties of this expression (other than its type). The result is
     * bit-signficant. These properties are used for optimizations. In general, if
     * property bit is set, it is true, but if it is unset, the value is unknown.
     *
     * @return a set of flags indicating static properties of this expression
     */

    public int computeSpecialProperties() {
        return super.computeSpecialProperties() |
                StaticProperty.SINGLE_DOCUMENT_NODESET;
    }

    /**
     * Determine (at run-time) the name code of the element being constructed
     * @param context the XPath dynamic evaluation context
     * @param copiedNode
     * @return the integer name code representing the element name
     * @throws XPathException if a failure occurs
     */

    public abstract int getNameCode(XPathContext context, NodeInfo copiedNode)
    throws XPathException;

    /**
     * Get the base URI for the element being constructed
     * @param context the XPath dynamic evaluation context
     * @param copiedNode the node being copied (for xsl:copy), otherwise null
     * @return the base URI of the constructed element
     */

    protected abstract String getNewBaseURI(XPathContext context, NodeInfo copiedNode);

    /**
     * Callback to output namespace nodes for the new element. This method is responsible
     * for ensuring that a namespace node is always generated for the namespace of the element
     * name itself.
     * @param context The execution context
     * @param receiver the Receiver where the namespace nodes are to be written
     * @param nameCode the name code of the element being created
     * @param copiedNode the node being copied (for xsl:copy) or null otherwise
     * @throws client.net.sf.saxon.ce.trans.XPathException
     */

    protected abstract void outputNamespaceNodes(XPathContext context, Receiver receiver, int nameCode, NodeInfo copiedNode)
    throws XPathException;

    /**
     * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
     * This method indicates which of these methods is prefered. For instructions this is the process() method.
     */

    public int getImplementationMethod() {
        return Expression.PROCESS_METHOD | Expression.EVALUATE_METHOD;
    }

    /**
     * Evaluate the instruction to produce a new element node. This method is typically used when there is
     * a parent element or document in a result tree, to which the new element is added.
     * @param context XPath dynamic evaluation context
     * @return null (this instruction never returns a tail call)
     * @throws XPathException
     */
    public TailCall processLeavingTail(XPathContext context)
    throws XPathException {
        return processLeavingTail(context, null);
    }

    /**
     * Evaluate the instruction to produce a new element node. This method is typically used when there is
     * a parent element or document in a result tree, to which the new element is added.
     * @param context XPath dynamic evaluation context
     * @param copiedNode null except in the case of xsl:copy, when it is the node being copied
     * @return null (this instruction never returns a tail call)
     * @throws XPathException
     */
    protected final TailCall processLeavingTail(XPathContext context, NodeInfo copiedNode)
    throws XPathException {

        try {

            int nameCode = getNameCode(context, copiedNode);

            SequenceReceiver out = context.getReceiver();

            if (out.getSystemId() == null) {
                out.setSystemId(getNewBaseURI(context, copiedNode));
            }
            int properties = (inheritNamespaces ? 0 : ReceiverOptions.DISINHERIT_NAMESPACES);
            out.startElement(nameCode, properties);

            // output the required namespace nodes via a callback

            outputNamespaceNodes(context, out, nameCode, copiedNode);

            // process subordinate instructions to generate attributes and content
            content.process(context);

            // output the element end tag (which will fail if validation fails)
            out.endElement();
            return null;

        } catch (XPathException e) {
            e.maybeSetLocation(getSourceLocator());
            e.maybeSetContext(context);
            throw e;
        }
    }

    /**
     * Evaluate the constructor, returning the constructed element node. If lazy construction
     * mode is in effect, then an UnconstructedParent object is returned instead.
     */

    public Item evaluateItem(XPathContext context) throws XPathException {
        return constructElement(context, null);
    }

    /**
     * Construct the element node as a free-standing (parentless) node in a tiny tree
     * @param context XPath dynamic evaluation context
     * @return the constructed element node
     * @throws XPathException
     */
    private NodeInfo constructElement(XPathContext context, NodeInfo copiedNode) throws XPathException {
        try {
            Controller controller = context.getController();
            XPathContext c2 = context.newMinorContext();
            SequenceOutputter seq = controller.allocateSequenceOutputter(1);
            PipelineConfiguration pipe = controller.makePipelineConfiguration();
            seq.setPipelineConfiguration(pipe);

            int nameCode = getNameCode(c2, copiedNode);

            c2.setTemporaryReceiver(seq);
            if (seq.getSystemId() == null) {
                seq.setSystemId(getNewBaseURI(c2, copiedNode));
            }

            seq.open();
            int properties = (inheritNamespaces ? 0 : ReceiverOptions.DISINHERIT_NAMESPACES);
            seq.startElement(nameCode, properties);

            // output the namespace nodes for the new element
            outputNamespaceNodes(c2, seq, nameCode, null);

            content.process(c2);

            seq.endElement();
            seq.close();

            // the constructed element is the first and only item in the sequence
            NodeInfo result = (NodeInfo)seq.popLastItem();
            seq.reset();
            return result;

        } catch (XPathException err) {
            err.maybeSetLocation(getSourceLocator());
            err.maybeSetContext(context);
            throw err;
        }
    }

}

// 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.expr.instruct.ElementCreator

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.