001 package toolbus.process; 002 003 import java.util.HashSet; 004 import java.util.Iterator; 005 import java.util.LinkedList; 006 import java.util.List; 007 import java.util.Set; 008 import java.util.Stack; 009 import toolbus.AtomList; 010 import toolbus.State; 011 import toolbus.StateElement; 012 import toolbus.TBTermFactory; 013 import toolbus.ToolBus; 014 import toolbus.atom.Atom; 015 import toolbus.environment.Environment; 016 import toolbus.exceptions.ToolBusException; 017 import toolbus.process.debug.ExecutionResult; 018 import aterm.ATerm; 019 020 /** 021 * @author paulk, Jul 23, 2002 022 */ 023 public class ProcessInstance{ 024 private final ProcessDefinition definition; 025 private final String processName; 026 private final int processId; 027 028 private final AtomList elements; 029 030 private final State initialState; // Needed for debugging purposes. 031 private State currentState; 032 033 private final ToolBus toolbus; 034 private final TBTermFactory tbfactory; 035 036 private final List<ATerm> subscriptions; 037 private final List<ATerm> notes; 038 039 private boolean running = true; 040 041 private boolean deregistered = false; 042 043 public ProcessInstance(ToolBus TB, ProcessCall call, int processId) throws ToolBusException{ 044 toolbus = TB; 045 tbfactory = TB.getTBTermFactory(); 046 this.processId = processId; 047 subscriptions = new LinkedList<ATerm>(); 048 notes = new LinkedList<ATerm>(); 049 call.setEvalArgs(false); 050 processName = call.getName(); 051 052 definition = TB.getProcessDefinition(processName, call.actuals.getLength()); 053 054 call.computeFirst(); 055 call.replaceFormals(new Environment(tbfactory)); 056 Stack<String> stack = new Stack<String>(); 057 stack.push("TOPLEVEL"); 058 call.compile(this, stack, new State()); 059 060 elements = call.getAtoms(); 061 062 currentState = call.getFirst(); 063 initialState = call.PE.getFirst(); 064 currentState.activate(); 065 } 066 067 public ProcessDefinition getProcessDefinition(){ 068 return definition; 069 } 070 071 public TBTermFactory getTBTermFactory(){ 072 return tbfactory; 073 } 074 075 public ToolBus getToolBus(){ 076 return toolbus; 077 } 078 079 public long getRunTime(){ 080 return toolbus.getRunTime(); 081 } 082 083 public int getProcessId(){ 084 return processId; 085 } 086 087 public String getProcessName(){ 088 return processName; 089 } 090 091 public void terminate(){ 092 running = false; 093 094 deregisterCommunicationAtoms(elements); 095 } 096 097 public void deregisterCommunicationAtoms(AtomList atoms){ 098 if(!deregistered){ 099 Iterator<Atom> atomsIterator = atoms.iterator(); 100 while(atomsIterator.hasNext()){ 101 Atom atom = atomsIterator.next(); 102 atom.destroy(); 103 } 104 deregistered = true; 105 } 106 } 107 108 public boolean getNoteFromQueue(ATerm pat, Environment env){ 109 Iterator<ATerm> notesIterator = notes.iterator(); 110 while(notesIterator.hasNext()){ 111 ATerm note = notesIterator.next(); 112 if(tbfactory.matchPatternToValue(pat, env, note)){ 113 notesIterator.remove(); 114 //LoggerFactory.log(definition.getName(), "getNotefromQueue: " + note, IToolBusLoggerConstants.NOTES); 115 return true; 116 } 117 } 118 return false; 119 } 120 121 public boolean noNoteInQueue(ATerm pat, Environment env){ 122 //LoggerFactory.log(definition.getName(), "noNoteinQueue: " + pat, IToolBusLoggerConstants.NOTES); 123 Iterator<ATerm> notesIterator = notes.iterator(); 124 while(notesIterator.hasNext()){ 125 ATerm note = notesIterator.next(); 126 if(tbfactory.patternMatchesToValue(pat, env, note)){ 127 return false; 128 } 129 } 130 return true; 131 } 132 133 public void subscribe(ATerm pat){ 134 //LoggerFactory.log(definition.getName(), "subscribe " + pat, IToolBusLoggerConstants.NOTES); 135 if(!subscriptions.contains(pat)) subscriptions.add(pat); 136 } 137 138 public void unsubscribe(ATerm pat){ 139 //LoggerFactory.log(definition.getName(), "unsubscribe: " + pat, IToolBusLoggerConstants.NOTES); 140 subscriptions.remove(pat); 141 } 142 143 public boolean putNoteInQueue(ATerm note){ 144 //LoggerFactory.log(definition.getName(), "putNoteinQueue: " + note, IToolBusLoggerConstants.NOTES); 145 146 Iterator<ATerm> subscriptionsIterator = subscriptions.iterator(); 147 while(subscriptionsIterator.hasNext()){ 148 ATerm sub = subscriptionsIterator.next(); 149 if(tbfactory.mightMatch(sub, note)){ 150 notes.add(note); 151 return true; 152 } 153 } 154 return false; 155 } 156 157 public boolean hasNotes(){ 158 return !notes.isEmpty(); 159 } 160 161 public List<ATerm> getSubscriptions(){ 162 return subscriptions; 163 } 164 165 public List<ATerm> getNoteQueue(){ 166 return notes; 167 } 168 169 public State getProcessState(){ 170 return currentState; 171 } 172 173 public boolean contains(StateElement a){ 174 return currentState.contains(a); 175 } 176 177 public State getCurrentState(){ 178 return currentState; 179 } 180 181 public void gotoNextStateAndActivate(){ 182 currentState = currentState.gotoNextStateAndActivate(); 183 } 184 185 public void gotoNextStateAndActivate(StateElement se){ 186 currentState = currentState.gotoNextStateAndActivate(se); 187 } 188 189 public boolean step() throws ToolBusException{ 190 if(running && currentState.execute()){ 191 gotoNextStateAndActivate(); 192 return true; 193 } 194 return false; 195 } 196 197 /** 198 * Executes on step in debug mode, where the state element that was executed is returned as result. 199 * 200 * @return The result of the execution (if contains the state element and partners); null if 201 * nothing was executed. 202 * @throws ToolBusException Thrown if something went wrong. 203 */ 204 public ExecutionResult debugStep() throws ToolBusException{ 205 if(running){ 206 ExecutionResult executionResult = currentState.debugExecute(); 207 if(executionResult != null){ 208 StateElement stateElement = executionResult.stateElement; 209 // If we just encountered a (dynamic) process call, find out what element it executed (so we can pretent it got inlined). 210 if(stateElement instanceof ProcessCall){ 211 executionResult = new ExecutionResult(((ProcessCall) stateElement).getExecutedStateElement(), executionResult.partners); 212 }else if(stateElement instanceof DynamicProcessCall){ 213 executionResult = new ExecutionResult(((DynamicProcessCall) stateElement).getExecutedStateElement(), executionResult.partners); 214 } 215 gotoNextStateAndActivate(); 216 return executionResult; 217 } 218 } 219 return null; 220 } 221 222 public boolean isTerminated(){ 223 if(!running || currentState.size() == 0){ 224 return true; 225 } 226 return false; 227 } 228 229 public String toString(){ 230 return "ProcessInstance(" + definition.getName() + ", " + processId + ", " + currentState + ")"; 231 } 232 233 public String showStatus(){ 234 String r1 = "process " + definition.getName() + "(" + processId + "):\n " + elements.size() + " elements\n" + currentState; 235 if(subscriptions.size() > 0){ 236 String r2 = "\n Subscriptions: {"; 237 Iterator<ATerm> SubscriptionsIterator = subscriptions.iterator(); 238 while(SubscriptionsIterator.hasNext()){ 239 ATerm sub = SubscriptionsIterator.next(); 240 r2 = r2 + "\n " + sub.toString(); 241 } 242 if(notes.size() > 0){ 243 String r3 = "}\n Note queue:{"; 244 Iterator<ATerm> notesIterator = notes.iterator(); 245 while(notesIterator.hasNext()){ 246 ATerm note = notesIterator.next(); 247 248 r3 = r3 + "\n " + note.toString(); 249 } 250 r3 = r3 + "}"; 251 return r1 + r2 + r3; 252 } 253 return r1 + r2; 254 } 255 return r1; 256 } 257 258 public void showAutomaton(){ 259 // LoggerFactory.log("process " + processId + ": " + call, IToolBusLoggerConstants.CALLS); 260 // LoggerFactory.log("process " + processId + ": atoms: =" + elements, IToolBusLoggerConstants.CALLS); 261 // LoggerFactory.log("process " + processId + ": currentState = " + currentState, IToolBusLoggerConstants.CALLS); 262 /*Iterator<Atom> atomSetIterator = elements.iterator(); 263 while(atomSetIterator.hasNext()){ 264 Atom a = atomSetIterator.next(); 265 //LoggerFactory.log(definition.getName(), a + " --> " + a.getFollow(), IToolBusLoggerConstants.CALLS); 266 }*/ 267 } 268 269 /** 270 * Returns a complete list of state elements in this process instance. 271 * This method is only required for obtaining a reference to a state element, so we can set a 272 * break point on it when running the toolbus in debug mode. 273 * 274 * @return A complete list of atoms in this process instance. 275 */ 276 public Set<StateElement> getStateElements(){ 277 Set<StateElement> stateElementsSet = new HashSet<StateElement>(); 278 List<StateElement> stateElementsToDo = new LinkedList<StateElement>(); 279 280 stateElementsToDo.addAll(initialState.getElementsAsList()); 281 do{ 282 StateElement stateElement = stateElementsToDo.remove(0); 283 State state = stateElement.getFollow(); 284 List<StateElement> stateElements = state.getElementsAsList(); 285 Iterator<StateElement> stateElementsIterator = stateElements.iterator(); 286 while(stateElementsIterator.hasNext()){ 287 StateElement se = stateElementsIterator.next(); 288 if(!stateElementsSet.contains(se)){ 289 stateElementsToDo.add(se); 290 } 291 stateElementsSet.add(se); 292 } 293 }while(!stateElementsToDo.isEmpty()); 294 295 return stateElementsSet; 296 } 297 }