rdonkin 2003/07/13 14:28:36 Modified: betwixt/src/java/org/apache/commons/betwixt ElementDescriptor.java XMLIntrospector.java Log: Added support for simple reading of beans with mixed content. Patch submitted by Aslak Hellesoy. Revision Changes Path 1.11 +29 -5 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.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- ElementDescriptor.java 1 Jul 2003 19:10:45 -0000 1.10 +++ ElementDescriptor.java 13 Jul 2003 21:28:35 -0000 1.11 @@ -349,6 +349,30 @@ } return contentDescriptors; } + + /** + * <p>Gets the primary descriptor for body text of this element. + * Betwixt collects all body text for any element together. + * This makes it rounds tripping difficult for beans that write more than one + * mixed content property. + * </p><p> + * The algorithm used in the default implementation is that the first TextDescriptor + * found amongst the descriptors is returned. + * + * @return the primary descriptor or null if this element has no mixed body content + */ + public TextDescriptor getPrimaryBodyTextDescriptor() { + // todo: this probably isn't the most efficent algorithm + // but should avoid premature optimization + Descriptor[] descriptors = getContentDescriptors(); + for (int i=0, size=descriptors.length; i<size; i++) { + if (descriptors[i] instanceof TextDescriptor) { + return (TextDescriptor) descriptors[i]; + } + } + // if we haven't found anything, return null. + return null; + } /** * Sets the descriptors for the child content of the element this describes. 1.21 +212 -4 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/XMLIntrospector.java Index: XMLIntrospector.java =================================================================== RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/XMLIntrospector.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- XMLIntrospector.java 15 Apr 2003 21:51:44 -0000 1.20 +++ XMLIntrospector.java 13 Jul 2003 21:28:35 -0000 1.21 @@ -61,6 +61,7 @@ import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.List; @@ -71,6 +72,8 @@ import org.apache.commons.betwixt.expression.EmptyExpression; import org.apache.commons.betwixt.expression.IteratorExpression; import org.apache.commons.betwixt.expression.StringExpression; +import org.apache.commons.betwixt.expression.MethodExpression; +import org.apache.commons.betwixt.expression.MethodUpdater; import org.apache.commons.betwixt.registry.DefaultXMLBeanInfoRegistry; import org.apache.commons.betwixt.registry.XMLBeanInfoRegistry; import org.apache.commons.betwixt.strategy.DefaultNameMapper; @@ -292,7 +295,7 @@ Class beanClass = beanDescriptor.getBeanClass(); String name = beanDescriptor.getName(); // Array's contain a bad character - if (beanClass.isArray()) { + if (beanClass.isArray()) { // called all array's Array name = "Array"; } @@ -328,14 +331,15 @@ } else { List elements = new ArrayList(); List attributes = new ArrayList(); + List contents = new ArrayList(); - addProperties( beanInfo, elements, attributes ); + addProperties( beanInfo, elements, attributes, contents ); BeanInfo[] additionals = beanInfo.getAdditionalBeanInfo(); if ( additionals != null ) { for ( int i = 0, size = additionals.length; i < size; i++ ) { BeanInfo otherInfo = additionals[i]; - addProperties( otherInfo, elements, attributes ); + addProperties( otherInfo, elements, attributes, contents ); } } @@ -351,6 +355,14 @@ attributes.toArray( descriptors ); elementDescriptor.setAttributeDescriptors( descriptors ); } + size = contents.size(); + if ( size > 0 ) { + if ( size > 0 ) { + Descriptor[] descriptors = new Descriptor[size]; + contents.toArray( descriptors ); + elementDescriptor.setContentDescriptors( descriptors ); + } + } } answer.setElementDescriptor( elementDescriptor ); @@ -489,6 +501,132 @@ } + /** + * Create a XML descriptor from a bean one. + * Go through and work out whether it's a loop property, a primitive or a standard. + * The class property is ignored. + * + * @param propertyDescriptor create a <code>NodeDescriptor</code> for this property + * @param useAttributesForPrimitives write primitives as attributes (rather than elements) + * @return a correctly configured <code>NodeDescriptor</code> for the property + * @throws IntrospectionException when bean introspection fails + */ + public Descriptor createDescriptor( + PropertyDescriptor propertyDescriptor, + boolean useAttributesForPrimitives + ) throws IntrospectionException { + String name = propertyDescriptor.getName(); + Class type = propertyDescriptor.getPropertyType(); + + if (log.isTraceEnabled()) { + log.trace("Creating descriptor for property: name=" + + name + " type=" + type); + } + + Descriptor descriptor = null; + Method readMethod = propertyDescriptor.getReadMethod(); + Method writeMethod = propertyDescriptor.getWriteMethod(); + + if ( readMethod == null ) { + if (log.isTraceEnabled()) { + log.trace( "No read method for property: name=" + + name + " type=" + type); + } + return null; + } + + if ( log.isTraceEnabled() ) { + log.trace( "Read method=" + readMethod.getName() ); + } + + // choose response from property type + + // XXX: ignore class property ?? + if ( Class.class.equals( type ) && "class".equals( name ) ) { + log.trace( "Ignoring class property" ); + return null; + } + if ( isPrimitiveType( type ) ) { + if (log.isTraceEnabled()) { + log.trace( "Primitive type: " + name); + } + if ( useAttributesForPrimitives ) { + if (log.isTraceEnabled()) { + log.trace( "Adding property as attribute: " + name ); + } + descriptor = new AttributeDescriptor(); + } else { + if (log.isTraceEnabled()) { + log.trace( "Adding property as element: " + name ); + } + descriptor = new ElementDescriptor(true); + } + descriptor.setTextExpression( new MethodExpression( readMethod ) ); + if ( writeMethod != null ) { + descriptor.setUpdater( new MethodUpdater( writeMethod ) ); + } + } else if ( isLoopType( type ) ) { + if (log.isTraceEnabled()) { + log.trace("Loop type: " + name); + log.trace("Wrap in collections? " + isWrapCollectionsInElement()); + } + ElementDescriptor loopDescriptor = new ElementDescriptor(); + loopDescriptor.setContextExpression( + new IteratorExpression( new MethodExpression( readMethod ) ) + ); + loopDescriptor.setWrapCollectionsInElement( isWrapCollectionsInElement() ); + // XXX: need to support some kind of 'add' or handle arrays, Lists or indexed properties + //loopDescriptor.setUpdater( new MethodUpdater( writeMethod ) ); + if ( Map.class.isAssignableFrom( type ) ) { + loopDescriptor.setQualifiedName( "entry" ); + // add elements for reading + loopDescriptor.addElementDescriptor( new ElementDescriptor( "key" ) ); + loopDescriptor.addElementDescriptor( new ElementDescriptor( "value" ) ); + } + + ElementDescriptor elementDescriptor = new ElementDescriptor(); + elementDescriptor.setWrapCollectionsInElement( isWrapCollectionsInElement() ); + elementDescriptor.setElementDescriptors( new ElementDescriptor[] { loopDescriptor } ); + + descriptor = elementDescriptor; + } else { + if (log.isTraceEnabled()) { + log.trace( "Standard property: " + name); + } + ElementDescriptor elementDescriptor = new ElementDescriptor(); + elementDescriptor.setContextExpression( new MethodExpression( readMethod ) ); + if ( writeMethod != null ) { + elementDescriptor.setUpdater( new MethodUpdater( writeMethod ) ); + } + + descriptor = elementDescriptor; + } + + if (descriptor instanceof NodeDescriptor) { + NodeDescriptor nodeDescriptor = (NodeDescriptor) descriptor; + if (descriptor instanceof AttributeDescriptor) { + // we want to use the attributemapper only when it is an attribute.. + nodeDescriptor.setLocalName( + getAttributeNameMapper().mapTypeToElementName( name ) ); + } else { + nodeDescriptor.setLocalName( + getElementNameMapper().mapTypeToElementName( name ) ); + } + } + + descriptor.setPropertyName( propertyDescriptor.getName() ); + descriptor.setPropertyType( type ); + + // XXX: associate more bean information with the descriptor? + //nodeDescriptor.setDisplayName( propertyDescriptor.getDisplayName() ); + //nodeDescriptor.setShortDescription( propertyDescriptor.getShortDescription() ); + + if (log.isTraceEnabled()) { + log.trace("Created descriptor:"); + log.trace(descriptor); + } + return descriptor; + } @@ -566,7 +704,74 @@ * @param beanInfo the BeanInfo whose properties will be processed * @param elements ElementDescriptor list to which elements will be added * @param attributes AttributeDescriptor list to which attributes will be added + * @param contents Descriptor list to which mixed content will be added + * @throws IntrospectionException if the bean introspection fails + */ + protected void addProperties( + BeanInfo beanInfo, + List elements, + List attributes, + List contents) + throws + IntrospectionException { + PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); + if ( descriptors != null ) { + for ( int i = 0, size = descriptors.length; i < size; i++ ) { + addProperty(beanInfo, descriptors[i], elements, attributes, contents); + } + } + if (log.isTraceEnabled()) { + log.trace(elements); + log.trace(attributes); + log.trace(contents); + } + } + + /** + * Process a property. + * Go through and work out whether it's a loop property, a primitive or a standard. + * The class property is ignored. + * + * @param beanInfo the BeanInfo whose property is being processed + * @param propertyDescriptor the PropertyDescriptor to process + * @param elements ElementDescriptor list to which elements will be added + * @param attributes AttributeDescriptor list to which attributes will be added + * @param contents Descriptor list to which mixed content will be added + * @throws IntrospectionException if the bean introspection fails + */ + protected void addProperty( + BeanInfo beanInfo, + PropertyDescriptor propertyDescriptor, + List elements, + List attributes, + List contents) + throws + IntrospectionException { + Descriptor nodeDescriptor = XMLIntrospectorHelper + .createDescriptor(propertyDescriptor, + isAttributesForPrimitives(), + this); + if (nodeDescriptor == null) { + return; + } + if (nodeDescriptor instanceof ElementDescriptor) { + elements.add(nodeDescriptor); + } else if (nodeDescriptor instanceof AttributeDescriptor) { + attributes.add(nodeDescriptor); + } else { + contents.add(nodeDescriptor); + } + } + + /** + * Loop through properties and process each one + * + * @param beanInfo the BeanInfo whose properties will be processed + * @param elements ElementDescriptor list to which elements will be added + * @param attributes AttributeDescriptor list to which attributes will be added * @throws IntrospectionException if the bean introspection fails + * @deprecated this method does not support mixed content. + * Use [EMAIL PROTECTED] #addProperties(BeanInfo, List, List, List)} instead. */ protected void addProperties( BeanInfo beanInfo, @@ -596,6 +801,8 @@ * @param elements ElementDescriptor list to which elements will be added * @param attributes AttributeDescriptor list to which attributes will be added * @throws IntrospectionException if the bean introspection fails + * @deprecated this method does not support mixed content. + * Use [EMAIL PROTECTED] #addProperty(BeanInfo, PropertyDescriptor, List, List, List)} instead. */ protected void addProperty( BeanInfo beanInfo, @@ -617,6 +824,7 @@ attributes.add(nodeDescriptor); } } + /** * Factory method to create XMLBeanInfo instances
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]