edu.ucsd.crbs.cws.workflow.WorkflowFromVersionOneMomlXmlFactory.java Source code

Java tutorial

Introduction

Here is the source code for edu.ucsd.crbs.cws.workflow.WorkflowFromVersionOneMomlXmlFactory.java

Source

/*
 * COPYRIGHT AND LICENSE
 * 
 * Copyright 2014 The Regents of the University of California All Rights Reserved
 * 
 * Permission to copy, modify and distribute any part of this CRBS Workflow 
 * Service for educational, research and non-profit purposes, without fee, and
 * without a written agreement is hereby granted, provided that the above 
 * copyright notice, this paragraph and the following three paragraphs appear
 * in all copies.
 * 
 * Those desiring to incorporate this CRBS Workflow Service into commercial 
 * products or use for commercial purposes should contact the Technology
 * Transfer Office, University of California, San Diego, 9500 Gilman Drive, 
 * Mail Code 0910, La Jolla, CA 92093-0910, Ph: (858) 534-5815, 
 * FAX: (858) 534-7345, E-MAIL:invent@ucsd.edu.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR 
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 
 * LOST PROFITS, ARISING OUT OF THE USE OF THIS CRBS Workflow Service, EVEN IF 
 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 * 
 * THE CRBS Workflow Service PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE
 * UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. THE UNIVERSITY OF CALIFORNIA MAKES
 * NO REPRESENTATIONS AND EXTENDS NO WARRANTIES OF ANY KIND, EITHER IMPLIED OR 
 * EXPRESS, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR THAT THE USE OF 
 * THE CRBS Workflow Service WILL NOT INFRINGE ANY PATENT, TRADEMARK OR OTHER
 * RIGHTS. 
 */

package edu.ucsd.crbs.cws.workflow;

import edu.ucsd.crbs.cws.rest.Constants;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.filter.Filters;
import org.jdom2.input.SAXBuilder;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;

/**
 * Instances of this class parse a 1.x kepler XML file to generate a Workflow
 * object.
 *
 * @author Christopher Churas <churas@ncmir.ucsd.edu>
 */
public class WorkflowFromVersionOneMomlXmlFactory {

    /**
     * MoML Xpath to get basic canvas parameters
     */
    public static final String MOML_XPATH_STRING = "/entity/property[@class='ptolemy.data.expr.StringParameter']";
    public static final String MOML_XPATH_NUMBER = "/entity/property[@class='ptolemy.data.expr.Parameter']";
    public static final String MOML_XPATH_FILE = "/entity/property[@class='ptolemy.data.expr.FileParameter']";

    // Should I go this way to reduce the number of xpath queries?
    //public static final String MOML_CANVAS_PARAMETER = "/entity/property[@class='ptolemy.data.expr.StringParameter' or @class='ptolemy.data.expr.Parameter' or @class='ptolemy.data.expr.FileParameter']";

    /**
     * MoML Xpath to get release notes from annotation on canvas
     */
    public static final String MOML_RELEASE_NOTES = "/entity/property[@class='ptolemy.vergil.kernel.attributes.TextAttribute'][lower-case(@name)='releasenotes']/property[@name='text']";

    /**
     * MoML Xpath to get release notes from annotation on canvas
     */
    public static final String MOML_DESCRIPTION = "/entity/property[@class='ptolemy.vergil.kernel.attributes.TextAttribute'][lower-case(@name)='description']/property[@name='text']";

    /**
     * MoML Xpath to get release notes from annotation on canvas
     */
    public static final String MOML_WORKFLOWNAME = "/entity/property[@class='ptolemy.vergil.kernel.attributes.TextAttribute'][lower-case(@name)='workflowname']/property[@name='text']";

    public static final String KEPLER_PARAMETER_STRING = "String";
    public static final String KEPLER_PARAMETER_FILE = "File";
    public static final String KEPLER_PARAMETER_NUMBER = "Number";

    public static final String KEPLER_CHECKBOX_FALSE = "false";
    public static final String KEPLER_CHECKBOX_TRUE = "true";

    public static final String ELEMENT_NAME_KEY = "name";
    public static final String ELEMENT_VALUE_KEY = "value";
    public static final String ELEMENT_PROPERTY_KEY = "property";

    public static final String ATTRIBUTE_NAME_KEY = "name";
    public static final String ATTRIBUTE_VALUE_KEY = "value";

    public static final HashMap<String, String> _keplerParameterTypes;

    public static final Logger log = Logger.getLogger(WorkflowFromVersionOneMomlXmlFactory.class.getName());

    static {
        _keplerParameterTypes = new HashMap<>();

        _keplerParameterTypes.put(KEPLER_PARAMETER_STRING, MOML_XPATH_STRING);
        _keplerParameterTypes.put(KEPLER_PARAMETER_NUMBER, MOML_XPATH_NUMBER);
        _keplerParameterTypes.put(KEPLER_PARAMETER_FILE, MOML_XPATH_FILE);

    }

    private InputStream _in;

    /**
     * Sets the workflow to parse when getWorkflow() is called
     *
     * @param in XML to parse
     */
    public void setWorkflowXml(InputStream in) {
        _in = in;
    }

    /**
     *
     * @return @throws Exception
     */
    public Workflow getWorkflow() throws Exception {

        Document doc;
        try {
            doc = getDocument(_in);
        } catch (Exception ex) {
            log.log(Level.SEVERE, "There was a problem parsing the workflow xml {0}", ex.getMessage());
            return null;
        }
        if (doc == null) {
            log.warning("getDocument(Workflow xml input stream) returned null");
            return null;
        }
        return getWorkflowFromDocument(doc);
    }

    /**
     * Returns the root element of parsed XML document
     *
     * @param in XML document to parse
     * @return Root element of document
     * @throws Exception If there is a problem parsing the document
     */
    private Document getDocument(InputStream in) throws Exception {
        SAXBuilder builder = new SAXBuilder();
        builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        return builder.build(in);
    }

    /**
     * Using Xpath queries parses MOML to create Workflow object
     * @param doc Document to parse
     * @return Workflow object upon success or null if none found
     * @throws Exception If there is a parsing error or format error
     */
    private Workflow getWorkflowFromDocument(Document doc) throws Exception {

        // create the workflow object and set basic information
        Workflow workflow = new Workflow();

        addReleaseNotes(workflow, doc);
        addDescription(workflow, doc);
        addWorkflowName(workflow, doc);

        for (String keplerParameterType : _keplerParameterTypes.keySet()) {
            XPathExpression<Element> xpath = XPathFactory.instance()
                    .compile(_keplerParameterTypes.get(keplerParameterType), Filters.element());

            List<Element> elements = xpath.evaluate(doc);
            if (elements != null && elements.isEmpty() == false) {
                addParametersToWorkflow(workflow, elements, keplerParameterType);
            }
        }
        return workflow;
    }

    private String getContentOfValueAttributeFromFirstElementInQuery(Document doc, final String query)
            throws Exception {
        XPathExpression<Element> xpath = XPathFactory.instance().compile(query, Filters.element());
        Element e = xpath.evaluateFirst(doc);
        if (e == null) {
            return null;
        }
        return e.getAttributeValue(ATTRIBUTE_VALUE_KEY);
    }

    private void addReleaseNotes(Workflow workflow, Document doc) throws Exception {
        workflow.setReleaseNotes(getContentOfValueAttributeFromFirstElementInQuery(doc, MOML_RELEASE_NOTES));
    }

    private void addDescription(Workflow workflow, Document doc) throws Exception {
        workflow.setDescription(getContentOfValueAttributeFromFirstElementInQuery(doc, MOML_DESCRIPTION));
    }

    private void addWorkflowName(Workflow workflow, Document doc) throws Exception {
        workflow.setName(getContentOfValueAttributeFromFirstElementInQuery(doc, MOML_WORKFLOWNAME));
    }

    private void addParametersToWorkflow(Workflow workflow, List<Element> elements,
            final String keplerParameterType) throws Exception {

        List<WorkflowParameter> params = workflow.getParameters();

        //If there are no parameters for this workflow create an empty array and set it
        if (params == null) {
            params = new ArrayList<>();
            workflow.setParameters(params);
        }
        for (Element e : elements) {

            String elementNameKey = e.getAttributeValue(ELEMENT_NAME_KEY);
            WorkflowParameter wParam = new WorkflowParameter();

            wParam.setName(elementNameKey);
            wParam.setValue(e.getAttributeValue(ELEMENT_VALUE_KEY));
            setDisplayName(e, wParam, elementNameKey);
            setKeplerParameterAttributes(e, wParam);

            //if the parameter name matches one of the 4 special parameters set the type
            //to hidden cause it should not be displayed to the user
            if (elementNameKey.equalsIgnoreCase(Constants.CWS_USER)
                    || elementNameKey.equalsIgnoreCase(Constants.CWS_JOBNAME)
                    || elementNameKey.equalsIgnoreCase(Constants.CWS_OUTPUTDIR)
                    || elementNameKey.equalsIgnoreCase(Constants.CWS_JOBID)) {
                wParam.setType(WorkflowParameter.Type.HIDDEN);
            }

            //only add parameters with a type
            if (wParam.getType() != null) {
                params.add(wParam);
            }
        }
    }

    private void setDisplayName(Element element, WorkflowParameter wParam, final String defaultValue) {

        Element dispElem = element.getChild("display");
        if (dispElem != null) {
            wParam.setDisplayName(dispElem.getAttributeValue(ELEMENT_NAME_KEY));
            return;
        }

        wParam.setDisplayName(defaultValue);
    }

    private void setKeplerParameterAttributes(Element element, WorkflowParameter wParam) throws Exception {
        List<Element> subPropElements = element.getChildren(ELEMENT_PROPERTY_KEY);
        for (Element subEl : subPropElements) {
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("help")) {
                wParam.setHelp(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("type")) {
                String theType = subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY);
                if (theType == null) {
                    throw new Exception(
                            "value of displaytype attribute for Parameter " + wParam.getName() + " is null. ");
                }
                if (WorkflowParameter.Type.isValidType(theType)) {
                    wParam.setType(theType.toLowerCase());
                } else {
                    throw new Exception(theType + " is not a valid WorkflowParameter.Type");
                }
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("namevaluedelimiter")) {
                wParam.setNameValueDelimiter(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("linedelimiter")) {
                wParam.setLineDelimiter(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }

            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("advanced")) {
                String advVal = subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY);
                if (advVal != null) {
                    if (advVal.equals("") || advVal.equalsIgnoreCase("true")) {
                        wParam.setIsAdvanced(true);
                    } else if (advVal.equalsIgnoreCase("false")) {
                        wParam.setIsAdvanced(false);
                    }
                }
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("required")) {
                String requiredString = subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY);
                if (requiredString != null && !requiredString.trim().equals("")) {
                    if (requiredString.equalsIgnoreCase("true") || requiredString.equalsIgnoreCase("false")) {
                        wParam.setIsRequired(Boolean.valueOf(requiredString));
                    }
                }
            }

            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("rows")) {
                wParam.setRows(new Long(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY)));
            }

            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("columns")) {
                wParam.setColumns(new Long(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY)));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("selected")) {
                wParam.setSelected(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }

            //this checks for the presence of elements for validation properties
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("validationtype")) {
                wParam.setValidationType(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("validationhelp")) {
                wParam.setValidationHelp(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("minvalue")) {
                wParam.setMinValue(Double.parseDouble(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY)));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("maxvalue")) {
                wParam.setMaxValue(Double.parseDouble(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY)));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("validationregex")) {
                wParam.setValidationRegex(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("maxlength")) {
                wParam.setMaxLength(Long.parseLong(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY)));
            }
            if (subEl.getAttributeValue(ATTRIBUTE_NAME_KEY).equalsIgnoreCase("maxfilesize")) {
                wParam.setMaxFileSize(Long.parseLong(subEl.getAttributeValue(ATTRIBUTE_VALUE_KEY)));
            }
        }
    }

};