Author: rahul Date: Tue Dec 19 16:12:09 2006 New Revision: 488863 URL: http://svn.apache.org/viewvc?view=rev&rev=488863 Log: Allow app developers to define custom Commons SCXML actions in namespaces of their choice. For example:
<dialog name="foo" scxmlconfig="dialog01.xml"> <scxmlaction name="bar" uri="http://some.ns.uri" actionclassname="package.Class"/> </dialog> allows the use of custom Commons SCXML action with local name 'bar' in namespace uri 'http://some.ns.uri' for the dialog described by dialog01.xml. Updated DTD accordingly. Some renaming in DialogMetadata to appease digester setproperties (XML vocabulary wins over camelcase or mnemonics in my book). Also add a note in package.html and Javadoc that these classes (the ones in the oasds.config package) are not meant for app developer use (some need to be public to let digester do its thing etc.). SHALE-366 Modified: shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/ConfigurationParser.java shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/DialogMetadata.java shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/package.html shale/framework/trunk/shale-dialog-scxml/src/main/resources/org/apache/shale/dialog/scxml/dialog-scxml-config_1_0.dtd Modified: shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/ConfigurationParser.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/ConfigurationParser.java?view=diff&rev=488863&r1=488862&r2=488863 ============================================================================== --- shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/ConfigurationParser.java (original) +++ shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/ConfigurationParser.java Tue Dec 19 16:12:09 2006 @@ -35,7 +35,7 @@ import org.apache.shale.dialog.scxml.Globals; import org.apache.shale.dialog.scxml.action.RedirectAction; import org.apache.shale.dialog.scxml.action.ViewAction; -import org.xml.sax.Attributes; +import org.apache.shale.dialog.scxml.config.DialogMetadata.SCXMLAction; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -84,12 +84,6 @@ /** - * <p>Default FQCN for dialog data.</p> - */ - private static final String DEFAULT_DIALOG_DATA_CLASS_NAME = "java.util.HashMap"; - - - /** * <p><code>Map</code> of <code>Dialog</code> instances resulting * from parsing, keyed by dialog name.</p> */ @@ -225,9 +219,15 @@ // Configure processing rules // dialogs/dialog + digester.addObjectCreate("dialogs/dialog", DialogMetadata.class); + digester.addSetProperties("dialogs/dialog"); digester.addRule("dialogs/dialog", new AddDialogMetadataRule()); - return digester; + digester.addObjectCreate("dialogs/dialog/scxmlaction", SCXMLAction.class); + digester.addSetProperties("dialogs/dialog/scxmlaction"); + digester.addSetNext("dialogs/dialog/scxmlaction", "addDialogAction"); + + return digester; } @@ -245,28 +245,68 @@ Iterator iterator = metadata.entrySet().iterator(); - // Define the custom Commons SCXML actions used by Shale dialogs and - // create a list of custom actions as needed by the SCXMLDigester API - List customDialogActions = new ArrayList(); + // Create a list of the custom Commons SCXML actions defined by the + // Shale dialog Commons SCXML implementation + List shaleDialogActions = new ArrayList(); // <shale:redirect> CustomAction redirectAction = new CustomAction(Globals.CUSTOM_SCXML_ACTIONS_URI, "redirect", RedirectAction.class); - customDialogActions.add(redirectAction); + shaleDialogActions.add(redirectAction); // <shale:view> CustomAction viewAction = new CustomAction(Globals.CUSTOM_SCXML_ACTIONS_URI, "view", ViewAction.class); - customDialogActions.add(viewAction); + shaleDialogActions.add(viewAction); + + // Class loader for app developer defined custom Commons SCXML actions + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if (loader == null) { + loader = ConfigurationParser.class.getClassLoader(); + } while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); String name = (String) entry.getKey(); DialogMetadata dMetadata = (DialogMetadata) entry.getValue(); - String scxmlconfig = dMetadata.getConfig(); + String scxmlconfig = dMetadata.getScxmlconfig(); + + // The custom actions available to this dialog is the + // summation of the ones defined by this Shale dialog module + // and those defined by the app developer using the dialog + // configuration file for this dialog + List customDialogActions = new ArrayList(); + customDialogActions.addAll(shaleDialogActions); + + List devActions = dMetadata.getDialogActions(); + for (int i = 0; i < devActions.size(); i++) { + SCXMLAction scxmlAction = (SCXMLAction) devActions.get(i); + String actionname = scxmlAction.getName(); + String uri = scxmlAction.getUri(); + String actionFQCN = scxmlAction.getActionclassname(); + if (actionname == null || uri == null || actionFQCN == null) { + // shouldn't happen if dialog-config is validated + throw new IllegalArgumentException("A custom Commons" + + " SCXML action (<scxmlaction> element) in the" + + " dialog configuration is missing the 'name'," + + " 'uri' or 'actionclassname'"); + } + Class customActionClass = null; + try { + customActionClass = loader.loadClass(actionFQCN); + } catch (Exception e) { + throw new IllegalArgumentException("Cannot load " + + "custom Commons SCXML action class '" + + actionFQCN + "' for action with name '" + + actionname + "'"); + } + CustomAction customAction = new CustomAction(uri, + actionname, customActionClass); + customDialogActions.add(customAction); + } URL resource = new URL(getResource(), scxmlconfig); InputSource source = new InputSource(resource.toExternalForm()); @@ -307,19 +347,13 @@ /** * [EMAIL PROTECTED] * - * @see Rule#begin(String, String, Attributes) + * @see Rule#end(String,String) */ - public final void begin(final String namespace, final String qname, - final Attributes attributes) { + public void end(String namespace, String name) throws Exception { - Map metadata = (Map) getDigester().peek(); - String name = attributes.getValue("name"); - String scxmlconfig = attributes.getValue("scxmlconfig"); - String dataclassname = attributes.getValue("dataclassname"); - if (dataclassname == null || dataclassname.trim().length() == 0) { - dataclassname = DEFAULT_DIALOG_DATA_CLASS_NAME; - } - metadata.put(name, new DialogMetadata(name, scxmlconfig, dataclassname)); + DialogMetadata dialog = (DialogMetadata) getDigester().peek(); + Map map = (Map) getDigester().peek(1); + map.put(dialog.getName(), dialog); } Modified: shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/DialogMetadata.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/DialogMetadata.java?view=diff&rev=488863&r1=488862&r2=488863 ============================================================================== --- shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/DialogMetadata.java (original) +++ shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/DialogMetadata.java Tue Dec 19 16:12:09 2006 @@ -18,6 +18,8 @@ package org.apache.shale.dialog.scxml.config; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.apache.commons.scxml.model.SCXML; @@ -35,9 +37,15 @@ * the above document.</li> * <li>The dialog data class name, an instance of which will be set as * dialog data once an instance of this dialog is started.</li> + * <li>A list of Commons SCXML custom actions, that will be defined for this + * dialog.</li> * </ul> * </p> * + * <p><strong>WARNING</strong> - These classes should <strong>ONLY</strong> + * be used by the dialog framework infrastructure. They are + * <strong>NOT</strong> meant to be used by the application.</p> + * * @since 1.0.4 * * $Id$ @@ -52,6 +60,12 @@ private static final long serialVersionUID = -4399162240006113135L; /** + * <p>Default FQCN for dialog data.</p> + */ + private static final String DEFAULT_DIALOG_DATA_CLASS_NAME = "java.util.HashMap"; + + + /** * The dialog name. */ private String name; @@ -59,7 +73,7 @@ /** * The location where the SCXML document for this dialog resides. */ - private String config; + private String scxmlconfig; /** @@ -74,33 +88,23 @@ /** * The FQCN of the dialog data. */ - private String dataClassName; + private String dataclassname; - //---------------------------------------- Default scope - /** - * Constructor. - * - * @param name The dialog name - * @param config The location where the SCXML document for this dialog resides - * @param dataClassName The FQCN of the dialog data + * The custom Commons SCXML actions for this dialog. */ - DialogMetadata(String name, String config, String dataClassName) { - this.name = name; - this.config = config; - this.dataClassName = dataClassName; - } + private List dialogActions; + + //---------------------------------------- Constructors /** - * Set the Commons SCXML object model describing the state machine - * for this dialog. - * - * @param stateMachine The stateMachine to set. + * Constructor. */ - public void setStateMachine(SCXML stateMachine) { - this.stateMachine = stateMachine; + public DialogMetadata() { + this.dataclassname = DEFAULT_DIALOG_DATA_CLASS_NAME; + this.dialogActions = new ArrayList(); } @@ -117,22 +121,54 @@ /** + * Set the dialog name. + * + * @param name The dialog name. + */ + public void setName(String name) { + this.name = name; + } + + + /** * Get the data class FQN. * - * @return Returns the dataClassName. + * @return Returns the dataclassname. */ public String getDataclassname() { - return dataClassName; + return dataclassname; + } + + + /** + * Set the data class FQN. + * + * @param dataclassname The data class FQN. + */ + public void setDataclassname(String dataclassname) { + if (dataclassname != null && dataclassname.trim().length() > 0) { + this.dataclassname = dataclassname; + } } /** * Get the location where the SCXML document for this dialog resides. * - * @return Returns the config. + * @return Returns the scxmlconfig. */ - public String getConfig() { - return config; + public String getScxmlconfig() { + return scxmlconfig; + } + + + /** + * Set the location where the SCXML document for this dialog resides. + * + * @param scxmlconfig The SCXML dialog configuration file location. + */ + public void setScxmlconfig(String config) { + this.scxmlconfig = config; } @@ -144,6 +180,132 @@ */ public SCXML getStateMachine() { return stateMachine; + } + + + /** + * Set the Commons SCXML object model describing the state machine + * for this dialog. + * + * @param stateMachine The stateMachine to set. + */ + public void setStateMachine(SCXML stateMachine) { + this.stateMachine = stateMachine; + } + + /** + * Add this Commons SCXML custom action for this specific dialog. + * + * @param scxmlAction The SCXMLAction to be added. + */ + public void addDialogAction(SCXMLAction scxmlAction) { + dialogActions.add(scxmlAction); + } + + + /** + * Get the list of dialog actions defined for this specific dialog. + * + * @return Returns the list of DialogActions. + */ + public List getDialogActions() { + return dialogActions; + } + + + /** + * A POJO representing the bits of a custom Commons SCXML action used + * in a Shale dialog. + * + */ + public static class SCXMLAction implements Serializable { + + /** + * Serial version UID. + */ + private static final long serialVersionUID = 1L; + + //------------------------------------------- Properties + /** + * The action name. + */ + private String name; + + /** + * The action URI. + */ + private String uri; + + /** + * The action class FQN. + */ + private String actionclassname; + + //------------------------------------------- Constructor + + /** + * Constructor. + */ + public SCXMLAction() { + super(); + } + + //-------------------------------------------- Public methods + + /** + * Get the action name. + * + * @return The action name. + */ + public String getName() { + return name; + } + + /** + * Set the action name. + * + * @param The action name. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Get the action URI. + * + * @return The action URI. + */ + public String getUri() { + return uri; + } + + /** + * Set the action URI. + * + * @param The action URI. + */ + public void setUri(String uri) { + this.uri = uri; + } + + /** + * Get the action class FQN. + * + * @return The action class FQN. + */ + public String getActionclassname() { + return actionclassname; + } + + /** + * Set the action class FQN. + * + * @param The action class FQN. + */ + public void setActionclassname(String actionclassname) { + this.actionclassname = actionclassname; + } + } } Modified: shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/package.html URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/package.html?view=diff&rev=488863&r1=488862&r2=488863 ============================================================================== --- shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/package.html (original) +++ shale/framework/trunk/shale-dialog-scxml/src/main/java/org/apache/shale/dialog/scxml/config/package.html Tue Dec 19 16:12:09 2006 @@ -24,5 +24,9 @@ <p>Classes that help in parsing the SCXML documents describing the Shale dialogs.</p> + <p><strong>WARNING</strong> - These classes should <strong>ONLY</strong> + be used by the dialog framework infrastructure. They are + <strong>NOT</strong> meant to be used by the application.</p> + </body> </html> Modified: shale/framework/trunk/shale-dialog-scxml/src/main/resources/org/apache/shale/dialog/scxml/dialog-scxml-config_1_0.dtd URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-scxml/src/main/resources/org/apache/shale/dialog/scxml/dialog-scxml-config_1_0.dtd?view=diff&rev=488863&r1=488862&r2=488863 ============================================================================== --- shale/framework/trunk/shale-dialog-scxml/src/main/resources/org/apache/shale/dialog/scxml/dialog-scxml-config_1_0.dtd (original) +++ shale/framework/trunk/shale-dialog-scxml/src/main/resources/org/apache/shale/dialog/scxml/dialog-scxml-config_1_0.dtd Tue Dec 19 16:12:09 2006 @@ -61,8 +61,25 @@ SCXML dialog configuration file that is validated by this DTD) --> -<!ELEMENT dialog EMPTY> +<!ELEMENT dialog (scxmlaction*)> <!ATTLIST dialog dataclassname CDATA #IMPLIED> <!ATTLIST dialog name CDATA #REQUIRED> <!ATTLIST dialog scxmlconfig CDATA #REQUIRED> + +<!-- The "scxmlaction" element defines a custom Commons SCXML action that + may then be used for this dialog. The following attributes are defined: + + actionclassname Fully qualified class name of custom + Commons SCXML action. + + name Local name of custom action. + + uri The namespace URI for the custom action. + Note: Custom Commons SCXML actions cannot be + defined in the SCXML namespace. +--> +<!ELEMENT scxmlaction EMPTY> +<!ATTLIST scxmlaction actionclassname CDATA #REQUIRED> +<!ATTLIST scxmlaction name CDATA #REQUIRED> +<!ATTLIST scxmlaction uri CDATA #REQUIRED>
