mvdb 2002/11/08 14:09:01
Modified: betwixt/src/java/org/apache/commons/betwixt/io
SAXBeanWriter.java
Added: betwixt/src/test/org/apache/commons/betwixt/io
SAXContentHandler.java TestSAXBeanWriter.java
Log:
The SAXBeanWriter was incorrectly creating xml content, esp. body text was
misplaced. Fixed this and added a SAXContentHanlder and TestSaxBeanWriter.
Many thanks go to Harald Dietrich (contact at hdietrich.net) for providing the test
cases and a use scenario.
I removed the dependency on XMLSerializer (for people using Crimson ;) and made
another ContentHandler to prove it is working.
(the code with XMLSerializer also works though). I also removed a failure taking
place on the #text node, since those nodes cannot be avoided (thnx jt..)
Revision Changes Path
1.4 +32 -35
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.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SAXBeanWriter.java 19 Jul 2002 00:54:55 -0000 1.3
+++ SAXBeanWriter.java 8 Nov 2002 22:09:01 -0000 1.4
@@ -61,26 +61,10 @@
*/
package org.apache.commons.betwixt.io;
-import java.beans.IntrospectionException;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Iterator;
-import java.util.HashMap;
+import java.util.Stack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
-import org.apache.commons.betwixt.AttributeDescriptor;
-import org.apache.commons.betwixt.ElementDescriptor;
-import org.apache.commons.betwixt.XMLBeanInfo;
-import org.apache.commons.betwixt.XMLIntrospector;
-import org.apache.commons.betwixt.expression.Context;
-import org.apache.commons.betwixt.expression.Expression;
-import org.apache.commons.betwixt.io.id.SequentialIDGenerator;
-
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -100,10 +84,15 @@
/** Where the output goes */
private ContentHandler contentHandler;
/** Log used for logging (Doh!) */
- private Log log = LogFactory.getLog( BeanWriter.class );
+ private Log log = LogFactory.getLog( SAXBeanWriter.class );
private String lastElementName;
+ /**
+ * Place holder for elements that are started.
+ */
+ private Stack elementStack;
+
private AttributesImpl attributes;
private boolean elementWaiting = false;
@@ -141,12 +130,15 @@
/** Express an element tag start using given qualified name */
protected void expressElementStart(String qualifiedName) throws SAXException {
- // make sure any previous elements have been sent
- sendElementStart();
- // ok prepare for new one
- elementWaiting = true;
+ if (elementStack == null) {
+ elementStack = new Stack();
+ }
+ if (elementWaiting) {
+ sendElementStart();
+ }
attributes = new AttributesImpl();
- lastElementName = qualifiedName;
+ elementStack.push(qualifiedName);
+ elementWaiting = true;
}
protected void expressTagClose() {
@@ -156,8 +148,10 @@
/** Express an element end tag using given qualifiedName */
protected void expressElementEnd(String qualifiedName) throws SAXException {
- // make sure that we sent the last element to be handled
- sendElementStart();
+ if (elementWaiting) {
+ elementWaiting = false;
+ sendElementStart();
+ }
// can't handle namespaces yet
contentHandler.endElement("","",qualifiedName);
}
@@ -165,7 +159,8 @@
/** Express an empty element end */
protected void expressElementEnd() throws SAXException {
// last element name must be correct since there haven't been any tag in
between
- contentHandler.endElement("","",lastElementName);
+ String lastElement = (String) elementStack.peek();
+ contentHandler.endElement("","",lastElement);
}
/** Express body text */
@@ -173,6 +168,10 @@
// FIX ME
// CHECK UNICODE->CHAR CONVERSION!
// THIS WILL QUITE POSSIBLY BREAK FOR NON-ROMAN
+ if (elementWaiting) {
+ elementWaiting = false;
+ sendElementStart();
+ }
char[] body = text.toCharArray();
contentHandler.characters(body, 0, body.length);
}
@@ -193,10 +192,8 @@
//-------------------------------------------------------------------------
private void sendElementStart() throws SAXException {
- if (elementWaiting) {
- contentHandler.startElement("","",lastElementName,attributes);
- elementWaiting = false;
- }
+ String lastElement = (String)elementStack.peek();
+ contentHandler.startElement("","",lastElement,attributes);
}
/**
* This will announce the start of the document
1.1
jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/io/SAXContentHandler.java
Index: SAXContentHandler.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/io/SAXContentHandler.java,v
1.1 2002/11/08 22:09:01 mvdb Exp $
* $Revision: 1.1 $
* $Date: 2002/11/08 22:09:01 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* $Id: SAXContentHandler.java,v 1.1 2002/11/08 22:09:01 mvdb Exp $
*/
package org.apache.commons.betwixt.io;
import java.io.IOException;
import java.io.Writer;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Simple SAXContentHandler to test the SAXBeanWriter
*
* @author <a href="mailto:martin@;mvdb.net">Martin van den Bemt</a>
* @version $Id: SAXContentHandler.java,v 1.1 2002/11/08 22:09:01 mvdb Exp $
*/
public class SAXContentHandler extends DefaultHandler {
private Writer out;
/**
* Constructor for SAXContentHandler.
*/
public SAXContentHandler(Writer out) {
this.out = out;
}
/**
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int length)
throws SAXException
{
try {
out.write(" "+new String(ch, start, length)+"\n");
}catch(IOException ioe) {
}
}
/**
* @see org.xml.sax.ContentHandler#endElement(String, String, String)
*/
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException
{
try {
out.write("</"+qName+">\n");
}catch (IOException e) {
}
}
/**
* @see org.xml.sax.ContentHandler#startDocument()
*/
public void startDocument() throws SAXException
{
try {
out.write("<?xml version=\"1.0\"?>\n");
}catch (IOException e){
}
}
/**
* @see org.xml.sax.ContentHandler#startElement(String, String, String,
Attributes)
*/
public void startElement(
String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException
{
try {
StringBuffer sb = new StringBuffer();
sb.append("<"+qName);
for (int i=0; i < atts.getLength();i++)
{
sb.append(" "+atts.getQName(i));
sb.append("=\"");
sb.append(atts.getValue(i));
sb.append("\"");
}
sb.append(">\n");
out.write(sb.toString());
} catch (IOException e) {
}
}
}
1.1
jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/io/TestSAXBeanWriter.java
Index: TestSAXBeanWriter.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/io/TestSAXBeanWriter.java,v
1.1 2002/11/08 22:09:01 mvdb Exp $
* $Revision: 1.1 $
* $Date: 2002/11/08 22:09:01 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* $Id: TestSAXBeanWriter.java,v 1.1 2002/11/08 22:09:01 mvdb Exp $
*/
package org.apache.commons.betwixt.io;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;
import org.apache.commons.betwixt.PersonBean;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* Test harness for SAXBeanWriter.
*
* @author <a href="mailto:contact@;hdietrich.net">Harald Dietrich</a>
* @author <a href="mailto:martin@;mvdb.net">Martin van den Bemt</a>
* @version $Id: TestSAXBeanWriter.java,v 1.1 2002/11/08 22:09:01 mvdb Exp $
*/
public class TestSAXBeanWriter extends TestCase {
public static final String XML = "<?xml version='1.0'?><PersonBean
id='1'><age>35</age><name>John Smith</name></PersonBean>";
public TestSAXBeanWriter(String name) {
super(name);
}
public void testWrite() throws Exception {
PersonBean bean = new PersonBean(35, "John Smith");
// writer bean into string
StringWriter out = new StringWriter();
SAXBeanWriter writer = new SAXBeanWriter(new SAXContentHandler(out));
writer.write(bean);
String beanString = out.getBuffer().toString();
// test the result
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
factory.setIgnoringElementContentWhitespace(true);
InputSource in = new InputSource();
StringReader reader = new StringReader(beanString);
in.setCharacterStream(reader);
Document doc = builder.parse(in);
this.assertNotNull("Document missing", doc);
Element root = doc.getDocumentElement();
this.assertNotNull("Document root missing", root);
this.assertEquals("Document root name wrong", "PersonBean",
root.getNodeName());
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equals("age")) {
this.assertNotNull("Person age missing", child.getFirstChild());
this.assertEquals("Person age wrong", "35",
child.getFirstChild().getNodeValue().trim());
} else if (child.getNodeName().equals("name")) {
this.assertNotNull("Person name missing", child.getFirstChild());
this.assertEquals("Person name wrong", "John Smith",
child.getFirstChild().getNodeValue().trim());
} else {
if (!child.getNodeName().equals("#text")) {
this.fail("Unknown attribute " + child.getNodeName());
}
}
}
}
public static Test suite() {
return new TestSuite(TestSAXBeanWriter.class);
}
public static void main(String[] args) {
TestRunner.run(suite());
}
}
--
To unsubscribe, e-mail: <mailto:commons-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@;jakarta.apache.org>