You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2004/08/24 23:00:50 UTC
cvs commit: jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/dotbetwixt SimpleTestBean.java
rdonkin 2004/08/24 14:00:50
Modified: betwixt/src/java/org/apache/commons/betwixt
XMLIntrospector.java
betwixt/src/java/org/apache/commons/betwixt/io
AbstractBeanWriter.java BeanReader.java
betwixt/src/test/org/apache/commons/betwixt/dotbetwixt
SimpleTestBean.java
Log:
Added support for custom dotbetwixt mappings.
Revision Changes Path
1.33 +58 -5 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.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- XMLIntrospector.java 6 Aug 2004 19:40:25 -0000 1.32
+++ XMLIntrospector.java 24 Aug 2004 21:00:50 -0000 1.33
@@ -21,6 +21,7 @@
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
@@ -49,6 +50,8 @@
import org.apache.commons.betwixt.strategy.TypeBindingStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
/**
* <p><code>XMLIntrospector</code> an introspector of beans to create a
@@ -437,6 +440,30 @@
return xmlInfo;
}
+
+
+ /**
+ * <p>Introspects the given <code>Class</code> using the dot betwixt
+ * document in the given <code>InputSource</code>.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> that the given mapping will <em>not</em>
+ * be registered by this method. Use {@link #register(Class, InputSource)}
+ * instead.
+ * </p>
+ * @param aClass <code>Class</code>, not null
+ * @param source <code>InputSource</code>, not null
+ * @return <code>XMLBeanInfo</code> describing the mapping.
+ * @throws SAXException when the input source cannot be parsed
+ * @throws IOException
+ */
+ public synchronized XMLBeanInfo introspect(Class aClass, InputSource source) throws IOException, SAXException {
+ // need to synchronize since we only use one instance and SAX is essentially one thread only
+ configureDigester(aClass);
+ XMLBeanInfo result = (XMLBeanInfo) digester.parse(source);
+ return result;
+ }
+
/** Create a standard <code>XMLBeanInfo</code> by introspection.
* The actual introspection depends only on the <code>BeanInfo</code>
@@ -501,6 +528,24 @@
}
/**
+ * <p>Registers the class mapping specified in the standard dot-betwixt file.
+ * Subsequent introspections will use this registered mapping for the class.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> that this method will override any existing mapping
+ * for this class.
+ * </p>
+ * @param aClass <code>Class</code>, not null
+ * @param source <code>InputSource</code>, not null
+ * @throws SAXException when the source cannot be parsed
+ * @throws IOException
+ */
+ public void register(Class aClass, InputSource source) throws IOException, SAXException {
+ XMLBeanInfo xmlBeanInfo = introspect(aClass, source);
+ getRegistry().put(aClass, xmlBeanInfo);
+ }
+
+ /**
* Populates the given <code>XMLBeanInfo</code> based on the given type of bean.
*
* @param xmlBeanInfo populate this, not null
@@ -941,11 +986,7 @@
}
// synchronized method so this digester is only used by
// one thread at once
- if ( digester == null ) {
- digester = new XMLBeanInfoDigester();
- digester.setXMLIntrospector( this );
- }
- digester.setBeanClass( aClass );
+ configureDigester(aClass);
return (XMLBeanInfo) digester.parse( urlText );
} catch (Exception e) {
getLog().warn( "Caught exception trying to parse: " + name, e );
@@ -958,6 +999,18 @@
return null;
}
+ /**
+ * Configures the single <code>Digester</code> instance used by this introspector.
+ * @param aClass <code>Class</code>, not null
+ */
+ private synchronized void configureDigester(Class aClass) {
+ if ( digester == null ) {
+ digester = new XMLBeanInfoDigester();
+ digester.setXMLIntrospector( this );
+ }
+ digester.setBeanClass( aClass );
+ }
+
/**
* Loop through properties and process each one
*
1.31 +62 -4 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.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- AbstractBeanWriter.java 23 Aug 2004 19:35:14 -0000 1.30
+++ AbstractBeanWriter.java 24 Aug 2004 21:00:50 -0000 1.31
@@ -36,6 +36,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -186,6 +187,33 @@
end();
}
+ /**
+ * <p>Writes the bean using the mapping specified in the <code>InputSource</code>.
+ * </p><p>
+ * <strong>Note:</strong> that the custom mapping will <em>not</em>
+ * be registered for later use. Please use {@link XMLIntrospector#register}
+ * to register the custom mapping for the class and then call
+ * {@link #write(Object)}.
+ * </p>
+ * @see #write(Object) since the standard notes also apply
+ * @param bean <code>Object</code> to be written as xml, not null
+ * @param mapping <code>InputSource/code> containing an xml document
+ * specifying the mapping to be used (in the usual way), not null
+ * @throws IOException
+ * @throws SAXException
+ * @throws IntrospectionException
+ */
+ public void write(Object bean, InputSource source)
+ throws IOException, SAXException, IntrospectionException {
+ writeBean(
+ null,
+ null,
+ null,
+ bean,
+ makeContext( bean ),
+ getXMLIntrospector().introspect(bean.getClass(), source));
+ }
+
/**
* <p>Writes the given bean to the current stream
* using the given <code>qualifiedName</code>.</p>
@@ -221,6 +249,38 @@
// introspect to obtain bean info
XMLBeanInfo beanInfo = introspector.introspect( bean );
+ writeBean(namespaceUri, localName, qualifiedName, bean, context, beanInfo);
+
+ log.trace( "Finished writing bean graph." );
+ }
+
+ /**
+ * <p>Writes the given bean to the current stream
+ * using the given mapping.</p>
+ *
+ * <p>This method will throw a <code>CyclicReferenceException</code> when a cycle
+ * is encountered in the graph <strong>only</strong> if the <code>getMapIDs()</code>
+ * setting of the <code>BindingConfiguration</code> is false.</p>
+ *
+ * @param namespaceUri the namespace uri, or null to use the automatic binding
+ * @param localName the local name or null to use the automatic binding
+ * @param qualifiedName the <code>String</code> naming the root element
+ * or null to use the automatic binding
+ * @param bean <code>Object</code> to be written, not null
+ * @param context <code>Context</code>, not null
+ * @param beanInfo <code>XMLBeanInfo</code>, not null
+ * @throws IOException
+ * @throws SAXException
+ * @throws IntrospectionException
+ */
+ private void writeBean(
+ String namespaceUri,
+ String localName,
+ String qualifiedName,
+ Object bean,
+ Context context,
+ XMLBeanInfo beanInfo)
+ throws IOException, SAXException, IntrospectionException {
if ( beanInfo != null ) {
ElementDescriptor elementDescriptor = beanInfo.getElementDescriptor();
if ( elementDescriptor != null ) {
@@ -329,10 +389,8 @@
}
}
}
-
- log.trace( "Finished writing bean graph." );
}
-
+
/**
* Get <code>IDGenerator</code> implementation used to
* generate <code>ID</code> attribute values .
1.23 +65 -20 jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanReader.java
Index: BeanReader.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanReader.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- BeanReader.java 4 Jul 2004 16:58:17 -0000 1.22
+++ BeanReader.java 24 Aug 2004 21:00:50 -0000 1.23
@@ -16,6 +16,7 @@
package org.apache.commons.betwixt.io;
import java.beans.IntrospectionException;
+import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@@ -32,6 +33,8 @@
import org.apache.commons.digester.RuleSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/** <p><code>BeanReader</code> reads a tree of beans from an XML document.</p>
@@ -115,20 +118,7 @@
*/
public void registerBeanClass(Class beanClass) throws IntrospectionException {
if ( ! registeredClasses.contains( beanClass ) ) {
- if ( log.isTraceEnabled() ) {
- log.trace( "Registering class " + beanClass );
- }
- registeredClasses.add( beanClass );
-
- // introspect and find the ElementDescriptor to use as the root
- XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
- ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();
-
- String path = elementDescriptor.getQualifiedName();
- if (log.isTraceEnabled()) {
- log.trace("Added path: " + path + ", mapped to: " + beanClass.getName());
- }
- addBeanCreateRule( path, elementDescriptor, beanClass );
+ register(beanClass, null);
} else {
if ( log.isWarnEnabled() ) {
@@ -137,6 +127,32 @@
}
}
+ /**
+ * Registers the given class at the given path.
+ * @param beanClass <code>Class</code> for binding
+ * @param path the path at which the bean class should be registered
+ * or null if the automatic path is to be used
+ * @throws IntrospectionException
+ */
+ private void register(Class beanClass, String path) throws IntrospectionException {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "Registering class " + beanClass );
+ }
+ XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
+ registeredClasses.add( beanClass );
+
+ ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();
+
+ if (path == null) {
+ path = elementDescriptor.getQualifiedName();
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace("Added path: " + path + ", mapped to: " + beanClass.getName());
+ }
+ addBeanCreateRule( path, elementDescriptor, beanClass );
+ }
+
/**
* <p>Registers a bean class
* and add mapping rules for this bean class at the given path expression.</p>
@@ -165,13 +181,42 @@
*/
public void registerBeanClass(String path, Class beanClass) throws IntrospectionException {
if ( ! registeredClasses.contains( beanClass ) ) {
- registeredClasses.add( beanClass );
- // introspect and find the ElementDescriptor to use as the root
- XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
- ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();
-
- addBeanCreateRule( path, elementDescriptor, beanClass );
+ register(beanClass, path);
+
+ } else {
+ if ( log.isWarnEnabled() ) {
+ log.warn("Cannot add class " + beanClass.getName() + " since it already exists");
+ }
+ }
+ }
+
+
+ /**
+ * <p>Registers a class with a custom mapping.
+ * This mapping is specified by the standard dot betwixt document
+ * contained in the given <code>InputSource</code>.
+ * </p><p>
+ * <strong>Note:</strong> the custom mapping will be registered with
+ * the introspector. This must remain so for the reading to work correctly
+ * It is recommended that use of the pre-registeration process provided
+ * by {@link XMLIntrospector#register} be considered as an alternative to this method.
+ * </p>
+ * @see {@link #registerBeanClass(Class)} since the general notes given there
+ * apply equally to this
+ * @param mapping <code>InputSource</code> giving the dot betwixt document specifying
+ * the mapping
+ * @param beanClass <code>Class</code> that should be register
+ * @throws IntrospectionException
+ * @throws SAXException
+ * @throws IOException
+ */
+ public void registerBeanClass(InputSource mapping, Class beanClass) throws IntrospectionException, IOException, SAXException {
+ if ( ! registeredClasses.contains( beanClass ) ) {
+
+ introspector.register( beanClass, mapping );
+ register(beanClass, null);
+
} else {
if ( log.isWarnEnabled() ) {
log.warn("Cannot add class " + beanClass.getName() + " since it already exists");
1.5 +3 -0 jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/dotbetwixt/SimpleTestBean.java
Index: SimpleTestBean.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/dotbetwixt/SimpleTestBean.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SimpleTestBean.java 28 Feb 2004 13:38:35 -0000 1.4
+++ SimpleTestBean.java 24 Aug 2004 21:00:50 -0000 1.5
@@ -29,6 +29,9 @@
private String gamma;
//-------------------------- Constructors
+
+ public SimpleTestBean() {}
+
public SimpleTestBean(String alpha, String beta, String gamma) {
setAlpha(alpha);
setBeta(beta);
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org