org.yawlfoundation.yawl.elements.YDecomposition.java Source code

Java tutorial

Introduction

Here is the source code for org.yawlfoundation.yawl.elements.YDecomposition.java

Source

/*
 * Copyright (c) 2004-2012 The YAWL Foundation. All rights reserved.
 * The YAWL Foundation is a collaboration of individuals and
 * organisations who are committed to improving workflow technology.
 *
 * This file is part of YAWL. YAWL is free software: you can
 * redistribute it and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation.
 *
 * YAWL is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
 * Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with YAWL. If not, see <http://www.gnu.org/licenses/>.
 */

package org.yawlfoundation.yawl.elements;

import org.jdom2.Document;
import org.jdom2.Element;
import org.yawlfoundation.yawl.elements.data.YParameter;
import org.yawlfoundation.yawl.engine.YNetData;
import org.yawlfoundation.yawl.engine.YPersistenceManager;
import org.yawlfoundation.yawl.exceptions.YPersistenceException;
import org.yawlfoundation.yawl.logging.YLogPredicate;
import org.yawlfoundation.yawl.util.DynamicValue;
import org.yawlfoundation.yawl.util.JDOMUtil;
import org.yawlfoundation.yawl.util.StringUtil;
import org.yawlfoundation.yawl.util.YVerificationHandler;

import java.util.*;

/**
 * 
 * @author Lachlan Aldred
 * Date: 25/09/2003
 * Time: 16:04:21
 *
 * Refactored for 2.0 by Michael Adams 
 * 
 */

public abstract class YDecomposition implements Cloneable, YVerifiable {
    protected String _id;
    protected YSpecification _specification;
    private String _name;
    private String _documentation;
    private Map<String, YParameter> _inputParameters;
    private Map<String, YParameter> _outputParameters;
    private Map<String, YParameter> _enablementParameters; // only used to generate editor xml
    private Set<String> _outputExpressions;
    protected Document _data;
    private YNetData _casedata = null;
    private YAttributeMap _attributes;
    private YLogPredicate _logPredicate;

    // if true, this decomposition requires resourcing decisions made at runtime
    protected boolean _manualInteraction = true;

    protected String _codelet; // specified codelet to execute for automated tasks

    // CONSTRUCTOR //

    public YDecomposition(String id, YSpecification specification) {
        _id = id;
        _specification = specification;
        _inputParameters = new HashMap<String, YParameter>();
        _outputParameters = new HashMap<String, YParameter>();
        _enablementParameters = new HashMap<String, YParameter>();
        _outputExpressions = new HashSet<String>();
        _data = new Document();
        _attributes = new YAttributeMap();

        _data.setRootElement(new Element(getRootDataElementName()));
    }

    /*****************************************************************************/

    // PERSISTENCE METHODS //

    public void initializeDataStore(YPersistenceManager pmgr, YNetData casedata) throws YPersistenceException {
        _casedata = casedata;
        _casedata.setData(JDOMUtil.documentToString(_data));

        if (pmgr != null)
            pmgr.storeObjectFromExternal(_casedata);
    }

    public void restoreData(YNetData casedata) {
        _casedata = casedata;
        _data = getNetDataDocument(casedata.getData());
    }

    public Document getNetDataDocument(String netData) {
        return JDOMUtil.stringToDocument(netData);
    }

    /******************************************************************************/

    // GETTERS & SETTERS //

    public String getID() {
        return _id;
    }

    public void setID(String id) {
        _id = id;
    }

    public YAttributeMap getAttributes() {
        return _attributes;
    }

    public void setAttributes(Map<String, String> attributes) {
        _attributes.set(attributes);
    }

    public String getAttribute(String name) {
        return _attributes.get(name);
    }

    public void setAttribute(String name, String value) {
        _attributes.put(name, value);
    }

    public void setAttribute(String name, DynamicValue value) {
        _attributes.put(name, value);
    }

    public String getDocumentation() {
        return _documentation;
    }

    public void setDocumentation(String documentation) {
        _documentation = documentation;
    }

    public String getName() {
        return _name;
    }

    public void setName(String name) {
        _name = name;
    }

    public Map<String, YParameter> getInputParameters() {
        return _inputParameters;
    }

    public Map<String, YParameter> getOutputParameters() {
        return _outputParameters;
    }

    public void addInputParameter(YParameter parameter) {
        if (parameter.isInput()) {
            String paramName = parameter.getPreferredName();
            if (paramName != null) {
                _inputParameters.put(paramName, parameter);
            }
        } else
            throw new RuntimeException("Can't set an output param as an input param.");
    }

    public YParameter removeInputParameter(YParameter parameter) {
        return _inputParameters.remove(parameter.getPreferredName());
    }

    public YParameter removeInputParameter(String name) {
        return _inputParameters.remove(name);
    }

    public void addOutputParameter(YParameter parameter) {
        if (parameter.isInput()) {
            throw new RuntimeException("Can't set an input param as an output param.");
        }
        if (parameter.isEnablement())
            setEnablementParameter(parameter);
        else {
            String paramName = parameter.getPreferredName();
            if (paramName != null) {
                _outputParameters.put(paramName, parameter);
            }
        }
    }

    public YParameter removeOutputParameter(YParameter parameter) {
        return _outputParameters.remove(parameter.getPreferredName());
    }

    public YParameter removeOutputParameter(String name) {
        return _outputParameters.remove(name);
    }

    public void setEnablementParameter(YParameter parameter) {
        if (parameter.isInput()) {
            throw new RuntimeException("Can't set an input param as an enablement param.");
        }
        String paramName = parameter.getPreferredName();
        if (paramName != null) {
            _enablementParameters.put(paramName, parameter);
        }
    }

    public void setOutputExpression(String query) {
        _outputExpressions.add(query);
    }

    public Set<String> getOutputQueries() {
        return _outputExpressions;
    }

    // if set to true, any task that decomposes to this will need to have a resourcing
    // strategy specified
    public void setExternalInteraction(boolean interaction) {
        _manualInteraction = interaction;
    }

    // when external interactions are specified as manual, tasks that decompose to
    // this will require resourcing decisions to be specified at design time
    public boolean requiresResourcingDecisions() {
        return _manualInteraction;
    }

    public String getCodelet() {
        return _codelet;
    }

    public void setCodelet(String codelet) {
        _codelet = codelet;
    }

    public YLogPredicate getLogPredicate() {
        return _logPredicate;
    }

    public void setLogPredicate(YLogPredicate predicate) {
        _logPredicate = predicate;
    }

    public String toXML() {

        // just do the decomposition facts (not the surrounding element) - to keep life simple
        StringBuilder xml = new StringBuilder();
        if (_name != null)
            xml.append(StringUtil.wrapEscaped(_name, "name"));
        if (_documentation != null)
            xml.append(StringUtil.wrapEscaped(_documentation, "documentation"));

        xml.append(paramMapToXML(_inputParameters));

        for (String expression : _outputExpressions) {
            xml.append("<outputExpression query=\"").append(JDOMUtil.encodeEscapes(expression)).append("\"/>");
        }

        xml.append(paramMapToXML(_outputParameters));
        xml.append(paramMapToXML(_enablementParameters));

        if (_logPredicate != null)
            xml.append(_logPredicate.toXML());

        return xml.toString();
    }

    private String paramMapToXML(Map<String, YParameter> paramMap) {
        StringBuilder result = new StringBuilder();
        List<YParameter> parameters = new ArrayList<YParameter>(paramMap.values());
        Collections.sort(parameters);
        for (YParameter parameter : parameters) {
            result.append(parameter.toXML());
        }
        return result.toString();
    }

    public void verify(YVerificationHandler handler) {
        if (_id == null)
            handler.error(this, this + " cannot have null id.");

        for (YParameter param : _inputParameters.values())
            param.verify(handler);

        for (YParameter param : _outputParameters.values())
            param.verify(handler);
    }

    public Set<String> getInputParameterNames() {
        return _inputParameters.keySet();
    }

    public Set<String> getOutputParameterNames() {
        return _outputParameters.keySet();
    }

    /**
     * Returns a link to the containing specification.
     * @return the specification containing this decomposition.
     */
    public YSpecification getSpecification() {
        return _specification;
    }

    public void setSpecification(YSpecification specification) {
        _specification = specification;
    }

    /**
     * Gets those params that bypass the decomposition state space.
     * @return a map of them.
     */
    public Map<String, YParameter> getStateSpaceBypassParams() {
        Map<String, YParameter> result = new HashMap<String, YParameter>();
        for (YParameter parameter : _outputParameters.values()) {
            if (parameter.bypassesDecompositionStateSpace()) {
                result.put(parameter.getPreferredName(), parameter);
            }
        }
        return result;
    }

    public String toString() {
        String fullClassName = getClass().getName();
        String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
        return shortClassName + ":" + getID();
    }

    public Object clone() throws CloneNotSupportedException {
        YDecomposition copy = (YDecomposition) super.clone();
        copy._inputParameters = new HashMap<String, YParameter>();
        for (YParameter parameter : _inputParameters.values()) {
            YParameter copyParam = (YParameter) parameter.clone();
            copy.addInputParameter(copyParam);
        }
        return copy;
    }

    /**
     * @return the document containing runtime variable values
     */
    public Document getInternalDataDocument() {
        return _data;
    }

    /**
     * This method returns the list of data from a decomposition. According to
     * its declared output parameters.  Only useful for Beta 4 and above.
     * The data inside this decomposition is groomed so to speak so that the
     * output data is returned in sequence.  Furthermore no internal variables, \
     * or input only parameters are returned.
     * @return a JDom Document of the output data.
     */
    public Document getOutputData() {

        //create a new output document to return
        Document outputDoc = new Document();
        Element root = _data.getRootElement();
        outputDoc.setRootElement(new Element(root.getName()));

        //now prepare a list of output params to iterate over.
        List<YParameter> outputParamsList = new ArrayList<YParameter>(getOutputParameters().values());
        Collections.sort(outputParamsList);

        for (YParameter parameter : outputParamsList) {
            Element child = root.getChild(parameter.getPreferredName());
            outputDoc.getRootElement().addContent(child.clone());
        }
        return outputDoc;
    }

    public Element getVariableDataByName(String name) {
        return _data.getRootElement().getChild(name);
    }

    public void assignData(YPersistenceManager pmgr, Element variable) throws YPersistenceException {

        _data.getRootElement().removeChild(variable.getName());
        _data.getRootElement().addContent(variable);
        _casedata.setData(JDOMUtil.documentToString(_data));

        if (pmgr != null)
            pmgr.updateObjectExternal(_casedata);
    }

    protected void addData(YPersistenceManager pmgr, Element element) throws YPersistenceException {
        assignData(pmgr, element.clone());
    }

    public void initialise(YPersistenceManager pmgr) throws YPersistenceException {
        for (YParameter inputParam : _inputParameters.values()) {
            Element initialValueXML;
            String initialValue = inputParam.getInitialValue();
            if (initialValue != null) {
                initialValue = StringUtil.wrap(initialValue, inputParam.getName());
                initialValueXML = JDOMUtil.stringToElement(initialValue);
            } else
                initialValueXML = new Element(inputParam.getName());

            addData(pmgr, initialValueXML);
        }
    }

    public String getRootDataElementName() {
        return _specification.getSchemaVersion().usesSimpleRootData() ? "data" : _id;
    }

}