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

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

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

import client.net.sf.saxon.ce.event.NoOpenStartTagException;
import client.net.sf.saxon.ce.event.SequenceReceiver;
import client.net.sf.saxon.ce.expr.*;
import client.net.sf.saxon.ce.lib.NamespaceConstant;
import client.net.sf.saxon.ce.om.*;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.tree.util.Navigator;
import client.net.sf.saxon.ce.tree.util.URI;
import client.net.sf.saxon.ce.type.ItemType;
import client.net.sf.saxon.ce.type.Type;
import client.net.sf.saxon.ce.type.TypeHierarchy;

import java.util.Iterator;


/**
* An xsl:copy-of element in the stylesheet.
*/

public class CopyOf extends Instruction {

    private Expression select;
    private boolean copyNamespaces;
    private String staticBaseUri;

    /**
     * Create an xsl:copy-of instruction (also used in XQuery for implicit copying)
     * @param select expression that selects the nodes to be copied
     * @param copyNamespaces true if namespaces are to be copied
     * if duplicates are handled by discarding all but the first (XSLT).
     */

    public CopyOf(Expression select,
                  boolean copyNamespaces) {
        this.select = select;
        this.copyNamespaces = copyNamespaces;
        adoptChildExpression(select);
    }

     /**
     * Set the static base URI of the xsl:copy-of instruction
     * @param base the static base URI
     */

    public void setStaticBaseUri(String base) {
        staticBaseUri = base;
    }

    /**
     * Determine whether this instruction creates new nodes.
     * The result depends on the type of the select expression.
     */

    public final boolean createsNewNodes() {
        Executable exec = getExecutable();
        if (exec == null) {
            return true;    // This shouldn't happen, but we err on the safe side
        }
        final TypeHierarchy th = exec.getConfiguration().getTypeHierarchy();
        return !select.getItemType(th).isAtomicType();
    }

    /**
     * Get the name of this instruction, for diagnostics and tracing
     */

    public int getInstructionNameCode() {
        return StandardNames.XSL_COPY_OF;
    }

    /**
     * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
     * This method indicates which of these methods is provided. This implementation provides both iterate() and
     * process() methods natively.
     */

    public int getImplementationMethod() {
        return PROCESS_METHOD;
    }


    public Expression simplify(ExpressionVisitor visitor) throws XPathException {
        select = visitor.simplify(select);
        return this;
    }

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

    public int getCardinality() {
        return select.getCardinality();
    }

    public int getDependencies() {
        return select.getDependencies();
    }

    protected void promoteInst(PromotionOffer offer) throws XPathException {
        select = doPromotion(select, offer);
    }

    public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
        select = visitor.typeCheck(select, contextItemType);
        adoptChildExpression(select);
        return this;
    }

    public Expression optimize(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
        select = visitor.optimize(select, contextItemType);
        adoptChildExpression(select);
        final TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
        if (select.getItemType(th).isAtomicType()) {
            return select;
        }
        return this;
    }


    public Iterator<Expression> iterateSubExpressions() {
        return monoIterator(select);
    }

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

    /**
     * Process this xsl:copy-of instruction
     *
     * @param context the dynamic context for the transformation
     * @return null - this implementation of the method never returns a TailCall
     */

    public TailCall processLeavingTail(XPathContext context) throws XPathException {

        SequenceReceiver out = context.getReceiver();
        boolean copyBaseURI = (out.getSystemId() == null);
            // if the copy is being attached to an existing parent, it inherits the base URI of the parent

        int copyOptions = CopyOptions.TYPE_ANNOTATIONS;
        if (copyNamespaces) {
            copyOptions |= CopyOptions.ALL_NAMESPACES;
        }

        //int whichNamespaces = (copyNamespaces ? NodeInfo.ALL_NAMESPACES : NodeInfo.NO_NAMESPACES);

        SequenceIterator iter = select.iterate(context);
        while (true) {
            Item item = iter.next();
            if (item == null) {
                break;
            }
            if (item instanceof NodeInfo) {
                NodeInfo source = (NodeInfo) item;
                int kind = source.getNodeKind();

                switch (kind) {

                    case Type.ELEMENT: {
                        if (copyBaseURI) {
                            out.setSystemId(computeNewBaseUri(source));
                        }

                        source.copy(out, copyOptions);
                        break;
                    }
                    case Type.ATTRIBUTE:
                        try {
                            context.getReceiver().attribute(source.getNameCode(), source.getStringValueCS());
                        } catch (NoOpenStartTagException err) {
                            dynamicError(err.getMessage(), err.getErrorCodeLocalPart(), context);
                        }
                        break;
                    case Type.TEXT:
                        out.characters(source.getStringValueCS());
                        break;

                    case Type.PROCESSING_INSTRUCTION:
                        if (copyBaseURI) {
                            out.setSystemId(source.getBaseURI());
                        }
                        out.processingInstruction(source.getDisplayName(), source.getStringValueCS());
                        break;

                    case Type.COMMENT:
                        out.comment(source.getStringValueCS());
                        break;

                    case Type.NAMESPACE:
                        try {
                            source.copy(out, 0);
                        } catch (NoOpenStartTagException err) {
                            dynamicError(err.getMessage(), err.getErrorCodeLocalPart(), context);
                        }
                        break;

                    case Type.DOCUMENT: {
                        out.setPipelineConfiguration(out.getPipelineConfiguration());
                        if (copyBaseURI) {
                            out.setSystemId(source.getBaseURI());
                        }
                        source.copy(out, copyOptions);
                        break;
                    }
                    default:
                        throw new IllegalArgumentException("Unknown node kind " + source.getNodeKind());
                }

            } else {
                out.append(item, NodeInfo.ALL_NAMESPACES);
            }
        }
        return null;
    }

    private String computeNewBaseUri(NodeInfo source) {
        // These rules are the rules for xsl:copy-of instruction in XSLT. The same code is used to support the
        // validate{} expression in XQuery. XQuery says nothing about the base URI of a node that results
        // from a validate{} expression, so until it does, we might as well use the same logic.
        String newBaseUri;
        String xmlBase = Navigator.getAttributeValue(source, NamespaceConstant.XML, "base");
        if (xmlBase != null) {
            try {
                URI xmlBaseUri = new URI(xmlBase, true);
                if (xmlBaseUri.isAbsolute()) {
                    newBaseUri = xmlBase;
                } else if (staticBaseUri != null) {
                    URI sbu = new URI(staticBaseUri);
                    URI abs = sbu.resolve(xmlBaseUri.toString());
                    newBaseUri = abs.toString();
                } else {
                    newBaseUri = source.getBaseURI();
                }
            } catch (URI.URISyntaxException err) {
                newBaseUri = source.getBaseURI();
            }
        } else {
            newBaseUri = source.getBaseURI();
        }
        return newBaseUri;
    }

}

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

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.