org.yawlfoundation.yawl.unmarshal.YSpecificationParser.java Source code

Java tutorial

Introduction

Here is the source code for org.yawlfoundation.yawl.unmarshal.YSpecificationParser.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.unmarshal;

import org.jdom2.Attribute;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.yawlfoundation.yawl.elements.*;
import org.yawlfoundation.yawl.exceptions.YSyntaxException;
import org.yawlfoundation.yawl.schema.YSchemaVersion;
import org.yawlfoundation.yawl.util.JDOMUtil;

import javax.xml.XMLConstants;
import java.text.ParseException;
import java.util.*;

/**
 * Parses, or builds, specification objects from XML doclets.
 * 
 * @author Lachlan Aldred
 * 
    
 */
class YSpecificationParser {
    private YSpecification _specification;
    private YDecompositionParser[] _decompositionParser;
    private Map<String, String> _decompAndTypeMap = new HashMap<String, String>();
    private Namespace _yawlNS;
    private List<String> _emptyComplexTypeFlagTypes = new ArrayList<String>();

    private static final String _schema4SchemaURI = XMLConstants.W3C_XML_SCHEMA_NS_URI;
    private static final String _defaultSchema = "<xs:schema xmlns:xs=\"" + _schema4SchemaURI + "\"/>";

    static final String INITIAL_VERSION = "0.1"; // initial spec version

    /**
     * build a specification object from part of an XML document
     * @param specificationElem the specification part of an XMl document
     * @param version the version of the XML representation (i.e. beta2 or beta3).
     * @throws YSyntaxException
     */
    public YSpecificationParser(Element specificationElem, YSchemaVersion version) throws YSyntaxException {
        _yawlNS = specificationElem.getNamespace();

        parseSpecification(specificationElem, version);
        linkDecompositions();
    }

    private void parseSpecification(Element specificationElem, YSchemaVersion version) throws YSyntaxException {
        List<Element> decompositionElems = specificationElem.getChildren("decomposition", _yawlNS);
        for (Element decompositionElem : decompositionElems) {
            Namespace xsiNameSpc = decompositionElem.getNamespace("xsi");
            String decompID = decompositionElem.getAttributeValue("id");
            Attribute type = decompositionElem.getAttribute("type", xsiNameSpc);
            if (type != null) {
                String decompType = type.getValue();
                _decompAndTypeMap.put(decompID, decompType);
            }
        }
        String uriString = specificationElem.getAttributeValue("uri");
        _specification = new YSpecification(uriString);
        _specification.setVersion(version);
        _specification.setMetaData(parseMetaData(specificationElem));
        String name = specificationElem.getChildText("name", _yawlNS);
        String documentation = specificationElem.getChildText("documentation", _yawlNS);

        // if name and doco fields missing from spec, see if they are in metadata
        if (name == null)
            name = _specification.getMetaData().getTitle();
        if (documentation == null)
            documentation = _specification.getMetaData().getDescription();
        _specification.setName(name);
        _specification.setDocumentation(documentation);

        Namespace schema4SchemaNS = Namespace.getNamespace(_schema4SchemaURI);
        Element schemaElem = specificationElem.getChild("schema", schema4SchemaNS);
        if (null != schemaElem) {
            extractEmptyComplexTypeFlagTypeNames(schemaElem);
            _specification.setSchema(JDOMUtil.elementToString(schemaElem));
        } else {

            // if the spec has no schema definition insert a default one so that a
            // DataValidator gets created
            _specification.setSchema(_defaultSchema);
        }

        //If is version beta2 we loop through in a slightly different way.
        if (isBeta2Version()) {
            _decompositionParser = new YDecompositionParser[decompositionElems.size() + 1];
            Element rootNetElem = specificationElem.getChild("rootNet", _yawlNS);
            _decompositionParser[0] = new YDecompositionParser(rootNetElem, this,
                    _specification.getSchemaVersion());
            YNet rootNet = (YNet) _decompositionParser[0].getDecomposition();
            _specification.setRootNet(rootNet);

            for (int i = 1; i <= decompositionElems.size(); i++) {
                Element decompositionElem = decompositionElems.get(i - 1);
                _decompositionParser[i] = new YDecompositionParser(decompositionElem, this,
                        _specification.getSchemaVersion());
                YDecomposition decomposition = _decompositionParser[i].getDecomposition();
                _specification.addDecomposition(decomposition);
            }
        } else {//must be beta3 or greater
            _decompositionParser = new YDecompositionParser[decompositionElems.size()];
            for (int i = 0; i < decompositionElems.size(); i++) {
                Element decompositionElem = decompositionElems.get(i);
                _decompositionParser[i] = new YDecompositionParser(decompositionElem, this,
                        _specification.getSchemaVersion());
                YDecomposition decomposition = _decompositionParser[i].getDecomposition();
                _specification.addDecomposition(decomposition);
            }
        }
        addSchema(specificationElem);
    }

    YMetaData parseMetaData(Element specificationElem) {
        Element metaDataElem = specificationElem.getChild("metaData", _yawlNS);
        YMetaData metaData = new YMetaData();

        metaData.setTitle(metaDataElem.getChildText("title", _yawlNS));

        for (Element creatorElem : metaDataElem.getChildren("creator", _yawlNS)) {
            metaData.addCreator(creatorElem.getText());
        }

        for (Element subjectElem : metaDataElem.getChildren("subject", _yawlNS)) {
            metaData.addSubject(subjectElem.getText());
        }

        metaData.setDescription(metaDataElem.getChildText("description", _yawlNS));

        for (Element contributor : metaDataElem.getChildren("contributor", _yawlNS)) {
            metaData.addContributor(contributor.getText());
        }

        metaData.setCoverage(metaDataElem.getChildText("coverage", _yawlNS));

        String validFrom = metaDataElem.getChildText("validFrom", _yawlNS);
        if (validFrom != null) {
            try {
                metaData.setValidFrom(YMetaData.dateFormat.parse(validFrom));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        String validUntil = metaDataElem.getChildText("validUntil", _yawlNS);
        if (validUntil != null) {
            try {
                metaData.setValidUntil(YMetaData.dateFormat.parse(validUntil));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        String created = metaDataElem.getChildText("created", _yawlNS);
        if (created != null) {
            try {
                metaData.setCreated(YMetaData.dateFormat.parse(created));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        String version = metaDataElem.getChildText("version", _yawlNS);
        if (version != null && version.trim().length() > 0) {
            metaData.setVersion(new YSpecVersion(version.trim()));
        } else
            metaData.setVersion(new YSpecVersion(INITIAL_VERSION));

        metaData.setStatus(metaDataElem.getChildText("status", _yawlNS));
        /**
         * AJH: Add in support for the persistent property. This is simply a property which indicates if
         *      a custom service processing workitems from this specification needs to perform any
         *      "persistence" activities.
         */
        {
            String persistentText = metaDataElem.getChildText("persistent", _yawlNS);
            if (persistentText == null) {
                metaData.setPersistent(false);
            } else {
                metaData.setPersistent(persistentText.trim().equalsIgnoreCase("TRUE"));
            }
        }

        String uniqueID = metaDataElem.getChildText("identifier", _yawlNS);
        if (uniqueID != null)
            metaData.setUniqueID(uniqueID);

        return metaData;
    }

    /**
     * @return whether this is a a beta 2 specification version or not.
     */
    private boolean isBeta2Version() {
        return _specification.getSchemaVersion().isBeta2();
    }

    /**
     * adds the XML schema library to the specification.
     * @param specificationElem
     */
    private void addSchema(Element specificationElem) throws YSyntaxException {

        Element schemaElem = specificationElem.getChild("schema");
        if (schemaElem != null) {
            _specification.setSchema(JDOMUtil.elementToString(schemaElem));
        }
    }

    private void extractEmptyComplexTypeFlagTypeNames(Element schemaElem) {
        if (schemaElem != null) {
            for (Element elem : schemaElem.getChildren()) {
                if (elem.getName().equals("complexType") && elem.getChildren().isEmpty()) {
                    _emptyComplexTypeFlagTypes.add(elem.getAttributeValue("name"));
                }
            }
        }
    }

    protected List<String> getEmptyComplexTypeFlagTypeNames() {
        return _emptyComplexTypeFlagTypes;
    }

    private void linkDecompositions() {
        for (YDecompositionParser parser : _decompositionParser) {
            Map<YTask, String> decomposesToIDs = parser.getDecomposesToIDs();
            for (YTask task : decomposesToIDs.keySet()) {
                String decompID = decomposesToIDs.get(task);
                YDecomposition implementation = _specification.getDecomposition(decompID);
                task.setDecompositionPrototype(implementation);
            }
        }
    }

    /**
     * Method getSpecification.
     * @return YSpecification
     */
    public YSpecification getSpecification() {
        return _specification;
    }

    public String getDecompositionType(String decomposesToID) {
        return _decompAndTypeMap.get(decomposesToID);
    }

}