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>


Reply via email to