001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kew.engine.transition;
017    
018    import org.kuali.rice.kew.engine.RouteContext;
019    import org.kuali.rice.kew.engine.RouteHelper;
020    import org.kuali.rice.kew.engine.node.Node;
021    import org.kuali.rice.kew.engine.node.ProcessResult;
022    import org.kuali.rice.kew.engine.node.RouteNode;
023    import org.kuali.rice.kew.engine.node.RouteNodeInstance;
024    
025    import java.util.ArrayList;
026    import java.util.List;
027    
028    
029    /**
030     * Common superclass for all Transition Engines.  A TransitionEngine handles transitioning into and out of
031     * a {@link RouteNodeInstance}.  The TransitionEngine is also responsible for determining if a Node has completed.
032     *
033     * @author Kuali Rice Team (rice.collab@kuali.org)
034     */
035    public abstract class TransitionEngine {
036        
037            private RouteHelper helper;
038            
039            public RouteNodeInstance transitionTo(RouteNodeInstance nextNodeInstance, RouteContext context) throws Exception {
040                    return nextNodeInstance;
041            }
042        
043        /**
044         * Tell the WorkflowEngine processing the activeNodeInstance if the node is complete and transitionFrom can 
045         * be called.
046         *
047         * @return boolean
048         * @param context for routing
049         * @throws Exception
050         */
051        public abstract ProcessResult isComplete(RouteContext context) throws Exception;
052            
053        public Transition transitionFrom(RouteContext context, ProcessResult processResult) throws Exception {
054            return new Transition(resolveNextNodeInstances(context.getNodeInstance()));
055        }
056        
057        protected void setRouteHelper(RouteHelper helper) {
058            this.helper = helper;
059        }
060        
061        protected RouteHelper getRouteHelper() {
062            return helper;
063        }
064        
065        protected Node getNode(RouteNode routeNode, Class nodeClass) throws Exception {
066                    return helper.getNode(routeNode);
067        }
068        
069        /**
070         * Determines the next nodes instances for the transition.  If the node instance already
071         * has next nodes instances (i.e. a dynamic node), then those will be returned.  Otherwise
072         * it will resolve the next nodes from the RouteNode prototype.
073         * @param nodeInstance for the transition
074         * @param nextRouteNodes list of route notes
075         * @return list of route note instances
076         */
077        protected List<RouteNodeInstance> resolveNextNodeInstances(RouteNodeInstance nodeInstance, List<RouteNode> nextRouteNodes) {
078            List<RouteNodeInstance> nextNodeInstances = new ArrayList<RouteNodeInstance>();
079            for (RouteNode nextRouteNode : nextRouteNodes)
080            {
081                RouteNode nextNode = (RouteNode) nextRouteNode;
082                RouteNodeInstance nextNodeInstance = getRouteHelper().getNodeFactory().createRouteNodeInstance(nodeInstance.getDocumentId(), nextNode);
083                nextNodeInstance.setBranch(nodeInstance.getBranch());
084                nextNodeInstance.setProcess(nodeInstance.getProcess());
085                nextNodeInstances.add(nextNodeInstance);
086            }
087            return nextNodeInstances;
088        }
089        
090        protected List<RouteNodeInstance> resolveNextNodeInstances(RouteNodeInstance nodeInstance) {
091            return resolveNextNodeInstances(nodeInstance, nodeInstance.getRouteNode().getNextNodes());
092        }
093        
094    }