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
198 }
199
200
201
202
203
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 }