You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shale.apache.org by cr...@apache.org on 2006/09/01 08:21:10 UTC
svn commit: r439203 - in
/shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml:
Globals.java ScxmlContext.java ScxmlContexts.java
ShaleDialogELEvaluator.java config/ config/ConfigurationParser.java
Author: craigmcc
Date: Thu Aug 31 23:21:09 2006
New Revision: 439203
URL: http://svn.apache.org/viewvc?rev=439203&view=rev
Log:
Commit the proposed Commons SCXML based implementation of the sandbox
dialog2 APIs (see SHALE-263) as is, before doing any refactoring or
renaming.
Added:
shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/Globals.java
shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ShaleDialogELEvaluator.java
shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/config/
shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/config/ConfigurationParser.java
Modified:
shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContext.java
shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContexts.java
Added: shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/Globals.java
URL: http://svn.apache.org/viewvc/shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/Globals.java?rev=439203&view=auto
==============================================================================
--- shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/Globals.java (added)
+++ shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/Globals.java Thu Aug 31 23:21:09 2006
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shale.dialog2.scxml;
+
+/**
+ * <p>Manifest constants and well known event names for the
+ * Jakarta Commons SCXML driven Shale dialog implementation.</p>
+ *
+ * @since 1.0.4
+ */
+public class Globals {
+
+
+ /**
+ * <p>Context initialization paramater name under which a comma separated
+ * list of configuration resources to be parsed exists.</p>
+ */
+ public static final String CONFIGURATION =
+ "org.apache.shale.dialog2.scxml.CONFIGURATION";
+
+
+ /**
+ * <p>Application scope attribute under which a <code>Map</code> of
+ * {@link Dialog} definitions (keyed by dialog name) is stored.</p>
+ */
+ public static final String DIALOGS =
+ "org.apache.shale.dialog2.scxml.DIALOGS";
+
+
+ /**
+ * <p>The name of the postback event that the state machines should
+ * use to author transitions for, out of a "view" state.</p>
+ */
+ public static final String POSTBACK_EVENT =
+ "faces.outcome";
+
+
+ /**
+ * <p>The variable that holds the postback outcome in the root context
+ * of the state machine instance. Expressions within the SCXML document
+ * can then make references to this variable.</p>
+ */
+ public static final String POSTBACK_OUTCOME =
+ "outcome";
+
+}
+
+
Modified: shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContext.java
URL: http://svn.apache.org/viewvc/shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContext.java?rev=439203&r1=439202&r2=439203&view=diff
==============================================================================
--- shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContext.java (original)
+++ shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContext.java Thu Aug 31 23:21:09 2006
@@ -17,7 +17,18 @@
package org.apache.shale.dialog2.scxml;
import java.io.Serializable;
+import java.util.Iterator;
+
import javax.faces.context.FacesContext;
+
+import org.apache.commons.scxml.SCXMLExecutor;
+import org.apache.commons.scxml.TriggerEvent;
+import org.apache.commons.scxml.env.SimpleDispatcher;
+import org.apache.commons.scxml.env.SimpleErrorReporter;
+import org.apache.commons.scxml.env.SimpleSCXMLListener;
+import org.apache.commons.scxml.model.ModelException;
+import org.apache.commons.scxml.model.SCXML;
+import org.apache.commons.scxml.model.State;
import org.apache.shale.dialog2.Context;
import org.apache.shale.dialog2.Contexts;
@@ -37,13 +48,31 @@
* <p>Construct a new instance.</p>
*
* @param instances {@link IContexts instance that owns us
+ * @param dialog The dialog's state machine (whose executable instance needs
+ * to be created)
+ * @param name The dialog's logical name
* @param id Dialog identifier assigned to this instance
- * @param name Logical name of the dialog to be executed
*/
- ScxmlContext(Contexts instances, String id, String name) {
+ ScxmlContext(Contexts instances, SCXML dialog, String name, String id) {
this.instances = instances;
- this.id = id;
this.name = name;
+ this.id = id;
+
+ this.executor = new SCXMLExecutor(new ShaleDialogELEvaluator(),
+ new SimpleDispatcher(), new SimpleErrorReporter());
+ this.executor.setStateMachine(dialog);
+ this.executor.addListener(dialog, new SimpleSCXMLListener());
+
+ // TODO - Consider adding an explicit root context backed by either the
+ // request or session map for greater EL capacities in the SCXML
+ // document describing this dialog
+
+ try {
+ this.executor.go();
+ } catch (ModelException me) {
+ // FIXME - Better exception
+ throw new IllegalArgumentException("SCXML dialog cannot start:" + name);
+ }
}
@@ -80,6 +109,13 @@
private String name = null;
+ /**
+ * <p>The {@link SCXMLExecutor}, an instance of the state machine
+ * defined for the SCXML document for this dialog.</p>
+ */
+ private SCXMLExecutor executor = null;
+
+
// ----------------------------------------------------- Context Properties
@@ -119,7 +155,25 @@
/** {@inheritDoc} */
public String advance(FacesContext context, String outcome) {
- return null; // FIXME - advance()
+
+ ((ShaleDialogELEvaluator) this.executor.getEvaluator()).
+ setFacesContext(context);
+ this.executor.getRootContext().setLocal(Globals.POSTBACK_OUTCOME, outcome);
+
+ try {
+ this.executor.triggerEvent(new TriggerEvent(Globals.POSTBACK_EVENT,
+ TriggerEvent.SIGNAL_EVENT));
+ } catch (ModelException me) {
+ // FIXME - Not an IAE
+ throw new IllegalArgumentException(me.getMessage());
+ }
+
+ // TODO - Re-evaluate before leaving sandbox
+ // Using C/C, "View" state ID is JSF viewId, which is an acceptable
+ // approach with Commons SCXML v0.5
+ Iterator iterator = this.executor.getCurrentStatus().getStates().iterator();
+ return ((State) iterator.next()).getId();
+
}
Modified: shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContexts.java
URL: http://svn.apache.org/viewvc/shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContexts.java?rev=439203&r1=439202&r2=439203&view=diff
==============================================================================
--- shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContexts.java (original)
+++ shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ScxmlContexts.java Thu Aug 31 23:21:09 2006
@@ -18,10 +18,16 @@
import java.io.Serializable;
import java.util.HashMap;
+import java.util.Map;
+
+import javax.faces.FacesException;
import javax.faces.context.FacesContext;
+
+import org.apache.commons.scxml.model.SCXML;
import org.apache.shale.dialog2.Constants;
import org.apache.shale.dialog2.Context;
import org.apache.shale.dialog2.Contexts;
+import org.apache.shale.dialog2.scxml.config.ConfigurationParser;
/**
* <p>Implementation of {@link Contexts} for integrating
@@ -36,10 +42,17 @@
/**
+ * <p><code>Map</code> of {@link SCXML} configurations, keyed
+ * by dialog name. This value is lazily instantiated.</p>
+ */
+ private Map dialogs = null;
+
+
+ /**
* <p>Map containing all currently active {@link Context} instances for
* the current user.</p>
*/
- private final HashMap map = new HashMap();
+ private final Map map = new HashMap();
/**
@@ -53,7 +66,17 @@
/** {@inheritDoc} */
public Context create(FacesContext context, String name) {
- ScxmlContext instance = new ScxmlContext(this, generateId(), name);
+
+ // Look up the specified dialog configuration
+ Map dialogs = dialogs(context);
+ SCXML dialog = (SCXML) dialogs.get(name);
+ if (dialog == null) {
+ throw new IllegalArgumentException("No definition for dialog name '"
+ + name + "' can be found");
+ }
+
+ // Configure a new ScxmlContext instance
+ ScxmlContext instance = new ScxmlContext(this, dialog, name, generateId());
instance.setData(new HashMap());
map.put(instance.getId(), instance);
context.getExternalContext().getRequestMap().put(Constants.CONTEXT_BEAN, instance);
@@ -76,6 +99,67 @@
// --------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Return a <code>Map</code> of the configured {@link SCXML} instances,
+ * keyed by logical dialog name. Upon the first request, the
+ * configuration resources will be processed.</p>
+ *
+ * @param context FacesContext for the current request
+ */
+ private Map dialogs(FacesContext context) {
+
+ // Return the cached instance (if any)
+ if (this.dialogs != null) {
+ return this.dialogs;
+ }
+
+ // Return the previously configured application scope instance (if any)
+ this.dialogs = (Map)
+ context.getExternalContext().getApplicationMap().get(Globals.DIALOGS);
+ if (this.dialogs != null) {
+ return this.dialogs;
+ }
+
+ // Parse our configuration resources and cache the results
+ ConfigurationParser parser = new ConfigurationParser();
+ parser.setDialogs(new HashMap());
+ String resources =
+ context.getExternalContext().getInitParameter(Globals.CONFIGURATION);
+ if (resources == null) {
+ resources = "";
+ }
+ int comma = 0;
+ String path = null;
+ try {
+ while (true) {
+ comma = resources.indexOf(",");
+ if (comma < 0) {
+ path = resources.trim();
+ resources = "";
+ } else {
+ path = resources.substring(0, comma).trim();
+ resources = resources.substring(comma + 1);
+ }
+ if (path.length() < 1) {
+ break;
+ }
+ parser.setResource(context.getExternalContext().getResource(path));
+ parser.parse();
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new FacesException(e);
+ }
+
+ // Cache the results both locally and in application scope
+ this.dialogs = parser.getDialogs();
+ context.getExternalContext().getApplicationMap().put(Globals.DIALOGS, this.dialogs);
+ return this.dialogs;
+
+ }
/**
Added: shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ShaleDialogELEvaluator.java
URL: http://svn.apache.org/viewvc/shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ShaleDialogELEvaluator.java?rev=439203&view=auto
==============================================================================
--- shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ShaleDialogELEvaluator.java (added)
+++ shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/ShaleDialogELEvaluator.java Thu Aug 31 23:21:09 2006
@@ -0,0 +1,160 @@
+/*
+ *
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.shale.dialog2.scxml;
+
+import java.util.regex.Pattern;
+
+import javax.faces.context.FacesContext;
+import javax.faces.el.EvaluationException;
+import javax.faces.el.MethodBinding;
+import javax.faces.el.MethodNotFoundException;
+import javax.faces.el.ReferenceSyntaxException;
+
+import org.apache.commons.scxml.Context;
+import org.apache.commons.scxml.SCXMLExpressionException;
+import org.apache.commons.scxml.env.jsp.ELEvaluator;
+
+
+/**
+ * <p>EL evaluator, for evaluating the expressions in SCXML documents used
+ * to specify Shale dialogs.</p>
+ *
+ * <p>This evaluator uses the following premises for evaluation:
+ * <ol>
+ * <li>JSF method binding expressions will take the form:
+ * #{...}
+ * These will return a <code>java.lang.String</code> object as
+ * required by the methods associated with
+ * <code>org.apache.shale.dialog.ActionState</code></li>
+ * <li>JSP 2.0 EL expressions will take the form:
+ * ${...}</li>
+ * </ol>
+ * </p>
+ *
+ * <p>This evaluator delegates to the following expression evaluators:
+ * <ol>
+ * <li>JSF method binding expressions get delegated to the JSF
+ * implementation (Ex: Apache MyFaces).</li>
+ * <li>JSP expressions get delegated to the Apache Jakarta Commons
+ * EL ExpressionEvaluator implementation. This evaluator adds
+ * ability to evaluate special predicates defined by SCXML.</li>
+ * </ol>
+ * </p>
+ */
+
+public class ShaleDialogELEvaluator extends ELEvaluator {
+
+
+ /**
+ * Shale ActionState method parameters.
+ */
+ private static final Object[] PARAMETERS = new Object[0];
+
+
+ /**
+ * Shale ActionState method signature.
+ */
+ private static final Class[] SIGNATURE = new Class[0];
+
+
+ // We do not have the privilege of having specific element attributes
+ // associated with specific types of expressions
+ /** Pattern for recognizing the method / value binding expression. */
+ private static Pattern jsfBindingExpr =
+ Pattern.compile("^//s*#//{.*//}//s*$");
+
+
+ /** FacesContext for this request. */
+ private FacesContext context;
+
+
+ /**
+ * Constructor.
+ */
+ public ShaleDialogELEvaluator() {
+ super();
+ this.context = null;
+ }
+
+
+ /**
+ * Set per request context.
+ *
+ * @param context The FacesContext for this request.
+ */
+ public void setFacesContext(final FacesContext context) {
+ this.context = context;
+ }
+
+
+ /**
+ * Evaluate an expression.
+ *
+ * @param ctx variable context
+ * @param expr expression
+ * @return Object The result of the evaluation
+ * @throws SCXMLExpressionException For a malformed expression
+ * @see ELEvaluator#eval(Context, String)
+ */
+ public Object eval(final Context ctx, final String expr)
+ throws SCXMLExpressionException {
+
+ if (jsfBindingExpr.matcher(expr).matches()) {
+ return invokeShaleActionStateMethod(expr);
+ }
+
+ return super.eval(ctx, expr);
+ }
+
+
+ /**
+ * Invoke method binding expression for Shale <code>ActionState</code>.
+ * Shale requires return type to be a <code>java.lang.String</code>.
+ *
+ * @param expr Method binding expression
+ * @return String Method return value
+ * @throws SCXMLExpressionException Re-throw potential Faces
+ * exceptions as a SCXMLExpressionException.
+ */
+ private String invokeShaleActionStateMethod(final String expr)
+ throws SCXMLExpressionException {
+
+ try {
+
+ MethodBinding mb = context.getApplication().
+ createMethodBinding(expr, SIGNATURE);
+ return (String) mb.invoke(context, PARAMETERS);
+
+ //Rethrow any exception as SCXMLExpressionException instance
+ } catch (ReferenceSyntaxException rse) {
+
+ throw new SCXMLExpressionException(rse.getMessage(), rse);
+
+ } catch (MethodNotFoundException mnfe) {
+
+ throw new SCXMLExpressionException(mnfe.getMessage(), mnfe);
+
+ } catch (EvaluationException ee) {
+
+ throw new SCXMLExpressionException(ee.getMessage(), ee);
+
+ }
+ }
+
+}
Added: shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/config/ConfigurationParser.java
URL: http://svn.apache.org/viewvc/shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/config/ConfigurationParser.java?rev=439203&view=auto
==============================================================================
--- shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/config/ConfigurationParser.java (added)
+++ shale/sandbox/shale-dialog2-scxml/src/main/java/org/apache/shale/dialog2/scxml/config/ConfigurationParser.java Thu Aug 31 23:21:09 2006
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shale.dialog2.scxml.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.digester.Rule;
+import org.apache.commons.scxml.env.SimpleErrorHandler;
+import org.apache.commons.scxml.io.SCXMLDigester;
+import org.apache.commons.scxml.model.ModelException;
+import org.apache.commons.scxml.model.SCXML;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>Configuration utility for parsing SCXML documents as resources for
+ * defining dialogs. This class has no dependencies on web tier APIs,
+ * only on the Commons SCXML state machine engine library, and
+ * on the parsing technology (Commons Digester) being used.</p>
+ *
+ * <p>TODO: Review Javadocs below if moved out of sandbox.
+ * The configuration for each Shale dialog exists as a standalone
+ * SCXML document, with additional dialog "metadata" file(s)
+ * that serve as the entry point for the Shale Dialog Manager.</p>
+ *
+ * <p>The analogy to the legacy dialog-config.xml file(s) are
+ * scxml-config.xml(s) that look like this:
+ * <scxmldialogs>
+ * <dialog name="Foo" scxmlconfig="foo.scxml" />
+ * <dialog name="Bar" scxmlconfig="bar.scxml" />
+ * <dialog name="Baz" scxmlconfig="baz.scxml" />
+ * <!-- etc. -->
+ * </scxmldialogs>
+ * </p>
+ *
+ * <p>To use this utility, instantiate a new instance and set the
+ * <code>dialogs</code>, <code>resource</code>, and <code>validating</code>
+ * properties. Then, call the <code>parse()</code> method. You can parse
+ * more than one resource by resetting the <code>resource</code>
+ * property and calling <code>parse()</code> again.</p>
+ *
+ * @since 1.0.4
+ */
+
+public final class ConfigurationParser {
+
+
+ // -------------------------------------------------------------- Properties
+
+ /**
+ * <p><code>Map</code> of <code>Dialog</code> instances resulting
+ * from parsing, keyed by dialog name.</p>
+ */
+ private Map dialogs = null;
+
+
+ /**
+ * <p>Return the <code>Map</code> of <code>Dialog</code> instances
+ * into which parsed information will be stored, keyed by dialog
+ * name.</p>
+ */
+ public Map getDialogs() {
+ return this.dialogs;
+ }
+
+
+ /**
+ * <p>Set the <code>Map</code> of <code>Dialog</code> instances
+ * into which parsed information will be stored, keyed by dialog
+ * name.</p>
+ *
+ * @param dialogs The new map
+ */
+ public void setDialogs(Map dialogs) {
+ this.dialogs = dialogs;
+ }
+
+
+ /**
+ * <p>The URL of the configuration resource to be parsed.</p>
+ */
+ private URL resource = null;
+
+
+ /**
+ * <p>Return the URL of the configuration resource to be parsed.</p>
+ */
+ public URL getResource() {
+ return this.resource;
+ }
+
+
+ /**
+ * <p>Set the URL of the configuration resource to be parsed.</p>
+ *
+ * @param resource The new resource URL
+ */
+ public void setResource(URL resource) {
+ this.resource = resource;
+ }
+
+
+ /**
+ * <p>Flag indicating whether we should do a validating parse or not.</p>
+ * FIXME - Change to true (also in Javadoc below), see to do listed below.
+ */
+ private boolean validating = false;
+
+
+ /**
+ * <p>Return a flag indicating whether we will be doing a validating parse
+ * or not. Default value is <code>false</code>.</p>
+ */
+ public boolean isValidating() {
+ return this.validating;
+ }
+
+
+ /**
+ * <p>Set a flag indicating whether we will be doing a validating parse
+ * or not.</p>
+ *
+ * @param validating New flag value
+ */
+ public void setValidating(boolean validating) {
+ // TODO:
+ // Need a scxml-config DTD for Shale, ignore validity check requests
+ // Will need to be fixed if this class comes out of sandbox
+ //this.validating = validating;
+ }
+
+
+ // ---------------------------------------------------------- Public Methods
+
+
+ /**
+ * <p>Parse the configuration resource identified by the <code>resource</code>
+ * property, storing resulting information in the <code>Map</code> specified
+ * by the <code>dialogs</code> property.</p>
+ *
+ * @exception IOException if an input/output error occurs
+ * @exception SAXException if an XML parsing error occurs
+ */
+ public void parse() throws IOException, SAXException {
+
+ Map metadata = new HashMap();
+ Digester digester = digester();
+ digester.clear();
+ digester.push(metadata);
+ InputSource source = new InputSource(getResource().toExternalForm());
+ source.setByteStream(getResource().openStream());
+ digester.parse(source);
+
+ parseDialogs(metadata);
+ }
+
+
+ // --------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Return a fully configured <code>Digester</code> instance.</p>
+ */
+ private Digester digester() {
+
+ Digester digester = new Digester();
+
+ // Configure global characteristics
+ digester.setNamespaceAware(false);
+ digester.setUseContextClassLoader(true);
+ digester.setValidating(isValidating());
+
+ // Configure processing rules
+
+ // scxmldialogs/dialog
+ digester.addRule("scxmldialogs/dialog", new AddDialogMetadataRule());
+
+ return digester;
+
+ }
+
+
+ /**
+ * <p>Parse an individual SCXML document, storing resulting information
+ * as an entry in the <code>Map</code> specified by the <code>dialogs</code>
+ * property.</p>
+ */
+ private void parseDialogs(Map metadata) throws IOException, SAXException {
+
+ Iterator iterator = metadata.entrySet().iterator();
+
+ while (iterator.hasNext()) {
+
+ Map.Entry entry = (Map.Entry) iterator.next();
+ String name = (String) entry.getKey();
+ String scxmlconfig = (String) entry.getValue();
+
+ // TODO - Relative URL testing
+ URL resource = new URL(getResource(), scxmlconfig);
+ InputSource source = new InputSource(resource.toExternalForm());
+ source.setByteStream(resource.openStream());
+
+ SCXML dialog = null;
+ try {
+ dialog = SCXMLDigester.digest(source, new SimpleErrorHandler());
+ } catch (ModelException me) {
+ throw new SAXException(me.getMessage(), me);
+ }
+
+ dialogs.put(name, dialog);
+
+ }
+
+ }
+
+
+ // -------------------------------------------- Private Rule Implementations
+
+
+ /**
+ * <p>Custom <code>Digester</code> rule to add a dialog.</p>
+ */
+ static class AddDialogMetadataRule extends Rule {
+
+ /**
+ * Constructor.
+ */
+ public AddDialogMetadataRule() {
+ super();
+ }
+
+ /**
+ * @see Rule#begin(String, String, Attributes)
+ */
+ public final void begin(final String namespace, final String qname,
+ final Attributes attributes) {
+
+ Map metadata = (Map) getDigester().peek();
+ metadata.put(attributes.getValue("name"),
+ attributes.getValue("scxmlconfig"));
+
+ }
+
+ }
+
+}