[jboss-svn-commits] JBL Code SVN: r20107 - in labs/jbossrules/trunk/drools-core/src/main/java/org/drools: workflow/core/node and 1 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed May 21 20:13:10 EDT 2008


Author: KrisVerlaenen
Date: 2008-05-21 20:13:10 -0400 (Wed, 21 May 2008)
New Revision: 20107

Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/core/node/CompositeNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java
Log:
JBRULES-1616: Composite Node
 - added xml persistence and validation for composite nodes

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java	2008-05-22 00:13:05 UTC (rev 20106)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/validation/RuleFlowProcessValidator.java	2008-05-22 00:13:10 UTC (rev 20107)
@@ -33,6 +33,7 @@
 import org.drools.workflow.core.Node;
 import org.drools.workflow.core.impl.DroolsConsequenceAction;
 import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.core.node.CompositeNode;
 import org.drools.workflow.core.node.EndNode;
 import org.drools.workflow.core.node.Join;
 import org.drools.workflow.core.node.MilestoneNode;
@@ -42,8 +43,8 @@
 import org.drools.workflow.core.node.SubProcessNode;
 import org.drools.workflow.core.node.WorkItemNode;
 import org.mvel.ErrorDetail;
+import org.mvel.ParserContext;
 import org.mvel.compiler.ExpressionCompiler;
-import org.mvel.ParserContext;
 
 /**
  * Default implementation of a RuleFlow validator.
@@ -57,6 +58,9 @@
 
     private static RuleFlowProcessValidator instance;
 
+    private boolean startNodeFound;
+    private boolean endNodeFound;
+    
     private RuleFlowProcessValidator() {
     }
 
@@ -91,9 +95,32 @@
                 "Process has no start node."));
         }
 
-        boolean startNodeFound = false;
-        boolean endNodeFound = false;
+        startNodeFound = false;
+        endNodeFound = false;
         final Node[] nodes = process.getNodes();
+        validateNodes(nodes, errors, process);
+        if (!startNodeFound) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no start node."));
+        }
+        if (!endNodeFound) {
+            errors.add(new ProcessValidationErrorImpl(process,
+                "Process has no end node."));
+        }
+        for (final Iterator<Variable> it = process.getVariableScope().getVariables().iterator(); it.hasNext(); ) {
+            final Variable variable = it.next();
+            if (variable.getType() == null) {
+                errors.add(new ProcessValidationErrorImpl(process,
+                    "Variable '" + variable.getName() + "' has no type."));
+            }
+        }
+
+        checkAllNodesConnectedToStart(process, errors);
+
+        return errors.toArray(new ProcessValidationError[errors.size()]);
+    }
+    
+    private void validateNodes(Node[] nodes, List<ProcessValidationError> errors, RuleFlowProcess process) {
         for ( int i = 0; i < nodes.length; i++ ) {
             final Node node = nodes[i];
             if (node instanceof StartNode) {
@@ -205,33 +232,33 @@
                     errors.add(new ProcessValidationErrorImpl(process,
                         "Action node '" + node.getName() + "' [" + node.getId() + "] has no action."));
                 } else {
-                	if (actionNode.getAction() instanceof DroolsConsequenceAction) {
-                		DroolsConsequenceAction droolsAction = (DroolsConsequenceAction) actionNode.getAction();
-                		String actionString = droolsAction.getConsequence();
-                		if (actionString == null) {
+                    if (actionNode.getAction() instanceof DroolsConsequenceAction) {
+                        DroolsConsequenceAction droolsAction = (DroolsConsequenceAction) actionNode.getAction();
+                        String actionString = droolsAction.getConsequence();
+                        if (actionString == null) {
                             errors.add(new ProcessValidationErrorImpl(process,
                                 "Action node '" + node.getName() + "' [" + node.getId() + "] has empty action."));
-                		} else {
-	                    	try {
-	                    		ExpressionCompiler compiler = new ExpressionCompiler(actionString);
-	                    		compiler.setVerifying(true);
-		                		ParserContext parserContext = new ParserContext();
-		                		//parserContext.setStrictTypeEnforcement(true);
-		                		compiler.compile(parserContext);
-		                		List<ErrorDetail> mvelErrors = parserContext.getErrorList();
-		                		if (mvelErrors != null) {
-		                			for (Iterator<ErrorDetail> iterator = mvelErrors.iterator(); iterator.hasNext(); ) {
-		                			    ErrorDetail error = iterator.next();
-		                                errors.add(new ProcessValidationErrorImpl(process,
-	                                        "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + error.getMessage() + "."));
-		                			}
-		                		}
-	                    	} catch (Throwable t) {
+                        } else {
+                            try {
+                                ExpressionCompiler compiler = new ExpressionCompiler(actionString);
+                                compiler.setVerifying(true);
+                                ParserContext parserContext = new ParserContext();
+                                //parserContext.setStrictTypeEnforcement(true);
+                                compiler.compile(parserContext);
+                                List<ErrorDetail> mvelErrors = parserContext.getErrorList();
+                                if (mvelErrors != null) {
+                                    for (Iterator<ErrorDetail> iterator = mvelErrors.iterator(); iterator.hasNext(); ) {
+                                        ErrorDetail error = iterator.next();
+                                        errors.add(new ProcessValidationErrorImpl(process,
+                                            "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + error.getMessage() + "."));
+                                    }
+                                }
+                            } catch (Throwable t) {
                                 errors.add(new ProcessValidationErrorImpl(process,
                                     "Action node '" + node.getName() + "' [" + node.getId() + "] has invalid action: " + t.getMessage() + "."));
-	                    	}
-                		}
-                	}
+                            }
+                        }
+                    }
                 }
             } else if (node instanceof WorkItemNode) {
                 final WorkItemNode workItemNode = (WorkItemNode) node;
@@ -253,27 +280,24 @@
                             "WorkItem node '" + node.getName() + "' [" + node.getId() + "] has no work name."));
                     }
                 }
+            } else if (node instanceof CompositeNode) {
+                final CompositeNode compositeNode = (CompositeNode) node;
+                for (String inType: compositeNode.getLinkedIncomingNodes().keySet()) {
+                    if (compositeNode.getIncomingConnections(inType).size() == 0) {
+                        errors.add(new ProcessValidationErrorImpl(process,
+                            "Composite node '" + node.getName() + "' [" + node.getId() + "] has no incoming connection for type " + inType));
+                    }
+                }
+                for (String outType: compositeNode.getLinkedOutgoingNodes().keySet()) {
+                    if (compositeNode.getOutgoingConnections(outType).size() == 0) {
+                        errors.add(new ProcessValidationErrorImpl(process,
+                            "Composite node '" + node.getName() + "' [" + node.getId() + "] has no outgoing connection for type " + outType));
+                    }
+                }
+                validateNodes(compositeNode.getNodes(), errors, process);
             } 
         }
-        if (!startNodeFound) {
-            errors.add(new ProcessValidationErrorImpl(process,
-                "Process has no start node."));
-        }
-        if (!endNodeFound) {
-            errors.add(new ProcessValidationErrorImpl(process,
-                "Process has no end node."));
-        }
-        for (final Iterator<Variable> it = process.getVariableScope().getVariables().iterator(); it.hasNext(); ) {
-            final Variable variable = it.next();
-            if (variable.getType() == null) {
-                errors.add(new ProcessValidationErrorImpl(process,
-                    "Variable '" + variable.getName() + "' has no type."));
-            }
-        }
 
-        checkAllNodesConnectedToStart(process, errors);
-
-        return errors.toArray(new ProcessValidationError[errors.size()]);
     }
 
     private void checkAllNodesConnectedToStart(final RuleFlowProcess process,

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/core/node/CompositeNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/core/node/CompositeNode.java	2008-05-22 00:13:05 UTC (rev 20106)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/core/node/CompositeNode.java	2008-05-22 00:13:10 UTC (rev 20107)
@@ -53,10 +53,18 @@
         node.setNodeContainer(null);
     }
     
+    public void linkIncomingConnections(String inType, long inNodeId, String inNodeType) {
+        inConnectionMap.put(inType, new NodeAndType(inNodeId, inNodeType));
+    }
+    
     public void linkIncomingConnections(String inType, CompositeNode.NodeAndType inNode) {
         inConnectionMap.put(inType, inNode);
     }
     
+    public void linkOutgoingConnections(long outNodeId, String outNodeType, String outType) {
+        inConnectionMap.put(outType, new NodeAndType(outNodeId, outNodeType));
+    }
+    
     public void linkOutgoingConnections(CompositeNode.NodeAndType outNode, String outType) {
         outConnectionMap.put(outType, outNode);
     }
@@ -69,6 +77,14 @@
         return outConnectionMap.get(outType);
     }
     
+    public Map<String, CompositeNode.NodeAndType> getLinkedIncomingNodes() {
+        return inConnectionMap;
+    }
+    
+    public Map<String, CompositeNode.NodeAndType> getLinkedOutgoingNodes() {
+        return outConnectionMap;
+    }
+    
     public void validateAddIncomingConnection(final String type, final Connection connection) {
         CompositeNode.NodeAndType nodeAndType = getLinkedIncomingNode(type);
         if (nodeAndType == null) {
@@ -143,23 +159,41 @@
         }
     }
     
-    public static class NodeAndType {
+    public class NodeAndType {
 
-        private Node node;
+        private long nodeId;
         private String type;
+        private transient Node node;
         
+        public NodeAndType(long nodeId, String type) {
+            if (type == null) {
+                throw new IllegalArgumentException(
+                    "Node or type may not be null!");
+            }
+            this.nodeId = nodeId;
+            this.type = type;
+        }
+        
         public NodeAndType(Node node, String type) {
             if (node == null || type == null) {
                 throw new IllegalArgumentException(
                     "Node or type may not be null!");
             }
+            this.nodeId = node.getId();
             this.node = node;
             this.type = type;
         }
         
         public Node getNode() {
+            if (node == null) {
+                node = nodeContainer.getNode(nodeId);
+            }
             return node;
         }
+        
+        public long getNodeId() {
+            return nodeId;
+        }
 
         public String getType() {
             return type;
@@ -167,14 +201,14 @@
         
         public boolean equals(Object o) {
             if (o instanceof NodeAndType) {
-                return node.equals(((NodeAndType) o).node)
+                return nodeId == ((NodeAndType) o).nodeId
                     && type.equals(((NodeAndType) o).type); 
             }
             return false;
         }
         
         public int hashCode() {
-            return node.hashCode() + 13*type.hashCode();
+            return 7*(int)nodeId + 13*type.hashCode();
         }
         
     }
@@ -183,21 +217,30 @@
 
         private static final long serialVersionUID = 400L;
         
-        private Node outNode;
-        private String outType;
+        private long inNodeId;
+        private transient Node inNode;
+        private String inType;
         
         public CompositeNodeStart(Node outNode, String outType) {
             setName("Composite node start");
-            this.outNode = outNode;
-            this.outType = outType;
+            this.inNodeId = outNode.getId();
+            this.inNode = outNode;
+            this.inType = outType;
         }
         
         public Node getInNode() {
-            return outNode;
+            if (inNode == null) {
+                inNode = getNodeContainer().getNode(inNodeId);
+            }
+            return inNode;
         }
         
+        public long getInNodeId() {
+            return inNodeId;
+        }
+        
         public String getInType() {
-            return outType;
+            return inType;
         }
         
         public Connection getTo() {
@@ -215,19 +258,28 @@
 
         private static final long serialVersionUID = 400L;
         
-        private Node outNode;
+        private long outNodeId;
+        private transient Node outNode;
         private String outType;
         
         public CompositeNodeEnd(Node outNode, String outType) {
             setName("Composite node end");
+            this.outNodeId = outNode.getId();
             this.outNode = outNode;
             this.outType = outType;
         }
         
         public Node getOutNode() {
+            if (outNode == null) {
+                outNode = getNodeContainer().getNode(outNodeId);
+            }
             return outNode;
         }
         
+        public long getOutNodeId() {
+            return outNodeId;
+        }
+        
         public String getOutType() {
             return outType;
         }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java	2008-05-22 00:13:05 UTC (rev 20106)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceFactoryRegistry.java	2008-05-22 00:13:10 UTC (rev 20107)
@@ -5,6 +5,7 @@
 
 import org.drools.workflow.core.Node;
 import org.drools.workflow.core.node.ActionNode;
+import org.drools.workflow.core.node.CompositeNode;
 import org.drools.workflow.core.node.EndNode;
 import org.drools.workflow.core.node.FaultNode;
 import org.drools.workflow.core.node.Join;
@@ -18,6 +19,7 @@
 import org.drools.workflow.instance.impl.factory.CreateNewNodeFactory;
 import org.drools.workflow.instance.impl.factory.ReuseNodeFactory;
 import org.drools.workflow.instance.node.ActionNodeInstance;
+import org.drools.workflow.instance.node.CompositeNodeInstance;
 import org.drools.workflow.instance.node.EndNodeInstance;
 import org.drools.workflow.instance.node.FaultNodeInstance;
 import org.drools.workflow.instance.node.JoinInstance;
@@ -60,6 +62,8 @@
                   new CreateNewNodeFactory( TimerNodeInstance.class ) );
         register( FaultNode.class,
                   new CreateNewNodeFactory( FaultNodeInstance.class ) );
+        register( CompositeNode.class,
+                  new CreateNewNodeFactory( CompositeNodeInstance.class ) );
     }
 
     public void register(Class< ? extends Node> cls,




More information about the jboss-svn-commits mailing list