/*
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.guvnor.server.builder;
import org.drools.definition.process.Connection;
import org.drools.definition.process.Node;
import org.drools.guvnor.client.asseteditor.ruleflow.*;
import org.drools.guvnor.client.rpc.RuleFlowContentModel;
import org.drools.process.core.Work;
import org.jbpm.ruleflow.core.RuleFlowProcess;
import org.jbpm.workflow.core.Constraint;
import org.jbpm.workflow.core.impl.ConnectionRef;
import org.jbpm.workflow.core.node.ActionNode;
import org.jbpm.workflow.core.node.CompositeNode;
import org.jbpm.workflow.core.node.EndNode;
import org.jbpm.workflow.core.node.EventNode;
import org.jbpm.workflow.core.node.FaultNode;
import org.jbpm.workflow.core.node.ForEachNode;
import org.jbpm.workflow.core.node.HumanTaskNode;
import org.jbpm.workflow.core.node.*;
import org.jbpm.workflow.core.node.RuleSetNode;
import org.jbpm.workflow.core.node.StartNode;
import org.jbpm.workflow.core.node.SubProcessNode;
import org.jbpm.workflow.core.node.TimerNode;
import org.jbpm.workflow.core.node.WorkItemNode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class RuleFlowContentModelBuilder {
public static RuleFlowContentModel createModel(RuleFlowProcess process) {
RuleFlowContentModel model = new RuleFlowContentModel();
Collection<TransferNode> transferNodes = createNodesAndConnections(process.getNodes(),
model);
model.getNodes().addAll(transferNodes);
return model;
}
/**
* Creates transfer nodes from RuleFlowProcess nodes.
*
* @param nodes from the rule flow XML.
* @param model RuleFlowContentModel that contains the transfer nodes for client side.
*/
private static List<TransferNode> createNodesAndConnections(Node[] nodes,
RuleFlowContentModel model) {
List<TransferNode> transferNodes = new ArrayList<TransferNode>();
for (Node node : nodes) {
TransferNode.Type type = getType(node);
TransferNode tn = null;
if (type == TransferNode.Type.WORK_ITEM) {
tn = createWorkItemTransfernode((WorkItemNode) node);
} else if (type == TransferNode.Type.HUMANTASK) {
tn = createHumanTaskTransferNode((HumanTaskNode) node);
} else if (type == TransferNode.Type.SPLIT) {
tn = createSplitNode((Split) node);
} else if (type == TransferNode.Type.FOR_EACH) {
tn = createRuleFlowContentModelTransferNode(((ForEachNode) node).getNodes());
} else if (type == TransferNode.Type.COMPOSITE) {
tn = createRuleFlowContentModelTransferNode(((CompositeNode) node).getNodes());
} else {
tn = new TransferNode();
}
/*
* Creates connections for from and to this node.
*/
createConnections(model,
node);
tn.setId(node.getId());
//Guard needed to Migrate v4 ruleflows to v5
Integer x = (Integer) node.getMetaData("x");
if (x != null) {
tn.setX(x);
}
// Guard needed to Migrate v4 ruleflows to v5
Integer y = (Integer) node.getMetaData("y");
if (y != null) {
tn.setY(y);
}
Integer height = (Integer) node.getMetaData("height");
if (height != null) {
tn.setHeight(height);
}
Integer width = (Integer) node.getMetaData("width");
if (width != null) {
tn.setWidth(width);
}
tn.setName(node.getName());
tn.setType(type);
transferNodes.add(tn);
}
return transferNodes;
}
private static ElementContainerTransferNode createRuleFlowContentModelTransferNode(Node[] nodes) {
ElementContainerTransferNode fetn = new ElementContainerTransferNode();
RuleFlowContentModel model = new RuleFlowContentModel();
List<TransferNode> transferNodes = createNodesAndConnections(nodes,
model);
model.setNodes(transferNodes);
fetn.setContentModel(model);
return fetn;
}
/**
* Checks this node for out and in going connections and creates a transfer object from them.
*
* @param model
* @param node
*/
private static void createConnections(RuleFlowContentModel model,
Node node) {
for (List<Connection> inConnections : node.getIncomingConnections().values()) {
for (Connection connection : inConnections) {
// if ( !"DROOLS_DEFAULT".equals( connection.getFromType() ) && !"DROOLS_DEFAULT".equals( connection.getToType() ) ) {
createConnection(model,
connection);
// }
}
}
for (List<Connection> outConnections : node.getOutgoingConnections().values()) {
for (Connection connection : outConnections) {
// if ( !"DROOLS_DEFAULT".equals( connection.getFromType() ) && !"DROOLS_DEFAULT".equals( connection.getToType() ) ) {
createConnection(model,
connection);
// }
}
}
}
/**
* Creates a single connection to be transferred.
*
* @param model
* @param connection
*/
private static void createConnection(RuleFlowContentModel model,
Connection connection) {
TransferConnection tc = new TransferConnection();
tc.setFromId(connection.getFrom().getId());
tc.setToId(connection.getTo().getId());
model.getConnections().add(tc);
}
private static TransferNode createHumanTaskTransferNode(HumanTaskNode node) {
HumanTaskTransferNode httn = new HumanTaskTransferNode();
Work work = node.getWork();
if (work != null) {
for (String key : work.getParameters().keySet()) {
Object o = work.getParameters().get(key);
String value;
if (o == null) {
value = "";
} else {
value = o.toString();
}
httn.getParameters().put(key,
value);
}
}
return httn;
}
private static SplitTransferNode createSplitNode(Split s) {
SplitTransferNode sn = new SplitTransferNode();
sn.setSplitType(SplitTransferNode.Type.getType(s.getType()));
for (ConnectionRef connection : s.getConstraints().keySet()) {
SplitNode.ConnectionRef ref = new SplitNode.ConnectionRef();
ref.setNodeId(connection.getNodeId());
ref.setToType(connection.getToType());
SplitNode.Constraint constraint = getConstraint(s.getConstraints().get(connection));
sn.getConstraints().put(ref,
constraint);
}
return sn;
}
private static WorkItemTransferNode createWorkItemTransfernode(WorkItemNode node) {
WorkItemTransferNode tn = new WorkItemTransferNode();
Work work = node.getWork();
if (work != null) {
tn.setWorkName(work.getName());
for (String key : work.getParameters().keySet()) {
Object o = work.getParameters().get(key);
String value;
if (o == null) {
value = "";
} else {
value = o.toString();
}
tn.getParameters().put(key,
value);
}
}
return tn;
}
private static org.drools.guvnor.client.asseteditor.ruleflow.SplitNode.Constraint getConstraint(Constraint constraint) {
SplitNode.Constraint c = new SplitNode.Constraint();
c.setConstraint(constraint.getConstraint());
c.setDialect(constraint.getDialect());
c.setName(constraint.getName());
c.setPriority(constraint.getPriority());
c.setType(constraint.getType());
return c;
}
private static TransferNode.Type getType(Node node) {
if (node instanceof StartNode) {
return TransferNode.Type.START;
} else if (node instanceof EndNode) {
return TransferNode.Type.END;
} else if (node instanceof ActionNode) {
return TransferNode.Type.ACTION_NODE;
} else if (node instanceof RuleSetNode) {
return TransferNode.Type.RULESET;
} else if (node instanceof SubProcessNode) {
return TransferNode.Type.SUB_PROCESS;
} else if (node instanceof ForEachNode) {
return TransferNode.Type.FOR_EACH;
} else if (node instanceof CompositeNode) {
return TransferNode.Type.COMPOSITE;
} else if (node instanceof Join) {
return TransferNode.Type.JOIN;
} else if (node instanceof Split) {
return TransferNode.Type.SPLIT;
} else if (node instanceof MilestoneNode) {
return TransferNode.Type.MILESTONE;
} else if (node instanceof TimerNode) {
return TransferNode.Type.TIMER;
} else if (node instanceof HumanTaskNode) {
return TransferNode.Type.HUMANTASK;
} else if (node instanceof WorkItemNode) {
return TransferNode.Type.WORK_ITEM;
} else if (node instanceof FaultNode) {
return TransferNode.Type.FAULT;
} else if (node instanceof EventNode) {
return TransferNode.Type.EVENT;
}
throw new IllegalArgumentException("Unkown node type " + node);
}
}