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.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.util.Map;
24
25 import org.apache.commons.digester.Digester;
26 import org.apache.commons.digester.Rule;
27 import org.apache.shale.dialog.basic.model.Dialog;
28 import org.xml.sax.InputSource;
29 import org.xml.sax.SAXException;
30
31 /***
32 * <p>Configuration utility for parsing configuration resources for
33 * defining dialogs. This class has no dependencies on web tier APIs,
34 * only on the parsing technology (Commons Digester) being used.</p>
35 *
36 * <p>To use this utility, instantiate a new instance and set the
37 * <code>dialogs</code>, <code>resource</code>, and <code>validating</code>
38 * properties. Then, call the <code>parse()</code> method. You can parse
39 * more than one resource by resetting the <code>resource</code>
40 * property and calling <code>parse()</code> again.</p>
41 *
42 * @since 1.0.4
43 */
44
45 public final class ConfigurationParser {
46
47
48
49
50
51 /***
52 * <p>Registration information for the DTD we will use to validate.</p>
53 */
54 private static final String[] REGISTRATIONS =
55 { "-//Apache Software Foundation//DTD Shale Dialog Configuration 1.0//EN",
56 "/org/apache/shale/dialog/dialog-config_1_0.dtd",
57 "-//Apache Software Foundation//DTD Shale Dialog Configuration 1.1//EN",
58 "/org/apache/shale/dialog/dialog-config_1_1.dtd" };
59
60
61
62
63
64 /***
65 * <p><code>Map</code> of <code>Dialog</code> instances resulting
66 * from parsing, keyed by dialog name.</p>
67 */
68 private Map dialogs = null;
69
70
71 /***
72 * <p>Return the <code>Map</code> of <code>Dialog</code> instances
73 * into which parsed information will be stored, keyed by dialog
74 * name.</p>
75 *
76 * @return The map of available {@link Dialog}s, keyed by name
77 */
78 public Map getDialogs() {
79 return this.dialogs;
80 }
81
82
83 /***
84 * <p>Set the <code>Map</code> of <code>Dialog</code> instances
85 * into which parsed information will be stored, keyed by dialog
86 * name.</p>
87 *
88 * @param dialogs The new map
89 */
90 public void setDialogs(Map dialogs) {
91 this.dialogs = dialogs;
92 }
93
94
95 /***
96 * <p>The URL of the configuration resource to be parsed.</p>
97 */
98 private URL resource = null;
99
100
101 /***
102 * <p>Return the URL of the configuration resource to be parsed.</p>
103 *
104 * @return The URL of the dialogs configuration resource
105 */
106 public URL getResource() {
107 return this.resource;
108 }
109
110
111 /***
112 * <p>Set the URL of the configuration resource to be parsed.</p>
113 *
114 * @param resource The new resource URL
115 */
116 public void setResource(URL resource) {
117 this.resource = resource;
118 }
119
120
121 /***
122 * <p>Flag indicating whether we should do a validating parse or not.</p>
123 */
124 private boolean validating = true;
125
126
127 /***
128 * <p>Return a flag indicating whether we will be doing a validating parse
129 * or not. Default value is <code>true</code>.</p>
130 *
131 * @return Whether the parse is a validating one
132 */
133 public boolean isValidating() {
134 return this.validating;
135 }
136
137
138 /***
139 * <p>Set a flag indicating whether we will be doing a validating parse
140 * or not.</p>
141 *
142 * @param validating New flag value
143 */
144 public void setValidating(boolean validating) {
145 this.validating = validating;
146 }
147
148
149
150
151
152 /***
153 * <p>Parse the configuration resource identified by the <code>resource</code>
154 * property, storing resulting information in the <code>Map</code> specified
155 * by the <code>dialogs</code> property.</p>
156 *
157 * @exception IOException if an input/output error occurs
158 * @exception SAXException if an XML parsing error occurs
159 */
160 public void parse() throws IOException, SAXException {
161
162 Digester digester = digester();
163 digester.clear();
164 digester.push(getDialogs());
165 InputSource source = new InputSource(getResource().toExternalForm());
166 InputStream stream = null;
167 try {
168 stream = getResource().openStream();
169 source.setByteStream(stream);
170 digester.parse(source);
171 } catch (IOException e) {
172 throw e;
173 } catch (SAXException e) {
174 throw e;
175 } finally {
176 if (stream != null) {
177 try {
178 stream.close();
179 } catch (IOException e) {
180 ;
181 }
182 }
183 }
184
185 }
186
187
188
189
190
191 /***
192 * <p>Return a fully configured <code>Digester</code> instance.</p>
193 *
194 * @return The fully configured {@link Digester} instance for parsing
195 * the dialog configuration resource
196 */
197 private Digester digester() {
198
199 Digester digester = new Digester();
200
201
202 digester.setNamespaceAware(false);
203 digester.setUseContextClassLoader(true);
204 digester.setValidating(isValidating());
205
206
207 for (int i = 0; i < REGISTRATIONS.length; i += 2) {
208 URL url = this.getClass().getResource(REGISTRATIONS[i + 1]);
209 digester.register(REGISTRATIONS[i], url.toString());
210 }
211
212
213
214
215 digester.addObjectCreate("dialogs/dialog", "className", DialogImpl.class);
216 digester.addSetProperties("dialogs/dialog");
217 digester.addSetProperty("dialogs/dialog/property", "name", "value");
218 digester.addRule("dialogs/dialog", new AddDialogRule());
219
220
221 digester.addObjectCreate("dialogs/dialog/action", "className",
222 ActionStateImpl.class);
223 digester.addSetProperties("dialogs/dialog/action");
224 digester.addSetProperty("dialogs/dialog/action/property", "name", "value");
225 digester.addSetNext("dialogs/dialog/action",
226 "addState", "org.apache.shale.dialog.basic.model.State");
227
228
229 digester.addObjectCreate("dialogs/dialog/action/transition", "className",
230 TransitionImpl.class);
231 digester.addSetProperties("dialogs/dialog/action/transition");
232 digester.addSetProperty("dialogs/dialog/action/transition/property", "name", "value");
233 digester.addSetNext("dialogs/dialog/action/transition",
234 "addTransition", "org.apache.shale.dialog.basic.model.Transition");
235
236
237 digester.addObjectCreate("dialogs/dialog/end", "className",
238 EndStateImpl.class);
239 digester.addSetProperties("dialogs/dialog/end");
240 digester.addSetProperty("dialogs/dialog/end/property", "name", "value");
241 digester.addSetNext("dialogs/dialog/end",
242 "addState", "org.apache.shale.dialog.basic.model.State");
243
244
245 digester.addObjectCreate("dialogs/dialog/end/transition", "className",
246 TransitionImpl.class);
247 digester.addSetProperties("dialogs/dialog/end/transition");
248 digester.addSetProperty("dialogs/dialog/end/transition/property", "name", "value");
249 digester.addSetNext("dialogs/dialog/end/transition",
250 "addTransition", "org.apache.shale.dialog.basic.model.Transition");
251
252
253 digester.addObjectCreate("dialogs/dialog/subdialog", "className",
254 SubdialogStateImpl.class);
255 digester.addSetProperties("dialogs/dialog/subdialog");
256 digester.addSetProperty("dialogs/dialog/subdialog/property", "name", "value");
257 digester.addSetNext("dialogs/dialog/subdialog",
258 "addState", "org.apache.shale.dialog.basic.model.State");
259
260
261 digester.addObjectCreate("dialogs/dialog/subdialog/transition", "className",
262 TransitionImpl.class);
263 digester.addSetProperties("dialogs/dialog/subdialog/transition");
264 digester.addSetProperty("dialogs/dialog/subdialog/transition/property", "name", "value");
265 digester.addSetNext("dialogs/dialog/subdialog/transition",
266 "addTransition", "org.apache.shale.dialog.basic.model.Transition");
267
268
269 digester.addObjectCreate("dialogs/dialog/transition", "className",
270 TransitionImpl.class);
271 digester.addSetProperties("dialogs/dialog/transition");
272 digester.addSetProperty("dialogs/dialog/transition/property", "name", "value");
273 digester.addSetNext("dialogs/dialog/transition",
274 "addTransition", "org.apache.shale.dialog.basic.model.Transition");
275
276
277 digester.addObjectCreate("dialogs/dialog/view", "className",
278 ViewStateImpl.class);
279 digester.addSetProperties("dialogs/dialog/view");
280 digester.addSetProperty("dialogs/dialog/view/property", "name", "value");
281 digester.addSetNext("dialogs/dialog/view",
282 "addState", "org.apache.shale.dialog.basic.model.State");
283
284
285 digester.addObjectCreate("dialogs/dialog/view/transition", "className",
286 TransitionImpl.class);
287 digester.addSetProperties("dialogs/dialog/view/transition");
288 digester.addSetProperty("dialogs/dialog/view/transition/property", "name", "value");
289 digester.addSetNext("dialogs/dialog/view/transition",
290 "addTransition", "org.apache.shale.dialog.basic.model.Transition");
291
292 return digester;
293
294 }
295
296
297
298
299
300 /***
301 * <p>Custom <code>Digester</code> rule to add a dialog.</p>
302 */
303 static class AddDialogRule extends Rule {
304
305 /***
306 * <p>Process the "end" event for this rule.</p>
307 *
308 * @param namespace XML namespace of this element
309 * @param name Name of this element
310 *
311 * @exception Exception if a processing exception occurs
312 */
313 public void end(String namespace, String name) throws Exception {
314
315 Dialog dialog = (Dialog) getDigester().peek();
316 Map map = (Map) getDigester().peek(1);
317 map.put(dialog.getName(), dialog);
318
319 }
320
321 }
322
323
324 }