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

com.xmlcalabash.runtime.XViewport Maven / Gradle / Ivy

There is a newer version: 1.1.20-p16-98
Show newest version
package com.xmlcalabash.runtime;

import java.math.BigDecimal;
import java.math.MathContext;

import com.xmlcalabash.io.Pipe;
import com.xmlcalabash.io.ReadablePipe;
import com.xmlcalabash.io.WritablePipe;
import com.xmlcalabash.core.XProcRuntime;
import com.xmlcalabash.core.XProcException;
import com.xmlcalabash.core.XProcData;
import com.xmlcalabash.util.MessageFormatter;
import com.xmlcalabash.util.ProcessMatchingNodes;
import com.xmlcalabash.util.ProcessMatch;
import com.xmlcalabash.util.TreeWriter;
import com.xmlcalabash.util.XProcMessageListenerHelper;
import com.xmlcalabash.model.*;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XdmNode;

/**
 * Created by IntelliJ IDEA.
 * User: ndw
 * Date: Oct 15, 2008
 * Time: 7:03:35 AM
 * To change this template use File | Settings | File Templates.
 */
public class XViewport extends XCompoundStep implements ProcessMatchingNodes {
    private Pipe current = null;
    private ProcessMatch matcher = null;
    private int sequencePosition = 0;
    private int sequenceLength = 0;

    public XViewport(XProcRuntime runtime, Step step, XCompoundStep parent) {
        super(runtime, step, parent);
    }

    public ReadablePipe getBinding(String stepName, String portName) {
        if (name.equals(stepName) && ("#current".equals(portName) || "current".equals(portName))) {
            if (current == null) {
                current = new Pipe(runtime);
            }
            return new Pipe(runtime,current.documents());
        } else {
            return super.getBinding(stepName, portName);
        }
    }

    protected void copyInputs() throws SaxonApiException {
        // nop;
    }

    public void reset() {
        super.reset();
        sequenceLength = 0;
        sequencePosition = 0;
    }

    public void run() throws SaxonApiException {
        logger.trace("Running p:viewport " + step.getName());

        XProcData data = runtime.getXProcData();
        data.openFrame(this);

        if (current == null) {
            current = new Pipe(runtime);
        }

        RuntimeValue match = ((Viewport) step).getMatch();

        String iport = "#viewport-source";
        ReadablePipe vsource = null;

        if (inputs.get(iport).size() != 1) {
            throw XProcException.dynamicError(3);
        } else {
            vsource = inputs.get(iport).get(0);
        }

        XdmNode doc = vsource.read();
        if (doc == null || vsource.moreDocuments()) {
            throw XProcException.dynamicError(3);
        }
        
        matcher = new ProcessMatch(runtime, this);

        // FIXME: Only do this if we really need to!
        sequenceLength = matcher.count(doc, match, false);

        runtime.getXProcData().setIterationSize(sequenceLength);

        runtime.start(this);
        try {
            XProcMessageListenerHelper.openStep(runtime, this);
        } catch (Throwable e) {
            throw handleException(e);
        }
        try {
            matcher.match(doc, match);
        } finally {
            runtime.getMessageListener().closeStep();
        }
        runtime.finish(this);

        for (String port : inputs.keySet()) {
            if (port.startsWith("|")) {
                String wport = port.substring(1);
                WritablePipe pipe = outputs.get(wport);
                XdmNode result = matcher.getResult();
                pipe.write(result);
                logger.trace(MessageFormatter.nodeMessage(step.getNode(), "Viewport output copy from matcher to " + pipe));
            }
        }
    }

    public boolean processStartDocument(XdmNode node) {
        return true;
    }

    public void processEndDocument(XdmNode node) {
        // nop
    }

    public boolean processStartElement(XdmNode node) {
        try {
            runtime.getMessageListener().openStep(this, getNode(), null, null, BigDecimal.ONE.divide(new BigDecimal(sequenceLength), MathContext.DECIMAL128));
        } catch (Throwable e) {
            throw handleException(e);
        }
        try {

        // Use a TreeWriter to make the matching node into a proper document
        TreeWriter treeWriter = new TreeWriter(runtime);
        treeWriter.startDocument(node.getBaseURI());
        treeWriter.addSubtree(node);
        treeWriter.endDocument();

        current.resetWriter();
        current.write(treeWriter.getResult());

        logger.trace(MessageFormatter.nodeMessage(step.getNode(), "Viewport copy matching node to " + current));

        sequencePosition++;
        runtime.getXProcData().setIterationPosition(sequencePosition);

        // Calculate all the variables
        inScopeOptions = parent.getInScopeOptions();
        for (Variable var : step.getVariables()) {
            RuntimeValue value = computeValue(var);
            inScopeOptions.put(var.getName(), value);
        }

        for (XStep step : subpipeline) {
            step.reset();
            try {
                step.run();
            } catch (Throwable e) {
                throw handleException(e);
            }
        }


        try {
            int count = 0;
            for (String port : inputs.keySet()) {
                if (port.startsWith("|")) {
                    for (ReadablePipe reader : inputs.get(port)) {
                        while (reader.moreDocuments()) {
                            count++;

                            if (count > 1) {
                                XOutput output = getOutput(port.substring(1));
                                if (!output.getSequence()) {
                                    throw XProcException.dynamicError(7);
                                }
                            }

                            XdmNode doc = reader.read();
                            matcher.addSubtree(doc);
                        }
                        reader.resetReader();
                    }
                }
            }
        } catch (SaxonApiException sae) {
            throw new XProcException(sae);
        }

        } finally {
            runtime.getMessageListener().closeStep();
        }

        return false;
    }

    public void processEndElement(XdmNode node) {
    }

    public void processText(XdmNode node) {
        throw new UnsupportedOperationException("Can't run a viewport over text, PI, or comments");
    }

    public void processComment(XdmNode node) {
        throw new UnsupportedOperationException("Can't run a viewport over text, PI, or comments");
    }

    public void processPI(XdmNode node) {
        throw new UnsupportedOperationException("Can't run a viewport over text, PI, or comments");
    }

    public void processAttribute(XdmNode node) {
        throw new UnsupportedOperationException("Can't run a viewport over attributes");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy