commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rdon...@apache.org
Subject cvs commit: jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io AbstractBeanWriter.java SAXBeanWriter.java BeanWriter.java
Date Thu, 18 Jul 2002 23:19:07 GMT
rdonkin     2002/07/18 16:19:07

  Modified:    betwixt/src/java/org/apache/commons/betwixt/io
                        BeanWriter.java
  Added:       betwixt/src/java/org/apache/commons/betwixt/io
                        AbstractBeanWriter.java SAXBeanWriter.java
  Log:
  This is highly experimental code. This commit is to allow martin to take it forward.
  
  Revision  Changes    Path
  1.8       +13 -397   jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java
  
  Index: BeanWriter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanWriter.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- BeanWriter.java	15 Jun 2002 23:24:32 -0000	1.7
  +++ BeanWriter.java	18 Jul 2002 23:19:07 -0000	1.8
  @@ -81,6 +81,7 @@
   import org.apache.commons.betwixt.expression.Expression;
   import org.apache.commons.betwixt.io.id.SequentialIDGenerator;
   
  +import org.xml.sax.SAXException;
   
   /** <p><code>BeanWriter</code> outputs beans as XML to an io stream.</p>
     *
  @@ -129,7 +130,7 @@
     * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
     * @version $Revision$
     */
  -public class BeanWriter {
  +public class BeanWriter extends AbstractBeanWriter {
   
       /** Escaped <code>&lt;</code> entity */
       private final static String LESS_THAN_ENTITY = "&lt;";
  @@ -142,8 +143,6 @@
       /** Escaped <code>"</code> entity */
       private final static String QUOTE_ENTITY = "&quot;";
   
  -    /** Introspector used */
  -    private XMLIntrospector introspector = new XMLIntrospector();
       /** Where the output goes */
       private Writer writer;    
       /** text used for end of lines. Defaults to <code>\n</code>*/
  @@ -152,18 +151,11 @@
       private String endOfLine = EOL;
       /** indentation text */
       private String indent;
  -    /** indentation level */
  -    private int indentLevel;
  +
       /** should we flush after writing bean */
       private boolean autoFlush;
       /** Log used for logging (Doh!) */
       private Log log = LogFactory.getLog( BeanWriter.class );
  -    /** Map containing ID attribute values for beans */
  -    private HashMap idMap = new HashMap();
  -    /** Used to generate ID attribute values*/
  -    private IDGenerator idGenerator = new SequentialIDGenerator();
  -    /** Should generated <code>ID</code> attribute values be added to the elements? */
  -    private boolean writeIDs = true;
       
       /**
        * <p> Constructor uses <code>System.out</code> for output.</p>
  @@ -191,136 +183,16 @@
           this.writer = writer;
       }
   
  -    /** 
  -     * <p> Writes the given bean to the current stream using the XML introspector.</p>
  -     * 
  -     * <p> This writes an xml fragment representing the bean to the current stream.</p>
  -     *
  -     * <p>This method will throw a <code>CyclicReferenceException</code> when a cycle
  -     * is encountered in the graph <strong>only</strong> if the <code>WriteIDs</code>
  -     * property is false.</p>
  -     *
  -     * @throws CyclicReferenceException when a cyclic reference is encountered 
  -     *
  -     * @param bean write out representation of this bean
  -     */
  -    public void write(Object bean) throws IOException, IntrospectionException  {
  -        log.debug( "Writing bean graph..." );
  -        log.debug( bean );
  -        
  -        write( null, bean );
  +    public void write(Object bean) throws IOException, SAXException, IntrospectionException  {
  +
  +        super.write(bean);
   
           if ( autoFlush ) {
               writer.flush();
           }
  -        
  -        log.debug( "Finished writing bean graph." );
       }
       
  -    /** 
  -     * <p>Writes the given bean to the current stream using the given <code>qualifiedName</code>.</p>
  -     *
  -     * <p>This method will throw a <code>CyclicReferenceException</code> when a cycle
  -     * is encountered in the graph <strong>only</strong> if the <code>WriteIDs</code>
  -     * property is false.</p>
  -     *
  -     * @throws CyclicReferenceException when a cyclic reference is encountered 
  -     */
  -    public void write(
  -                String qualifiedName, 
  -                Object bean) 
  -                    throws 
  -                        IOException, 
  -                        IntrospectionException {
  -                    
  -        
  -        if ( log.isTraceEnabled() ) {
  -            log.trace( "Writing bean graph (qualified name '" + qualifiedName + "'" );
  -        }
  -        
  -        // introspect to obtain bean info
  -        XMLBeanInfo beanInfo = introspector.introspect( bean );
  -        if ( beanInfo != null ) {
  -            ElementDescriptor elementDescriptor = beanInfo.getElementDescriptor();
  -            if ( elementDescriptor != null ) {
  -                Context context = new Context( bean, log );
  -                if ( qualifiedName == null ) {
  -                    qualifiedName = elementDescriptor.getQualifiedName();
  -                }
  -                
  -                Object ref = null;
  -                Object id = null;
  -                
  -                // only give id's to non-primatives
  -                if ( elementDescriptor.isPrimitiveType() ) {
  -                    // write without an id
  -                    write( 
  -                        qualifiedName, 
  -                        elementDescriptor, 
  -                        context );
  -                } 
  -                else {
  -                
  -                    ref = idMap.get( context.getBean() );
  -                    if ( ref == null ) {
  -                        // this is the first time that this bean has be written
  -                        AttributeDescriptor idAttribute = beanInfo.getIDAttribute();
  -                        if (idAttribute == null) {
  -                            // use a generated id
  -                            id = new Integer( idGenerator.nextId() );
  -                            idMap.put( bean, id);
  -                            
  -                            if ( writeIDs ) {
  -                                // write element with id
  -                                write( 
  -                                    qualifiedName, 
  -                                    elementDescriptor, 
  -                                    context , 
  -                                    beanInfo.getIDAttributeName(),
  -                                    id.toString());
  -                                    
  -                            } else {    
  -                                // write element without ID
  -                                write( 
  -                                    qualifiedName, 
  -                                    elementDescriptor, 
  -                                    context );
  -                            }
  -                                                        
  -                        } else {
  -                            // use id from bean property
  -                            // it's up to the user to ensure uniqueness
  -                            // XXX should we trap nulls?
  -                            id = idAttribute.getTextExpression().evaluate( context );
  -                            idMap.put( bean, id);
  -                            
  -                            // the ID attribute should be written automatically
  -                            write( 
  -                                qualifiedName, 
  -                                elementDescriptor, 
  -                                context );
  -                        }
  -                    } 
  -                    else {
  -                        // we have a cyclic reference
  -                        if ( !writeIDs ) {
  -                            // if we're not writing IDs, then throw exception
  -                            throw new CyclicReferenceException();
  -                        }
  -                        
  -                        // we've already written this bean so write an IDREF
  -                        writeIDREFElement( 
  -                                        qualifiedName,  
  -                                        beanInfo.getIDREFAttributeName(), 
  -                                        ref.toString());
  -                    }
  -                }
  -            }
  -        }
  -        
  -        log.trace( "Finished writing bean graph." );
  -    }
  -
  + 
       /**
        * <p> Switch on formatted output.
        * This sets the end of line and the indent.
  @@ -360,62 +232,6 @@
       public void setIndent(String indent) {
           this.indent = indent;
       }
  -    
  -    /** 
  -      * Get <code>IDGenerator</code> implementation used to generate <code>ID</code> attribute values .
  -      *
  -      * @return implementation used for <code>ID</code> attribute generation
  -      */
  -    public IDGenerator getIdGenerator() {
  -        return idGenerator;
  -    }
  -    
  -    /** 
  -      * Set <code>IDGenerator</code> implementation used to generate <code>ID</code> attribute values.
  -      * This property can be used to customize the algorithm used for generation.
  -      *
  -      * @param idGenerator use this implementation for <code>ID</code> attribute generation
  -      */
  -    public void setIdGenerator(IDGenerator idGenerator) {
  -        this.idGenerator = idGenerator;
  -    }
  -    
  -    /** Get whether generated <code>ID</code> attribute values should be added to the elements */
  -    public boolean getWriteIDs() {
  -        return writeIDs;
  -    }
  -
  -    /** 
  -     * Set whether generated <code>ID</code> attribute values should be added to the elements 
  -     * If this property is set to false, then <code>CyclicReferenceException</code> 
  -     * will be thrown whenever a cyclic occurs in the bean graph.
  -     */
  -    public void setWriteIDs(boolean writeIDs) {
  -        this.writeIDs = writeIDs;
  -    }
  -
  -    /**
  -     * <p> Get the introspector used. </p>
  -     *
  -     * <p> The {@link XMLBeanInfo} used to map each bean is created by the <code>XMLIntrospector</code>.
  -     * One way in which the mapping can be customized is by altering the <code>XMLIntrospector</code>. </p>
  -     */
  -    public XMLIntrospector getXMLIntrospector() {
  -        return introspector;
  -    }
  -    
  -
  -    /**
  -     * <p> Set the introspector to be used. </p>
  -     *
  -     * <p> The {@link XMLBeanInfo} used to map each bean is created by the <code>XMLIntrospector</code>.
  -     * One way in which the mapping can be customized is by altering the <code>XMLIntrospector</code>. </p>
  -     *
  -     * @param introspector use this introspector
  -     */
  -    public void  setXMLIntrospector(XMLIntrospector introspector) {
  -        this.introspector = introspector;
  -    }
   
       /**
        * <p> Get the current level for logging. </p>
  @@ -453,6 +269,10 @@
           writer.write( qualifiedName );
       }
       
  +    protected void expressTagClose() throws IOException {
  +        writer.write( '>' );
  +    }
  +    
       /** Express an element end tag using given qualifiedName */
       protected void expressElementEnd(String qualifiedName) throws IOException {
           if (qualifiedName == null) {
  @@ -478,7 +298,7 @@
               log.error( "[expressBodyText]Body text is null" );
               
           } else {
  -            writer.write( text );
  +            writer.write( escapeBodyValue(text) );
           }
       }
       
  @@ -503,218 +323,14 @@
           writer.write( ' ' );
           writer.write( qualifiedName );
           writer.write( "=\"" );
  -        writer.write( value );
  +        writer.write( escapeAttributeValue(value) );
           writer.write( '\"' );
       }
   
   
       // Implementation methods
       //-------------------------------------------------------------------------    
  -    
  -
  -    /** Writes the given element */
  -    protected void write( 
  -                            String qualifiedName, 
  -                            ElementDescriptor elementDescriptor, 
  -                            Context context ) 
  -                                throws 
  -                                    IOException, 
  -                                    IntrospectionException {
  -                                        
  -        if (elementDescriptor.isWrapCollectionsInElement()) {
  -            expressElementStart( qualifiedName );
  -        }
  -        
  -        writeRestOfElement( qualifiedName, elementDescriptor, context);
  -    }
  -    
  -    
  -
  -    /** Writes the given element adding an ID attribute */
  -    protected void write( 
  -                            String qualifiedName, 
  -                            ElementDescriptor elementDescriptor, 
  -                            Context context,
  -                            String idAttribute,
  -                            String idValue ) 
  -                                throws 
  -                                    IOException, 
  -                                    IntrospectionException {
  -                                  
  -        expressElementStart( qualifiedName );
  -             
  -        expressAttribute( idAttribute, idValue );        
  -        
  -        writeRestOfElement( qualifiedName, elementDescriptor, context );
  -    }
  -    
  -    /** Write attributes, child elements and element end */
  -    protected void writeRestOfElement( 
  -                            String qualifiedName, 
  -                            ElementDescriptor elementDescriptor, 
  -                            Context context ) 
  -                                throws 
  -                                    IOException, 
  -                                    IntrospectionException {
  -
  -        if (elementDescriptor.isWrapCollectionsInElement()) {
  -            writeAttributes( elementDescriptor, context );
  -        }
  -
  -        if ( writeContent( elementDescriptor, context ) ) {
  -            if (elementDescriptor.isWrapCollectionsInElement()) {
  -                expressElementEnd( qualifiedName );
  -            }
  -        }  
  -        else {
  -            if (elementDescriptor.isWrapCollectionsInElement()) {
  -                expressElementEnd();
  -            }
  -        }
  -    }
  -    
  -
  -    
  -    
  -    protected void writeIDREFElement( 
  -                                    String qualifiedName, 
  -                                    String idrefAttributeName,
  -                                    String idrefAttributeValue ) 
  -                                        throws 
  -                                            IOException, 
  -                                            IntrospectionException {
  -
  -        // write IDREF element
  -        expressElementStart( qualifiedName );
  -        
  -        expressAttribute( idrefAttributeName, idrefAttributeValue );
  -                             
  -        expressElementEnd();
  -    }
  -        
  -    /** Writes the element content.
  -     *
  -     * @return true if some content was written
  -     */
  -    protected boolean writeContent( 
  -                        ElementDescriptor elementDescriptor, 
  -                        Context context ) 
  -                            throws 
  -                                IOException, 
  -                                IntrospectionException {        
  -        ElementDescriptor[] childDescriptors = elementDescriptor.getElementDescriptors();
  -        boolean writtenContent = false;
  -        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();
  -                        // XXXX: should we handle nulls better
  -                        if ( childBean instanceof Iterator ) {
  -                            for ( Iterator iter = (Iterator) childBean; iter.hasNext(); ) {
  -                                if ( ! writtenContent ) {
  -                                    writtenContent = true;
  -                                    writer.write( '>' );
  -                                }
  -                                ++indentLevel;
  -                                write( qualifiedName, iter.next() );
  -                                --indentLevel;
  -                            }
  -                        }
  -                        else {
  -                            if ( ! writtenContent ) {
  -                                writtenContent = true;
  -                                writer.write( '>' );
  -                            }
  -                            ++indentLevel;
  -                            write( qualifiedName, childBean );
  -                            --indentLevel;
  -                        }
  -                    }                    
  -                }
  -                else {
  -                    if ( ! writtenContent ) {
  -                        writtenContent = true;
  -                        writer.write( '>' );
  -                    }
  -                    if (childDescriptor.isWrapCollectionsInElement()) {
  -                        ++indentLevel;
  -                    }
  -
  -                     write( childDescriptor.getQualifiedName(), childDescriptor, childContext );
  -
  -                    if (childDescriptor.isWrapCollectionsInElement()) {
  -                        --indentLevel;
  -                    }
  -                }
  -            }
  -            if ( writtenContent ) {
  -                writePrintln();
  -                writeIndent();
  -            }
  -        }
  -        else {
  -            // evaluate the body text 
  -            Expression expression = elementDescriptor.getTextExpression();
  -            if ( expression != null ) {
  -                Object value = expression.evaluate( context );
  -                if ( value != null ) {
  -                    String text = escapeBodyValue(value);
  -                    if ( text != null && text.length() > 0 ) {
  -                        if ( ! writtenContent ) {
  -                            writtenContent = true;
  -                            writer.write( '>' );
  -                        }
  -                        expressBodyText(text);
  -                    }
  -                }                
  -            }
  -        }
  -        return writtenContent;
  -    }
  -    
  -    /** Writes the attribute declarations */
  -    protected void writeAttributes( 
  -                    ElementDescriptor elementDescriptor, 
  -                    Context context ) 
  -                        throws 
  -                            IOException {
  -        if (!elementDescriptor.isWrapCollectionsInElement()) 
  -            return;
               
  -        AttributeDescriptor[] attributeDescriptors = elementDescriptor.getAttributeDescriptors();
  -        if ( attributeDescriptors != null ) {
  -            for ( int i = 0, size = attributeDescriptors.length; i < size; i++ ) {
  -                AttributeDescriptor attributeDescriptor = attributeDescriptors[i];
  -                writeAttribute( attributeDescriptor, context );
  -            }
  -        }
  -    }
  -
  -    
  -    /** Writes an attribute declaration */
  -    protected void writeAttribute( 
  -                        AttributeDescriptor attributeDescriptor, 
  -                        Context context ) 
  -                            throws 
  -                                IOException {
  -        Expression expression = attributeDescriptor.getTextExpression();
  -        if ( expression != null ) {
  -            Object value = expression.evaluate( context );
  -            if ( value != null ) {
  -                String text = escapeAttributeValue(value);
  -                if ( text != null && text.length() > 0 ) {
  -                    expressAttribute(attributeDescriptor.getQualifiedName(), text);
  -                }
  -            }                
  -        }
  -    }
  -    
       /** Writes out an empty line.
        * Uses current <code>endOfLine</code>.
        */
  
  
  
  1.1                  jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/AbstractBeanWriter.java
  
  Index: AbstractBeanWriter.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/AbstractBeanWriter.java,v 1.1 2002/07/18 23:19:07 rdonkin Exp $
   * $Revision: 1.1 $
   * $Date: 2002/07/18 23:19:07 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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: AbstractBeanWriter.java,v 1.1 2002/07/18 23:19:07 rdonkin Exp $
   */
  package org.apache.commons.betwixt.io;
  
  import java.beans.IntrospectionException;
  import java.io.BufferedWriter;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.Writer;
  import java.util.Iterator;
  import java.util.HashMap;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import org.apache.commons.betwixt.AttributeDescriptor;
  import org.apache.commons.betwixt.ElementDescriptor;
  import org.apache.commons.betwixt.XMLBeanInfo;
  import org.apache.commons.betwixt.XMLIntrospector;
  import org.apache.commons.betwixt.expression.Context;
  import org.apache.commons.betwixt.expression.Expression;
  import org.apache.commons.betwixt.io.id.SequentialIDGenerator;
  
  import org.xml.sax.SAXException;
  
  // FIX ME!!!
  // Logging logic!
  
  // FIX ME!!
  // Error handling strategy!
  // i'm going to add SAXExceptions everywhere since it's the easiest way to make things work quick
  // but this is a poor strategy
  
  /**
    * @author <a href="mailto:rdonkin@apache.org">Robert Burrell Donkin</a>
    * @version $Revision: 1.1 $
    */
  abstract public class AbstractBeanWriter {
  
      /** Introspector used */
      protected XMLIntrospector introspector = new XMLIntrospector();
  
      /** Log used for logging (Doh!) */
      private Log log = LogFactory.getLog( AbstractBeanWriter.class );
      /** Map containing ID attribute values for beans */
      protected HashMap idMap = new HashMap();
      /** Used to generate ID attribute values*/
      protected IDGenerator idGenerator = new SequentialIDGenerator();
      /** Should generated <code>ID</code> attribute values be added to the elements? */
      protected boolean writeIDs = true;
      
      /** indentation level */
      protected int indentLevel;
  
      /** 
       * <p> Writes the given bean to the current stream using the XML introspector.</p>
       * 
       * <p> This writes an xml fragment representing the bean to the current stream.</p>
       *
       * <p>This method will throw a <code>CyclicReferenceException</code> when a cycle
       * is encountered in the graph <strong>only</strong> if the <code>WriteIDs</code>
       * property is false.</p>
       *
       * @throws CyclicReferenceException when a cyclic reference is encountered 
       *
       * @param bean write out representation of this bean
       */
      public void write(Object bean) throws IOException, SAXException, IntrospectionException  {
          log.debug( "Writing bean graph..." );
          log.debug( bean );
          
          write( null, bean );
  
          log.debug( "Finished writing bean graph." );
      }
      
      /** 
       * <p>Writes the given bean to the current stream using the given <code>qualifiedName</code>.</p>
       *
       * <p>This method will throw a <code>CyclicReferenceException</code> when a cycle
       * is encountered in the graph <strong>only</strong> if the <code>WriteIDs</code>
       * property is false.</p>
       *
       * @throws CyclicReferenceException when a cyclic reference is encountered 
       */
      public void write(
                  String qualifiedName, 
                  Object bean) 
                      throws 
                          IOException, 
                          SAXException,
                          IntrospectionException {
                      
          
          if ( log.isTraceEnabled() ) {
              log.trace( "Writing bean graph (qualified name '" + qualifiedName + "'" );
          }
          
          // introspect to obtain bean info
          XMLBeanInfo beanInfo = introspector.introspect( bean );
          if ( beanInfo != null ) {
              ElementDescriptor elementDescriptor = beanInfo.getElementDescriptor();
              if ( elementDescriptor != null ) {
                  Context context = new Context( bean, log );
                  if ( qualifiedName == null ) {
                      qualifiedName = elementDescriptor.getQualifiedName();
                  }
                  
                  Object ref = null;
                  Object id = null;
                  
                  // only give id's to non-primatives
                  if ( elementDescriptor.isPrimitiveType() ) {
                      // write without an id
                      write( 
                          qualifiedName, 
                          elementDescriptor, 
                          context );
                  } 
                  else {
                  
                      ref = idMap.get( context.getBean() );
                      if ( ref == null ) {
                          // this is the first time that this bean has be written
                          AttributeDescriptor idAttribute = beanInfo.getIDAttribute();
                          if (idAttribute == null) {
                              // use a generated id
                              id = new Integer( idGenerator.nextId() );
                              idMap.put( bean, id);
                              
                              if ( writeIDs ) {
                                  // write element with id
                                  write( 
                                      qualifiedName, 
                                      elementDescriptor, 
                                      context , 
                                      beanInfo.getIDAttributeName(),
                                      id.toString());
                                      
                              } else {    
                                  // write element without ID
                                  write( 
                                      qualifiedName, 
                                      elementDescriptor, 
                                      context );
                              }
                                                          
                          } else {
                              // use id from bean property
                              // it's up to the user to ensure uniqueness
                              // XXX should we trap nulls?
                              id = idAttribute.getTextExpression().evaluate( context );
                              idMap.put( bean, id);
                              
                              // the ID attribute should be written automatically
                              write( 
                                  qualifiedName, 
                                  elementDescriptor, 
                                  context );
                          }
                      } 
                      else {
                          // we have a cyclic reference
                          if ( !writeIDs ) {
                              // if we're not writing IDs, then throw exception
                              throw new CyclicReferenceException();
                          }
                          
                          // we've already written this bean so write an IDREF
                          writeIDREFElement( 
                                          qualifiedName,  
                                          beanInfo.getIDREFAttributeName(), 
                                          ref.toString());
                      }
                  }
              }
          }
          
          log.trace( "Finished writing bean graph." );
      }
      
      /** 
        * Get <code>IDGenerator</code> implementation used to generate <code>ID</code> attribute values .
        *
        * @return implementation used for <code>ID</code> attribute generation
        */
      public IDGenerator getIdGenerator() {
          return idGenerator;
      }
      
      /** 
        * Set <code>IDGenerator</code> implementation used to generate <code>ID</code> attribute values.
        * This property can be used to customize the algorithm used for generation.
        *
        * @param idGenerator use this implementation for <code>ID</code> attribute generation
        */
      public void setIdGenerator(IDGenerator idGenerator) {
          this.idGenerator = idGenerator;
      }
      
      /** Get whether generated <code>ID</code> attribute values should be added to the elements */
      public boolean getWriteIDs() {
          return writeIDs;
      }
  
      /** 
       * Set whether generated <code>ID</code> attribute values should be added to the elements 
       * If this property is set to false, then <code>CyclicReferenceException</code> 
       * will be thrown whenever a cyclic occurs in the bean graph.
       */
      public void setWriteIDs(boolean writeIDs) {
          this.writeIDs = writeIDs;
      }
  
      /**
       * <p> Get the introspector used. </p>
       *
       * <p> The {@link XMLBeanInfo} used to map each bean is created by the <code>XMLIntrospector</code>.
       * One way in which the mapping can be customized is by altering the <code>XMLIntrospector</code>. </p>
       */
      public XMLIntrospector getXMLIntrospector() {
          return introspector;
      }
      
  
      /**
       * <p> Set the introspector to be used. </p>
       *
       * <p> The {@link XMLBeanInfo} used to map each bean is created by the <code>XMLIntrospector</code>.
       * One way in which the mapping can be customized is by altering the <code>XMLIntrospector</code>. </p>
       *
       * @param introspector use this introspector
       */
      public void  setXMLIntrospector(XMLIntrospector introspector) {
          this.introspector = introspector;
      }
  
      /**
       * <p> Get the current level for logging. </p>
       *
       * @return a <code>org.apache.commons.logging.Log</code> level constant
       */ 
      public Log getLog() {
          return log;
      }
  
      /**
       * <p> Set the current logging level. </p>
       *
       * @param level a <code>org.apache.commons.logging.Log</code> level constant
       */ 
      public void setLog(Log log) {
          this.log = log;
      }
      
          
      // Expression methods
      //-------------------------------------------------------------------------    
  
      /** Express an element tag start using given qualified name */
      abstract protected void expressElementStart(String qualifiedName) throws IOException, SAXException;
          
      abstract protected void expressTagClose() throws IOException, SAXException;
      
      /** Express an element end tag using given qualifiedName */
      abstract protected void expressElementEnd(String qualifiedName) throws IOException, SAXException;
      
      /** Express an empty element end */
      abstract protected void expressElementEnd() throws IOException, SAXException;
  
      /** Express body text */
      abstract protected void expressBodyText(String text) throws IOException, SAXException;
      
      /** Express an attribute */
      abstract protected void expressAttribute(
                                  String qualifiedName, 
                                  String value) 
                                      throws
                                          IOException, 
                                          SAXException;
  
  
      // Implementation methods
      //-------------------------------------------------------------------------    
      
  
      /** Writes the given element */
      protected void write( 
                              String qualifiedName, 
                              ElementDescriptor elementDescriptor, 
                              Context context ) 
                                  throws 
                                      IOException, 
                                      SAXException,
                                      IntrospectionException {
                                          
          if (elementDescriptor.isWrapCollectionsInElement()) {
              expressElementStart( qualifiedName );
          }
          
          writeRestOfElement( qualifiedName, elementDescriptor, context);
      }
      
      
  
      /** Writes the given element adding an ID attribute */
      protected void write( 
                              String qualifiedName, 
                              ElementDescriptor elementDescriptor, 
                              Context context,
                              String idAttribute,
                              String idValue ) 
                                  throws 
                                      IOException, 
                                      SAXException,
                                      IntrospectionException {
                                    
          expressElementStart( qualifiedName );
               
          expressAttribute( idAttribute, idValue );        
          
          writeRestOfElement( qualifiedName, elementDescriptor, context );
      }
      
      /** Write attributes, child elements and element end */
      protected void writeRestOfElement( 
                              String qualifiedName, 
                              ElementDescriptor elementDescriptor, 
                              Context context ) 
                                  throws 
                                      IOException, 
                                      SAXException,
                                      IntrospectionException {
  
          if (elementDescriptor.isWrapCollectionsInElement()) {
              writeAttributes( elementDescriptor, context );
          }
  
          if ( writeContent( elementDescriptor, context ) ) {
              if (elementDescriptor.isWrapCollectionsInElement()) {
                  expressElementEnd( qualifiedName );
              }
          }  
          else {
              if (elementDescriptor.isWrapCollectionsInElement()) {
                  expressElementEnd();
              }
          }
      }
      
  
      
      
      protected void writeIDREFElement( 
                                      String qualifiedName, 
                                      String idrefAttributeName,
                                      String idrefAttributeValue ) 
                                          throws 
                                              IOException, 
                                              SAXException,
                                              IntrospectionException {
  
          // write IDREF element
          expressElementStart( qualifiedName );
          
          expressAttribute( idrefAttributeName, idrefAttributeValue );
                               
          expressElementEnd();
      }
          
      /** Writes the element content.
       *
       * @return true if some content was written
       */
      protected boolean writeContent( 
                          ElementDescriptor elementDescriptor, 
                          Context context ) 
                              throws 
                                  IOException, 
                                  SAXException,
                                  IntrospectionException {        
          ElementDescriptor[] childDescriptors = elementDescriptor.getElementDescriptors();
          boolean writtenContent = false;
          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();
                          // XXXX: should we handle nulls better
                          if ( childBean instanceof Iterator ) {
                              for ( Iterator iter = (Iterator) childBean; iter.hasNext(); ) {
                                  if ( ! writtenContent ) {
                                      writtenContent = true;
                                      expressTagClose();
                                  }
                                  ++indentLevel;
                                  write( qualifiedName, iter.next() );
                                  --indentLevel;
                              }
                          }
                          else {
                              if ( ! writtenContent ) {
                                  writtenContent = true;
                                  expressTagClose();
                              }
                              ++indentLevel;
                              write( qualifiedName, childBean );
                              --indentLevel;
                          }
                      }                    
                  }
                  else {
                      if ( ! writtenContent ) {
                          writtenContent = true;
                          expressTagClose();
                      }
                      if (childDescriptor.isWrapCollectionsInElement()) {
                          ++indentLevel;
                      }
  
                       write( childDescriptor.getQualifiedName(), childDescriptor, childContext );
  
                      if (childDescriptor.isWrapCollectionsInElement()) {
                          --indentLevel;
                      }
                  }
              }
              if ( writtenContent ) {
                  writePrintln();
                  writeIndent();
              }
          }
          else {
              // evaluate the body text 
              Expression expression = elementDescriptor.getTextExpression();
              if ( expression != null ) {
                  Object value = expression.evaluate( context );
                  if ( value != null ) {
                      String text = value.toString();
                      if ( text != null && text.length() > 0 ) {
                          if ( ! writtenContent ) {
                              writtenContent = true;
                              expressTagClose();
                          }
                          expressBodyText(text);
                      }
                  }                
              }
          }
          return writtenContent;
      }
      
      /** Writes the attribute declarations */
      protected void writeAttributes( 
                      ElementDescriptor elementDescriptor, 
                      Context context ) 
                          throws 
                              IOException, SAXException {
          if (!elementDescriptor.isWrapCollectionsInElement()) 
              return;
              
          AttributeDescriptor[] attributeDescriptors = elementDescriptor.getAttributeDescriptors();
          if ( attributeDescriptors != null ) {
              for ( int i = 0, size = attributeDescriptors.length; i < size; i++ ) {
                  AttributeDescriptor attributeDescriptor = attributeDescriptors[i];
                  writeAttribute( attributeDescriptor, context );
              }
          }
      }
  
      
      /** Writes an attribute declaration */
      protected void writeAttribute( 
                          AttributeDescriptor attributeDescriptor, 
                          Context context ) 
                              throws 
                                  IOException, SAXException {
          Expression expression = attributeDescriptor.getTextExpression();
          if ( expression != null ) {
              Object value = expression.evaluate( context );
              if ( value != null ) {
                  String text = value.toString();
                  if ( text != null && text.length() > 0 ) {
                      expressAttribute(attributeDescriptor.getQualifiedName(), text);
                  }
              }                
          }
      }
  
      protected void writePrintln() throws IOException {}
      protected void writeIndent() throws IOException {}
  }
  
  
  
  1.1                  jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/SAXBeanWriter.java
  
  Index: SAXBeanWriter.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/SAXBeanWriter.java,v 1.1 2002/07/18 23:19:07 rdonkin Exp $
   * $Revision: 1.1 $
   * $Date: 2002/07/18 23:19:07 $
   *
   * ====================================================================
   *
   * 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 apache@apache.org.
   *
   * 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: SAXBeanWriter.java,v 1.1 2002/07/18 23:19:07 rdonkin Exp $
   */
  package org.apache.commons.betwixt.io;
  
  import java.beans.IntrospectionException;
  import java.io.BufferedWriter;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.Writer;
  import java.util.Iterator;
  import java.util.HashMap;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import org.apache.commons.betwixt.AttributeDescriptor;
  import org.apache.commons.betwixt.ElementDescriptor;
  import org.apache.commons.betwixt.XMLBeanInfo;
  import org.apache.commons.betwixt.XMLIntrospector;
  import org.apache.commons.betwixt.expression.Context;
  import org.apache.commons.betwixt.expression.Expression;
  import org.apache.commons.betwixt.io.id.SequentialIDGenerator;
  
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  // FIX ME
  // At the moment, namespaces are NOT supported!
  
  /**
    * 
    */
  public class SAXBeanWriter {
  
      /** Where the output goes */
      private ContentHandler contentHandler;    
      /** Log used for logging (Doh!) */
      private Log log = LogFactory.getLog( BeanWriter.class );
      
      private String lastElementName;
      
      private AttributesImpl attributes;
      
      private boolean elementWaiting = false;
      
      /**
       * <p> Constructor sets writer used for output.</p>
       *
       * @param writer write out representations to this writer
       */
      public SAXBeanWriter(ContentHandler contentHandler) {
          this.contentHandler = contentHandler;
      }
  
      /**
       * <p> Get the current level for logging. </p>
       *
       * @return a <code>org.apache.commons.logging.Log</code> level constant
       */ 
      public Log getLog() {
          return log;
      }
  
      /**
       * <p> Set the current logging level. </p>
       *
       * @param level a <code>org.apache.commons.logging.Log</code> level constant
       */ 
      public void setLog(Log log) {
          this.log = log;
      }
      
          
      // Expression methods
      //-------------------------------------------------------------------------    
      
      /** Express an element tag start using given qualified name */
      protected void expressElementStart(String qualifiedName) throws SAXException  {
          // make sure any previous elements have been sent
          sendElementStart();
          // ok prepare for new one
  	elementWaiting = true;
          attributes = new AttributesImpl();
          lastElementName = qualifiedName;
      }
      
      protected void expressTagClose() {
          // using this could probably make life easier
          // but i only know that i needed it after i'd written the rest
      }
      
      /** Express an element end tag using given qualifiedName */
      protected void expressElementEnd(String qualifiedName) throws SAXException  {
          // make sure that we sent the last element to be handled
          sendElementStart();
          // can't handle namespaces yet
          contentHandler.endElement("","",qualifiedName);
      }    
      
      /** Express an empty element end */
      protected void expressElementEnd() throws SAXException  {
          // last element name must be correct since there haven't been any tag in between
          contentHandler.endElement("","",lastElementName);
      }
  
      /** Express body text */
      protected void expressBodyText(String text) throws SAXException  {
          // FIX ME
          // CHECK UNICODE->CHAR CONVERSION!
          // THIS WILL QUITE POSSIBLY BREAK FOR NON-ROMAN
          char[] body = text.toCharArray();
          contentHandler.characters(body, 0, body.length);
      }
      
      /** Express an attribute */
      protected void expressAttribute(
                                  String qualifiedName, 
                                  String value) 
                                      throws
                                          SAXException  {
          // FIX ME
          // SHOULD PROBABLY SUPPORT ID IDREF HERE
          attributes.addAttribute("", "", qualifiedName, "CDATA", value);
      }
  
  
      // Implementation methods
      //-------------------------------------------------------------------------    
      
      private void sendElementStart() throws SAXException {
          if (elementWaiting) {
              contentHandler.startElement("","",lastElementName,attributes);
              elementWaiting = false;
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message