2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.dialog.basic.config;
19
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23 import org.apache.shale.dialog.basic.model.Dialog;
24 import org.apache.shale.dialog.basic.model.State;
25 import org.apache.shale.dialog.basic.model.Transition;
26
27 /***
28 * <p>{@link DialogImpl} is a basic implementation of {@link Dialog}.</p>
29 *
30 * @since 1.0.4
31 */
32 public final class DialogImpl implements Dialog {
33
34
35
36
37
38 /***
39 * <p>The class of a JavaBean to be instantiated as the initial
40 * value of the <code>data</code> property of a newly instantiated
41 * <code>DialogContext</code>.</p>
42 */
43 private Class dataClass = HashMap.class;
44
45
46 /***
47 * <p>Name of this {@link Dialog}.</p>
48 */
49 private String name = null;
50
51
52 /***
53 * <p>Name of the starting {@link State} for this {@link Dialog}.</p>
54 */
55 private String start = null;
56
57
58 /***
59 * <p>The {@link State}s owned by this {@link Dialog}, keyed by
60 * identifier.</p>
61 */
62 private Map states = new HashMap();
63
64
65 /***
66 * <p>The global {@link Transition}s owned by this {@link Dialog}, keyed by
67 * outcome. Logic that performs transition management should first check
68 * for a {@link Transition} associated with the origin {@link State}, then
69 * consult the {@link Dialog} for a global definition.</p>
70 */
71 private Map transitions = new HashMap();
72
73
74
75
76
77 /***
78 * <p>Return the class of a JavaBean to be instantiated as the initial
79 * value of the <code>data</code> property of a newly instantiated
80 * <code>DialogContext</code>.</p>
81 *
82 * @return The JavaBean class whose instance becomes the <code>data</code>
83 * property of a new instance of this dialog
84 */
85 public Class getDataClass() {
86
87 return this.dataClass;
88
89 }
90
91
92 /***
93 * <p>Return the name of this {@link Dialog}.</p>
94 *
95 * @return The name of this {@link Dialog}
96 */
97 public String getName() {
98
99 return this.name;
100
101 }
102
103
104 /***
105 * <p>Return the name of the starting {@link State} for this
106 * {@link Dialog}.</p>
107 *
108 * @return The starting state associated with this {@link Dialog}
109 */
110 public String getStart() {
111
112 return this.start;
113
114 }
115
116
117 /***
118 * <p>Return an <code>Iterator</code> over the names of {@link State}s
119 * that are owned by this {@link Dialog}. If there are no such
120 * {@link State}s, an empty <code>Iterator</code> is returned.</p>
121 *
122 * @return An <code>Iterator</code> over all the {@link State}s in this
123 * {@link Dialog}
124 */
125 public Iterator getStateIds() {
126
127 return this.states.keySet().iterator();
128
129 }
130
131
132 /***
133 * <p>Return an <code>Iterator</code> over the logical outcomes of
134 * global {@link Transition}s for this {@link Dialog}. If there are
135 * no such {@link Transition}s, an empty <code>Iterator</code> is
136 * returned.</p>
137 *
138 * @return An <code>Iterator</code> over the logical outcomes of global
139 * {@link Transition}s for this {@link Dialog}
140 */
141 public Iterator getTransitionOutcomes() {
142
143 return this.transitions.keySet().iterator();
144
145 }
146
147
148
149
150
151 /***
152 * <p>Return the specified {@link State}, owned by this {@link Dialog},
153 * if any. Otherwise, return <code>null</code>.</p>
154 *
155 * @param id Identifier of the requested {@link State}
156 * @return The {@link State} specified by the identifier, may be null
157 */
158 public State findState(String id) {
159
160 return (State) states.get(id);
161
162 }
163
164
165 /***
166 * <p>Return the global {@link Transition} for the specified logical outcome,
167 * if any; otherwise, return <code>null</code>.</p>
168 *
169 * @param outcome Logical outcome for which to return a {@link Transition}
170 * @return The global {@link Transition} for the specified logical outcome
171 */
172 public Transition findTransition(String outcome) {
173
174 return (Transition) transitions.get(outcome);
175
176 }
177
178
179 /***
180 * <p>Render a printable version of this instance.</p>
181 *
182 * @return A printable version of this instance
183 */
184 public String toString() {
185
186 return "Dialog[name=" + this.name + ",start=" + this.start + "]";
187
188 }
189
190
191
192
193
194 /***
195 * <p>Add the specified {@link State} to the {@link State}s owned by
196 * this {@link Dialog}.</p>
197 *
198 * @param state {@link State} to be added
199 *
200 * @exception IllegalArgumentException if there is already a {@link State}
201 * with the specified <code>id</code> owned by this {@link Dialog}
202 */
203 public void addState(State state) throws IllegalArgumentException {
204
205 if (states.containsKey(state.getName())) {
206 throw new IllegalArgumentException(state.getName());
207 }
208 states.put(state.getName(), state);
209 if (state instanceof AbstractState) {
210 ((AbstractState) state).setDialog(this);
211 }
212
213 }
214
215
216 /***
217 * <p>Add the specified {@link Transition} to the global {@link Transition}s
218 * associated with this {@link Dialog}.</p>
219 *
220 * @param transition {@link Transition} to be added
221 *
222 * @exception IllegalArgumentException if the specified {@link Transition}
223 * cannot be added to this {@link State}
224 */
225 public void addTransition(Transition transition) throws IllegalArgumentException {
226
227
228 transitions.put(transition.getOutcome(), transition);
229
230 }
231
232
233 /***
234 * <p>Return the data class name for the <code>data</code> property
235 * of a newly instantiated <code>DialogContext</code>.</p>
236 *
237 * @return The fully qualified class name whose instance becomes the
238 * <code>data</code> property of a new instance of this dialog
239 */
240 public String getDataClassName() {
241
242 return dataClass.getName();
243
244 }
245
246
247 /***
248 * <p>Set the data class name for the <code>data</code> property
249 * of a newly instantiated <code>DialogContext</code>.</p>
250 *
251 * @param dataClassName New data class name
252 *
253 * @exception Exception if the specified class name cannot be loaded
254 */
255 public void setDataClassName(String dataClassName) {
256
257 ClassLoader loader = Thread.currentThread().getContextClassLoader();
258 if (loader == null) {
259 loader = DialogImpl.class.getClassLoader();
260 }
261 try {
262 this.dataClass = loader.loadClass(dataClassName);
263 } catch (RuntimeException e) {
264 throw e;
265 } catch (Exception e) {
266 throw new IllegalArgumentException(e.toString());
267 }
268
269 }
270
271
272 /***
273 * <p>Set the name of this {@link Dialog}.</p>
274 *
275 * @param name New name
276 */
277 public void setName(String name) {
278
279 this.name = name;
280
281 }
282
283
284 /***
285 * <p>Set the name of the starting {@link State} for this
286 * {@link Dialog}.</p>
287 *
288 * @param start Name of the starting {@link State}
289 */
290 public void setStart(String start) {
291
292 this.start = start;
293
294 }
295
296
297 /***
298 * <p>Remove the specified {@link State} from the {@link State}s owned by
299 * this {@link Dialog}, if it is currently registered. Otherwise,
300 * do nothing.</p>
301 *
302 * @param state {@link State} to be removed
303 */
304 public void removeState(State state) {
305
306 states.remove(state.getName());
307 if (state instanceof AbstractState) {
308 ((AbstractState) state).setDialog(null);
309 }
310
311 }
312
313
314 /***
315 * <p>Remove the specified {@link Transition} from the global
316 * {@link Transition}s associated with this {@link Dialog}, if it is
317 * currently registered. Otherwise, do nothing.</p>
318 *
319 * @param transition {@link Transition} to be removed
320 */
321 public void removeTransition(Transition transition) {
322
323 transitions.remove(transition.getOutcome());
324
325 }
326
327
328 }