rdonkin 2003/03/19 14:59:02 Modified: betwixt/src/java/org/apache/commons/betwixt ElementDescriptor.java NodeDescriptor.java betwixt/src/java/org/apache/commons/betwixt/digester ElementRule.java XMLBeanInfoDigester.java betwixt/src/java/org/apache/commons/betwixt/io AbstractBeanWriter.java Added: betwixt/src/java/org/apache/commons/betwixt Descriptor.java TextDescriptor.java betwixt/src/java/org/apache/commons/betwixt/digester MappedPropertyRule.java TextRule.java Log: Added support for writing mixed content text. Added a new element called text to the betwixt file format. This allows a descriptor to be specifies which allows either static or property mapped mixed content text to be specified. Revision Changes Path 1.8 +95 -0 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/ElementDescriptor.java Index: ElementDescriptor.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/ElementDescriptor.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- ElementDescriptor.java 29 Jan 2003 18:55:09 -0000 1.7 +++ ElementDescriptor.java 19 Mar 2003 22:59:01 -0000 1.8 @@ -90,6 +90,12 @@ private ElementDescriptor[] elementDescriptors; /** + * Descriptors for child content + * Constructed lazily on demand from a List. + */ + private Descriptor[] contentDescriptors; + + /** * The List used on construction. It will be GC'd * after initilization and the array is lazily constructed */ @@ -100,6 +106,12 @@ * after initilization and the array is lazily constructed */ private List elementList; + + /** + * The list used o construct array. It will be GC'd after + * initialization when the array is lazily constructed. + */ + private List contentList; /** the expression used to evaluate the new context of this node * or null if the same context is to be used */ @@ -169,6 +181,16 @@ } /** + * Returns true if this element has child content. + * @return true if this element has either child mixed content or child elements + * @see #getContentDescriptors + */ + public boolean hasContent() { + return contentDescriptors != null && contentDescriptors.length > 0; + } + + + /** * Sets whether <code>Collection</code> bean properties should wrap items in a parent element. * In other words, should the mapping for bean properties which are <code>Collection</code>s * enclosed the item elements within a parent element. @@ -253,6 +275,7 @@ } getElementList().add( descriptor ); elementDescriptors = null; + addContentDescriptor( descriptor ); } /** @@ -277,12 +300,58 @@ /** * Sets the descriptors for the child element of the element this describes. + * Also sets the child content descriptors for this element + * * @param elementDescriptors the <code>ElementDescriptor</code>s of the element * that this describes */ public void setElementDescriptors(ElementDescriptor[] elementDescriptors) { this.elementDescriptors = elementDescriptors; this.elementList = null; + setContentDescriptors( elementDescriptors ); + } + + /** + * Adds a descriptor for child content. + * + * @param descriptor the <code>Descriptor</code> describing the child content to add + */ + public void addContentDescriptor(Descriptor descriptor) { + if ( contentList == null ) { + contentList = new ArrayList(); + } + getContentList().add( descriptor ); + contentDescriptors = null; + } + + /** + * Returns descriptors for the child content of the element this describes. + * @return the <code>Descriptor</code> describing the child elements + * of the element that this <code>ElementDescriptor</code> describes + */ + public Descriptor[] getContentDescriptors() { + if ( contentDescriptors == null ) { + if ( contentList == null ) { + contentDescriptors = new Descriptor[0]; + } else { + contentDescriptors = new Descriptor[ contentList.size() ]; + contentList.toArray( contentDescriptors ); + + // allow GC of List when initialized + contentList = null; + } + } + return contentDescriptors; + } + + /** + * Sets the descriptors for the child content of the element this describes. + * @param contentDescriptors the <code>Descriptor</code>s of the element + * that this describes + */ + public void setContentDescriptors(Descriptor[] contentDescriptors) { + this.contentDescriptors = contentDescriptors; + this.contentList = null; } /** @@ -370,6 +439,32 @@ } } return elementList; + } + + /** + * Lazily creates the mutable List of child content descriptors. + * This nullifies the contentDescriptors array so that + * as items are added to the list the Array is ignored until it is + * explicitly asked for. + * + * @return list of <code>Descriptor</code>'s describe the child content of + * the element that this <code>Descriptor</code> describes + */ + protected List getContentList() { + if ( contentList == null ) { + if ( contentDescriptors != null ) { + int size = contentDescriptors.length; + contentList = new ArrayList( size ); + for ( int i = 0; i < size; i++ ) { + contentList.add( contentDescriptors[i] ); + } + // force lazy recreation later + contentDescriptors = null; + } else { + contentList = new ArrayList(); + } + } + return contentList; } /** 1.6 +1 -107 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/NodeDescriptor.java Index: NodeDescriptor.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/NodeDescriptor.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- NodeDescriptor.java 13 Jan 2003 18:07:52 -0000 1.5 +++ NodeDescriptor.java 19 Mar 2003 22:59:01 -0000 1.6 @@ -73,7 +73,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> * @version $Revision$ */ -public class NodeDescriptor { +public class NodeDescriptor extends Descriptor { /** The local name of this node without any namespace prefix */ private String localName; @@ -81,17 +81,6 @@ private String qualifiedName; /** The namespace URI of this node */ private String uri = ""; - /** the expression used to evaluate the text value of this node */ - private Expression textExpression; - /** the updater used to update the current bean from the text value of this node */ - private Updater updater; - /** The property expression to which this node refers to, or null if it is just a constant */ - private String propertyName; - /** the property type associated with this node, if any */ - private Class propertyType; - /** the singular property type (i.e. the type ignoring the Collection or Array */ - private Class singularPropertyType; - /** Base constructor */ public NodeDescriptor() { @@ -179,99 +168,4 @@ } this.uri = uri; } - - /** - * Gets the expression used to evaluate the text value of this node - * for a particular <code>Context</code>. - * @return the expression used to evaluate the text value of this node - */ - public Expression getTextExpression() { - return textExpression; - } - - /** - * Sets the expression used to evaluate the text value of this node - * for a particular <code>Context</code> - * @param textExpression the Expression to be used to evaluate the value of this node - */ - public void setTextExpression(Expression textExpression) { - this.textExpression = textExpression; - } - - /** - * Gets the <code>Updater</code> used to update a <code>Context</code> from the text value - * corresponding to this node in an xml document - * @return the Update that should be used to update the value of this node - */ - public Updater getUpdater() { - return updater; - } - - /** - * Sets the <code>Updater</code> used to update a <code>Context</code> from the text value - * corresponding to this node in an xml document - * @param updater the Updater to be used to update the values of this node - */ - public void setUpdater(Updater updater) { - this.updater = updater; - } - - /** - * Gets the type of the bean property associated with this node, if any - * @return the property type associated with this node, if any - */ - public Class getPropertyType() { - return propertyType; - } - - /** - * Sets the type of the bean property associated with this node, if any - * @param propertyType the Class of the bean property - */ - public void setPropertyType(Class propertyType) { - this.propertyType = propertyType; - } - - - /** - * Gets the name of the bean property to which this node refers - * @return the name of the bean property to which this node refers to, - * or null if it is just a constant - */ - public String getPropertyName() { - return propertyName; - } - - /** - * Sets the name of the bean property to which this node refers - * @param propertyName the name of the bean property. - * Or null, if this node is not mapped to to a bean property - */ - public void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - /** - * Gets the underlying type ignoring any wrapping a Collection or Array. - * - * @return if this property is a 1-N relationship then this returns the type - * of a single property value. - */ - public Class getSingularPropertyType() { - if ( singularPropertyType == null ) { - return getPropertyType(); - } - return singularPropertyType; - } - - /** - * Sets the underlying type ignoring any wrapping Collection or Array. - * - * @param singularPropertyType the Class of the items in the Collection or Array. - * If node is associated with a collective bean property, then this should not be null. - */ - public void setSingularPropertyType(Class singularPropertyType) { - this.singularPropertyType = singularPropertyType; - } - } 1.1 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/Descriptor.java Index: Descriptor.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/Descriptor.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ * $Revision: 1.1 $ * $Date: 2003/03/19 22:59: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: Descriptor.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ */ package org.apache.commons.betwixt; import org.apache.commons.betwixt.expression.Expression; import org.apache.commons.betwixt.expression.Updater; /** <p>Describes a content node mapping.</p> * Common superclass for types of <code>Descriptor</code></p> * * @author Robert Burrell Donkin * @version $Revision: 1.1 $ */ public abstract class Descriptor { /** the expression used to evaluate the text value of this node */ private Expression textExpression; /** the updater used to update the current bean from the text value of this node */ private Updater updater; /** The property expression to which this node refers to, or null if it is just a constant */ private String propertyName; /** the property type associated with this node, if any */ private Class propertyType; /** the singular property type (i.e. the type ignoring the Collection or Array */ private Class singularPropertyType; /** Base constructor */ public Descriptor() { } /** * Gets the expression used to evaluate the text value of this node * for a particular <code>Context</code>. * @return the expression used to evaluate the text value of this node */ public Expression getTextExpression() { return textExpression; } /** * Sets the expression used to evaluate the text value of this node * for a particular <code>Context</code> * @param textExpression the Expression to be used to evaluate the value of this node */ public void setTextExpression(Expression textExpression) { this.textExpression = textExpression; } /** * Gets the <code>Updater</code> used to update a <code>Context</code> from the text value * corresponding to this node in an xml document * @return the Update that should be used to update the value of this node */ public Updater getUpdater() { return updater; } /** * Sets the <code>Updater</code> used to update a <code>Context</code> from the text value * corresponding to this node in an xml document * @param updater the Updater to be used to update the values of this node */ public void setUpdater(Updater updater) { this.updater = updater; } /** * Gets the type of the bean property associated with this node, if any * @return the property type associated with this node, if any */ public Class getPropertyType() { return propertyType; } /** * Sets the type of the bean property associated with this node, if any * @param propertyType the Class of the bean property */ public void setPropertyType(Class propertyType) { this.propertyType = propertyType; } /** * Gets the name of the bean property to which this node refers * @return the name of the bean property to which this node refers to, * or null if it is just a constant */ public String getPropertyName() { return propertyName; } /** * Sets the name of the bean property to which this node refers * @param propertyName the name of the bean property. * Or null, if this node is not mapped to to a bean property */ public void setPropertyName(String propertyName) { this.propertyName = propertyName; } /** * Gets the underlying type ignoring any wrapping a Collection or Array. * * @return if this property is a 1-N relationship then this returns the type * of a single property value. */ public Class getSingularPropertyType() { if ( singularPropertyType == null ) { return getPropertyType(); } return singularPropertyType; } /** * Sets the underlying type ignoring any wrapping Collection or Array. * * @param singularPropertyType the Class of the items in the Collection or Array. * If node is associated with a collective bean property, then this should not be null. */ public void setSingularPropertyType(Class singularPropertyType) { this.singularPropertyType = singularPropertyType; } } 1.1 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/TextDescriptor.java Index: TextDescriptor.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/TextDescriptor.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ * $Revision: 1.1 $ * $Date: 2003/03/19 22:59: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: TextDescriptor.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ */ package org.apache.commons.betwixt; /** <p>Describes mixed-content text. * A mixed content element contains elements mixed with text. * For example: * <pre> * <foo>middle<bar/></foo> * </pre> * In the above example, a <code>TextDescriptor</code> could be used * to allow the mixed content text <code>middle</code> to be mapped.</p> * * <p>This is really just a marker class - all functionality is inherited.</p> * * @author Robert Burrell Donkin * @version $Revision: 1.1 $ */ public class TextDescriptor extends Descriptor { /** Base constructor */ public TextDescriptor() { } } 1.9 +4 -85 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/ElementRule.java Index: ElementRule.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/ElementRule.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- ElementRule.java 18 Mar 2003 22:30:43 -0000 1.8 +++ ElementRule.java 19 Mar 2003 22:59:01 -0000 1.9 @@ -77,18 +77,15 @@ * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> * @version $Id$ */ -public class ElementRule extends RuleSupport { +public class ElementRule extends MappedPropertyRule { /** Logger */ private static final Log log = LogFactory.getLog( ElementRule.class ); - /** Classloader used to load classes by name */ - private ClassLoader classLoader; + /** Class for which the .bewixt file is being digested */ private Class beanClass; /** Base constructor */ - public ElementRule() { - this.classLoader = getClass().getClassLoader(); - } + public ElementRule() {} // Rule interface //------------------------------------------------------------------------- @@ -179,46 +176,6 @@ // Implementation methods //------------------------------------------------------------------------- - /** - * Gets the type of a property - * - * @param propertyClassName class name for property type (may be null) - * @param beanClass class that has property - * @param propertyName the name of the property whose type is to be determined - * @return property type - */ - protected Class getPropertyType( String propertyClassName, - Class beanClass, String propertyName ) { - // XXX: should use a ClassLoader to handle - // complex class loading situations - if ( propertyClassName != null ) { - try { - Class answer = classLoader.loadClass(propertyClassName); - if (answer != null) { - if (log.isTraceEnabled()) { - log.trace("Used specified type " + answer); - } - return answer; - } - } catch (Exception e) { - log.warn("Cannot load specified type", e); - } - } - - PropertyDescriptor descriptor = - getPropertyDescriptor( beanClass, propertyName ); - if ( descriptor != null ) { - return descriptor.getPropertyType(); - } - - if (log.isTraceEnabled()) { - log.trace("Cannot find property type."); - log.trace(" className=" + propertyClassName - + " base=" + beanClass + " name=" + propertyName); - } - return null; - } - /** * Set the Expression and Updater from a bean property name * @@ -236,43 +193,5 @@ getProcessedPropertyNameSet().add( name ); } } - } - - /** - * Returns the property descriptor for the class and property name. - * Note that some caching could be used to improve performance of - * this method. Or this method could be added to PropertyUtils. - * - * @param beanClass descriptor for property in this class - * @param propertyName descriptor for property with this name - * @return property descriptor for the named property in the given class - */ - protected PropertyDescriptor getPropertyDescriptor( Class beanClass, - String propertyName ) { - if ( beanClass != null && propertyName != null ) { - if (log.isTraceEnabled()) { - log.trace("Searching for property " + propertyName + " on " + beanClass); - } - try { - BeanInfo beanInfo = Introspector.getBeanInfo( beanClass ); - PropertyDescriptor[] descriptors = - beanInfo.getPropertyDescriptors(); - if ( descriptors != null ) { - for ( int i = 0, size = descriptors.length; i < size; i++ ) { - PropertyDescriptor descriptor = descriptors[i]; - if ( propertyName.equals( descriptor.getName() ) ) { - log.trace("Found matching method."); - return descriptor; - } - } - } - log.trace("No match found."); - return null; - } catch (Exception e) { - log.warn( "Caught introspection exception", e ); - } - } - return null; - } - + } } 1.4 +1 -0 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLBeanInfoDigester.java Index: XMLBeanInfoDigester.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLBeanInfoDigester.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- XMLBeanInfoDigester.java 7 Jan 2003 22:32:57 -0000 1.3 +++ XMLBeanInfoDigester.java 19 Mar 2003 22:59:01 -0000 1.4 @@ -204,6 +204,7 @@ addRule( "info", new InfoRule() ); addRule( "*/element", new ElementRule() ); + addRule( "*/text", new TextRule() ); addRule( "*/attribute", new AttributeRule() ); addRule( "*/hide", new HideRule() ); addRule( "*/addDefaults", new AddDefaultsRule() ); 1.1 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/MappedPropertyRule.java Index: MappedPropertyRule.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/MappedPropertyRule.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ * $Revision: 1.1 $ * $Date: 2003/03/19 22:59: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: MappedPropertyRule.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ */ package org.apache.commons.betwixt.digester; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.beans.BeanInfo; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** <p>Factors out common code used by Betwixt rules that access bean properties. * Maybe a lot of this should be moved into <code>BeanUtils</code>.</p> * * @author Robert Burrell Donkin * @version $Revision: 1.1 $ */ abstract public class MappedPropertyRule extends RuleSupport { /** Logger */ private static final Log log = LogFactory.getLog( MappedPropertyRule.class ); /** Classloader used to load classes by name */ private ClassLoader classLoader; /** Base constructor */ public MappedPropertyRule() { this.classLoader = getClass().getClassLoader(); } // Implementation methods //------------------------------------------------------------------------- /** * Returns the property descriptor for the class and property name. * Note that some caching could be used to improve performance of * this method. Or this method could be added to PropertyUtils. * * @param beanClass descriptor for property in this class * @param propertyName descriptor for property with this name * @return property descriptor for the named property in the given class */ protected PropertyDescriptor getPropertyDescriptor( Class beanClass, String propertyName ) { if ( beanClass != null && propertyName != null ) { if (log.isTraceEnabled()) { log.trace("Searching for property " + propertyName + " on " + beanClass); } try { BeanInfo beanInfo = Introspector.getBeanInfo( beanClass ); PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); if ( descriptors != null ) { for ( int i = 0, size = descriptors.length; i < size; i++ ) { PropertyDescriptor descriptor = descriptors[i]; if ( propertyName.equals( descriptor.getName() ) ) { log.trace("Found matching method."); return descriptor; } } } log.trace("No match found."); return null; } catch (Exception e) { log.warn( "Caught introspection exception", e ); } } return null; } /** * Gets the type of a property * * @param propertyClassName class name for property type (may be null) * @param beanClass class that has property * @param propertyName the name of the property whose type is to be determined * @return property type */ protected Class getPropertyType( String propertyClassName, Class beanClass, String propertyName ) { // XXX: should use a ClassLoader to handle // complex class loading situations if ( propertyClassName != null ) { try { Class answer = classLoader.loadClass(propertyClassName); if (answer != null) { if (log.isTraceEnabled()) { log.trace("Used specified type " + answer); } return answer; } } catch (Exception e) { log.warn("Cannot load specified type", e); } } PropertyDescriptor descriptor = getPropertyDescriptor( beanClass, propertyName ); if ( descriptor != null ) { return descriptor.getPropertyType(); } if (log.isTraceEnabled()) { log.trace("Cannot find property type."); log.trace(" className=" + propertyClassName + " base=" + beanClass + " name=" + propertyName); } return null; } } 1.1 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/TextRule.java Index: TextRule.java =================================================================== package org.apache.commons.betwixt.digester; /* * ==================================================================== * * 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/>. * */ import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import org.apache.commons.betwixt.expression.MethodExpression; import org.apache.commons.betwixt.expression.ConstantExpression; import org.apache.commons.betwixt.TextDescriptor; import org.apache.commons.betwixt.ElementDescriptor; import org.apache.commons.betwixt.XMLBeanInfo; import org.apache.commons.betwixt.XMLUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; /** * <p>Rule for parsing <text> elements. * These allow mixed content text to be specified. * A mixed content element example: * <pre> * <foo>text<bar/></foo> * </pre> * </p> * * @author Robert Burrell Donkin * @version $Id: TextRule.java,v 1.1 2003/03/19 22:59:01 rdonkin Exp $ */ public class TextRule extends MappedPropertyRule { /** Logger */ private static final Log log = LogFactory.getLog( TextRule.class ); /** Class for which the .bewixt file is being digested */ private Class beanClass; /** Base constructor */ public TextRule() {} // Rule interface //------------------------------------------------------------------------- /** * Process the beginning of this element. * * @param attributes The attribute list of this element * @throws SAXException 1. If this tag's parent is not an element tag. * 2. If this tag has a value attribute together with either a property * or type attribute. */ public void begin(Attributes attributes) throws SAXException { TextDescriptor descriptor = new TextDescriptor(); String value = attributes.getValue( "value" ); String propertyName = attributes.getValue( "property" ); String propertyType = attributes.getValue( "type" ); if ( value != null) { if ( propertyName != null || propertyType != null ) { // not allowed throw new SAXException("You cannot specify attribute 'value' together with either " + " the 'property' or 'type' attributes"); } // fixed value text descriptor.setTextExpression( new ConstantExpression( value ) ); } else { // property based text descriptor.setPropertyName( propertyName ); // set the property type using reflection descriptor.setPropertyType( getPropertyType( propertyType, beanClass, propertyName ) ); Class beanClass = getBeanClass(); if ( beanClass != null ) { String name = descriptor.getPropertyName(); PropertyDescriptor propertyDescriptor = getPropertyDescriptor( beanClass, name ); if ( propertyDescriptor != null ) { Method readMethod = propertyDescriptor.getReadMethod(); descriptor.setTextExpression( new MethodExpression( readMethod ) ); getProcessedPropertyNameSet().add( name ); } } } Object top = digester.peek(); if ( top instanceof XMLBeanInfo ) { XMLBeanInfo beanInfo = (XMLBeanInfo) top; ElementDescriptor elementDescriptor = beanInfo.getElementDescriptor(); if (elementDescriptor == null) { elementDescriptor.addContentDescriptor( descriptor ); } beanClass = beanInfo.getBeanClass(); } else if ( top instanceof ElementDescriptor ) { ElementDescriptor parent = (ElementDescriptor) top; parent.addContentDescriptor( descriptor ); } else { throw new SAXException( "Invalid use of <text>. It should " + "be nested <text> nodes" ); } } } 1.15 +49 -32 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.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- AbstractBeanWriter.java 27 Feb 2003 19:20:17 -0000 1.14 +++ AbstractBeanWriter.java 19 Mar 2003 22:59:02 -0000 1.15 @@ -68,6 +68,7 @@ import org.apache.commons.betwixt.AttributeDescriptor; import org.apache.commons.betwixt.ElementDescriptor; +import org.apache.commons.betwixt.Descriptor; import org.apache.commons.betwixt.XMLBeanInfo; import org.apache.commons.betwixt.XMLIntrospector; import org.apache.commons.betwixt.expression.Context; @@ -688,39 +689,55 @@ SAXException, IntrospectionException { - ElementDescriptor[] childDescriptors = elementDescriptor.getElementDescriptors(); + Descriptor[] childDescriptors = elementDescriptor.getContentDescriptors(); if ( childDescriptors != null && childDescriptors.length > 0 ) { // process child elements for ( int i = 0, size = childDescriptors.length; i < size; i++ ) { - ElementDescriptor childDescriptor = childDescriptors[i]; - Context childContext = context; - Expression childExpression = childDescriptor.getContextExpression(); - if ( childExpression != null ) { - Object childBean = childExpression.evaluate( context ); - if ( childBean != null ) { - String qualifiedName = childDescriptor.getQualifiedName(); - String namespaceUri = childDescriptor.getURI(); - String localName = childDescriptor.getLocalName(); - // XXXX: should we handle nulls better - if ( childBean instanceof Iterator ) { - for ( Iterator iter = (Iterator) childBean; iter.hasNext(); ) { - Object object = iter.next(); - if (object == null) { - continue; + if (childDescriptors[i] instanceof ElementDescriptor) { + // Element content + ElementDescriptor childDescriptor = (ElementDescriptor) childDescriptors[i]; + Context childContext = context; + Expression childExpression = childDescriptor.getContextExpression(); + if ( childExpression != null ) { + Object childBean = childExpression.evaluate( context ); + if ( childBean != null ) { + String qualifiedName = childDescriptor.getQualifiedName(); + String namespaceUri = childDescriptor.getURI(); + String localName = childDescriptor.getLocalName(); + // XXXX: should we handle nulls better + if ( childBean instanceof Iterator ) { + for ( Iterator iter = (Iterator) childBean; iter.hasNext(); ) { + Object object = iter.next(); + if (object == null) { + continue; + } + writeBean( namespaceUri, localName, qualifiedName, object ); } - writeBean( namespaceUri, localName, qualifiedName, object ); + } else { + writeBean( namespaceUri, localName, qualifiedName, childBean ); } - } else { - writeBean( namespaceUri, localName, qualifiedName, childBean ); - } - } + } + } else { + writeElement( + childDescriptor.getURI(), + childDescriptor.getLocalName(), + childDescriptor.getQualifiedName(), + childDescriptor, + childContext ); + } } else { - writeElement( - childDescriptor.getURI(), - childDescriptor.getLocalName(), - childDescriptor.getQualifiedName(), - childDescriptor, - childContext ); + // Mixed text content + // evaluate the body text + Expression expression = childDescriptors[i].getTextExpression(); + if ( expression != null ) { + Object value = expression.evaluate( context ); + if ( value != null ) { + String text = value.toString(); + if ( text != null && text.length() > 0 ) { + bodyText(text); + } + } + } } } } else {
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]