|  1 |     | 
     | 
  |  2 |     | 
     | 
  |  3 |     | 
     | 
  |  4 |     | 
     | 
  |  5 |     | 
     | 
  |  6 |     | 
     | 
  |  7 |     | 
     | 
  |  8 |     | 
     | 
  |  9 |     | 
     | 
  |  10 |     | 
     | 
  |  11 |     | 
     | 
  |  12 |     | 
     | 
  |  13 |     | 
     | 
  |  14 |     | 
     | 
  |  15 |     | 
     | 
  |  16 |     | 
     | 
  |  17 |     | 
   package org.kuali.rice.kew.engine.transition;  | 
  |  18 |     | 
     | 
  |  19 |     | 
   import org.kuali.rice.kew.engine.RouteContext;  | 
  |  20 |     | 
   import org.kuali.rice.kew.engine.node.*;  | 
  |  21 |     | 
   import org.kuali.rice.kew.exception.RouteManagerException;  | 
  |  22 |     | 
     | 
  |  23 |     | 
   import java.util.HashSet;  | 
  |  24 |     | 
   import java.util.Iterator;  | 
  |  25 |     | 
   import java.util.List;  | 
  |  26 |     | 
   import java.util.Set;  | 
  |  27 |     | 
     | 
  |  28 |     | 
     | 
  |  29 |     | 
     | 
  |  30 |     | 
     | 
  |  31 |     | 
     | 
  |  32 |     | 
     | 
  |  33 |     | 
     | 
  |  34 |     | 
     | 
  |  35 |     | 
     | 
  |  36 |     | 
     | 
  |  37 |    0 |    public class DynamicTransitionEngine extends TransitionEngine { | 
  |  38 |     | 
     | 
  |  39 |     | 
         | 
  |  40 |     | 
         | 
  |  41 |     | 
         | 
  |  42 |     | 
         | 
  |  43 |     | 
       public RouteNodeInstance transitionTo(RouteNodeInstance dynamicNodeInstance, RouteContext context) throws Exception { | 
  |  44 |    0 |            dynamicNodeInstance.setInitial(false);  | 
  |  45 |    0 |            dynamicNodeInstance.setActive(false);  | 
  |  46 |    0 |            DynamicNode dynamicNode = (DynamicNode) getNode(dynamicNodeInstance.getRouteNode(), DynamicNode.class);  | 
  |  47 |    0 |            DynamicResult result = dynamicNode.transitioningInto(context, dynamicNodeInstance, getRouteHelper());  | 
  |  48 |    0 |            RouteNodeInstance nextNodeInstance = result.getNextNodeInstance();  | 
  |  49 |    0 |            RouteNodeInstance finalNodeInstance = null;  | 
  |  50 |    0 |            if (result.isComplete()) { | 
  |  51 |    0 |                dynamicNodeInstance.setComplete(true);  | 
  |  52 |    0 |                finalNodeInstance = getFinalNodeInstance(dynamicNodeInstance, context);   | 
  |  53 |    0 |                if (nextNodeInstance == null) { | 
  |  54 |    0 |                    nextNodeInstance = finalNodeInstance;  | 
  |  55 |     | 
               }  | 
  |  56 |     | 
           }  | 
  |  57 |     | 
           | 
  |  58 |    0 |            if (nextNodeInstance !=null) { | 
  |  59 |    0 |                initializeNodeGraph(context, dynamicNodeInstance, nextNodeInstance, new HashSet<RouteNodeInstance>(), finalNodeInstance);  | 
  |  60 |     | 
           }  | 
  |  61 |    0 |            return nextNodeInstance;     | 
  |  62 |     | 
       }  | 
  |  63 |     | 
         | 
  |  64 |     | 
       public ProcessResult isComplete(RouteContext context) throws Exception { | 
  |  65 |    0 |            throw new UnsupportedOperationException("isComplete() should not be invoked on a Dynamic node!"); | 
  |  66 |     | 
       }  | 
  |  67 |     | 
         | 
  |  68 |     | 
       public Transition transitionFrom(RouteContext context, ProcessResult processResult) throws Exception { | 
  |  69 |     | 
             | 
  |  70 |    0 |            Transition transition = new Transition();  | 
  |  71 |    0 |            RouteNodeInstance dynamicNodeInstance = context.getNodeInstance().getProcess();  | 
  |  72 |    0 |            DynamicNode dynamicNode = (DynamicNode) getNode(dynamicNodeInstance.getRouteNode(), DynamicNode.class);  | 
  |  73 |    0 |            DynamicResult result = dynamicNode.transitioningOutOf(context, getRouteHelper());  | 
  |  74 |    0 |            if (result.getNextNodeInstance() == null && result.getNextNodeInstances().isEmpty() && result.isComplete()) { | 
  |  75 |    0 |                dynamicNodeInstance.setComplete(true);  | 
  |  76 |    0 |                RouteNodeInstance finalNodeInstance = getFinalNodeInstance(dynamicNodeInstance, context);  | 
  |  77 |    0 |                if (finalNodeInstance != null) { | 
  |  78 |    0 |                    transition.getNextNodeInstances().add(finalNodeInstance);      | 
  |  79 |     | 
               }  | 
  |  80 |    0 |            } else { | 
  |  81 |    0 |                if (result.getNextNodeInstance() != null) { | 
  |  82 |    0 |                    result.getNextNodeInstance().setProcess(dynamicNodeInstance);  | 
  |  83 |    0 |                    transition.getNextNodeInstances().add(result.getNextNodeInstance());      | 
  |  84 |     | 
               }  | 
  |  85 |    0 |                for (Iterator iter = result.getNextNodeInstances().iterator(); iter.hasNext();) { | 
  |  86 |    0 |                    RouteNodeInstance nextNodeInstance = (RouteNodeInstance) iter.next();  | 
  |  87 |    0 |                    nextNodeInstance.setProcess(dynamicNodeInstance);  | 
  |  88 |    0 |                }  | 
  |  89 |    0 |                transition.getNextNodeInstances().addAll(result.getNextNodeInstances());  | 
  |  90 |     | 
           }  | 
  |  91 |    0 |            return transition;  | 
  |  92 |     | 
       }  | 
  |  93 |     | 
     | 
  |  94 |     | 
         | 
  |  95 |     | 
     | 
  |  96 |     | 
     | 
  |  97 |     | 
     | 
  |  98 |     | 
     | 
  |  99 |     | 
       private void initializeNodeGraph(RouteContext context, RouteNodeInstance dynamicNodeInstance, RouteNodeInstance nodeInstance, Set<RouteNodeInstance> nodeInstances, RouteNodeInstance finalNodeInstance) throws Exception { | 
  |  100 |    0 |            if (nodeInstances.contains(nodeInstance)) { | 
  |  101 |    0 |                throw new RouteManagerException("A cycle was detected in the node graph returned from the dynamic node.", context); | 
  |  102 |     | 
           }  | 
  |  103 |    0 |            nodeInstances.add(nodeInstance);  | 
  |  104 |    0 |            nodeInstance.setProcess(dynamicNodeInstance);  | 
  |  105 |    0 |            List<RouteNodeInstance> nextNodeInstances = nodeInstance.getNextNodeInstances();  | 
  |  106 |     | 
             | 
  |  107 |    0 |            if (nextNodeInstances.size() > 1) { | 
  |  108 |     | 
                 | 
  |  109 |     | 
     | 
  |  110 |     | 
           }  | 
  |  111 |    0 |            for (RouteNodeInstance nextNodeInstance : nextNodeInstances)  | 
  |  112 |     | 
           { | 
  |  113 |    0 |                initializeNodeGraph(context, dynamicNodeInstance, nextNodeInstance, nodeInstances, finalNodeInstance);  | 
  |  114 |     | 
           }  | 
  |  115 |    0 |            if (nextNodeInstances.isEmpty() && finalNodeInstance != null) { | 
  |  116 |    0 |                nodeInstance.addNextNodeInstance(finalNodeInstance);  | 
  |  117 |     | 
           }  | 
  |  118 |    0 |        }  | 
  |  119 |     | 
     | 
  |  120 |     | 
       private RouteNodeInstance getFinalNodeInstance(RouteNodeInstance dynamicNodeInstance, RouteContext context) throws Exception { | 
  |  121 |    0 |            List<RouteNode> nextNodes = dynamicNodeInstance.getRouteNode().getNextNodes();  | 
  |  122 |    0 |            if (nextNodes.size() > 1) { | 
  |  123 |    0 |                throw new RouteManagerException("There should only be 1 next node following a dynamic node, there were " + nextNodes.size(), context); | 
  |  124 |     | 
           }  | 
  |  125 |    0 |            RouteNodeInstance finalNodeInstance = null;  | 
  |  126 |    0 |            if (!nextNodes.isEmpty()) { | 
  |  127 |    0 |                finalNodeInstance = getRouteHelper().getNodeFactory().createRouteNodeInstance(context.getDocument().getRouteHeaderId(), (RouteNode) nextNodes.get(0));  | 
  |  128 |    0 |                finalNodeInstance.setBranch(dynamicNodeInstance.getBranch());  | 
  |  129 |    0 |                finalNodeInstance.setProcess(dynamicNodeInstance.getProcess());  | 
  |  130 |     | 
           }  | 
  |  131 |    0 |            return finalNodeInstance;  | 
  |  132 |     | 
       }  | 
  |  133 |     | 
   }  |