1
2
3
4
5
6
7 package org.state4j.sm;
8
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12
13
14 /***
15 * @author andrea
16 *
17 */
18 public class SmCompositeStateImpl extends SmStateImpl implements SmCompositeState {
19 private Map<String, SmState> states;
20
21 public SmState getInitialState() {
22 SmState candidateResult = null;
23 Iterator itStates = this.getStates().values().iterator();
24 while (itStates.hasNext()) {
25 SmState currState = (SmState) itStates.next();
26 if (currState.isInitial()) {
27 return currState;
28 }
29 candidateResult = currState;
30 }
31 if (candidateResult == null) {
32 throw new RuntimeException("Sorry!! cannot found initial state");
33 } else if (candidateResult instanceof SmCompositeState) {
34 return ((SmCompositeState) candidateResult).getInitialState();
35 } else {
36 return candidateResult;
37 }
38 }
39
40 public SmState getState(String stateName) {
41 if (!this.hasState(stateName)) {
42 throw new RuntimeException("Sorry! cannot get state " + stateName + ". Does not exists");
43 }
44 return this.getStates().get(stateName);
45 }
46
47 public Map<String, SmState> getStates() {
48 return states;
49 }
50
51 public boolean hasState(String stateName) {
52 if (stateName == null || stateName.equals("")) {
53 throw new RuntimeException("Sorry!! cannot check state with name null/empty");
54 }
55 return this.getStates().containsKey(stateName) && this.getStates().get(stateName) != null;
56 }
57
58 public boolean hasStates() {
59 return this.states != null && !this.states.isEmpty();
60 }
61
62 public void setStates(Map<String, SmState> states) {
63 this.states = states;
64 if (!this.hasStates()) {
65 return;
66 }
67 Iterator itStates = this.getStates().values().iterator();
68 while (itStates.hasNext()) {
69 SmState currState = (SmState) itStates.next();
70 currState.setParent(this);
71 }
72 }
73
74 public List<SmTransition> getFireableTransitions(SmContext cntx, boolean withTrigger) {
75 List<SmTransition> result = super.getFireableTransitions(cntx, withTrigger);
76 if (!this.hasStates()) {
77 return result;
78 }
79 Iterator itStates = this.getStates().values().iterator();
80 while (itStates.hasNext()) {
81 SmState currState = (SmState) itStates.next();
82 result.addAll(currState.getFireableTransitions(cntx, withTrigger));
83 }
84 return result;
85 }
86
87 public SmState getActiveSubstate(SmContext cntx) {
88 SmState result = null;
89 Iterator itStates = this.getStates().values().iterator();
90 while (itStates.hasNext() && result == null) {
91 SmState currState = (SmState) itStates.next();
92 if (currState.isActive(cntx)) {
93 result = currState;
94 }
95 }
96 if (result == null) {
97 throw new RuntimeException("Sorry!! cannot get active state from " + this.getName());
98 }
99 return result;
100 }
101
102 public boolean hasActiveSubstate(SmContext cntx) {
103 boolean result = false;
104 if (!this.hasStates()) {
105 return result;
106 }
107 Iterator itStates = this.getStates().values().iterator();
108 while (itStates.hasNext() && !result) {
109 SmState currState = (SmState) itStates.next();
110 result = result || currState.isActive(cntx);
111 }
112 return result;
113 }
114
115 public boolean isActive(SmContext cntx) {
116 return super.isActive(cntx) || this.hasActiveSubstate(cntx);
117 }
118
119 public boolean deepContainsState(SmState state) {
120 boolean result = false;
121 if (!this.hasStates()) {
122 return result;
123 }
124 Iterator itStates = this.getStates().values().iterator();
125 while (itStates.hasNext() && !result) {
126 SmState currState = (SmState) itStates.next();
127 result = result || currState.equals(state) || currState.deepContainsState(state);
128 }
129 return result;
130 }
131
132 public boolean containsState(SmState state) {
133 boolean result = false;
134 if (!this.hasStates()) {
135 return result;
136 }
137 Iterator itStates = this.getStates().values().iterator();
138 while (itStates.hasNext() && !result) {
139 SmState currState = (SmState) itStates.next();
140 result = result || currState.equals(state);
141 }
142 return result;
143 }
144
145 public SmState closeDownState() {
146 return this.getInitialState().closeDownState();
147 }
148
149 public SmCompositeState getLCA(SmState state1, SmState state2) {
150 SmCompositeState result = null;
151 if (this.containsState(state1) && this.containsState(state2)) {
152 result = this;
153 }
154 Iterator itStates = this.getStates().values().iterator();
155 while (itStates.hasNext()) {
156 SmState currState = (SmState) itStates.next();
157 if (currState.deepContainsState(state1) && currState.deepContainsState(state2)) {
158 return ((SmCompositeState) currState).getLCA(state1, state2);
159 }
160 }
161 if (result == null) {
162 throw new RuntimeException("Sorry!! cannot get LCA from " + this.getName() + "; state1=" + state1.getName()
163 + " - state2=" + state2.getName());
164 }
165 return result;
166 }
167
168 public void registerLCA(SmTransition transition) {
169 if (this.deepContainsState(transition.getStateOut()) && this.deepContainsState(transition.getStateIn())) {
170 transition.setLCA(this);
171 } else {
172 if (this.hasParent()) {
173 this.getParent().registerLCA(transition);
174 } else {
175 throw new RuntimeException("Sorry!! cannot found LCA for transition " + transition.getName());
176 }
177 }
178 }
179
180 public void init() {
181 super.init();
182 if (this.hasStates()) {
183 Iterator itStates = this.getStates().values().iterator();
184 while (itStates.hasNext()) {
185 SmState currState = (SmState) itStates.next();
186 currState.init();
187 }
188 }
189 }
190 }