You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2002/12/15 20:03:35 UTC
cvs commit: jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/xmlunit rss-example.xml XmlTestCase.java
rdonkin 2002/12/15 11:03:35
Modified: betwixt/src/java/org/apache/commons/betwixt/io
AbstractBeanWriter.java BeanWriter.java
SAXBeanWriter.java
betwixt/src/test/org/apache/commons/betwixt
TestBeanWriter.java
betwixt/src/test/org/apache/commons/betwixt/dotbetwixt
TestBeanToXml.java
betwixt/src/test/org/apache/commons/betwixt/recursion
Element.java TestRecursion.java
betwixt/src/test/org/apache/commons/betwixt/xmlunit
XmlTestCase.java
Added: betwixt/src/test/org/apache/commons/betwixt/xmlunit
rss-example.xml
Log:
Improved betwixt cyclic graph detection as suggested by Darren Scott. Now a stack is used to store the bean parentage and only if a bean is it's own parent will the CyclicReferenceException be thrown. Also create test cases.
Revision Changes Path
1.7 +54 -19 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.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AbstractBeanWriter.java 14 Oct 2002 01:55:38 -0000 1.6
+++ AbstractBeanWriter.java 15 Dec 2002 19:03:34 -0000 1.7
@@ -73,6 +73,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.commons.collections.ArrayStack;
+
import org.apache.commons.betwixt.AttributeDescriptor;
import org.apache.commons.betwixt.ElementDescriptor;
import org.apache.commons.betwixt.XMLBeanInfo;
@@ -104,6 +106,8 @@
private Log log = LogFactory.getLog( AbstractBeanWriter.class );
/** Map containing ID attribute values for beans */
protected HashMap idMap = new HashMap();
+ /** Stack containing beans - used to detect cycles */
+ private ArrayStack beanStack = new ArrayStack();
/** Used to generate ID attribute values*/
protected IDGenerator idGenerator = new SequentialIDGenerator();
/** Should generated <code>ID</code> attribute values be added to the elements? */
@@ -205,8 +209,10 @@
context );
}
else {
-
- ref = (String) idMap.get( context.getBean() );
+ pushBean ( context.getBean() );
+ if ( writeIDs ) {
+ ref = (String) idMap.get( context.getBean() );
+ }
if ( ref == null ) {
// this is the first time that this bean has be written
AttributeDescriptor idAttribute = beanInfo.getIDAttribute();
@@ -256,11 +262,6 @@
}
}
else {
- // we have a cyclic reference
- if ( !writeIDs ) {
- // if we're not writing IDs, then throw exception
- throw new CyclicReferenceException();
- }
// we've already written this bean so write an IDREF
writeIDREFElement(
@@ -268,6 +269,7 @@
beanInfo.getIDREFAttributeName(),
ref);
}
+ popBean();
}
}
}
@@ -332,20 +334,18 @@
}
/**
- * <p> Get the current level for logging. </p>
- *
- * @return a <code>org.apache.commons.logging.Log</code> level constant
+ * <p> Get the current logging implementation. </p>
*/
- public Log getLog() {
+ public final Log getAbstractBeanWriterLog() {
return log;
}
/**
- * <p> Set the current logging level. </p>
+ * <p> Set the current logging implementation. </p>
*
- * @param level a <code>org.apache.commons.logging.Log</code> level constant
+ * @param log <code>Log</code> implementation to use
*/
- public void setLog(Log log) {
+ public final void setAbstractBeanWriterLog(Log log) {
this.log = log;
}
@@ -596,4 +596,39 @@
protected void writePrintln() throws IOException {}
protected void writeIndent() throws IOException {}
+
+ protected void pushBean( Object bean ) throws CyclicReferenceException {
+ // check that we don't have a cyclic reference when we're not writing IDs
+ if ( !writeIDs ) {
+ Iterator it = beanStack.iterator();
+ while ( it.hasNext() ) {
+ Object next = it.next();
+ // use absolute equality rather than equals
+ // we're only really bothered if objects are actually the same
+ if ( bean == next ) {
+ if ( log.isDebugEnabled() ) {
+ log.debug("Element stack: ");
+ Iterator debugStack = beanStack.iterator();
+ while ( debugStack.hasNext() ) {
+ log.debug(debugStack.next());
+ }
+ }
+ log.error("Cyclic reference at bean: " + bean);
+ throw new CyclicReferenceException();
+ }
+ }
+ }
+ if (log.isTraceEnabled()) {
+ log.trace( "Pushing onto object stack: " + bean );
+ }
+ beanStack.push( bean );
+ }
+
+ protected Object popBean() {
+ Object bean = beanStack.pop();
+ if (log.isTraceEnabled()) {
+ log.trace( "Popped from object stack: " + bean );
+ }
+ return bean;
+ }
}
1.10 +4 -4 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java
Index: BeanWriter.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- BeanWriter.java 1 Aug 2002 03:58:01 -0000 1.9
+++ BeanWriter.java 15 Dec 2002 19:03:34 -0000 1.10
@@ -260,7 +260,7 @@
}
/**
- * <p> Get the current level for logging. </p>
+ * <p> Set the log implementation used. </p>
*
* @return a <code>org.apache.commons.logging.Log</code> level constant
*/
@@ -269,11 +269,11 @@
}
/**
- * <p> Set the current logging level. </p>
+ * <p> Set the log implementation used. </p>
*
- * @param level a <code>org.apache.commons.logging.Log</code> level constant
+ * @param log <code>Log</code> implementation to use
*/
- public void setLog(Log log) {
+ public void setLog( Log log ) {
this.log = log;
}
1.5 +8 -10 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/SAXBeanWriter.java
Index: SAXBeanWriter.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/SAXBeanWriter.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SAXBeanWriter.java 8 Nov 2002 22:09:01 -0000 1.4
+++ SAXBeanWriter.java 15 Dec 2002 19:03:34 -0000 1.5
@@ -107,18 +107,16 @@
}
/**
- * <p> Get the current level for logging. </p>
- *
- * @return a <code>org.apache.commons.logging.Log</code> level constant
+ * <p> Set the log implementation used. </p>
*/
public Log getLog() {
return log;
}
/**
- * <p> Set the current logging level. </p>
+ * <p> Set the log implementation used. </p>
*
- * @param level a <code>org.apache.commons.logging.Log</code> level constant
+ * @param log <code>Log</code> implementation to use
*/
public void setLog(Log log) {
this.log = log;
1.6 +18 -1 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.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- TestBeanWriter.java 6 Nov 2002 21:40:25 -0000 1.5
+++ TestBeanWriter.java 15 Dec 2002 19:03:34 -0000 1.6
@@ -110,8 +110,20 @@
public void testLooping() throws Exception {
-
BeanWriter writer = new BeanWriter();
+
+ // logging for debugging jsut this method
+// SimpleLog log = new SimpleLog("[testLooping:BeanWriter]");
+// log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
+// writer.setLog(log);
+
+// log = new SimpleLog("[testLooping:AbstractBeanWriter]");
+// log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
+// writer.setAbstractBeanWriterLog(log);
+
+// log = new SimpleLog("[testLooping]");
+// log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
+
writer.enablePrettyPrint();
writer.write( LoopBean.createNoLoopExampleBean() );
writer.write( LoopBean.createLoopExampleBean() );
@@ -119,11 +131,16 @@
// test not writing IDs
writer.setWriteIDs(false);
+// log.info("Writing LoopBean.createNoLoopExampleBean...");
+
writer.write( LoopBean.createNoLoopExampleBean() );
+// log.info("Writing LoopBean.createIdOnlyLoopExampleBean...");
+
writer.write( LoopBean.createIdOnlyLoopExampleBean() );
try {
+// log.info("Writing LoopBean.createLoopExampleBean...");
writer.write( LoopBean.createLoopExampleBean() );
fail("CyclicReferenceException not thrown!");
1.4 +7 -7 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.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TestBeanToXml.java 30 Nov 2002 17:16:37 -0000 1.3
+++ TestBeanToXml.java 15 Dec 2002 19:03:34 -0000 1.4
@@ -107,10 +107,10 @@
public void testSimpleBean() throws Exception {
StringWriter out = new StringWriter();
out.write("<?xml version='1.0' encoding='UTF-8'?>");
- SimpleLog log = new SimpleLog("LOG");
- log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
+// SimpleLog log = new SimpleLog("LOG");
+// log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
BeanWriter writer = new BeanWriter(out);
- writer.getXMLIntrospector().setLog(log);
+// writer.getXMLIntrospector().setLog(log);
writer.setWriteIDs(false);
SimpleTestBean bean = new SimpleTestBean("alpha-value","beta-value","gamma-value");
1.2 +25 -5 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/recursion/Element.java
Index: Element.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/recursion/Element.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Element.java 30 Jul 2002 22:47:41 -0000 1.1
+++ Element.java 15 Dec 2002 19:03:34 -0000 1.2
@@ -63,6 +63,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Iterator;
/**
* This is just a simple element bean..
@@ -82,6 +83,13 @@
{
elements = new ArrayList();
}
+
+ public Element(String name)
+ {
+ this();
+ setName(name);
+ }
+
public void addElement(Element element)
{
elements.add(element);
@@ -104,7 +112,19 @@
public String toString()
{
- return getName()+"==>list : "+getElements();
+ StringBuffer buffer = new StringBuffer(getName() + "==>list: ");
+ Iterator it = getElements().iterator();
+ boolean first=true;
+ while (it.hasNext()) {
+ Element element = (Element) it.next();
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(",");
+ }
+ buffer.append(element.getName());
+ }
+ return buffer.toString();
}
1.5 +63 -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.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- TestRecursion.java 6 Nov 2002 18:31:26 -0000 1.4
+++ TestRecursion.java 15 Dec 2002 19:03:34 -0000 1.5
@@ -71,6 +71,7 @@
import org.apache.commons.betwixt.*;
import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
+import org.apache.commons.betwixt.io.CyclicReferenceException;
import org.apache.commons.betwixt.strategy.DecapitalizeNameMapper;
import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
import org.apache.commons.logging.impl.SimpleLog;
@@ -175,5 +176,62 @@
writer.setWriteIDs(true);
writer.write(bean);
}
+
+ /**
+ * Check that a cyclic reference exception is not thrown in this case
+ */
+ public void testCyclicReferenceStack1() throws Exception
+ {
+ Element alpha = new Element("Alpha");
+ Element beta = new Element("Beta");
+ Element gamma = new Element("Gamma");
+ Element epsilon = new Element("Epsilon");
+
+ alpha.addElement(beta);
+ beta.addElement(gamma);
+ gamma.addElement(epsilon);
+ alpha.addElement(epsilon);
+
+ StringWriter stringWriter = new StringWriter();
+ BeanWriter writer = new BeanWriter(stringWriter);
+ writer.setWriteIDs(false);
+ writer.write(alpha);
+ }
+
+ /**
+ * This should throw a cyclic reference
+ */
+ public void testCyclicReferenceStack2() throws Exception
+ {
+ Element alpha = new Element("Alpha");
+ Element beta = new Element("Beta");
+ Element gamma = new Element("Gamma");
+ Element epsilon = new Element("Epsilon");
+
+ alpha.addElement(beta);
+ beta.addElement(gamma);
+ gamma.addElement(epsilon);
+ epsilon.addElement(beta);
+
+ StringWriter stringWriter = new StringWriter();
+ BeanWriter writer = new BeanWriter(stringWriter);
+ writer.setWriteIDs(false);
+
+ //SimpleLog log = new SimpleLog("[testCyclicReferenceStack2:BeanWriter]");
+ //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
+ //writer.setLog(log);
+
+ //log = new SimpleLog("[testCyclicReferenceStack2:BeanWriter]");
+ //log.setLevel(SimpleLog.LOG_LEVEL_TRACE);
+ //writer.setAbstractBeanWriterLog(log);
+
+ try {
+ writer.write(alpha);
+ fail("Cycle was not detected!");
+
+ } catch (CyclicReferenceException e) {
+ // that's what we expected!
+ }
+ }
}
1.2 +10 -4 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.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XmlTestCase.java 7 Aug 2002 16:37:47 -0000 1.1
+++ XmlTestCase.java 15 Dec 2002 19:03:35 -0000 1.2
@@ -99,6 +99,12 @@
super(testName);
}
+ public void testXMLUnit() throws Exception {
+ xmlAssertIsomorphicContent(
+ parseFile("src/test/org/apache/commons/betwixt/xmlunit/rss-example.xml"),
+ parseFile("src/test/org/apache/commons/betwixt/xmlunit/rss-example.xml"));
+ }
+
public void xmlAssertIsomorphicContent(
org.w3c.dom.Document documentOne,
1.1 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/xmlunit/rss-example.xml
Index: rss-example.xml
===================================================================
<?xml version="1.0"?>
<!DOCTYPE rss PUBLIC
"-//Netscape Communications//DTD RSS 0.91//EN"
"http://my.netscape.com/publish/formats/rss-0.91.dtd">
<rss version="0.91">
<channel>
<title>MozillaZine</title>
<link>http://www.mozillazine.org</link>
<description>Your source for Mozilla news, advocacy,
interviews, builds, and more!</description>
<language>en-US</language>
<rating>(PICS-1.1 "http://www.rsac.org/ratingsv01.html"
2 gen true comment "RSACi North America Server"
for "http://www.rsac.org" on "1996.04.16T08:15-0500"
r (n 0 s 0 v 0 l 0))</rating>
<image>
<title>MozillaZine</title>
<url>http://www.mozillazine.org/image/mynetscape88.gif</url>
<link>http://www.mozillazine.org</link>
<width>88</width>
<height>31</height>
<description>Articles, discussions, builds, and more...</description>
</image>
<item>
<title>Java2 in Navigator 5?</title>
<link>http://www.mozillazine.org/talkback.html?article=607</link>
<description>Will Java2 be an integrated part of Navigator 5?
Read more about it in this discussion...</description>
</item>
<item>
<title>Communicator 4.61 Out</title>
<link>http://www.mozillazine.org/talkback.html?article=606</link>
<description>The latest version of Communicator is now
available. It includes security enhancements
and various bug fixes.</description>
</item>
<item>
<title>Mozilla Dispenses with Old,
Proprietary DOM</title>
<link>http://www.mozillazine.org/talkback.html?article=604</link>
</item>
<item>
<title>The Animation Contest is Now Closed</title>
<link>http://www.mozillazine.org/talkback.html?article=603</link>
</item>
<textinput>
<title>Send</title>
<description>Comments about MozillaZine?</description>
<name>responseText</name>
<link>http://www.mozillazine.org/cgi-bin/sampleonly.cgi</link>
</textinput>
<skipDays>
<day>Tuesday</day>
</skipDays>
</channel>
</rss>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>