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 + * "<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 { @@ -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". * */ -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"