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]