1 package org.jbpm.bpel.exe; 2 3 import java.io.Serializable ; 4 import java.util.Comparator ; 5 import java.util.Date ; 6 import java.util.Iterator ; 7 import java.util.TreeSet ; 8 9 import org.jbpm.context.exe.ContextInstance; 10 import org.jbpm.graph.exe.ExecutionContext; 11 import org.jbpm.graph.exe.Token; 12 13 import org.jbpm.bpel.def.Activity; 14 import org.jbpm.bpel.def.BpelDefinition; 15 import org.jbpm.bpel.def.Scope; 16 import org.jbpm.bpel.exe.state.ActiveState; 17 import org.jbpm.bpel.exe.state.EndedState; 18 import org.jbpm.bpel.exe.state.HandlingState; 19 import org.jbpm.bpel.exe.state.ScopeState; 20 21 25 public class ScopeInstance implements Serializable { 26 27 private static final long serialVersionUID = 1L; 28 29 final public static String SCOPE_NAME = ":scope"; 30 31 final public static ScopeFilter CHILDREN_TO_CANCEL = 32 new ScopeFilter(new Class [] {ActiveState.class, HandlingState.class}); 33 34 final public static ScopeFilter CHILDREN_TO_COMPENSATE = 35 new ScopeFilter(new Class [] {EndedState.COMPLETED.getClass()}); 36 37 private long id; 38 private ScopeState state; 39 private Token token; 40 private Fault fault; 41 42 protected ScopeInstance() { 43 } 44 45 protected ScopeInstance(Token token) { 46 this.token = token; 47 } 48 49 52 public void faulted(Fault fault) { 53 this.fault = fault; 54 state.faulted(this); 55 } 56 57 public void completed() { 58 state.completed(this); 59 } 60 61 public void terminate() { 62 state.terminate(this); 63 } 64 65 public void compensate() { 66 state.compensate(this); 67 } 68 69 public void exit() { 70 token.end(); 71 performExit(); 72 } 73 74 public void childTerminated(ScopeInstance child) { 75 Iterator it = new ScopeIterator(token, CHILDREN_TO_CANCEL); 76 if(!it.hasNext()) state.childrenTerminated(this); 77 } 78 79 public void childCompensated(ScopeInstance child) { 80 compensateNextChild(); 81 } 82 83 86 public void cancelChildren() { 87 token.end(); 88 89 Iterator it = new ScopeIterator(token, CHILDREN_TO_CANCEL); 90 if( !it.hasNext() ) { 91 state.childrenTerminated(this); 92 return; 93 } 94 95 do { 96 ScopeInstance child = (ScopeInstance) it.next(); 97 child.terminate(); 98 } while( it.hasNext() ); 99 } 100 101 public void compensateNextChild() { 102 Iterator it = new ScopeIterator(token, CHILDREN_TO_COMPENSATE); 103 if( !it.hasNext() ) { 104 ((HandlingState) state).childrenCompensated(this); 105 return; 106 } 107 108 TreeSet set = new TreeSet (new CompensationComparator()); 109 do { set.add(it.next()); } while(it.hasNext()); 110 111 ((ScopeInstance) set.iterator().next()).compensate(); 112 } 113 114 private void performExit() { 115 setState(EndedState.EXITED); 116 InstanceIterator it = new ScopeIterator(token); 117 while (it.hasNext()) { 118 ScopeInstance child = (ScopeInstance) it.next(); 119 child.performExit(); 120 } 121 } 122 123 126 public ScopeState getState() { 127 return state; 128 } 129 130 public void setState(ScopeState state) { 131 this.state = state; 132 } 133 134 public Fault getFault() { 135 return fault; 136 } 137 138 public void setFault(Fault fault) { 139 this.fault = fault; 140 } 141 142 public Token getToken() { 143 return token; 144 } 145 146 public void setToken(Token token) { 147 this.token = token; 148 } 149 150 public Scope getDefinition() { 151 Activity node = (Activity) token.getNode(); 152 153 if(node != null) { 154 return node.getScope(); 155 } 156 else if(token.isRoot()){ 157 return ((BpelDefinition)token.getProcessInstance().getProcessDefinition()).getScope(); 158 } 159 else { 160 throw new AssertionError ("tokens that are not the root of a bpel process must be located at a node."); 161 } 162 } 163 164 167 public ScopeInstance getParent() { 168 Token parentToken = token.getParent(); 169 return parentToken != null ? ScopeInstance.get(parentToken) : null; 170 } 171 172 public static ScopeInstance get(Token token) { 173 ContextInstance contextInstance = token.getProcessInstance().getContextInstance(); 174 return (ScopeInstance) contextInstance.getVariable(SCOPE_NAME, token); 175 } 176 177 public static ScopeInstance create(Token token) { 178 ContextInstance contextInstance = token.getProcessInstance().getContextInstance(); 179 ScopeInstance instance = new ScopeInstance(token); 180 instance.setState(ActiveState.NORMAL_PROCESSING); 182 contextInstance.createVariable(SCOPE_NAME, instance, token); 183 return instance; 184 } 185 186 public static class ScopeIterator extends InstanceIterator { 187 188 public ScopeIterator(Token parent) { 189 super(parent, null); 190 } 191 192 public ScopeIterator(Token parent, InstanceFilter filter) { 193 super(parent, filter); 194 } 195 196 197 public Object getInstance(Token token) { 198 ContextInstance contextInstance = (ContextInstance) token.getProcessInstance().getInstance(ContextInstance.class); 199 return contextInstance.getLocalVariable(SCOPE_NAME, token); 200 } 201 } 202 203 static class ScopeFilter extends InstanceIterator.InstanceFilter { 204 Class [] states; 205 206 public ScopeFilter(Class [] states) { 207 this.states = states; 208 } 209 210 public boolean evaluate(Object instance) { 211 ScopeInstance scope = (ScopeInstance) instance; 212 213 for(int i = 0; i < states.length; i++) { 214 if(states[i].isInstance(scope.getState())) 215 return true; 216 } 217 218 return false; 219 } 220 } 221 222 static class CompensationComparator implements Comparator { 223 224 225 public int compare(Object o1, Object o2) { 226 Date d1 = ((ScopeInstance)o1).getToken().getEnd(); 227 Date d2 = ((ScopeInstance)o2).getToken().getEnd(); 228 229 if (d1.before(d2)) { 230 return 1; 231 } 232 else if (d1.after(d2)) { 233 return -1; 234 } 235 236 return 0; 237 } 238 } 239 240 public void notifyCompletion() { 241 ScopeInstance parent = getParent(); 243 if(parent != null) { 244 Token parentToken = token.getParent(); 246 token.setAbleToReactivateParent(false); 247 parentToken.getNode().leave(new ExecutionContext(parentToken)); 248 } 249 } 250 } | Popular Tags |