001 /* 002 * Copyright 2005-2007 The Kuali Foundation 003 * 004 * 005 * Licensed under the Educational Community License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.opensource.org/licenses/ecl2.php 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.kuali.rice.kew.engine.node; 018 019 import java.util.HashSet; 020 import java.util.Iterator; 021 import java.util.Set; 022 import java.util.StringTokenizer; 023 024 import org.kuali.rice.kew.engine.RouteContext; 025 import org.kuali.rice.kew.exception.WorkflowRuntimeException; 026 import org.kuali.rice.kew.service.KEWServiceLocator; 027 import org.kuali.rice.kew.util.Utilities; 028 029 030 /** 031 * A basic implementation of the JoinEngine which handles join setup and makes determinations 032 * as to when a join condition has been satisfied. 033 * 034 * @author Kuali Rice Team (rice.collab@kuali.org) 035 */ 036 public class BasicJoinEngine implements JoinEngine { 037 038 public static final String EXPECTED_JOINERS = "ExpectedJoiners"; 039 public static final String ACTUAL_JOINERS = "ActualJoiners"; 040 041 public void createExpectedJoinState(RouteContext context, RouteNodeInstance joinInstance, RouteNodeInstance previousNodeInstance) { 042 RouteNodeInstance splitNode = previousNodeInstance.getBranch().getSplitNode(); 043 if (splitNode == null) { 044 throw new WorkflowRuntimeException("The split node retrieved from node with name '" + previousNodeInstance.getName() + "' and branch with name '" + previousNodeInstance.getBranch().getName() + "' was null"); 045 } 046 for (Iterator iter = splitNode.getNextNodeInstances().iterator(); iter.hasNext();) { 047 RouteNodeInstance splitNodeNextNode = (RouteNodeInstance) iter.next(); 048 splitNodeNextNode.getBranch().setJoinNode(joinInstance); 049 saveBranch(context, splitNodeNextNode.getBranch()); 050 addExpectedJoiner(joinInstance, splitNodeNextNode.getBranch()); 051 } 052 joinInstance.setBranch(splitNode.getBranch()); 053 joinInstance.setProcess(splitNode.getProcess()); 054 } 055 056 public void addExpectedJoiner(RouteNodeInstance nodeInstance, Branch branch) { 057 addJoinState(nodeInstance, branch, EXPECTED_JOINERS); 058 } 059 060 public void addActualJoiner(RouteNodeInstance nodeInstance, Branch branch) { 061 addJoinState(nodeInstance, branch, ACTUAL_JOINERS); 062 } 063 064 private void addJoinState(RouteNodeInstance nodeInstance, Branch branch, String key) { 065 NodeState state = nodeInstance.getNodeState(key); 066 if (state == null) { 067 state = new NodeState(); 068 state.setKey(key); 069 state.setValue(""); 070 state.setNodeInstance(nodeInstance); 071 nodeInstance.addNodeState(state); 072 } 073 state.setValue(state.getValue()+branch.getBranchId()+","); 074 } 075 076 public boolean isJoined(RouteNodeInstance nodeInstance) { 077 NodeState expectedState = nodeInstance.getNodeState(EXPECTED_JOINERS); 078 if (expectedState == null || Utilities.isEmpty(expectedState.getValue())) { 079 return true; 080 } 081 NodeState actualState = nodeInstance.getNodeState(ACTUAL_JOINERS); 082 Set expectedSet = loadIntoSet(expectedState); 083 Set actualSet = loadIntoSet(actualState); 084 for (Iterator iterator = expectedSet.iterator(); iterator.hasNext();) { 085 String value = (String) iterator.next(); 086 if (actualSet.contains(value)) { 087 iterator.remove(); 088 } 089 } 090 return expectedSet.size() == 0; 091 } 092 093 private Set loadIntoSet(NodeState state) { 094 Set set = new HashSet(); 095 StringTokenizer tokenizer = new StringTokenizer(state.getValue(), ","); 096 while (tokenizer.hasMoreTokens()) { 097 set.add(tokenizer.nextToken()); 098 } 099 return set; 100 } 101 102 private void saveBranch(RouteContext context, Branch branch) { 103 if (!context.isSimulation()) { 104 KEWServiceLocator.getRouteNodeService().save(branch); 105 } 106 } 107 108 }