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