Author: rahul Date: Fri Nov 21 12:57:08 2008 New Revision: 719709 URL: http://svn.apache.org/viewvc?rev=719709&view=rev Log: SCXMLSerializer does not serialize custom namespace declarations. Partial fix, with assumptions / limitations added to class Javadoc. SCXML-88
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java?rev=719709&r1=719708&r2=719709&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLParser.java Fri Nov 21 12:57:08 2008 @@ -728,6 +728,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/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java?rev=719709&r1=719708&r2=719709&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/io/SCXMLSerializer.java Fri Nov 21 12:57:08 2008 @@ -49,6 +49,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; @@ -62,11 +63,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 + * "<i>cs</i>" prefix</li> + * <li>All namespace prefixes needed throughout the document are + * declared on the document root element (<scxml>)</li> + * </ul> */ public class SCXMLSerializer { @@ -92,8 +104,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) { @@ -103,6 +115,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); @@ -585,6 +598,43 @@ } /** + * Serialize namespace declarations for the root SCXML element. + * + * @param holder The [EMAIL PROTECTED] NamespacePrefixesHolder} object + */ + private static String serializeNamespaceDeclarations( + final NamespacePrefixesHolder holder) { + Map ns = holder.getNamespaces(); + StringBuffer b = new StringBuffer(); + if (ns != null) { + Iterator iter = ns.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + String prefix = (String) entry.getKey(); + String nsURI = (String) 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/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java?rev=719709&r1=719708&r2=719709&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml/model/SCXML.java Fri Nov 21 12:57:08 2008 @@ -29,7 +29,7 @@ * root". * */ -public class SCXML implements Serializable { +public class SCXML implements Serializable, NamespacePrefixesHolder { /** * Serial version UID. @@ -81,6 +81,12 @@ private Map targets; /** + * The XML namespaces defined on the SCXML document root node, + * preserved primarily for serialization. + */ + private Map namespaces; + + /** * Indicates whether the legacy parser * ([EMAIL PROTECTED] org.apache.commons.scxml.io.SCXMLDigester}) was used. */ @@ -264,6 +270,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 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 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/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java?rev=719709&r1=719708&r2=719709&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java (original) +++ commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLSerializerTest.java Fri Nov 21 12:57:08 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; @@ -57,13 +59,21 @@ public void testSerializeSCXMLNoStates() { SCXML scxml = new SCXML(); + Map namespaces = new LinkedHashMap(); + 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)); } @@ -327,8 +337,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)); } @@ -364,8 +375,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"