View Javadoc

1   package org.state4j.sm;
2   
3   import java.util.Iterator;
4   import java.util.LinkedList;
5   import java.util.List;
6   import java.util.Map;
7   import java.util.TreeMap;
8   
9   import org.state4j.exceptions.PreconditionViolatedException;
10  
11  
12  public abstract class SmStateImpl implements SmState {
13      private SmAction         entryAction;
14      private SmAction         exitAction;
15      private String           name;
16      private String           subtype;
17      private SmCompositeState parent;
18  
19      public boolean hasEntryAction() {
20          return this.entryAction != null;
21      }
22  
23      public boolean hasExitAction() {
24          return this.exitAction != null;
25      }
26  
27      public boolean hasSubtype() {
28          return this.subtype != null;
29      }
30  
31      public SmAction getEntryAction() {
32          return entryAction;
33      }
34  
35      public void setEntryAction(SmAction entryAction) {
36          this.entryAction = entryAction;
37      }
38  
39      public SmAction getExitAction() {
40          return exitAction;
41      }
42  
43      public void setExitAction(SmAction exitAction) {
44          this.exitAction = exitAction;
45      }
46  
47      public String getName() {
48          return name;
49      }
50  
51      public void setName(String name) {
52          this.name = name;
53      }
54  
55      public boolean hasName() {
56          return this.name != null;
57      }
58  
59      public String getSubtype() {
60          return subtype;
61      }
62  
63      public void setSubtype(String subtype) {
64          this.subtype = subtype;
65      }
66  
67      public void entry(SmContext cntx) {
68          cntx.entryInState(this);
69          if (!this.hasEntryAction()) {
70              return;
71          }
72          this.getEntryAction().execute(cntx);
73      }
74  
75      public void entryUp(SmContext cntx, SmCompositeState toParent) {
76          if (this.hasParent() && !this.equals(toParent)) {
77              this.getParent().entryUp(cntx, toParent);
78          }
79          if (!this.equals(toParent)) {
80              cntx.entryInState(this);
81              if (this.hasEntryAction()) {
82                  this.getEntryAction().execute(cntx);
83              }
84          }
85      }
86  
87      public void exit(SmContext cntx) {
88          cntx.exitFromState(this);
89          if (!this.hasExitAction()) {
90              return;
91          }
92          this.getExitAction().execute(cntx);
93      }
94  
95      public void exitUp(SmContext cntx, SmCompositeState toParent) {
96          if (!this.equals(toParent)) {
97              cntx.exitFromState(this);
98              if (this.hasExitAction()) {
99                  this.getExitAction().execute(cntx);
100             }
101         }
102         if (this.hasParent() && !this.equals(toParent)) {
103             this.getParent().exitUp(cntx, toParent);
104         }
105     }
106 
107     public boolean isInitial() {
108         if (this.hasSubtype() && this.getSubtype().equals(SmNaming.ATT_STATE_INITIAL)) {
109             return true;
110         }
111         return false;
112     }
113 
114     public boolean isFinal() {
115         if (this.hasSubtype() && this.getSubtype().equals(SmNaming.ATT_STATE_FINAL)) {
116             return true;
117         }
118         return false;
119     }
120 
121     private Map<String, SmTransition> outTransitions = new TreeMap<String, SmTransition>();
122 
123     public List<SmTransition> getFireableTransitions(SmContext cntx, boolean withTrigger) {
124         if (!this.hasOutTransitions()) {
125             return new LinkedList<SmTransition>();
126         }
127         Iterator itTrans = this.getOutTransitions().values().iterator();
128         LinkedList<SmTransition> result = new LinkedList<SmTransition>();
129         while (itTrans.hasNext()) {
130             SmTransition currTran = (SmTransition) itTrans.next();
131             if (currTran.fireable(cntx, withTrigger)) {
132                 result.addLast(currTran);
133             }
134         }
135         return result;
136     }
137 
138     public SmTransition getOutTransition(String transName) {
139         if (!this.hasOutTransition(transName)) {
140             throw new RuntimeException("Sorry! cannot get transition " + transName + ". Does not exists");
141         }
142         return this.getOutTransitions().get(transName);
143     }
144 
145     public Map<String, SmTransition> getOutTransitions() {
146         return outTransitions;
147     }
148 
149     public boolean hasOutTransition(String transName) {
150         if (transName == null || transName.equals("")) {
151             throw new RuntimeException("Sorry!! cannot check transition with name null/empty");
152         }
153         return this.getOutTransitions().containsKey(transName) && this.getOutTransitions().get(transName) != null;
154     }
155 
156     public boolean hasOutTransitions() {
157         return this.outTransitions != null && !this.outTransitions.isEmpty();
158     }
159 
160     public void setOutTransitions(Map<String, SmTransition> transitions) {
161         this.outTransitions = transitions;
162     }
163 
164     public void fire(SmContext cntx) {
165         boolean done = false;
166         boolean withTrigger = true;
167         while (!done) {
168             List trans = this.getFireableTransitions(cntx, withTrigger);
169             if (!trans.isEmpty()) {
170                 SmTransition currentTransition = (SmTransition) trans.get(0);
171                 if (currentTransition != null) {
172                     currentTransition.fire(cntx);
173                 }
174             } else {
175                 done = !withTrigger;
176             }
177             withTrigger = false;
178         }
179         cntx.setCurrentEvent(null);
180     }
181 
182     public boolean isActive(SmContext cntx) {
183         if (cntx.getCurrentState().equals(this)) {
184             return true;
185         }
186         return false;
187     }
188 
189     public boolean equals(Object obj) {
190         if (obj instanceof SmState) {
191             return this.getName().equals(((SmState) obj).getName());
192         }
193         return false;
194     }
195 
196     public void init() {
197     // nothing to do
198     }
199 
200     /*
201      * (non-Javadoc)
202      * 
203      * @see com.tim.sm.interfaces.MyState#hasParent()
204      */
205     public boolean hasParent() {
206         return this.parent != null;
207     }
208 
209     /***
210      * @return Returns the parent.
211      */
212     public SmCompositeState getParent() {
213         if (!hasParent()) {
214             throw new PreconditionViolatedException("can't get parent!!!");
215         }
216         return parent;
217     }
218 
219     /***
220      * @param parent
221      *            The parent to set.
222      */
223     public void setParent(SmCompositeState parent) {
224         this.parent = parent;
225     }
226 
227     public void addOutTransition(SmTransition transition) {
228         if (transition.getStateOut() != this) {
229             throw new PreconditionViolatedException("Sorry!! cannot add transiction " + transition);
230         }
231         if (!transition.isInternal()) {
232             this.getParent().registerLCA(transition);
233         }
234         this.getOutTransitions().put(transition.getName(), transition);
235     }
236 }