001 /** 002 * @author paulk 003 */ 004 package toolbus; 005 006 import java.util.ArrayList; 007 import java.util.IdentityHashMap; 008 import java.util.Iterator; 009 import java.util.List; 010 import toolbus.atom.Atom; 011 import toolbus.atom.msg.SndMsg; 012 import toolbus.environment.Environment; 013 import toolbus.exceptions.ToolBusException; 014 import toolbus.process.ProcessInstance; 015 import toolbus.process.debug.ExecutionResult; 016 import aterm.ATerm; 017 018 /** 019 * class State represents one state in the state diagram of a process. It consists of StateElements 020 */ 021 public class State{ 022 private final List<StateElement> elements; 023 024 private final IdentityHashMap<StateElement, Boolean> cache; 025 026 private int nElements = 0; 027 028 private int lastElement = 0; 029 030 private boolean allAtoms = true; 031 032 public State(){ 033 elements = new ArrayList<StateElement>(); 034 035 cache = new IdentityHashMap<StateElement, Boolean>(); 036 } 037 038 public void addElement(StateElement a){ 039 if(!elements.contains(a)){ 040 elements.add(a); 041 nElements += 1; 042 if(!(a instanceof Atom)){ 043 allAtoms = false; 044 } 045 } 046 } 047 048 public void delElement(StateElement a){ 049 if(elements.remove(a)) nElements -= 1; 050 } 051 052 public State union(State b){ 053 State c = new State(); 054 055 Iterator<StateElement> elementsIterator = elements.iterator(); 056 while(elementsIterator.hasNext()){ 057 StateElement se = elementsIterator.next(); 058 059 c.addElement(se); 060 } 061 062 Iterator<StateElement> stateIterator = b.getElementsAsList().iterator(); 063 while(stateIterator.hasNext()){ 064 StateElement se = stateIterator.next(); 065 066 c.addElement(se); 067 } 068 return c; 069 } 070 071 public List<StateElement> getElementsAsList(){ 072 return elements; 073 } 074 075 public int size(){ 076 return elements.size(); 077 } 078 079 public void setTest(ATerm test, Environment env) throws ToolBusException{ 080 if(test != null){ 081 Iterator<StateElement> elementsIterator = elements.iterator(); 082 while(elementsIterator.hasNext()){ 083 StateElement a = elementsIterator.next(); 084 085 a.setTest(test, env); 086 } 087 } 088 } 089 090 public boolean isEnabled(){ 091 Iterator<StateElement> elementsIterator = elements.iterator(); 092 while(elementsIterator.hasNext()){ 093 StateElement a = elementsIterator.next(); 094 095 try{ 096 if(a.isEnabled()){ 097 return true; 098 } 099 }catch(ToolBusException e){ 100 // TODO Auto-generated catch block 101 e.printStackTrace(); 102 } 103 } 104 return false; 105 } 106 107 public String toString(){ 108 String sep = ""; 109 110 String s = "{"; 111 112 Iterator<StateElement> elementsIterator = elements.iterator(); 113 while(elementsIterator.hasNext()){ 114 StateElement a = elementsIterator.next(); 115 116 s += sep + a; 117 sep = ",\n "; 118 } 119 120 s += "}"; 121 122 return s; 123 } 124 125 public boolean contains(StateElement a){ 126 if(cache.containsKey(a)){ 127 Boolean bval = cache.get(a); 128 return bval.booleanValue(); 129 } 130 Iterator<StateElement> elementsIterator = elements.iterator(); 131 while(elementsIterator.hasNext()){ 132 StateElement b = elementsIterator.next(); 133 134 if(b.contains(a)){ 135 if(allAtoms) cache.put(a, Boolean.TRUE); 136 return true; 137 } 138 } 139 if(allAtoms) cache.put(a, Boolean.FALSE); 140 141 return false; 142 } 143 144 public State gotoNextStateAndActivate(){ 145 if(nElements > 0){ 146 return elements.get(lastElement).gotoNextStateAndActivate(); 147 } 148 return this; 149 } 150 151 public State gotoNextStateAndActivate(StateElement a){ 152 Iterator<StateElement> elementsIterator = elements.iterator(); 153 while(elementsIterator.hasNext()){ 154 StateElement b = elementsIterator.next(); 155 156 // System.err.println("State.getNextState2: trying " + b); 157 if(b.equals(a) || b.contains(a)){ 158 return b.gotoNextStateAndActivate(a); 159 } 160 } 161 System.err.println("State.GetNextState2: no element " + a); 162 return null; 163 } 164 165 public void activate(){ 166 // System.err.println("State.activate: " + this); 167 Iterator<StateElement> elementsIterator = elements.iterator(); 168 while(elementsIterator.hasNext()){ 169 StateElement e = elementsIterator.next(); 170 171 e.activate(); 172 } 173 } 174 175 /** 176 * Execute one step for an element in this state. 177 */ 178 public boolean execute() throws ToolBusException{ 179 if(nElements == 0) return false; 180 181 for(int index = (lastElement + 1) % nElements, nleft = nElements; nleft > 0; index = (index + 1) % nElements, nleft--){ 182 StateElement a = elements.get(index); 183 184 if(a.execute()){ 185 lastElement = index; 186 //LoggerFactory.log(a.getProcess().getProcessName(), "execute: " + a, IToolBusLoggerConstants.EXECUTE); 187 188 return true; 189 } 190 } 191 return false; 192 } 193 194 /** 195 * Executes one step in debug mode and returns the executed state element as result. 196 * 197 * @return The result of the execution (if contains the state element and partners); null if 198 * none was executed. 199 * @throws ToolBusException Thrown if something went wrong. 200 */ 201 public ExecutionResult debugExecute() throws ToolBusException{ 202 if(nElements == 0) return null; 203 204 for(int index = (lastElement + 1) % nElements, nleft = nElements; nleft > 0; index = (index + 1) % nElements, nleft--){ 205 StateElement a = elements.get(index); 206 207 ProcessInstance[] partners = a.debugExecute(); 208 if(partners != null){ 209 lastElement = index; 210 211 return new ExecutionResult(a, partners); 212 } 213 } 214 return null; 215 } 216 217 /** 218 * Returns the last executed state element in the current state. 219 * (This method is used for debugging only). 220 * @return The last executed state element in the current state. 221 */ 222 public StateElement getLastExecutedStateElement(){ 223 return elements.get(lastElement); 224 } 225 226 public List<StateElement> getUnhandledMessages(){ 227 List<StateElement> unhandledMessages = new ArrayList<StateElement>(); 228 229 int nrOfElements = elements.size(); 230 231 try{ 232 while((--nrOfElements) >= 0){ 233 StateElement element = elements.get(nrOfElements); 234 if(element instanceof SndMsg){ 235 unhandledMessages.add(element); 236 } 237 } 238 }catch(RuntimeException rex){ 239 // This will never happen, it's here just in case. 240 } 241 242 return unhandledMessages; 243 } 244 }