package org.jbpm.ui.jpdl3;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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.Action;
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.State;
import org.jbpm.ui.common.model.Subprocess;
import org.jbpm.ui.common.model.Swimlane;
import org.jbpm.ui.common.model.SwimlanedNode;
import org.jbpm.ui.common.model.TimerAction;
import org.jbpm.ui.common.model.Transition;
import org.jbpm.ui.common.model.WaitState;
import org.jbpm.ui.jpdl3.model.ActionImpl;
import org.jbpm.ui.jpdl3.model.ActionNode;
import org.jbpm.ui.jpdl3.model.Event;
import org.jbpm.ui.jpdl3.model.MailNode;
import org.jbpm.ui.jpdl3.model.MultiInstance;
import org.jbpm.ui.jpdl3.model.StartState;
import org.jbpm.ui.jpdl3.model.TaskState;
import org.jbpm.ui.util.SimpleErrorHandler;
import org.jbpm.ui.util.VariableMapping;
import org.jbpm.ui.util.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class JpdlSerializer_3_2 extends JpdlSerializer {
private static final String NAMESPACE = "urn:jbpm.org:jpdl-3.2";
private static final String XSD_FILE_NAME = "jpdl-3.2.xsd";
@Override
public Document getInitialProcessDefinitionDocument(String processName) throws ParserConfigurationException {
Document document = XmlUtil.createDocument("process-definition", null, null);
setAttribute(document.getDocumentElement(), "name", processName);
setAttribute(document.getDocumentElement(), XMLConstants.XMLNS_ATTRIBUTE, NAMESPACE);
return document;
}
@Override
public void validateProcessDefinitionXML(IFile file) throws SAXException {
// TODO move to XmlUtil
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/validation", true);
factory.setValidating(true);
// DTD validation
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
// XSD validation
factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", getClass().getResourceAsStream("/schema/" + XSD_FILE_NAME));
factory.setFeature("http://apache.org/xml/features/validation/schema", true);
factory.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
factory.setNamespaceAware(true);
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
documentBuilder.setErrorHandler(SimpleErrorHandler.getInstance());
documentBuilder.parse(file.getContents());
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean isSupported(Document document) {
return NAMESPACE.equals(document.getDocumentElement().getNamespaceURI());
}
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 MULTI_INSTANCE_STATE_NODE = "multiinstance-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 REPEAT_ATTR = "repeat";
private static final String TIMER_NODE = "timer";
private static final String ASSIGNMENT_NODE = "assignment";
private static final String TASK_STATE_NODE = "task-node";
private static final String TASK_NODE = "task";
private static final String ACTION_NODE_NODE = "node";
private static final String MAIL_NODE = "mail-node";
private static final String START_STATE_NODE = "start-state";
private static final String SWIMLANE_NODE = "swimlane";
private static final String REASSIGN_ATTR = "reassign";
private static final String END_TASKS_ATTR = "end-tasks";
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 EVENT_NODE = "event";
private static final String TRANSITION_NODE = "transition";
private static final String HANDLER_NODE = "handler";
private static final String DESCRIPTION_NODE = "description";
private static final String NAME_ATTR = "name";
private <T extends GraphElement> T create(Node node, GraphElement parent) {
return create(node, parent, node.getNodeName());
}
@SuppressWarnings("unchecked")
private <T extends GraphElement> T create(Node node, GraphElement parent, String typeName) {
GraphElement element = JpdlVersionRegistry.getElementTypeDefinition(jpdlVersion, typeName).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())) {
((Describable) element).setDescription(getTextContent(childNode));
}
if (HANDLER_NODE.equals(childNode.getNodeName()) || ASSIGNMENT_NODE.equals(childNode.getNodeName())) {
((Delegable) element).setDelegationClassName(getAttribute(childNode, CLASS_ATTR));
element.setDelegationConfiguration(getTextContent(childNode));
}
if (ACTION_NODE.equals(childNode.getNodeName())) {
// only transition actions loaded here
String eventType;
if (element instanceof Transition) {
eventType = Event.TRANSITION;
} else if (element instanceof ActionNode) {
eventType = Event.NODE_ACTION;
} else {
throw new RuntimeException("Unexpected action in XML, context of " + element);
}
parseAction(childNode, element, eventType);
}
if (TRANSITION_NODE.equals(childNode.getNodeName())) {
parseTransition(childNode, element);
}
}
return (T) element;
}
private void parseTransition(Node node, GraphElement parent) {
Transition transition = create(node, parent);
String targetName = getAttribute(node, TO_ATTR);
TRANSITION_TARGETS.put(transition, targetName);
}
private void parseAction(Node node, GraphElement parent, String eventType) {
ActionImpl action = JpdlVersionRegistry.getElementTypeDefinition(jpdlVersion, ACTION_NODE).createElement();
action.setDelegationClassName(getAttribute(node, CLASS_ATTR));
action.setDelegationConfiguration(getTextContent(node));
parent.addAction(action, -1);
action.setEventType(eventType);
}
private static Map<Transition, String> TRANSITION_TARGETS = new HashMap<Transition, String>();
@Override
public ProcessDefinition parseXML(Document document) {
TRANSITION_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);
NodeList stateChilds = node.getChildNodes();
for (int j = 0; j < stateChilds.getLength(); j++) {
Node stateNodeChild = stateChilds.item(j);
if (TASK_NODE.equals(stateNodeChild.getNodeName())) {
String swimlaneName = getAttribute(stateNodeChild, SWIMLANE_NODE);
Swimlane swimlane = definition.getSwimlaneByName(swimlaneName);
startState.setSwimlane(swimlane);
}
}
}
NodeList actionNodeNodes = document.getElementsByTagName(ACTION_NODE_NODE);
for (int i = 0; i < actionNodeNodes.getLength(); i++) {
Node node = actionNodeNodes.item(i);
ActionNode actionNode = create(node, definition);
NodeList aaa = node.getChildNodes();
for (int k = 0; k < aaa.getLength(); k++) {
Node a = aaa.item(k);
if (EVENT_NODE.equals(a.getNodeName())) {
String eventType = getAttribute(a, "type");
NodeList actionNodes = a.getChildNodes();
for (int l = 0; l < actionNodes.getLength(); l++) {
Node aa = actionNodes.item(l);
if (ACTION_NODE.equals(aa.getNodeName())) {
parseAction(aa, actionNode, eventType);
}
}
}
}
}
NodeList states = document.getElementsByTagName(TASK_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);
}
// TODO use SAX parser instead
NodeList stateChilds = node.getChildNodes();
for (int j = 0; j < stateChilds.getLength(); j++) {
Node stateNodeChild = stateChilds.item(j);
if (TASK_NODE.equals(stateNodeChild.getNodeName())) {
String swimlaneName = getAttribute(stateNodeChild, SWIMLANE_NODE);
if (swimlaneName != null && state instanceof SwimlanedNode) {
Swimlane swimlane = definition.getSwimlaneByName(swimlaneName);
((SwimlanedNode) state).setSwimlane(swimlane);
String reassign = getAttribute(stateNodeChild, REASSIGN_ATTR);
if (reassign != null) {
boolean forceReassign = Boolean.parseBoolean(reassign);
((State) state).setReassignmentEnabled(forceReassign);
}
}
NodeList aaa = stateNodeChild.getChildNodes();
for (int k = 0; k < aaa.getLength(); k++) {
Node a = aaa.item(k);
if (EVENT_NODE.equals(a.getNodeName())) {
String eventType = getAttribute(a, "type");
NodeList actionNodes = a.getChildNodes();
for (int l = 0; l < actionNodes.getLength(); l++) {
Node aa = actionNodes.item(l);
if (ACTION_NODE.equals(aa.getNodeName())) {
parseAction(aa, state, eventType);
}
}
}
}
}
if (TIMER_NODE.equals(stateNodeChild.getNodeName())) {
String dueDate = getAttribute(stateNodeChild, DUEDATE_ATTR);
((ITimed) state).setDueDate(dueDate);
NodeList actionNodes = stateNodeChild.getChildNodes();
for (int l = 0; l < actionNodes.getLength(); l++) {
Node aa = actionNodes.item(l);
if (ACTION_NODE.equals(aa.getNodeName())) {
TimerAction timerAction = new TimerAction(null);
timerAction.setDelegationClassName(getAttribute(aa, CLASS_ATTR));
timerAction.setDelegationConfiguration(getTextContent(aa));
timerAction.setRepeat(getAttribute(stateNodeChild, REPEAT_ATTR));
((ITimed) state).setTimerAction(timerAction);
}
}
}
}
}
NodeList mailNodes = document.getElementsByTagName(MAIL_NODE);
for (int i = 0; i < mailNodes.getLength(); i++) {
Node node = mailNodes.item(i);
MailNode mailNode = create(node, definition);
mailNode.setRecipient(getAttribute(node, "to"));
NodeList mailNodeChilds = node.getChildNodes();
for (int j = 0; j < mailNodeChilds.getLength(); j++) {
Node mailNodeChild = mailNodeChilds.item(i);
if ("body".equals(mailNodeChild.getNodeName())) {
mailNode.setMailBody(getTextContent(mailNodeChild));
}
if ("subject".equals(mailNodeChild.getNodeName())) {
mailNode.setSubject(getTextContent(mailNodeChild));
}
}
}
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 multiInstanceStates = document.getElementsByTagName(MULTI_INSTANCE_STATE_NODE);
for (int i = 0; i < multiInstanceStates.getLength(); i++) {
Node node = multiInstanceStates.item(i);
MultiInstance multiInstance = 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())) {
multiInstance.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);
}
}
multiInstance.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>(TRANSITION_TARGETS.keySet());
for (Transition transition : tmpTransitions) {
String targetName = TRANSITION_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) {
Element root = document.getDocumentElement();
NodeList nodes = root.getChildNodes();
if (nodes.getLength() > 0) {
for (int i = nodes.getLength() - 1; i != 0; i--) {
root.removeChild(nodes.item(i));
}
}
setAttribute(root, NAME_ATTR, definition.getName());
if (definition.getDescription() != null && definition.getDescription().length() > 0) {
Element desc = document.createElement(DESCRIPTION_NODE);
setNodeValue(desc, definition.getDescription());
root.appendChild(desc);
}
List<Swimlane> swimlanes = definition.getSwimlanes();
for (Swimlane swimlane : swimlanes) {
Element swimlaneElement = writeElement(document, root, swimlane);
writeDelegation(document, swimlaneElement, ASSIGNMENT_NODE, swimlane);
}
StartState startState = definition.getFirstChild(StartState.class);
if (startState != null) {
Element startStateElement = writeTaskState(document, root, startState);
writeTransitions(document, startStateElement, startState);
}
List<ActionNode> actionNodeNodes = definition.getChildren(ActionNode.class);
for (ActionNode actionNode : actionNodeNodes) {
Element actionNodeElement = writeNode(document, root, actionNode, null);
for (Action action : actionNode.getActions()) {
ActionImpl actionImpl = (ActionImpl) action;
if (!Event.NODE_ACTION.equals(actionImpl.getEventType())) {
writeEvent(document, actionNodeElement, new Event(actionImpl.getEventType()), actionImpl);
}
}
}
List<Decision> decisions = definition.getChildren(Decision.class);
for (Decision decision : decisions) {
writeNode(document, root, decision, HANDLER_NODE);
}
List<TaskState> states = definition.getChildren(TaskState.class);
for (TaskState state : states) {
Element stateElement = writeTaskState(document, root, state);
if (state.timerExist()) {
Element timerElement = document.createElement(TIMER_NODE);
setAttribute(timerElement, DUEDATE_ATTR, state.getDuration().getDuration());
if (!state.hasTimeoutTransition() && state.getTimerAction() != null) {
if (state.getTimerAction().getRepeat().hasDuration()) {
setAttribute(timerElement, REPEAT_ATTR, state.getTimerAction().getRepeat().getDuration());
}
writeDelegation(document, timerElement, ACTION_NODE, state.getTimerAction());
} else {
setAttribute(timerElement, TRANSITION_NODE, PluginConstants.TIMER_TRANSITION_NAME);
}
stateElement.appendChild(timerElement);
}
writeTransitions(document, stateElement, state);
}
List<WaitState> waitStates = definition.getChildren(WaitState.class);
for (WaitState waitState : waitStates) {
Element stateElement = writeWaitState(document, root, waitState);
writeTransitions(document, stateElement, waitState);
}
List<MailNode> mailNodes = definition.getChildren(MailNode.class);
for (MailNode mailNode : mailNodes) {
Element nodeElement = writeNode(document, root, mailNode, null);
setAttribute(nodeElement, "to", mailNode.getRecipient());
writeTransitions(document, nodeElement, mailNode);
Element subject = document.createElement("subject");
setNodeValue(subject, mailNode.getSubject());
nodeElement.appendChild(subject);
Element body = document.createElement("body");
setNodeValue(body, mailNode.getMailBody());
nodeElement.appendChild(body);
}
List<Fork> forks = definition.getChildren(Fork.class);
for (org.jbpm.ui.common.model.Node node : forks) {
writeNode(document, root, node, null);
}
List<Join> joins = definition.getChildren(Join.class);
for (org.jbpm.ui.common.model.Node node : joins) {
writeNode(document, root, node, null);
}
List<Subprocess> subprocesses = definition.getChildren(Subprocess.class);
boolean addSubprocessPermissionHandler = false;
for (Subprocess subprocess : subprocesses) {
addSubprocessPermissionHandler = true;
Element processStateElement = writeNode(document, root, subprocess, null);
Element subProcessElement = document.createElement(SUB_PROCESS_NODE);
setAttribute(subProcessElement, NAME_ATTR, subprocess.getSubProcessName());
setAttribute(subProcessElement, "binding", "late");
processStateElement.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());
processStateElement.appendChild(variableElement);
}
}
/*
List<MultiInstance> multiInstances = definition.getChildren(MultiInstance.class);
for (MultiInstance multiInstance : multiInstances) {
addSubprocessPermissionHandler = true;
Element processStateElement = writeNode(document, root, multiInstance, null);
Element subProcessElement = document.createElement(SUB_PROCESS_NODE);
setAttribute(subProcessElement, NAME_ATTR, multiInstance.getSubProcessName());
setAttribute(subProcessElement, "binding", "late");
processStateElement.appendChild(subProcessElement);
for (VariableMapping variable : multiInstance.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.getAccess());
processStateElement.appendChild(variableElement);
}
}
*/
if (addSubprocessPermissionHandler) {
// TODO add XML comment and move to own method (after event support will be added)
ActionImpl action = new ActionImpl();
action.setDelegationClassName("ru.runa.wf.jbpm.delegation.action.SetSubProcessPermissionsActionHandler");
writeEvent(document, root, new Event(Event.SUBPROCESS_CREATED), action);
}
EndState endState = definition.getFirstChild(EndState.class);
if (endState != null) {
writeElement(document, root, endState);
}
}
private Element writeNode(Document document, Element parent, org.jbpm.ui.common.model.Node node, String delegationNodeName) {
Element nodeElement = writeElement(document, parent, node);
if (delegationNodeName != null) {
writeDelegation(document, nodeElement, delegationNodeName, (Delegable) node);
}
writeTransitions(document, nodeElement, node);
return nodeElement;
}
private Element writeTaskState(Document document, Element parent, SwimlanedNode state) {
Element nodeElement = writeElement(document, parent, state);
Element taskElement = document.createElement(TASK_NODE);
setAttribute(taskElement, NAME_ATTR, state.getName());
setAttribute(taskElement, SWIMLANE_NODE, state.getSwimlaneName());
if (state instanceof State && ((State) state).isReassignmentEnabled()) {
setAttribute(taskElement, REASSIGN_ATTR, "true");
}
for (Action action : state.getActions()) {
ActionImpl actionImpl = (ActionImpl) action;
writeEvent(document, taskElement, new Event(actionImpl.getEventType()), actionImpl);
}
nodeElement.appendChild(taskElement);
if (state instanceof ITimed && ((ITimed) state).timerExist()) {
setAttribute(nodeElement, END_TASKS_ATTR, "true");
}
return nodeElement;
}
private Element writeWaitState(Document document, Element parent, WaitState state) {
Element nodeElement = writeElement(document, parent, state, "task-node");
Element taskElement = document.createElement(TASK_NODE);
setAttribute(taskElement, NAME_ATTR, state.getName());
nodeElement.appendChild(taskElement);
setAttribute(nodeElement, END_TASKS_ATTR, "true");
Element timerElement = document.createElement(TIMER_NODE);
setAttribute(timerElement, DUEDATE_ATTR, state.getDueDate());
if (state.getTimerAction() != null) {
if (state.getTimerAction().getRepeat().hasDuration()) {
setAttribute(timerElement, REPEAT_ATTR, state.getTimerAction().getRepeat().getDuration());
}
writeDelegation(document, timerElement, ACTION_NODE, state.getTimerAction());
}
setAttribute(timerElement, TRANSITION_NODE, PluginConstants.TIMER_TRANSITION_NAME);
nodeElement.appendChild(timerElement);
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 typeName) {
Element result = document.createElement(typeName);
if (element instanceof NamedGraphElement) {
setAttribute(result, NAME_ATTR, ((NamedGraphElement) element).getName());
}
if (element instanceof ActionNode) {
List<Action> nodeActions = ((ActionNode) element).getNodeActions();
for (Action nodeAction : nodeActions) {
writeDelegation(document, result, ACTION_NODE, nodeAction);
}
}
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());
for (Action action : transition.getActions()) {
writeDelegation(document, transitionElement, ACTION_NODE, action);
}
}
}
private void writeEvent(Document document, Element parent, Event event, ActionImpl action) {
Element eventElement = writeElement(document, parent, event, EVENT_NODE);
setAttribute(eventElement, "type", event.getType());
writeDelegation(document, eventElement, ACTION_NODE, action);
}
private void writeDelegation(Document document, Element parent, String elementName, Delegable delegable) {
Element delegationElement = document.createElement(elementName);
setAttribute(delegationElement, CLASS_ATTR, delegable.getDelegationClassName());
setAttribute(delegationElement, "config-type", "configuration-property");
setNodeValue(delegationElement, delegable.getDelegationConfiguration());
parent.appendChild(delegationElement);
}
}