Package org.jbpm.ui.jpdl2

Source Code of org.jbpm.ui.jpdl2.JpdlSerializer_2

package org.jbpm.ui.jpdl2;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.jbpm.ui.JpdlSerializer;
import org.jbpm.ui.JpdlVersionRegistry;
import org.jbpm.ui.PluginConstants;
import org.jbpm.ui.common.model.Active;
import org.jbpm.ui.common.model.Decision;
import org.jbpm.ui.common.model.Delegable;
import org.jbpm.ui.common.model.Describable;
import org.jbpm.ui.common.model.EndState;
import org.jbpm.ui.common.model.Fork;
import org.jbpm.ui.common.model.GraphElement;
import org.jbpm.ui.common.model.ITimed;
import org.jbpm.ui.common.model.Join;
import org.jbpm.ui.common.model.NamedGraphElement;
import org.jbpm.ui.common.model.ProcessDefinition;
import org.jbpm.ui.common.model.StartState;
import org.jbpm.ui.common.model.Subprocess;
import org.jbpm.ui.common.model.Swimlane;
import org.jbpm.ui.common.model.Transition;
import org.jbpm.ui.common.model.WaitState;
import org.jbpm.ui.jpdl2.model.ActionImpl;
import org.jbpm.ui.jpdl2.model.TimerState;
import org.jbpm.ui.util.VariableMapping;
import org.jbpm.ui.util.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class JpdlSerializer_2 extends JpdlSerializer {
    private static final String ACCESS_ATTR = "access";

    private static final String END_STATE_NODE = "end-state";

    private static final String VARIABLE_NODE = "variable";

    private static final String SUB_PROCESS_NODE = "sub-process";

    private static final String MAPPED_NAME_ATTR = "mapped-name";

    private static final String PROCESS_STATE_NODE = "process-state";

    private static final String DECISION_NODE = "decision";

    private static final String JOIN_NODE = "join";

    private static final String FORK_NODE = "fork";

    private static final String DUEDATE_ATTR = "duedate";

    private static final String TIMER_NODE = "timer";

    private static final String ASSIGNMENT_NODE = "assignment";

    private static final String STATE_NODE = "state";

    private static final String START_STATE_NODE = "start-state";

    private static final String SWIMLANE_NODE = "swimlane";

    private static final String EVENT_TYPE_ATTR = "event-type";

    private static final String TO_ATTR = "to";

    private static final String CLASS_ATTR = "class";

    private static final String ACTION_NODE = "action";

    private static final String TRANSITION_NODE = "transition";

    private static final String DELEGATION_NODE = "delegation";

    private static final String DESCRIPTION_NODE = "description";

    private static final String NAME_ATTR = "name";

    private static final String DOCTYPE_SYSTEM_ID = "processdefinition-2.0.dtd";

    @Override
    public boolean isSupported(Document document) {
        DocumentType documentType = document.getDoctype();
        if (documentType == null || documentType.getSystemId() == null)
            return false;
        return documentType.getSystemId().contains(DOCTYPE_SYSTEM_ID);
    }

    @Override
    public void validateProcessDefinitionXML(IFile file) throws SAXException {
        try {
            XmlUtil.parseDocumentValidateDTD(file.getContents());
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (CoreException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Document getInitialProcessDefinitionDocument(String processName) throws ParserConfigurationException {
        Document document = XmlUtil.createDocument("process-definition", null);
        setAttribute(document.getDocumentElement(), NAME_ATTR, processName);
        DocumentType documentType = document.getImplementation().createDocumentType("process-definition", "-//jBpm/jBpm Mapping DTD 2.0//EN",
                DOCTYPE_SYSTEM_ID);
        document.appendChild(documentType);
        return document;
    }

    private <T extends GraphElement> T create(Node node, GraphElement parent) {
      return create(node, parent, node.getNodeName());
    }
    private <T extends GraphElement> T create(Node node, GraphElement parent, String nodeType) {
        GraphElement element = JpdlVersionRegistry.getElementTypeDefinition(jpdlVersion, nodeType).createElement();
        if (parent != null) {
            parent.addChild(element);
        }
        if (element instanceof NamedGraphElement) {
            ((NamedGraphElement) element).setName(getAttribute(node, NAME_ATTR));
        }
        NodeList nodeList = node.getChildNodes();
        for (int j = 0; j < nodeList.getLength(); j++) {
            Node childNode = nodeList.item(j);
            if (DESCRIPTION_NODE.equals(childNode.getNodeName()) && element instanceof Describable) {
                ((Describable) element).setDescription(getTextContent(childNode));
            }
            if (DELEGATION_NODE.equals(childNode.getNodeName())) {
                ((Delegable) element).setDelegationClassName(getAttribute(childNode, CLASS_ATTR));
                element.setDelegationConfiguration(getTextContent(childNode));
            }
            if (TRANSITION_NODE.equals(childNode.getNodeName())) {
                parseTransition(childNode, element);
            }
            if (ACTION_NODE.equals(childNode.getNodeName())) {
                parseAction(childNode, element);
            }
        }
        return (T) element;
    }

    private void parseTransition(Node node, GraphElement parent) {
        Transition transition = create(node, parent);
        String targetName = getAttribute(node, TO_ATTR);
        TRANSION_TARGETS.put(transition, targetName);
    }

    private void parseAction(Node node, GraphElement parent) {
        ActionImpl action = create(node, parent);
        action.setEventType(getAttribute(node, EVENT_TYPE_ATTR));
    }

    private static Map<Transition, String> TRANSION_TARGETS = new HashMap<Transition, String>();

    @Override
    public ProcessDefinition parseXML(Document document) {
        TRANSION_TARGETS.clear();
        ProcessDefinition definition = create(document.getDocumentElement(), null);

        NodeList swimlanes = document.getElementsByTagName(SWIMLANE_NODE);
        for (int i = 0; i < swimlanes.getLength(); i++) {
            Node node = swimlanes.item(i);
            create(node, definition);
        }

        NodeList startStates = document.getElementsByTagName(START_STATE_NODE);
        if (startStates.getLength() == 1) {
            Node node = startStates.item(0);
            StartState startState = create(node, definition);
            String swimlaneName = getAttribute(node, SWIMLANE_NODE);
            Swimlane swimlane = definition.getSwimlaneByName(swimlaneName);
            startState.setSwimlane(swimlane);
        }

        NodeList states = document.getElementsByTagName(STATE_NODE);
        for (int i = 0; i < states.getLength(); i++) {
            Node node = states.item(i);
            NodeList nodeList = node.getChildNodes();
            int transitionsCount = 0;
            boolean hasTimeOutTransition = false;
            for (int j = 0; j < nodeList.getLength(); j++) {
                Node childNode = nodeList.item(j);
                if (TRANSITION_NODE.equals(childNode.getNodeName())) {
                  String transitionName = getAttribute(childNode, NAME_ATTR);
                  if (PluginConstants.TIMER_TRANSITION_NAME.equals(transitionName)) {
                    hasTimeOutTransition = true;
                  }
                  transitionsCount++;
                }
            }
            GraphElement state;
            if (transitionsCount == 1 && hasTimeOutTransition) {
              state = create(node, definition, "waitState");
            } else {
              state = create(node, definition);
            }
            for (int j = 0; j < nodeList.getLength(); j++) {
                Node childNode = nodeList.item(j);
                if (ASSIGNMENT_NODE.equals(childNode.getNodeName()) && state instanceof TimerState) {
                    String swimlaneName = getAttribute(childNode, SWIMLANE_NODE);
                    Swimlane swimlane = definition.getSwimlaneByName(swimlaneName);
                    ((TimerState) state).setSwimlane(swimlane);
                    String assignmentType = getAttribute(childNode, ASSIGNMENT_NODE);
                    ((TimerState) state).setReassignmentEnabled(assignmentType != null && "reassign".equals(assignmentType));
                }
                if (TIMER_NODE.equals(childNode.getNodeName())) {
                    ((ITimed) state).setDueDate(getAttribute(childNode, DUEDATE_ATTR));
                }
            }
        }

        NodeList forks = document.getElementsByTagName(FORK_NODE);
        for (int i = 0; i < forks.getLength(); i++) {
            Node node = forks.item(i);
            create(node, definition);
        }

        NodeList joins = document.getElementsByTagName(JOIN_NODE);
        for (int i = 0; i < joins.getLength(); i++) {
            Node node = joins.item(i);
            create(node, definition);
        }

        NodeList decisions = document.getElementsByTagName(DECISION_NODE);
        for (int i = 0; i < decisions.getLength(); i++) {
            Node node = decisions.item(i);
            create(node, definition);
        }

        NodeList processStates = document.getElementsByTagName(PROCESS_STATE_NODE);
        for (int i = 0; i < processStates.getLength(); i++) {
            Node node = processStates.item(i);
            Subprocess subprocess = create(node, definition);
            List<VariableMapping> variablesList = new ArrayList<VariableMapping>();
            NodeList nodeList = node.getChildNodes();
            for (int j = 0; j < nodeList.getLength(); j++) {
                Node childNode = nodeList.item(j);
                if (SUB_PROCESS_NODE.equals(childNode.getNodeName())) {
                    subprocess.setSubProcessName(getAttribute(childNode, NAME_ATTR));
                }
                if (VARIABLE_NODE.equals(childNode.getNodeName())) {
                    VariableMapping variable = new VariableMapping();
                    variable.setProcessVariable(getAttribute(childNode, NAME_ATTR));
                    variable.setSubprocessVariable(getAttribute(childNode, MAPPED_NAME_ATTR));
                    variable.setUsage(getAttribute(childNode, ACCESS_ATTR));
                    variablesList.add(variable);
                }
            }
            subprocess.setVariablesList(variablesList);
        }
        NodeList endStates = document.getElementsByTagName(END_STATE_NODE);
        for (int i = 0; i < endStates.getLength(); i++) {
            Node node = endStates.item(i);
            create(node, definition);
        }

        List<Transition> tmpTransitions = new ArrayList<Transition>(TRANSION_TARGETS.keySet());
        for (Transition transition : tmpTransitions) {
            String targetName = TRANSION_TARGETS.remove(transition);
            org.jbpm.ui.common.model.Node target = definition.getNodeByNameNotNull(targetName);
            transition.setTarget(target);
        }
        return definition;
    }

    @Override
    public void saveToXML(ProcessDefinition definition, Document document) {
        document.removeChild(document.getDocumentElement());

        Element root = writeElement(document, null, definition);
        document.appendChild(root);

        List<Swimlane> swimlanes = definition.getSwimlanes();
        for (Swimlane swimlane : swimlanes) {
            Element swimlaneElement = writeElement(document, root, swimlane);
            writeDelegation(document, swimlaneElement, swimlane);
        }

        StartState startState = definition.getFirstChild(StartState.class);
        if (startState != null) {
            Element startStateElement = writeElement(document, root, startState);
            setAttribute(startStateElement, SWIMLANE_NODE, startState.getSwimlaneName());
            writeTransitions(document, startStateElement, startState);
        }

        List<Subprocess> subprocesses = definition.getChildren(Subprocess.class);
        for (org.jbpm.ui.common.model.Node node : subprocesses) {
            writeNode(document, root, node);
        }
        List<Fork> forks = definition.getChildren(Fork.class);
        for (org.jbpm.ui.common.model.Node node : forks) {
            writeNode(document, root, node);
        }
        List<Join> joins = definition.getChildren(Join.class);
        for (org.jbpm.ui.common.model.Node node : joins) {
            writeNode(document, root, node);
        }
        List<Decision> decisions = definition.getChildren(Decision.class);
        for (org.jbpm.ui.common.model.Node node : decisions) {
            writeNode(document, root, node);
        }

        List<TimerState> states = definition.getChildren(TimerState.class);
        for (TimerState state : states) {
            writeState(document, root, state);
        }

        List<WaitState> waitStates = definition.getChildren(WaitState.class);
        for (WaitState state : waitStates) {
          Element waitStateElement = writeElement(document, root, state, "state");
            Element timerElement = document.createElement(TIMER_NODE);
            setAttribute(timerElement, DUEDATE_ATTR, state.getDueDate());
            setAttribute(timerElement, TRANSITION_NODE, PluginConstants.TIMER_TRANSITION_NAME);
            waitStateElement.appendChild(timerElement);
            //writeActions(document, waitStateElement, (Active) state);
          writeTransitions(document, waitStateElement, state);
        }

        EndState endState = definition.getFirstChild(EndState.class);
        if (endState != null) {
            writeElement(document, root, endState);
        }
    }

    private Element writeState(Document document, Element parent, TimerState state) {
        Element stateElement = writeElement(document, parent, state);

        if (state.getSwimlaneName() != null) {
            Element assignmentElement = document.createElement(ASSIGNMENT_NODE);
            setAttribute(assignmentElement, ASSIGNMENT_NODE, state.isReassignmentEnabled() ? "reassign" : "required");
            setAttribute(assignmentElement, SWIMLANE_NODE, state.getSwimlaneName());
            stateElement.appendChild(assignmentElement);
        }
        if (state.timerExist()) {
            Element timerElement = document.createElement(TIMER_NODE);
            setAttribute(timerElement, DUEDATE_ATTR, state.getDuration().getDuration());
            setAttribute(timerElement, TRANSITION_NODE, PluginConstants.TIMER_TRANSITION_NAME);
            stateElement.appendChild(timerElement);
        }

        writeActions(document, stateElement, (Active) state);
        writeTransitions(document, stateElement, state);
        return stateElement;
    }

    private Element writeNode(Document document, Element parent, org.jbpm.ui.common.model.Node node) {
        Element nodeElement = writeElement(document, parent, node);
        if (node instanceof Decision) {
            writeDelegation(document, nodeElement, (Decision) node);
        }
        if (node instanceof Active) {
            writeActions(document, nodeElement, (Active) node);
        }
        if (node instanceof Subprocess) {
            Subprocess subprocess = (Subprocess) node;
            Element subProcessElement = document.createElement(SUB_PROCESS_NODE);
            setAttribute(subProcessElement, NAME_ATTR, subprocess.getSubProcessName());
            nodeElement.appendChild(subProcessElement);
            for (VariableMapping variable : subprocess.getVariablesList()) {
                Element variableElement = document.createElement(VARIABLE_NODE);
                setAttribute(variableElement, NAME_ATTR, variable.getProcessVariable());
                setAttribute(variableElement, MAPPED_NAME_ATTR, variable.getSubprocessVariable());
                setAttribute(variableElement, ACCESS_ATTR, variable.getUsage());
                nodeElement.appendChild(variableElement);
            }
        }
        writeTransitions(document, nodeElement, node);
        return nodeElement;
    }

    private Element writeElement(Document document, Element parent, GraphElement element) {
      return writeElement(document, parent, element, element.getTypeName());
    }
    private Element writeElement(Document document, Element parent, GraphElement element, String nodeName) {
        Element result = document.createElement(nodeName);
        if (element instanceof NamedGraphElement) {
            setAttribute(result, NAME_ATTR, ((NamedGraphElement) element).getName());
        }
        if (element instanceof Describable) {
            String description = ((Describable) element).getDescription();
            if (description != null && description.length() > 0) {
                Element desc = document.createElement(DESCRIPTION_NODE);
                setNodeValue(desc, description);
                result.appendChild(desc);
            }
        }
        if (parent != null) {
            parent.appendChild(result);
        }
        return result;
    }

    private void writeTransitions(Document document, Element parent, org.jbpm.ui.common.model.Node node) {
        List<Transition> transitions = node.getLeavingTransitions();
        for (Transition transition : transitions) {
            Element transitionElement = writeElement(document, parent, transition);
            transitionElement.setAttribute(TO_ATTR, transition.getTargetName());
            writeActions(document, transitionElement, transition);
        }
    }

    private void writeActions(Document document, Element parent, Active active) {
        List<ActionImpl> actions = (List<ActionImpl>) active.getActions();
        for (ActionImpl action : actions) {
            Element actionElement = writeElement(document, parent, action);
            setAttribute(actionElement, EVENT_TYPE_ATTR, action.getEventType());
            writeDelegation(document, actionElement, action);
        }
    }

    private void writeDelegation(Document document, Element parent, Delegable delegable) {
        Element delegationElement = document.createElement(DELEGATION_NODE);
        setAttribute(delegationElement, CLASS_ATTR, delegable.getDelegationClassName());
        setNodeValue(delegationElement, delegable.getDelegationConfiguration());
        parent.appendChild(delegationElement);
    }
}
TOP

Related Classes of org.jbpm.ui.jpdl2.JpdlSerializer_2

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.