jstrachan 01/08/22 11:30:48 Modified: betwixt/src/java/org/apache/commons/betwixt ElementDescriptor.java NodeDescriptor.java XMLIntrospector.java betwixt/src/java/org/apache/commons/betwixt/expression Context.java betwixt/src/java/org/apache/commons/betwixt/io BeanWriter.java betwixt/src/test/org/apache/commons/betwixt CustomerBean.java TestBeanWriter.java TestXMLIntrospector.java Added: betwixt/src/test/org/apache/commons/betwixt AbstractTestCase.java AddressBean.java Log: Added support for simple pretty printing of XML together with simple bean navigation. Revision Changes Path 1.2 +18 -2 jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/ElementDescriptor.java Index: ElementDescriptor.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/ElementDescriptor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ElementDescriptor.java 2001/08/22 12:25:02 1.1 +++ ElementDescriptor.java 2001/08/22 18:30:48 1.2 @@ -5,21 +5,27 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: ElementDescriptor.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: ElementDescriptor.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; +import org.apache.commons.betwixt.expression.Expression; + /** <p><code>ElementDescriptor</code> describes the XML elements * to be created for a bean instance.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class ElementDescriptor extends NodeDescriptor { private AttributeDescriptor[] attributeDescriptors; private ElementDescriptor[] elementDescriptors; + /** the expression used to evaluate the new context of this node + * or null if the same context is to be used */ + private Expression contextExpression; + public ElementDescriptor() { } @@ -48,5 +54,15 @@ public void setElementDescriptors(ElementDescriptor[] elementDescriptors) { this.elementDescriptors = elementDescriptors; + } + + /** Returns the expression used to evaluate the new context of this element */ + public Expression getContextExpression() { + return contextExpression; + } + + /** Sets the expression used to evaluate the new context of this element */ + public void setContextExpression(Expression contextExpression) { + this.contextExpression = contextExpression; } } 1.2 +7 -7 jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/NodeDescriptor.java Index: NodeDescriptor.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/NodeDescriptor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- NodeDescriptor.java 2001/08/22 12:25:02 1.1 +++ NodeDescriptor.java 2001/08/22 18:30:48 1.2 @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: NodeDescriptor.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: NodeDescriptor.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; @@ -15,7 +15,7 @@ * to be created for a bean instance.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class NodeDescriptor { @@ -25,7 +25,7 @@ /** The namespace URI of this node */ private String uri; /** the expression used to evaluate the text value of this node */ - private Expression expression; + private Expression textExpression; public NodeDescriptor() { @@ -76,12 +76,12 @@ } /** Returns the expression used to evaluate the text value of this node */ - public Expression getExpression() { - return expression; + public Expression getTextExpression() { + return textExpression; } /** Sets the expression used to evaluate the text value of this node */ - public void setExpression(Expression expression) { - this.expression = expression; + public void setTextExpression(Expression textExpression) { + this.textExpression = textExpression; } } 1.2 +20 -11 jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/XMLIntrospector.java Index: XMLIntrospector.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/XMLIntrospector.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- XMLIntrospector.java 2001/08/22 12:25:02 1.1 +++ XMLIntrospector.java 2001/08/22 18:30:48 1.2 @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: XMLIntrospector.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: XMLIntrospector.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; @@ -27,7 +27,7 @@ /** <p><code>XMLIntrospector</code> an introspector of beans to create a XMLBeanInfo instance.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class XMLIntrospector { @@ -47,7 +47,7 @@ return introspect( info ); } - public XMLBeanInfo introspect(BeanInfo beanInfo) { + public XMLBeanInfo introspect(BeanInfo beanInfo) throws IntrospectionException { XMLBeanInfo answer = createXMLBeanInfo( beanInfo ); ArrayList elements = new ArrayList(); @@ -86,7 +86,7 @@ // Implementation methods //------------------------------------------------------------------------- - protected void addProperties(BeanInfo beanInfo, List elements, List attributes) { + protected void addProperties(BeanInfo beanInfo, List elements, List attributes) throws IntrospectionException { PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); if ( descriptors != null ) { for ( int i = 0, size = descriptors.length; i < size; i++ ) { @@ -95,20 +95,29 @@ } } - protected void addProperty(BeanInfo beanInfo, PropertyDescriptor propertyDescriptor, List elements, List attributes) { + protected void addProperty(BeanInfo beanInfo, PropertyDescriptor propertyDescriptor, List elements, List attributes) throws IntrospectionException { Class type = propertyDescriptor.getPropertyType(); NodeDescriptor nodeDescriptor = null; + Method readMethod = propertyDescriptor.getReadMethod(); + if ( readMethod == null ) { + return; + } if ( isPrimitiveType( type ) ) { - Method readMethod = propertyDescriptor.getReadMethod(); - if ( readMethod == null ) { - return; - } nodeDescriptor = new AttributeDescriptor(); - nodeDescriptor.setExpression( new MethodExpression( readMethod ) ); + nodeDescriptor.setTextExpression( new MethodExpression( readMethod ) ); attributes.add( nodeDescriptor ); } else { - nodeDescriptor = new ElementDescriptor(); + XMLBeanInfo childBeanInfo = introspect( type ); + ElementDescriptor childDescriptor = childBeanInfo.getElementDescriptor(); + + ElementDescriptor elementDescriptor = new ElementDescriptor(); + elementDescriptor.setElementDescriptors( childDescriptor.getElementDescriptors() ); + elementDescriptor.setAttributeDescriptors( childDescriptor.getAttributeDescriptors() ); + elementDescriptor.setContextExpression( new MethodExpression( readMethod ) ); + + nodeDescriptor = elementDescriptor; + elements.add( nodeDescriptor ); } nodeDescriptor.setLocalName( propertyDescriptor.getName() ); 1.2 +12 -2 jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/expression/Context.java Index: Context.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/expression/Context.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Context.java 2001/08/22 12:25:02 1.1 +++ Context.java 2001/08/22 18:30:48 1.2 @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: Context.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: Context.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt.expression; @@ -16,7 +16,7 @@ * bean expressions. This is mostly a bean together with a number of variables.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class Context { @@ -31,6 +31,16 @@ this.bean = bean; } + public Context(Object bean, Map variables) { + this.bean = bean; + this.variables = variables; + } + + /** Returns a new child context with the given bean */ + public Context newContext(Object newBean) { + return new Context(newBean, variables); + } + /** Returns the current bean */ public Object getBean() { 1.2 +83 -12 jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java Index: BeanWriter.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- BeanWriter.java 2001/08/22 12:25:02 1.1 +++ BeanWriter.java 2001/08/22 18:30:48 1.2 @@ -5,11 +5,12 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: BeanWriter.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: BeanWriter.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ 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; @@ -25,20 +26,30 @@ /** <p><code>BeanWriter</code> outputs a bean as XML.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class BeanWriter { + /** Introspector used */ private XMLIntrospector introspector = new XMLIntrospector(); - private Writer writer; + /** Where the output goes */ + private Writer writer; + /** text used for end of lines */ + private String endOfLine; + /** indentation text */ + private String indent; + /** indentation level */ + private int indentLevel; + /** should we flush after writing bean */ + private boolean autoFlush; - public BeanWriter() { this( System.out ); } public BeanWriter(OutputStream out) { - this.writer = new OutputStreamWriter( out ); + this.writer = new BufferedWriter( new OutputStreamWriter( out ) ); + this.autoFlush = true; } public BeanWriter(Writer writer) { @@ -55,7 +66,36 @@ write( elementDescriptor, context ); } } + if ( autoFlush ) { + writer.flush(); + } + } + + public void enablePrettyPrint() { + endOfLine = "\n"; + indent = " "; + } + + /** Returns the string used for end of lines */ + public String getEndOfLine() { + return endOfLine; + } + + /** Sets the string used for end of lines */ + public void setEndOfLine(String endOfLine) { + this.endOfLine = endOfLine; + } + + /** Returns the string used for indentation */ + public String getIndent() { + return indent; + } + + /** Sets the string used for end of lines */ + public void setIndent(String indent) { + this.indent = indent; } + // Implementation methods //------------------------------------------------------------------------- @@ -63,6 +103,7 @@ /** Writes the given element */ protected void write( ElementDescriptor elementDescriptor, Context context ) throws IOException { String qualifiedName = elementDescriptor.getQualifiedName(); + writeIndent(); writer.write( "<" ); writer.write( qualifiedName ); writeAttributes( elementDescriptor, context ); @@ -81,18 +122,34 @@ * * @return true if some content was written */ - protected boolean writeContent( ElementDescriptor elementDescriptor, Context context ) throws IOException { + protected boolean writeContent( ElementDescriptor elementDescriptor, Context context ) throws IOException { + boolean answer = false; ElementDescriptor[] childDescriptors = elementDescriptor.getElementDescriptors(); if ( childDescriptors != null && childDescriptors.length > 0 ) { writer.write( ">" ); + ++indentLevel; for ( int i = 0, size = childDescriptors.length; i < size; i++ ) { ElementDescriptor childDescriptor = childDescriptors[i]; - write( childDescriptor, context ); + Context childContext = context; + Expression childExpression = childDescriptor.getContextExpression(); + if ( childExpression != null ) { + Object childBean = childExpression.evaluate( context ); + if ( childBean == null ) { + // XXXX: should we handle nulls better + continue; + } + childContext = context.newContext( childBean ); + } + writePrintln(); + write( childDescriptor, childContext ); } - return true; + --indentLevel; + writePrintln(); + writeIndent(); + answer = true; } else { - Expression expression = elementDescriptor.getExpression(); + Expression expression = elementDescriptor.getTextExpression(); if ( expression != null ) { Object value = expression.evaluate( context ); if ( value != null ) { @@ -100,12 +157,12 @@ if ( text != null && text.length() > 0 ) { writer.write( ">" ); writer.write( text ); - return true; + answer = true; } } } } - return false; + return answer; } /** Writes the attribute declarations */ @@ -121,7 +178,7 @@ /** Writes an attribute declaration */ protected void writeAttribute( AttributeDescriptor attributeDescriptor, Context context ) throws IOException { - Expression expression = attributeDescriptor.getExpression(); + Expression expression = attributeDescriptor.getTextExpression(); if ( expression != null ) { Object value = expression.evaluate( context ); if ( value != null ) { @@ -134,6 +191,20 @@ writer.write( "\"" ); } } + } + } + + protected void writePrintln() throws IOException { + if ( endOfLine != null ) { + writer.write( endOfLine ); + } + } + + protected void writeIndent() throws IOException { + if ( indent != null ) { + for ( int i = 0; i < indentLevel; i++ ) { + writer.write( indent ); + } } } } 1.2 +38 -2 jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/CustomerBean.java Index: CustomerBean.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/CustomerBean.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- CustomerBean.java 2001/08/22 12:25:02 1.1 +++ CustomerBean.java 2001/08/22 18:30:48 1.2 @@ -5,22 +5,29 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: CustomerBean.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: CustomerBean.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; import java.io.Serializable; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import org.apache.commons.collections.IteratorEnumeration; + /** <p><code>CustomerBean</code> is a sample bean for use by the test cases.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class CustomerBean implements Serializable { private String id; private String name; private String email; + private AddressBean address; + private Map projectMap; public CustomerBean() { } @@ -37,6 +44,28 @@ return email; } + public AddressBean getAddress() { + return address; + } + + public Map getProjectMap() { + return projectMap; + } + + public Iterator getProjectNames() { + if ( projectMap == null ) { + return null; + } + return projectMap.keySet().iterator(); + } + + public Enumeration getProjectURLs() { + if ( projectMap == null ) { + return null; + } + return new IteratorEnumeration( projectMap.values().iterator() ); + } + public void setID(String id) { this.id = id; } @@ -49,4 +78,11 @@ this.email = email; } + public void setAddress(AddressBean address) { + this.address = address; + } + + public void setProjectMap(Map projectMap) { + this.projectMap = projectMap; + } } 1.2 +8 -11 jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/TestBeanWriter.java Index: TestBeanWriter.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/TestBeanWriter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TestBeanWriter.java 2001/08/22 12:25:02 1.1 +++ TestBeanWriter.java 2001/08/22 18:30:48 1.2 @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: TestBeanWriter.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: TestBeanWriter.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; @@ -19,9 +19,9 @@ /** Test harness for the BeanWriter * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ -public class TestBeanWriter extends TestCase { +public class TestBeanWriter extends AbstractTestCase { public static Test suite() { return new TestSuite(TestBeanWriter.class); @@ -42,14 +42,11 @@ String text = buffer.toString(); System.out.println( "Found: " + text ); - } - - protected Object createBean() { - CustomerBean bean = new CustomerBean(); - bean.setID( "1" ); - bean.setName( "James" ); - bean.setEmail( "[EMAIL PROTECTED]" ); - return bean; + System.out.println( "Now trying pretty print" ); + + writer = new BeanWriter(); + writer.enablePrettyPrint(); + writer.write( bean ); } } 1.2 +3 -11 jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/TestXMLIntrospector.java Index: TestXMLIntrospector.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/TestXMLIntrospector.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TestXMLIntrospector.java 2001/08/22 12:25:02 1.1 +++ TestXMLIntrospector.java 2001/08/22 18:30:48 1.2 @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * - * $Id: TestXMLIntrospector.java,v 1.1 2001/08/22 12:25:02 jstrachan Exp $ + * $Id: TestXMLIntrospector.java,v 1.2 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; @@ -17,9 +17,9 @@ /** Test harness for the XMLIntrospector * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ -public class TestXMLIntrospector extends TestCase { +public class TestXMLIntrospector extends AbstractTestCase { public static Test suite() { return new TestSuite(TestXMLIntrospector.class); @@ -45,14 +45,6 @@ AttributeDescriptor[] attributes = descriptor.getAttributeDescriptors(); assertTrue( "Found attributes", attributes != null && attributes.length > 0 ); - } - - protected Object createBean() { - CustomerBean bean = new CustomerBean(); - bean.setID( "1" ); - bean.setName( "James" ); - bean.setEmail( "[EMAIL PROTECTED]" ); - return bean; } } 1.1 jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/AbstractTestCase.java Index: AbstractTestCase.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * * $Id: AbstractTestCase.java,v 1.1 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; import junit.framework.*; import org.apache.commons.betwixt.io.BeanWriter; /** Abstract base class for test cases. * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> * @version $Revision: 1.1 $ */ public abstract class AbstractTestCase extends TestCase { public AbstractTestCase(String testName) { super(testName); } protected Object createBean() { CustomerBean bean = new CustomerBean(); bean.setID( "1" ); bean.setName( "James" ); bean.setEmail( "[EMAIL PROTECTED]" ); Map projects = new HashMap(); projects.put( "dom4j", "http://dom4j.org" ); projects.put( "jaxen", "http://jaxen.org" ); projects.put( "jakarta-commons", "http://jakarta.apache.org/commons/" ); projects.put( "jakarta-taglibs", "http://jakarta.apache.org/taglibs/" ); bean.setProjectMap( projects ); AddressBean address = new AddressBean(); address.setStreet( "Near the park" ); address.setCity( "London" ); address.setCountry( "UK" ); address.setCode( "N5" ); bean.setAddress( address ); return bean; } } 1.1 jakarta-commons-sandbox/betwixt/src/test/org/apache/commons/betwixt/AddressBean.java Index: AddressBean.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. * * $Id: AddressBean.java,v 1.1 2001/08/22 18:30:48 jstrachan Exp $ */ package org.apache.commons.betwixt; import java.io.Serializable; /** <p><code>CustomerBean</code> is a sample bean for use by the test cases.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> * @version $Revision: 1.1 $ */ public class AddressBean implements Serializable { private String street; private String city; private String code; private String country; public AddressBean() { } public String getStreet() { return street; } public String getCity() { return city; } public String getCode() { return code; } public String getCountry() { return country; } public void setStreet(String street) { this.street = street; } public void setCity(String city) { this.city = city; } public void setCode(String code) { this.code = code; } public void setCountry(String country) { this.country = country; } }