rdonkin 2003/02/13 10:41:49 Modified: betwixt/src/java/org/apache/commons/betwixt XMLUtils.java betwixt/src/java/org/apache/commons/betwixt/digester XMLIntrospectorHelper.java betwixt/src/java/org/apache/commons/betwixt/io AbstractBeanWriter.java BeanReader.java BeanRuleSet.java betwixt/src/test/org/apache/commons/betwixt TestBeanWriter.java TestRSSRoundTrip.java betwixt/src/test/org/apache/commons/betwixt/dotbetwixt TestBeanToXml.java betwixt/src/test/org/apache/commons/betwixt/recursion TestRecursion.java betwixt/src/test/org/apache/commons/betwixt/schema TestSchema.java betwixt/src/test/org/apache/commons/betwixt/strategy TestElementsIO.java betwixt/src/test/org/apache/commons/betwixt/strategy/alt TestElementsAlt.java betwixt/src/test/org/apache/commons/betwixt/xmlunit XmlTestCase.java betwixt/xdocs faq.xml tasks.xml Log: Added abiltiy to suppress writing of empty elements. Also tidied up come checkstyle violations. Revision Changes Path 1.2 +6 -6 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/XMLUtils.java Index: XMLUtils.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/XMLUtils.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- XMLUtils.java 19 Jan 2003 23:20:44 -0000 1.1 +++ XMLUtils.java 13 Feb 2003 18:41:47 -0000 1.2 @@ -420,7 +420,7 @@ * or element name. Returns false if <code>name</code> is null * @return true if this string would be a well-formed name */ - public static boolean isWellFormedXMLName( String name ) { + public static boolean isWellFormedXMLName( String name ) { if ( name == null ) { return false; } 1.18 +2 -2 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLIntrospectorHelper.java Index: XMLIntrospectorHelper.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLIntrospectorHelper.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- XMLIntrospectorHelper.java 3 Feb 2003 14:23:31 -0000 1.17 +++ XMLIntrospectorHelper.java 13 Feb 2003 18:41:48 -0000 1.18 @@ -392,8 +392,8 @@ if ( log.isDebugEnabled() ) { log.debug( "!! " + propertyName + " -> " + descriptor ); - log.debug( "!! " + name + " -> " + - (descriptor!=null?descriptor.getPropertyName():"") ); + log.debug( "!! " + name + " -> " + + (descriptor!=null?descriptor.getPropertyName():"") ); } if ( descriptor != null ) { 1.11 +131 -21 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/AbstractBeanWriter.java Index: AbstractBeanWriter.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/AbstractBeanWriter.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- AbstractBeanWriter.java 6 Jan 2003 22:50:44 -0000 1.10 +++ AbstractBeanWriter.java 13 Feb 2003 18:41:48 -0000 1.11 @@ -109,7 +109,8 @@ private IDGenerator idGenerator = new SequentialIDGenerator(); /** Should generated <code>ID</code> attribute values be added to the elements? */ private boolean writeIDs = true; - + /** Should empty elements be written out? */ + private boolean writeEmptyElements = true; /** indentation level */ private int indentLevel; @@ -204,7 +205,7 @@ if ( qualifiedName == null ) { qualifiedName = elementDescriptor.getQualifiedName(); } - + String ref = null; String id = null; @@ -269,11 +270,13 @@ } } else { - // we've already written this bean so write an IDREF - writeIDREFElement( - qualifiedName, - beanInfo.getIDREFAttributeName(), - ref); + if ( !ignoreElement( elementDescriptor, context )) { + // we've already written this bean so write an IDREF + writeIDREFElement( + qualifiedName, + beanInfo.getIDREFAttributeName(), + ref); + } } popBean(); } @@ -336,6 +339,34 @@ public void setWriteIDs(boolean writeIDs) { this.writeIDs = writeIDs; } + + /** + * <p>Gets whether empty elements should be written into the output.</p> + * + * <p>An empty element is one that has no attributes, no child elements + * and no body text. + * For example, <code><element/></code> is an empty element but + * <code><element attr='value'/></code> is not.</p> + * + * @return true if empty elements will be written into the output + */ + public boolean getWriteEmptyElements() { + return writeEmptyElements; + } + + /** + * <p>Sets whether empty elements should be written into the output.</p> + * + * <p>An empty element is one that has no attributes, no child elements + * and no body text. + * For example, <code><element/></code> is an empty element but + * <code><element attr='value'/></code> is not. + * + * @param writeEmptyElements true if empty elements should be written into the output + */ + public void setWriteEmptyElements(boolean writeEmptyElements) { + this.writeEmptyElements = writeEmptyElements; + } /** * <p>Gets the introspector used.</p> @@ -473,12 +504,21 @@ IOException, SAXException, IntrospectionException { - - if (elementDescriptor.isWrapCollectionsInElement()) { - expressElementStart( qualifiedName ); + if( log.isTraceEnabled() ) { + log.trace( "Writing: " + qualifiedName + " element: " + elementDescriptor ); } + + if ( !ignoreElement( elementDescriptor, context )) { + if ( log.isTraceEnabled() ) { + log.trace( "Element " + elementDescriptor + " is empty." ); + } - writeRestOfElement( qualifiedName, elementDescriptor, context); + if (elementDescriptor.isWrapCollectionsInElement()) { + expressElementStart( qualifiedName ); + } + + writeRestOfElement( qualifiedName, elementDescriptor, context); + } } @@ -505,12 +545,18 @@ IOException, SAXException, IntrospectionException { - - expressElementStart( qualifiedName ); + + if ( !ignoreElement( elementDescriptor, context ) ) { + + expressElementStart( qualifiedName ); - expressAttribute( idAttribute, idValue ); + expressAttribute( idAttribute, idValue ); - writeRestOfElement( qualifiedName, elementDescriptor, context ); + writeRestOfElement( qualifiedName, elementDescriptor, context ); + + } else if ( log.isTraceEnabled() ) { + log.trace( "Element " + qualifiedName + " is empty." ); + } } /** @@ -571,7 +617,7 @@ expressElementStart( qualifiedName ); expressAttribute( idrefAttributeName, idrefAttributeValue ); - + expressElementEnd(); } @@ -784,5 +830,69 @@ log.trace( "Popped from object stack: " + bean ); } return bean; + } + + /** + * Should this element (and children) be written out? + * + * @param descriptor the <code>ElementDescriptor</code> to evaluate + * @param context the <code>Context</code> against which the element will be evaluated + * @return true if this element should be written out + */ + private boolean ignoreElement( ElementDescriptor descriptor, Context context ) { + if ( ! getWriteEmptyElements() ) { + return isEmptyElement( descriptor, context ); + } + return false; + } + + /** + * <p>Will evaluating this element against this context result in an empty element?</p> + * + * <p>An empty element is one that has no attributes, no child elements + * and no body text. + * For example, <code><element/></code> is an empty element but + * <code><element attr='value'/></code> is not.</p> + * + * @param descriptor the <code>ElementDescriptor</code> to evaluate + * @param context the <code>Context</code> against which the element will be evaluated + * @return true if this element is empty on evaluation + */ + private boolean isEmptyElement( ElementDescriptor descriptor, Context context ) { + if ( log.isTraceEnabled() ) { + log.trace( "Is " + descriptor + " empty?" ); + } + + // an element which has attributes is not empty + if ( descriptor.hasAttributes() ) { + log.trace( "Element has attributes." ); + return false; + } + + // an element is not empty if it has a non-empty body + Expression expression = descriptor.getTextExpression(); + if ( expression != null ) { + Object value = expression.evaluate( context ); + if ( value != null ) { + String text = value.toString(); + if ( text != null && text.length() > 0 ) { + log.trace( "Element has body text which isn't empty." ); + return false; + } + } + } + + // now test child elements + // an element is empty if it has no non-empty child elements + if ( descriptor.hasChildren() ) { + for ( int i=0, size=descriptor.getElementDescriptors().length; i<size; i++ ) { + if ( ! isEmptyElement( descriptor.getElementDescriptors()[i], context ) ) { + log.trace( "Element has child which isn't empty." ); + return false; + } + } + } + + return true; } } 1.12 +6 -2 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanReader.java Index: BeanReader.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanReader.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- BeanReader.java 9 Feb 2003 22:27:17 -0000 1.11 +++ BeanReader.java 13 Feb 2003 18:41:48 -0000 1.12 @@ -71,7 +71,6 @@ import org.apache.commons.betwixt.XMLBeanInfo; import org.apache.commons.betwixt.XMLIntrospector; import org.apache.commons.digester.Digester; -import org.apache.commons.digester.Rule; import org.apache.commons.digester.RuleSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -330,7 +329,12 @@ String path, ElementDescriptor elementDescriptor, Class beanClass ) { - RuleSet ruleSet = new BeanRuleSet( introspector, path , elementDescriptor, beanClass, matchIDs); + RuleSet ruleSet = new BeanRuleSet( + introspector, + path , + elementDescriptor, + beanClass, + matchIDs); addRuleSet( ruleSet ); } 1.2 +6 -6 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanRuleSet.java Index: BeanRuleSet.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanRuleSet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- BeanRuleSet.java 9 Feb 2003 22:27:17 -0000 1.1 +++ BeanRuleSet.java 13 Feb 2003 18:41:48 -0000 1.2 @@ -198,7 +198,7 @@ * @param currentDescriptor add child rules for this descriptor * @param context the <code>Context</code> against which beans will be evaluated */ - private void addChildRules( + private void addChildRules( String prefix, ElementDescriptor currentDescriptor, Context context ) { 1.8 +88 -0 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/TestBeanWriter.java Index: TestBeanWriter.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/TestBeanWriter.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- TestBeanWriter.java 30 Dec 2002 18:16:47 -0000 1.7 +++ TestBeanWriter.java 13 Feb 2003 18:41:48 -0000 1.8 @@ -63,6 +63,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.io.StringWriter; import junit.framework.Test; import junit.framework.TestSuite; @@ -99,6 +100,7 @@ System.out.println( "Now trying pretty print" ); BeanWriter writer = new BeanWriter(); + writer.setWriteEmptyElements(true); writer.enablePrettyPrint(); writer.write( bean ); } @@ -106,6 +108,7 @@ public void testLooping() throws Exception { BeanWriter writer = new BeanWriter(); + writer.setWriteEmptyElements( true ); // logging for debugging jsut this method // SimpleLog log = new SimpleLog("[testLooping:BeanWriter]"); @@ -148,6 +151,7 @@ //XXX find a way to automatically verify test ByteArrayOutputStream out = new ByteArrayOutputStream(); BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements( true ); writer.enablePrettyPrint(); XMLIntrospector introspector = new XMLIntrospector(); introspector.setAttributesForPrimitives(true); @@ -201,6 +205,7 @@ */ public void testValidEndOfLine() throws Exception { BeanWriter writer = new BeanWriter(); + writer.setWriteEmptyElements(true); // store the system err PrintStream errStream = System.err; @@ -226,6 +231,89 @@ warning.reset(); // set the System.err back again.. System.setErr(errStream); + } + + /** Test simplest case for writing empty elements */ + public void testSimpleWriteEmptyElements() throws Exception{ + + // use same bean for both tests + AddressBean bean = new AddressBean(); + bean.setStreet("Pasture Lane"); + bean.setCity("Bradford"); + +// SimpleLog log = new SimpleLog( "[SimpleEmpty:AbstractBeanWriter]" ); +// log.setLevel(SimpleLog.LOG_LEVEL_TRACE); + +// SimpleLog baseLog = new SimpleLog( "[SimpleEmpty]" ); +// baseLog.setLevel(SimpleLog.LOG_LEVEL_TRACE); + + // test output when writing empty elements + StringWriter out = new StringWriter(); + out.write("<?xml version='1.0'?>"); + BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements(true); + writer.setWriteIDs(false); + writer.write(bean); +// baseLog.debug("SIMPLE EMPTY"); +// baseLog.debug(out.getBuffer().toString()); + String xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>" + + "<code/><country/></AddressBean>"; +// baseLog.debug(xml); + xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true); + + // test output when not writing empty elements + out = new StringWriter(); + out.write("<?xml version='1.0'?>"); + writer = new BeanWriter(out); + writer.setWriteEmptyElements(false); + writer.setWriteIDs(false); +// writer.setAbstractBeanWriterLog(log); + writer.write(bean); + xml = "<?xml version='1.0'?><AddressBean><street>Pasture Lane</street><city>Bradford</city>" + + "</AddressBean>"; +// baseLog.debug("SIMPLE NOT EMPTY"); +// baseLog.debug(out.getBuffer().toString()); + xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true); + + } + + /** Test nested case for writing empty elements */ + public void testNestedWriteEmptyElements() throws Exception{ + + // write same bean both times + LoopBean root = new LoopBean("base"); + LoopBean middle = new LoopBean(null); + root.setFriend(middle); + middle.setFriend(new LoopBean(null)); + +// SimpleLog baseLog = new SimpleLog( "[NestedEmpty]" ); +// baseLog.setLevel(SimpleLog.LOG_LEVEL_TRACE); + + // test output when writing empty elements + StringWriter out = new StringWriter(); + out.write("<?xml version='1.0'?>"); + BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements(true); + writer.setWriteIDs(false); + writer.write(root); +// baseLog.debug("NESTED EMPTY"); +// baseLog.debug(out.getBuffer().toString()); + String xml = "<?xml version='1.0'?><LoopBean><name>base</name><friend><name/><friend><name/></friend>" + + "</friend></LoopBean>"; + xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true); + + // test output when not writing empty elements + out = new StringWriter(); + out.write("<?xml version='1.0'?>"); + writer = new BeanWriter(out); + writer.setWriteEmptyElements(false); + writer.setWriteIDs(false); + writer.write(root); +// baseLog.debug("NESTED NOT EMPTY"); +// baseLog.debug(out.getBuffer().toString()); + xml = "<?xml version='1.0'?><LoopBean><name>base</name></LoopBean>"; + xmlAssertIsomorphicContent(parseString(out.getBuffer().toString()),parseString(xml), true); + } } 1.5 +1 -0 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/TestRSSRoundTrip.java Index: TestRSSRoundTrip.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/TestRSSRoundTrip.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- TestRSSRoundTrip.java 30 Dec 2002 18:16:47 -0000 1.4 +++ TestRSSRoundTrip.java 13 Feb 2003 18:41:48 -0000 1.5 @@ -225,6 +225,7 @@ protected void write(Object bean, Writer out) throws Exception { BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements(true); writer.getXMLIntrospector().setAttributesForPrimitives(false); writer.setWriteIDs(false); writer.enablePrettyPrint(); 1.9 +6 -4 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/dotbetwixt/TestBeanToXml.java Index: TestBeanToXml.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/dotbetwixt/TestBeanToXml.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- TestBeanToXml.java 19 Jan 2003 23:25:52 -0000 1.8 +++ TestBeanToXml.java 13 Feb 2003 18:41:48 -0000 1.9 @@ -105,6 +105,7 @@ // SimpleLog log = new SimpleLog("[testSimpleBean:XMLIntrospector]"); // log.setLevel(SimpleLog.LOG_LEVEL_TRACE); BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements( true ); // writer.getXMLIntrospector().setLog(log); // log = new SimpleLog("[testSimpleBean:XMLIntrospectorHelper]"); @@ -158,6 +159,7 @@ StringWriter out = new StringWriter(); out.write("<?xml version='1.0' encoding='UTF-8'?>"); BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements( true ); writer.write(new BadDotBetwixtNamesBean("one", "two")); System.out.println(out.toString()); 1.7 +9 -5 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/recursion/TestRecursion.java Index: TestRecursion.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/recursion/TestRecursion.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- TestRecursion.java 30 Dec 2002 18:16:48 -0000 1.6 +++ TestRecursion.java 13 Feb 2003 18:41:48 -0000 1.7 @@ -138,6 +138,7 @@ throws Exception { BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements( true ); writer.setXMLIntrospector(createXMLIntrospector()); // specifies weather to use collection elements or not. writer.getXMLIntrospector().setWrapCollectionsInElement(wrapIt); @@ -169,6 +170,7 @@ { IdBean bean = new IdBean("Hello, World"); BeanWriter writer = new BeanWriter(); + writer.setWriteEmptyElements( true ); writer.getXMLIntrospector().setAttributesForPrimitives(true); writer.setWriteIDs(true); writer.write(bean); @@ -191,6 +193,7 @@ StringWriter stringWriter = new StringWriter(); BeanWriter writer = new BeanWriter(stringWriter); + writer.setWriteEmptyElements( true ); writer.setWriteIDs(false); writer.write(alpha); } @@ -212,6 +215,7 @@ StringWriter stringWriter = new StringWriter(); BeanWriter writer = new BeanWriter(stringWriter); + writer.setWriteEmptyElements( true ); writer.setWriteIDs(false); //SimpleLog log = new SimpleLog("[testCyclicReferenceStack2:BeanWriter]"); 1.7 +1 -0 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/TestSchema.java Index: TestSchema.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/schema/TestSchema.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- TestSchema.java 9 Feb 2003 22:27:18 -0000 1.6 +++ TestSchema.java 13 Feb 2003 18:41:48 -0000 1.7 @@ -216,6 +216,7 @@ throws Exception { BeanWriter writer = new BeanWriter(out); + writer.setWriteEmptyElements( true ); writer.setXMLIntrospector(createXMLIntrospector()); // specifies weather to use collection elements or not. writer.getXMLIntrospector().setWrapCollectionsInElement(wrapCollectionsInElement); 1.3 +6 -4 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestElementsIO.java Index: TestElementsIO.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestElementsIO.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- TestElementsIO.java 30 Dec 2002 18:16:48 -0000 1.2 +++ TestElementsIO.java 13 Feb 2003 18:41:49 -0000 1.3 @@ -119,6 +119,7 @@ StringWriter out = new StringWriter(); BeanWriter writer = newBeanWriter(out, mapper); + writer.setWriteEmptyElements(true); writer.write(elements); writer.flush(); @@ -152,6 +153,7 @@ // log.setLevel(SimpleLog.LOG_LEVEL_TRACE); BeanWriter result = new BeanWriter(writer); + result.setWriteEmptyElements(true); // result.setLog(log); // log = new SimpleLog("[TextElementsIO:AbstractBeanWriter]"); 1.3 +6 -4 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/alt/TestElementsAlt.java Index: TestElementsAlt.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/alt/TestElementsAlt.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- TestElementsAlt.java 30 Dec 2002 18:16:48 -0000 1.2 +++ TestElementsAlt.java 13 Feb 2003 18:41:49 -0000 1.3 @@ -124,6 +124,7 @@ StringWriter out = new StringWriter(); BeanWriter writer = newBeanWriter(out, mapper); + writer.setWriteEmptyElements( true ); writer.write(elements); writer.flush(); @@ -157,6 +158,7 @@ // log.setLevel(SimpleLog.LOG_LEVEL_TRACE); BeanWriter result = new BeanWriter(writer); + result.setWriteEmptyElements( true ); // result.setLog(log); // log = new SimpleLog("[TestElementsAlt:AbstractBeanWriter]"); 1.4 +132 -19 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/xmlunit/XmlTestCase.java Index: XmlTestCase.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/xmlunit/XmlTestCase.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- XmlTestCase.java 30 Dec 2002 18:16:48 -0000 1.3 +++ XmlTestCase.java 13 Feb 2003 18:41:49 -0000 1.4 @@ -61,6 +61,12 @@ */ package org.apache.commons.betwixt.xmlunit; +import java.util.Collections; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Iterator; + import java.io.File; import java.io.IOException; import java.io.StringReader; @@ -76,6 +82,7 @@ import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; +import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -102,14 +109,21 @@ parseFile("src/test/org/apache/commons/betwixt/xmlunit/rss-example.xml")); } - public void xmlAssertIsomorphicContent( org.w3c.dom.Document documentOne, org.w3c.dom.Document documentTwo) throws - AssertionFailedError - { - xmlAssertIsomorphicContent(null, documentOne, documentTwo); + AssertionFailedError { + xmlAssertIsomorphicContent(documentOne, documentTwo, false); + } + + public void xmlAssertIsomorphicContent( + org.w3c.dom.Document documentOne, + org.w3c.dom.Document documentTwo, + boolean orderIndependent) + throws + AssertionFailedError { + xmlAssertIsomorphicContent(null, documentOne, documentTwo, orderIndependent); } public void xmlAssertIsomorphicContent( @@ -117,6 +131,17 @@ org.w3c.dom.Document documentOne, org.w3c.dom.Document documentTwo) throws + AssertionFailedError { + + xmlAssertIsomorphicContent(message, documentOne, documentTwo, false); + } + + public void xmlAssertIsomorphicContent( + String message, + org.w3c.dom.Document documentOne, + org.w3c.dom.Document documentTwo, + boolean orderIndependent) + throws AssertionFailedError { // two documents have isomorphic content iff their root elements @@ -126,20 +151,40 @@ documentOne.getDocumentElement(), documentTwo.getDocumentElement()); } + + + public void xmlAssertIsomorphic( + org.w3c.dom.Node rootOne, + org.w3c.dom.Node rootTwo) + throws + AssertionFailedError { + xmlAssertIsomorphic(rootOne, rootTwo, false); + } public void xmlAssertIsomorphic( org.w3c.dom.Node rootOne, - org.w3c.dom.Node rootTwo) + org.w3c.dom.Node rootTwo, + boolean orderIndependent) throws AssertionFailedError { - xmlAssertIsomorphic(null, rootOne, rootTwo); + xmlAssertIsomorphic(null, rootOne, rootTwo, orderIndependent); + } + + public void xmlAssertIsomorphic( + String message, + org.w3c.dom.Node rootOne, + org.w3c.dom.Node rootTwo) { + + xmlAssertIsomorphic(message, rootOne, rootTwo, false); + } public void xmlAssertIsomorphic( String message, org.w3c.dom.Node rootOne, - org.w3c.dom.Node rootTwo) + org.w3c.dom.Node rootTwo, + boolean orderIndependent) throws AssertionFailedError { @@ -147,15 +192,27 @@ rootOne.normalize(); rootTwo.normalize(); // going to use recursion so avoid normalizing each time - testIsomorphic(message, rootOne, rootTwo); + testIsomorphic(message, rootOne, rootTwo, orderIndependent); } - + private void testIsomorphic( String message, org.w3c.dom.Node nodeOne, org.w3c.dom.Node nodeTwo) throws + AssertionFailedError { + + testIsomorphic(message, nodeOne, nodeTwo, false); + } + + + private void testIsomorphic( + String message, + org.w3c.dom.Node nodeOne, + org.w3c.dom.Node nodeTwo, + boolean orderIndependent) + throws AssertionFailedError { try { @@ -241,16 +298,36 @@ log("Comparing children"); // this time order is important // so we can just go down the list and compare node-wise using recursion - NodeList childrenOne = nodeOne.getChildNodes(); - NodeList childrenTwo = nodeTwo.getChildNodes(); + List listOne = sanitize(nodeOne.getChildNodes()); + List listTwo = sanitize(nodeTwo.getChildNodes()); + + if (orderIndependent) { + Comparator nodeByName = new NodeByNameComparator(); + Collections.sort(listOne, nodeByName); + Collections.sort(listTwo, nodeByName); + } + Iterator it = listOne.iterator(); + Iterator iter2 = listOne.iterator(); + while (it.hasNext() & iter2.hasNext()) { + Node nextOne = ((Node)it.next()); + Node nextTwo = ((Node)iter2.next()); + log(nextOne.getNodeName() + ":" + nextOne.getNodeValue()); + log(nextTwo.getNodeName() + ":" + nextTwo.getNodeValue()); + } + assertEquals( (null == message ? "(Unequal child nodes)" : message + "(Unequal child nodes)"), - childrenOne.getLength(), - childrenTwo.getLength()); + listOne.size(), + listTwo.size()); - for (int i=0, size=childrenOne.getLength(); i<size; i++) { - testIsomorphic(message, childrenOne.item(i), childrenTwo.item(i)); + it = listOne.iterator(); + iter2 = listOne.iterator(); + while (it.hasNext() & iter2.hasNext()) { + Node nextOne = ((Node)it.next()); + Node nextTwo = ((Node)iter2.next()); + log(nextOne.getNodeName() + " vs " + nextTwo.getNodeName()); + testIsomorphic(message, nextOne, nextTwo); } @@ -329,6 +406,42 @@ } return trimThis.trim(); + } + + private List sanitize(NodeList nodes) { + ArrayList list = new ArrayList(); + + for (int i=0, size=nodes.getLength(); i<size; i++) { + if ( nodes.item(i).getNodeType() == Node.TEXT_NODE ) { + if ( !( nodes.item(i).getNodeValue() == null || + nodes.item(i).getNodeValue().trim().length() == 0 )) { + list.add(nodes.item(i)); + } + } else { + list.add(nodes.item(i)); + } + } + return list; + } + + private class NodeByNameComparator implements Comparator { + public int compare(Object objOne, Object objTwo) { + String nameOne = ((Node) objOne).getNodeName(); + String nameTwo = ((Node) objTwo).getNodeName(); + + if (nameOne == null) { + if (nameTwo == null) { + return 0; + } + return -1; + } + + if (nameTwo == null) { + return 1; + } + + return nameOne.compareTo(nameTwo); + } } } 1.5 +22 -0 jakarta-commons/betwixt/xdocs/faq.xml Index: faq.xml =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/xdocs/faq.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- faq.xml 19 Jan 2003 15:40:00 -0000 1.4 +++ faq.xml 13 Feb 2003 18:41:49 -0000 1.5 @@ -57,6 +57,11 @@ How can I stop Betwixt generating <code>ID</code> attribute values for my beans? </a> </li> + <li> + <a href="#empty-elements"> + How can I stop Betwixt write out empty elements? + </a> + </li> </ol> <p><strong>Reading Beans</strong></p> <ol> @@ -188,6 +193,23 @@ Once this property is set (to false), BeanWroter will throw a <code>CyclicReferenceException</code> when any cyclic references which are encountered in the bean graph. + </dd> + </dl> + + <dl> + <dt> + <a name="empty-elements"> + How can I stop Betwixt writing out empty elements? + </a> + </dt> + <dd> + An empty element (for this discussion) is one which has no attributes and no + child elements which are not empty. + If you want to stop Betwixt writing out empty elements, then call: +<source> +beanWriter.setWriteEmptyElements(false); +</source> + (before writing your bean). </dd> </dl> 1.7 +13 -6 jakarta-commons/betwixt/xdocs/tasks.xml Index: tasks.xml =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/xdocs/tasks.xml,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- tasks.xml 10 Feb 2003 20:19:28 -0000 1.6 +++ tasks.xml 13 Feb 2003 18:41:49 -0000 1.7 @@ -92,11 +92,6 @@ <subsection name="Medium priority"> <ul> <li> - <strong>Handle empty elements better.</strong> - Add option not to write empty elements. This is required to correctly write some kinds of xml. - The RSS full round tripping will only work with this functionality. - </li> - <li> <strong>Create design documentation</strong> This will help people understand the betwixt design. </li> @@ -192,6 +187,12 @@ a <code>BeanRuleSet</code> instance is used to set up the required rule on digester. Standard digester rules can be added before and after registration. </li> + <li> + <strong>Handle empty elements better.</strong> + An option not to write empty elements has been added. This is required to correctly write + some kinds of xml. + The RSS full round tripping will only work with this functionality. + </li> </ul> </subsection> </section> @@ -213,6 +214,12 @@ </ul> </subsection> </section> - </body> +<section name='Symantic Changes'> + <subsection name='Since 1.0-Alpha 1 Release'> + <ul> + </ul> + </subsection> +</section> +</body> </document>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]