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

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

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

import client.net.sf.saxon.ce.Controller;
import client.net.sf.saxon.ce.Controller.APIcommand;
import client.net.sf.saxon.ce.LogController;
import client.net.sf.saxon.ce.dom.HTMLDocumentWrapper;
import client.net.sf.saxon.ce.dom.HTMLNodeWrapper;
import client.net.sf.saxon.ce.dom.HTMLDocumentWrapper.DocType;
import client.net.sf.saxon.ce.dom.XMLDOM;
import client.net.sf.saxon.ce.event.PipelineConfiguration;
import client.net.sf.saxon.ce.event.Receiver;
import client.net.sf.saxon.ce.expr.*;
import client.net.sf.saxon.ce.functions.DocumentFn;
import client.net.sf.saxon.ce.functions.FunctionLibrary;
import client.net.sf.saxon.ce.functions.ResolveURI;
import client.net.sf.saxon.ce.js.JSObjectValue;
import client.net.sf.saxon.ce.om.*;
import client.net.sf.saxon.ce.pattern.EmptySequenceTest;
import client.net.sf.saxon.ce.pattern.NodeKindTest;
import client.net.sf.saxon.ce.style.StyleElement;
import client.net.sf.saxon.ce.sxpath.AbstractStaticContext;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.trans.update.DeleteAction;
import client.net.sf.saxon.ce.trans.update.InsertAction;
import client.net.sf.saxon.ce.trans.update.PendingUpdateList;
import client.net.sf.saxon.ce.tree.iter.AxisIterator;
import client.net.sf.saxon.ce.tree.iter.SingleNodeIterator;
import client.net.sf.saxon.ce.tree.util.URI;
//import client.net.sf.saxon.ce.tree.util.URI.URISyntaxException;
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 com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Node;
import com.google.gwt.logging.client.LogConfiguration;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Logger;


/**
* The compiled form of an xsl:result-document element in the stylesheet.
* <p/>
* The xsl:result-document element takes an attribute href="filename". The filename will
* often contain parameters, e.g. {position()} to ensure that a different file is produced
* for each element instance.
* <p/>
* There is a further attribute "format" which determines the format of the
* output file, it identifies the name of an xsl:output element containing the output
* format details. In addition, individual serialization properties may be specified as attributes.
* These are attribute value templates, so they may need to be computed at run-time.
*/

public class ResultDocument extends Instruction  {

    private Expression href;
    private Expression methodExpression;
    private Expression content;
    private NamespaceResolver nsResolver;
    private Logger logger = Logger.getLogger("Xstl20Processor");

    public final static int APPEND_CONTENT = 0;
    public final static int REPLACE_CONTENT = 1;

    /**
     * Create a result-document instruction
     * @param href                    href attribute of instruction
     * @param methodExpression        format attribute of instruction
     * @param baseURI                 base URI of the instruction
     * @param nsResolver              namespace resolver
     */

    public ResultDocument(Expression href,
                          Expression methodExpression,      // AVT defining the output format
                          String baseURI,
                          NamespaceResolver nsResolver) {
        this.href = href;
        this.methodExpression = methodExpression;
        this.nsResolver = nsResolver;
        adoptChildExpression(href);
        if (LogConfiguration.loggingIsEnabled() && LogController.traceIsEnabled()) {
          this.AddTraceProperty("href", href);
        }
    }

    /**
     * Set the expression that constructs the content
     * @param content the expression defining the content of the result document
     */

    public void setContentExpression(Expression content) {
        this.content = content;
        adoptChildExpression(content);
    }

    /**
     * Simplify an expression. This performs any static optimization (by rewriting the expression
     * as a different expression). The default implementation does nothing.
     * @param visitor an expression visitor
     * @return the simplified expression
     * @throws client.net.sf.saxon.ce.trans.XPathException
     *          if an error is discovered during expression rewriting
     */

    public Expression simplify(ExpressionVisitor visitor) throws XPathException {
        content = visitor.simplify(content);
        href = visitor.simplify(href);
        return this;
    }
   
    public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
        content = visitor.typeCheck(content, contextItemType);
        adoptChildExpression(content);
        if (href != null) {
            href = visitor.typeCheck(href, contextItemType);
            adoptChildExpression(href);
        }
        if (methodExpression != null) {
            methodExpression = visitor.typeCheck(methodExpression, contextItemType);
            adoptChildExpression(methodExpression);
        }
        return this;
    }

    public Expression optimize(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
        content = visitor.optimize(content, contextItemType);
        adoptChildExpression(content);
        if (href != null) {
            href = visitor.optimize(href, contextItemType);
            adoptChildExpression(href);
        }
        if (methodExpression != null) {
            methodExpression = visitor.optimize(methodExpression, contextItemType);
            adoptChildExpression(methodExpression);
        }
        return this;
    }

    public int getIntrinsicDependencies() {
        return StaticProperty.HAS_SIDE_EFFECTS;
    }

    /**
     * Handle promotion offers, that is, non-local tree rewrites.
     * @param offer The type of rewrite being offered
     * @throws XPathException
     */

    protected void promoteInst(PromotionOffer offer) throws XPathException {
        content = doPromotion(content, offer);
        if (href != null) {
            href = doPromotion(href, offer);
        }
    }

    /**
     * Get the name of this instruction for diagnostic and tracing purposes
     * (the string "xsl:result-document")
     */

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

    /**
     * Get the item type of the items returned by evaluating this instruction
     * @param th the type hierarchy cache
     * @return the static item type of the instruction. This is empty: the result-document instruction
     *         returns nothing.
     */

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


    /**
     * Get all the XPath expressions associated with this instruction
     * (in XSLT terms, the expression present on attributes of the instruction,
     * as distinct from the child instructions in a sequence construction)
     */

    public Iterator<Expression> iterateSubExpressions() {
        ArrayList list = new ArrayList(6);
        list.add(content);
        if (href != null) {
            list.add(href);
        }
        if (methodExpression != null) {
            list.add(methodExpression);
        }
        return list.iterator();
    }

    /**
     * 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 (content == original) {
            content = replacement;
            found = true;
        }
        if (href == original) {
            href = replacement;
            found = true;
        }
        return found;
    }
   
    /**
     * Return a valid URI - event if base URI is not set
     */
    public static String getValidAbsoluteURI(Controller controller, String href) throws XPathException {
      String baseURI = (controller.getBaseOutputURI() != null && controller.getBaseOutputURI().length() > 0)?
          controller.getBaseOutputURI() : Document.get().getURL();
        try {
            return ResolveURI.makeAbsolute(href, baseURI).toString();
       } catch (URI.URISyntaxException ue) {
         throw new XPathException(ue.getMessage());
       }
    }

    public TailCall processLeavingTail(XPathContext context) throws XPathException {
        final Controller controller = context.getController();
        final APIcommand command = controller.getApiCommand();
        XPathContext c2 = context.newMinorContext();
       
        int action = APPEND_CONTENT;
        if (methodExpression != null) {
            String method = methodExpression.evaluateAsString(context).toString();
            StructuredQName methodQ;
            if (method.indexOf(':') >= 0)  {
                methodQ = StructuredQName.fromLexicalQName(method, false, nsResolver);
            } else {
                methodQ = new StructuredQName("", "", method);
            }
            if ("replace-content".equals(methodQ.getLocalName())) {
                // TODO: check the namespace URI is NamespaceConstant.IXSL
                action = REPLACE_CONTENT;
            }
        }

        String hrefValue = null;
        if (href != null) {
          hrefValue = href.evaluateAsString(context).toString();
        } else if (command == APIcommand.UPDATE_HTML) {
          throw new XPathException("html update - no href value for result-document instruction");         
        } else {
          hrefValue = "result" + (controller.getResultDocumentCount() + 1);
        }
        NodeInfo target = null;
        Node targetNode = null;
        String contextNodeName = "";
        String absURI = "";
        if (command == APIcommand.TRANSFORM_TO_DOCUMENT) {
          absURI = getValidAbsoluteURI(controller, hrefValue);
          targetNode = XMLDOM.createDocument(absURI);
        } else if (command == APIcommand.TRANSFORM_TO_FRAGMENT || command == APIcommand.TRANSFORM_TO_HTML_FRAGMENT){
          absURI = getValidAbsoluteURI(controller, hrefValue);
          targetNode = HTMLDocumentWrapper.createDocumentFragment((Document)controller.getTargetNode());
        } else if (hrefValue.startsWith("#")) {
            hrefValue = hrefValue.substring(1);
            targetNode = ((Document)controller.getTargetNode()).getElementById(hrefValue); // com.google.gwt.dom.client.Document.get().getElementById(hrefValue);
        } else if (hrefValue.startsWith("?select=")) {
            String select = hrefValue.substring(8);
            AbstractStaticContext env = new AbstractStaticContext() {
                public String getURIForPrefix(String prefix) throws XPathException {
                    return null;
                }

                public Expression bindVariable(StructuredQName qName) throws XPathException {
                    return null;
                }

                public NamespaceResolver getNamespaceResolver() {
                    return null;
                }
                //override getFunctionLibrary to return that loaded for the prepared stylesheet
                public FunctionLibrary getFunctionLibrary() {
                  return controller.getPreparedStylesheet().getFunctionLibrary();
                }

            };
            ExpressionVisitor visitor = new ExpressionVisitor();
            visitor.setConfiguration(context.getConfiguration());
            visitor.setExecutable(new Executable(context.getConfiguration()));
            visitor.setStaticContext(env);
            env.setConfiguration(context.getConfiguration());
            Container container = (StyleElement)getSourceLocator();
            Expression expr = null;
            try {
            expr = ExpressionTool.make(select, env, container, 0, Token.EOF, getSourceLocator());
            } catch (Exception e) {
              // occurs if expression contains references to variables etc. within the dynamic context
              throw new XPathException("Error on evaluating (in static context) result-document href: " + hrefValue);
            }
            expr = visitor.typeCheck(expr, NodeKindTest.DOCUMENT);
            XPathContext c3 = context.newCleanContext();
            //context for ?select expression is the html page if an external node is the context
            Document page = (Document)controller.getTargetNode(); //com.google.gwt.dom.client.Document.get();
            Item cItem = context.getContextItem();
           
            NodeInfo currentContextItem;
            if (cItem instanceof JSObjectValue){
              currentContextItem = null;
            } else {
              currentContextItem = (NodeInfo)cItem;
            }
           
            boolean useCurrentContext;
            if (currentContextItem == null) {
              useCurrentContext = false;
            } else {
              useCurrentContext = (currentContextItem.getBaseURI().equals(page.getURL()));
            }
           
            NodeInfo contextItem;

            if (useCurrentContext) {
              contextItem = currentContextItem;
              if (LogConfiguration.loggingIsEnabled() && contextItem.getNodeKind() == Type.ELEMENT) {
                contextNodeName = controller.getNamePool().getLocalName(contextItem.getNameCode());
              }
            } else {
              contextItem = new HTMLDocumentWrapper(page, page.getURL(), context.getConfiguration(), DocType.UNKNOWN);
            }
            if (LogConfiguration.loggingIsEnabled()) {
              contextNodeName = (contextNodeName.equals("")? "" : " context node: " + contextNodeName);
            }

            AxisIterator iterator = SingleNodeIterator.makeIterator(contextItem);
            iterator.next(); // position on the single item
            c3.setCurrentIterator(iterator);
            SequenceIterator iter = expr.iterate(c3);
            Item resultItem = iter.next();
           
            if (resultItem == null) {} // do nothing
            else if (!(resultItem instanceof NodeInfo)) {
              throw new XPathException("non-node returned by result-document href: " + hrefValue);
            } else {
              target = (NodeInfo)resultItem;
              targetNode = (com.google.gwt.dom.client.Node)((HTMLNodeWrapper)target).getUnderlyingNode();
            }
        }
        else if (command == APIcommand.UPDATE_HTML) {
          throw new XPathException("expected '?select=' or '#' at start of result-document href, found: " + hrefValue);
        }
        if (targetNode == null) {
          logger.warning("result-document target not found for href: " + hrefValue + contextNodeName);
          return null;
        } else {
          logger.fine("processing result-document for href: " + hrefValue + contextNodeName);
        }

        //checkAcceptableUri(context, absoluteResultURI.toString());
        //IFrameElement container = Document.get().createIFrameElement();
       
        Node container = null;
        if (command == APIcommand.UPDATE_HTML) {
            container = HTMLDocumentWrapper.createDocumentFragment((Document)controller.getTargetNode());
        } else {
            addResultDocument(context, new DocumentURI(absURI), (Document)targetNode);
          container = targetNode;
        }

        PipelineConfiguration pipe = controller.makePipelineConfiguration();
       
        Receiver out = controller.openResult(pipe, c2, container, action);

        try {
            content.process(c2);
            out.endDocument();
        } catch (XPathException err) {
            err.setXPathContext(context);
            err.maybeSetLocation(getSourceLocator());
            throw err;
        }
        controller.closeResult(out, c2);
       
        if (command == APIcommand.UPDATE_HTML){
          PendingUpdateList list = controller.getPendingUpdateList();
          if (action == REPLACE_CONTENT && command == APIcommand.UPDATE_HTML) {
            int existingChildren = targetNode.getChildCount();
              for (int i=0; i<existingChildren; i++) {
                  Node child = targetNode.getChild(i);
                  list.add(new DeleteAction(child));
              }
          }
 
          list.add(new InsertAction(container, targetNode, InsertAction.LAST));
        }
        //controller.setResultTree(absoluteResultURI.toString(), root);
        return null;
    }

    private void addResultDocument(XPathContext context, DocumentURI documentKey, Document doc) throws XPathException {
        Controller controller = context.getController();

            if (controller.getDocumentPool().find(documentKey.toString()) != null) {
                dynamicError("Cannot write to a URI that has already been read: " + documentKey.toString(), "XTRE1500", context);
            }
           
            if (!controller.checkUniqueOutputDestination(documentKey)) {
                dynamicError("Cannot write more than one result document to the same URI: " + documentKey.toString(),"XTDE1490" ,context);
            } else {
              controller.addToResultDocumentPool(documentKey, doc);
                //controller.addUnavailableOutputDestination(documentKey);
            }
        //controller.setThereHasBeenAnExplicitResultDocument();
    }

}

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

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.