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 }