001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.kew.engine.transition;
017
018import org.kuali.rice.kew.engine.RouteContext;
019import org.kuali.rice.kew.engine.RouteHelper;
020import org.kuali.rice.kew.engine.node.Node;
021import org.kuali.rice.kew.engine.node.ProcessResult;
022import org.kuali.rice.kew.engine.node.RouteNode;
023import org.kuali.rice.kew.engine.node.RouteNodeInstance;
024
025import java.util.ArrayList;
026import 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 */
035public 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}