Author: rahul
Date: Fri Nov 21 12:58:46 2008
New Revision: 719710

URL: http://svn.apache.org/viewvc?rev=719710&view=rev
Log:
Porting r719709 from trunk.
SCXMLSerializer does not serialize custom namespace declarations.
Partial fix, with assumptions / limitations added to class Javadoc.
SCXML-88

Modified:
    
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java
    
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
    
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/model/SCXML.java
    
commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java

Modified: 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java?rev=719710&r1=719709&r2=719710&view=diff
==============================================================================
--- 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java
 (original)
+++ 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java
 Fri Nov 21 12:58:46 2008
@@ -727,6 +727,7 @@
         //// SCXML
         scxmlRules.add(XP_SM, new ObjectCreateRule(SCXML.class));
         scxmlRules.add(XP_SM, new SetPropertiesRule());
+        scxmlRules.add(XP_SM, new SetCurrentNamespacesRule());
 
         //// Datamodel at document root i.e. <scxml> datamodel
         addDatamodelRules(XP_SM + XPF_DM, scxmlRules, scxml, pr);

Modified: 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java?rev=719710&r1=719709&r2=719710&view=diff
==============================================================================
--- 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
 (original)
+++ 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java
 Fri Nov 21 12:58:46 2008
@@ -48,6 +48,7 @@
 import org.apache.commons.scxml.model.Initial;
 import org.apache.commons.scxml.model.Invoke;
 import org.apache.commons.scxml.model.Log;
+import org.apache.commons.scxml.model.NamespacePrefixesHolder;
 import org.apache.commons.scxml.model.OnEntry;
 import org.apache.commons.scxml.model.OnExit;
 import org.apache.commons.scxml.model.Parallel;
@@ -61,11 +62,22 @@
 import org.w3c.dom.Node;
 
 /**
- * Utility class for serializing the Commons SCXML Java object
+ * <p>Utility class for serializing the Commons SCXML Java object
  * model. Class uses the visitor pattern to trace through the
  * object heirarchy. Used primarily for testing, debugging and
- * visual verification.
+ * visual verification.</p>
  *
+ * <b>NOTE:</b> This serializer makes the following assumptions about the
+ * original SCXML document(s) parsed to create the object model:
+ * <ul>
+ *  <li>The default document namespace is the SCXML namespace:
+ *      <i>http://www.w3.org/2005/07/scxml</i></li>
+ *  <li>The Commons SCXML namespace
+ *      ( <i>http://commons.apache.org/scxml</i> ), if needed, uses the
+ *      &quot;<i>cs</i>&quot; prefix</li>
+ *  <li>All namespace prefixes needed throughout the document are
+ *      declared on the document root element (&lt;scxml&gt;)</li>
+ * </ul>
  */
 public class SCXMLSerializer {
 
@@ -91,8 +103,8 @@
         StringBuffer b =
             new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n").
                 append("<scxml xmlns=\"").append(NAMESPACE_SCXML).
-                append("\" xmlns:cs=\"").append(NAMESPACE_COMMONS_SCXML).
-                append("\" version=\"").append(scxml.getVersion()).
+                append("\"").append(serializeNamespaceDeclarations(scxml)).
+                append(" version=\"").append(scxml.getVersion()).
                 append("\" initial=\"").append(scxml.getInitial()).
                 append("\">\n");
         if (XFORMER == null) {
@@ -102,6 +114,7 @@
                 + " the document will be skipped since a suitable"
                 + " JAXP Transformer could not be instantiated.");
         }
+        b.append(INDENT).append("<!-- http://commons.apache.org/scxml -->\n");
         Datamodel dm = scxml.getDatamodel();
         if (dm != null) {
             serializeDatamodel(b, dm, INDENT);
@@ -573,6 +586,41 @@
     }
 
     /**
+     * Serialize namespace declarations for the root SCXML element.
+     *
+     * @param holder The [EMAIL PROTECTED] NamespacePrefixesHolder} object
+     */
+    private static String serializeNamespaceDeclarations(
+            final NamespacePrefixesHolder holder) {
+        Map<String, String> namespaces = holder.getNamespaces();
+        StringBuffer b = new StringBuffer();
+        if (namespaces != null) {
+            for (Map.Entry<String, String> entry : namespaces.entrySet()) {
+                String prefix = entry.getKey();
+                String nsURI = entry.getValue();
+                if (prefix.length() == 0 && !nsURI.equals(NAMESPACE_SCXML)) {
+                    org.apache.commons.logging.Log log = LogFactory.
+                        getLog(SCXMLSerializer.class);
+                    log.warn("When using the SCXMLSerializer, the default " +
+                        "namespace must be the SCXML namespace:" +
+                        NAMESPACE_SCXML);
+                } if (prefix.equals("cs") &&
+                        !nsURI.equals(NAMESPACE_COMMONS_SCXML)) {
+                    org.apache.commons.logging.Log log = LogFactory.
+                        getLog(SCXMLSerializer.class);
+                    log.warn("When using the SCXMLSerializer, the namespace" +
+                        "prefix \"cs\" must bind to the Commons SCXML " +
+                        "namespace:" + NAMESPACE_COMMONS_SCXML);
+                } else if (prefix.length() > 0) {
+                    b.append(" xmlns:").append(prefix).append("=\"").
+                        append(nsURI).append("\"");
+                }
+            }
+        }
+        return b.toString();
+    }
+
+    /**
      * Get a <code>Transformer</code> instance.
      *
      * @return Transformer The <code>Transformer</code> instance.

Modified: 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/model/SCXML.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/model/SCXML.java?rev=719710&r1=719709&r2=719710&view=diff
==============================================================================
--- 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/model/SCXML.java
 (original)
+++ 
commons/proper/scxml/branches/J6/src/main/java/org/apache/commons/scxml/model/SCXML.java
 Fri Nov 21 12:58:46 2008
@@ -29,7 +29,8 @@
  * root&quot;.
  *
  */
-public class SCXML implements Serializable, Observable {
+public class SCXML implements Serializable, Observable,
+                              NamespacePrefixesHolder {
 
     /**
      * Serial version UID.
@@ -81,6 +82,12 @@
     private Map<String, TransitionTarget> targets;
 
     /**
+     * The XML namespaces defined on the SCXML document root node,
+     * preserved primarily for serialization.
+     */
+    private Map<String, String> namespaces;
+
+    /**
      * Constructor.
      */
     public SCXML() {
@@ -258,6 +265,27 @@
     }
 
     /**
+     * Get the namespace definitions specified on the SCXML element.
+     * May be <code>null</code>.
+     *
+     * @return The namespace definitions specified on the SCXML element,
+     *         may be <code>null</code>.
+     */
+    public final Map<String, String> getNamespaces() {
+        return namespaces;
+    }
+
+    /**
+     * Set the namespace definitions specified on the SCXML element.
+     *
+     * @param namespaces The namespace definitions specified on the
+     *                   SCXML element.
+     */
+    public final void setNamespaces(final Map<String, String> namespaces) {
+        this.namespaces = namespaces;
+    }
+
+    /**
      * Get the ID of the initial state.
      *
      * @return String Returns the initial state ID (used by XML Digester only).

Modified: 
commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java?rev=719710&r1=719709&r2=719710&view=diff
==============================================================================
--- 
commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
 (original)
+++ 
commons/proper/scxml/branches/J6/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java
 Fri Nov 21 12:58:46 2008
@@ -17,7 +17,9 @@
 package org.apache.commons.scxml.io;
 
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -58,13 +60,21 @@
     
     public void testSerializeSCXMLNoStates() {
         SCXML scxml = new SCXML();
+        Map<String, String> namespaces = new LinkedHashMap<String, String>();
+        namespaces.put("", "http://www.w3.org/2005/07/scxml";);
+        namespaces.put("cs", "http://commons.apache.org/scxml";);
+        namespaces.put("foo", "http://f.o.o";);
+        namespaces.put("bar", "http://b.a.r";);
+        scxml.setNamespaces(namespaces);
         scxml.setVersion("version1");
         scxml.setInitial("off");
         scxml.addChild(new State());
         
         String assertValue = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
             + "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\"; 
xmlns:cs=\"http://commons.apache.org/scxml\"; "
-            + "version=\"version1\" initial=\"off\">\n <state>\n 
</state>\n</scxml>\n";
+            + "xmlns:foo=\"http://f.o.o\"; xmlns:bar=\"http://b.a.r\"; "
+            + "version=\"version1\" initial=\"off\">\n <!-- 
http://commons.apache.org/scxml -->\n <state>\n "
+            + "</state>\n</scxml>\n";
         
         assertEquals(assertValue, SCXMLSerializer.serialize(scxml));
     }
@@ -328,8 +338,9 @@
         scxml.addChild(s1);
 
         String assertValue = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-            + "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\"; 
xmlns:cs=\"http://commons.apache.org/scxml\"; "
-            + "version=\"1.0\" initial=\"S1\">\n <state id=\"S1\">\n 
</state>\n</scxml>\n";
+            + "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\"; "
+            + "version=\"1.0\" initial=\"S1\">\n <!-- 
http://commons.apache.org/scxml -->\n"
+            + " <state id=\"S1\">\n </state>\n</scxml>\n";
 
         assertEquals(assertValue, SCXMLSerializer.serialize(scxml));
     }
@@ -365,8 +376,9 @@
         scxml.addChild(par);
 
         String assertValue = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-            + "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\"; 
xmlns:cs=\"http://commons.apache.org/scxml\"; "
+            + "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\"; "
             + "version=\"1.0\" initial=\"par\">\n"
+            + " <!-- http://commons.apache.org/scxml -->\n"
             + " <parallel id=\"par\">\n"
             + "  <state id=\"S1\">\n"
             + "   <state id=\"S11\">\n"


Reply via email to