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

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

The newest version!
package com.xmlcalabash.runtime;

import com.xmlcalabash.core.XProcRuntime;
import com.xmlcalabash.core.XProcConstants;
import com.xmlcalabash.core.XProcData;
import com.xmlcalabash.core.XProcException;
import com.xmlcalabash.io.ReadablePipe;
import com.xmlcalabash.io.WritablePipe;
import com.xmlcalabash.io.ReadableEmpty;
import com.xmlcalabash.io.Pipe;
import com.xmlcalabash.model.*;
import com.xmlcalabash.util.MessageFormatter;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Created by IntelliJ IDEA.
 * User: ndw
 * Date: Oct 8, 2008
 * Time: 5:26:50 AM
 * To change this template use File | Settings | File Templates.
 */
public class XCompoundStep extends XAtomicStep {
    protected Hashtable variables = new Hashtable ();
    protected Vector subpipeline = new Vector ();

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

    /*
    public void addVariable(QName name, RuntimeValue value) {
        variables.put(name, value);
    }
    */

    public boolean hasInScopeVariableBinding(QName name) {
        if (variables.containsKey(name) || inScopeOptions.containsKey(name)) {
            return true;
        }

        return getParent() == null ? false : getParent().hasInScopeVariableBinding(name);
    }

    public boolean hasInScopeVariableValue(QName name) {
        if (variables.containsKey(name) || inScopeOptions.containsKey(name)) {
            RuntimeValue v = getVariable(name);
            return v != null &&  v.initialized();
        }

        return getParent() == null ? false : getParent().hasInScopeVariableValue(name);
    }

    public RuntimeValue getVariable(QName name) {
        if (variables.containsKey(name)) {
            return variables.get(name);
        } else {
            if (inScopeOptions.containsKey(name)) {
                return inScopeOptions.get(name);
            } else {
                return null;
            }
        }
    }

    public ReadablePipe getBinding(String stepName, String portName) {
        if (name.equals(stepName)) {
            XInput input = getInput(portName);
            return input.getReader();
        }

        for (XStep step : subpipeline) {
            if (stepName.equals(step.getName())) {
                XOutput output = step.getOutput(portName);
                if (output == null) {
                    return new ReadableEmpty();
                } else {
                    ReadablePipe rpipe = output.getReader();
                    return rpipe;
                }
            }
        }
        return parent.getBinding(stepName, portName);
    }

    protected void addStep(XStep step) {
        subpipeline.add(step);
    }

    public void instantiate(Step step) {
        logger.trace(MessageFormatter.nodeMessage(step.getNode(), "--> instantiate " + step));
        
        instantiateReaders(step);
        parent.addStep(this);

        DeclareStep decl = step.getDeclaration();

        for (Step substep : decl.subpipeline()) {
            if (XProcConstants.p_choose.equals(substep.getType())) {
                XChoose newstep = new XChoose(runtime, substep, this);
                newstep.instantiate(substep);
            } else if (XProcConstants.p_group.equals(substep.getType())) {
                XGroup newstep = new XGroup(runtime, substep, this);
                newstep.instantiate(substep);
            } else if (XProcConstants.p_try.equals(substep.getType())) {
                XTry newstep = new XTry(runtime, substep, this);
                newstep.instantiate(substep);
            } else if (XProcConstants.p_catch.equals(substep.getType())) {
                XCatch newstep = new XCatch(runtime, substep, this);
                newstep.instantiate(substep);
            } else if (XProcConstants.p_for_each.equals(substep.getType())) {
                XForEach newstep = new XForEach(runtime, substep, this);
                newstep.instantiate(substep);
            } else if (XProcConstants.p_viewport.equals(substep.getType())) {
                XViewport newstep = new XViewport(runtime, substep, this);
                newstep.instantiate(substep);
            } else if (XProcConstants.cx_until_unchanged.equals(substep.getType())) {
                XUntilUnchanged newstep = new XUntilUnchanged(runtime,substep,this);
                newstep.instantiate(substep);
            } else if (substep.isPipelineCall()) {
                XPipelineCall newstep = new XPipelineCall(runtime, substep, this);
                newstep.instantiate(substep);

                /*
                DeclareStep subdecl = substep.getDeclaration();
                // Make sure the caller's inputs and outputs have the right sequence values
                for (Input input : subdecl.inputs()) {
                    String port = input.getPort();
                    for (ReadablePipe rpipe : inputs.get(port)) {
                        rpipe.canReadSequence(input.getSequence());
                    }
                }

                for (Output output : subdecl.outputs()) {
                    String port = output.getPort();
                    WritablePipe wpipe = outputs.get(port);
                    wpipe.canWriteSequence(output.getSequence());
                }
                */
            } else {
                XAtomicStep newstep = new XAtomicStep(runtime, substep, this);
                newstep.instantiate(substep);
            }
        }

        for (Input input : step.inputs()) {
            String port = input.getPort();
            if (port.startsWith("|")) {
                Vector readers = null;
                if (inputs.containsKey(port)) {
                    readers = inputs.get(port);
                } else {
                    readers = new Vector ();
                    inputs.put(port, readers);
                }
                for (Binding binding : input.getBinding()) {
                    ReadablePipe pipe = getPipeFromBinding(binding);
                    pipe.canReadSequence(input.getSequence());
                    pipe.setReader(step);
                    readers.add(pipe);
                    logger.trace(MessageFormatter.nodeMessage(step.getNode(),
                            step.getName() + " reads from " + pipe + " for " + port));
                    
                    /* Attempted fix by ndw on 7 Dec...seems to work
                    if (binding.getBindingType() == Binding.PIPE_NAME_BINDING) {
                        PipeNameBinding pnbinding = (PipeNameBinding) binding;
                        ReadablePipe pipe = getBinding(pnbinding.getStep(), pnbinding.getPort());
                        pipe.canReadSequence(input.getSequence());
                        pipe.setReader(step);
                        readers.add(pipe);
                        finest(step.getNode(), step.getName() + " reads from " + pipe + " for " + port);
                    } else {
                        throw new XProcException("Don't know how to handle binding " + binding.getBindingType());
                    }
                    */
                }

                XInput xinput = new XInput(runtime, input);
                addInput(xinput);
            }
        }

        for (Output output : step.outputs()) {
            String port = output.getPort();
            if (port.endsWith("|")) {
                String rport = port.substring(0,port.length()-1);
                XInput xinput = getInput(rport);
                Pipe wpipe = xinput.getWriter();
                wpipe.setWriter(step);
                wpipe.canWriteSequence(true); // Let the other half work it out
                outputs.put(port, wpipe);
                logger.trace(MessageFormatter.nodeMessage(step.getNode(), step.getName() + " writes to " + wpipe + " for " + port));
            } else {
                XOutput xoutput = new XOutput(runtime, output);
                xoutput.setLogger(step.getLog(port));
                addOutput(xoutput);
                Pipe wpipe = xoutput.getWriter();
                wpipe.setWriter(step);
                wpipe.canWriteSequence(output.getSequence());
                outputs.put(port, wpipe);
                logger.trace(MessageFormatter.nodeMessage(step.getNode(), step.getName() + " writes to " + wpipe + " for " + port));
            }
        }
    }

    protected void copyInputs() throws SaxonApiException {
        for (String port : inputs.keySet()) {
            if (!port.startsWith("|")) {
                String wport = port + "|";
                WritablePipe pipe = outputs.get(wport);
                for (ReadablePipe reader : inputs.get(port)) {
                    while (reader.moreDocuments()) {
                        XdmNode doc = reader.read();
                        pipe.write(doc);
                        logger.trace(MessageFormatter.nodeMessage(step.getNode(), "Compound input copy from " + reader + " to " + pipe));
                    }
                }
            }
        }
    }

    public void reset() {
        super.reset();
        for (XStep step : subpipeline) {
            step.reset();
        }
    }

    protected void doRun() throws SaxonApiException {
        XProcData data = runtime.getXProcData();
        data.openFrame(this);
        
        copyInputs();

        // N.B. At this time, there are no compound steps that accept parameters or options,
        // so the order in which we calculate them doesn't matter. That will change if/when
        // there are such compound steps.

        // Calculate all the options
        inScopeOptions = parent.getInScopeOptions();
        for (QName name : step.getOptions()) {
            Option option = step.getOption(name);
            RuntimeValue value = computeValue(option);
            setOption(name, value);
            inScopeOptions.put(name, value);
        }

        for (Variable var : step.getVariables()) {
            RuntimeValue value = computeValue(var);
            inScopeOptions.put(var.getName(), value);
        }

        runtime.start(this);

        try {
            for (XStep step : subpipeline) {
                step.run();
            }

            for (String port : inputs.keySet()) {
                if (port.startsWith("|")) {
                    String wport = port.substring(1);
                    WritablePipe pipe = outputs.get(wport);
                    for (ReadablePipe reader : inputs.get(port)) {
                        while (reader.moreDocuments()) {
                            XdmNode doc = reader.read();
                            try {
	                            pipe.write(doc);
                            } catch (XProcException e) {
	                            if (e.getErrorCode().equals(XProcConstants.dynamicError(7)))
		                            throw new XProcException(e.getErrorCode(), this, e.getMessage(), e.getErrorCause());
	                            else
		                            throw e;
                            }
                            logger.trace(MessageFormatter.nodeMessage(step.getNode(), "Compound output copy from " + reader + " to " + pipe));
                        }
                    }
                }
            }
        } finally {
            runtime.finish(this);
            data.closeFrame();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy