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 BeanRuleSet.java
Date Fri, 11 Apr 2003 21:27:42 GMT
rdonkin     2003/04/11 14:27:42

  Modified:    betwixt/src/java/org/apache/commons/betwixt/digester
                        XMLIntrospectorHelper.java
               betwixt/src/java/org/apache/commons/betwixt/io
                        BeanRuleSet.java
  Added:       betwixt/src/java/org/apache/commons/betwixt/expression
                        MapEntryAdder.java
  Log:
  Added bean reader for maps. This allows the standard ooutput of a composite property which
is a map to be read back.
  
  Revision  Changes    Path
  1.20      +111 -43   jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLIntrospectorHelper.java
  
  Index: XMLIntrospectorHelper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/digester/XMLIntrospectorHelper.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- XMLIntrospectorHelper.java	8 Apr 2003 13:41:40 -0000	1.19
  +++ XMLIntrospectorHelper.java	11 Apr 2003 21:27:41 -0000	1.20
  @@ -74,6 +74,7 @@
   import org.apache.commons.betwixt.expression.IteratorExpression;
   import org.apache.commons.betwixt.expression.MethodExpression;
   import org.apache.commons.betwixt.expression.MethodUpdater;
  +import org.apache.commons.betwixt.expression.MapEntryAdder;
   import org.apache.commons.betwixt.strategy.PluralStemmer;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  @@ -193,6 +194,9 @@
               //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();
  @@ -441,57 +445,121 @@
                       // XXX: should we filter out non-void returning methods?
                       // some beans will return something as a helper
                       Class[] types = method.getParameterTypes();
  -                    if ( types != null && types.length == 1 ) {
  -                        String propertyName = Introspector.decapitalize( name.substring(3)
);
  +                    if ( types != null) {
                           if ( log.isTraceEnabled() ) {
  -                            log.trace( name + "->" + propertyName );
  -                        }
  -
  -                        // now lets try find the ElementDescriptor which displays
  -                        // a property which starts with propertyName
  -                        // and if so, we'll set a new Updater on it if there
  -                        // is not one already
  -                        ElementDescriptor descriptor = 
  -                            findGetCollectionDescriptor( 
  -                                                        introspector, 
  -                                                        rootDescriptor, 
  -                                                        propertyName );
  -
  -                        if ( log.isDebugEnabled() ) {
  -                            log.debug( "!! " + propertyName + " -> " + descriptor );
  -                            log.debug( "!! " + name + " -> " 
  -                             + (descriptor!=null?descriptor.getPropertyName():"") );
  +                            log.trace("Searching for match for " + method);
                           }
                           
  -                        if ( descriptor != null ) {
  -                            descriptor.setUpdater( new MethodUpdater( method ) );
  -                            descriptor.setSingularPropertyType( types[0] );
  -                            
  +                        if ( ( types.length == 1 ) || types.length == 2 ) {
  +                            String propertyName = Introspector.decapitalize( name.substring(3)
);
  +                            if ( log.isTraceEnabled() ) {
  +                                log.trace( name + "->" + propertyName );
  +                            }
  +    
  +                            // now lets try find the ElementDescriptor which displays
  +                            // a property which starts with propertyName
  +                            // and if so, we'll set a new Updater on it if there
  +                            // is not one already
  +                            ElementDescriptor descriptor = 
  +                                findGetCollectionDescriptor( 
  +                                                            introspector, 
  +                                                            rootDescriptor, 
  +                                                            propertyName );
  +    
                               if ( log.isDebugEnabled() ) {
  -                                log.debug( "!! " + method);
  -                                log.debug( "!! " + types[0]);
  +                                log.debug( "!! " + propertyName + " -> " + descriptor
);
  +                                log.debug( "!! " + name + " -> " 
  +                                + (descriptor!=null?descriptor.getPropertyName():"") );
                               }
  -                            
  -                            // is there a child element with no localName
  -                            ElementDescriptor[] children = descriptor.getElementDescriptors();
  -                            if ( children != null && children.length > 0 ) {
  -                                ElementDescriptor child = children[0];
  -                                String localName = child.getLocalName();
  -                                if ( localName == null || localName.length() == 0 ) {
  -                                    child.setLocalName( 
  -                                        introspector.getElementNameMapper()
  -                                            .mapTypeToElementName( propertyName ) );
  +                            if ( descriptor != null ) {
  +                                boolean isMapDescriptor 
  +                                    = Map.class.isAssignableFrom( descriptor.getPropertyType()
);
  +                                if ( !isMapDescriptor && types.length == 1 ) {
  +                                    // this may match a standard collection or iteration
  +                                    log.trace("Matching collection or iteration");
  +                                    
  +                                    descriptor.setUpdater( new MethodUpdater( method )
);
  +                                    descriptor.setSingularPropertyType( types[0] );
  +                                    
  +                                    if ( log.isDebugEnabled() ) {
  +                                        log.debug( "!! " + method);
  +                                        log.debug( "!! " + types[0]);
  +                                    }
  +                                    
  +                                    // is there a child element with no localName
  +                                    ElementDescriptor[] children 
  +                                        = descriptor.getElementDescriptors();
  +                                    if ( children != null && children.length >
0 ) {
  +                                        ElementDescriptor child = children[0];
  +                                        String localName = child.getLocalName();
  +                                        if ( localName == null || localName.length() ==
0 ) {
  +                                            child.setLocalName( 
  +                                                introspector.getElementNameMapper()
  +                                                    .mapTypeToElementName( propertyName
) );
  +                                        }
  +                                    }
  +
  +                                } else if ( isMapDescriptor && types.length ==
2 ) {
  +                                    // this may match a map
  +                                    log.trace("Matching map");
  +                                    ElementDescriptor[] children 
  +                                        = descriptor.getElementDescriptors();
  +                                    // see if the descriptor's been set up properly
  +                                    if ( children.length == 0 ) {
  +                                        
  +                                        log.info(
  +                                            "'entry' descriptor is missing for map. "
  +                                            + "Updaters cannot be set");
  +                                        
  +                                    } else {
  +                                        // loop through grandchildren 
  +                                        // adding updaters for key and value
  +                                        ElementDescriptor[] grandchildren
  +                                            = children[0].getElementDescriptors();
  +                                        MapEntryAdder adder = new MapEntryAdder(method);
  +                                        for ( 
  +                                            int n=0, 
  +                                                noOfGrandChildren = grandchildren.length;
  +                                            n < noOfGrandChildren;
  +                                            n++ ) {
  +                                            if ( "key".equals( 
  +                                                    grandchildren[n].getLocalName() ) )
{
  +                                            
  +                                                grandchildren[n].setUpdater( 
  +                                                                adder.getKeyUpdater() );
  +                                                grandchildren[n].setSingularPropertyType(

  +                                                                types[0] );
  +                                                if ( log.isTraceEnabled() ) {
  +                                                    log.trace(
  +                                                        "Key descriptor: " + grandchildren[n]);
  +                                                }                                     
         
  +                                                
  +                                            } else if ( 
  +                                                "value".equals( 
  +                                                    grandchildren[n].getLocalName() ) )
{
  +
  +                                                grandchildren[n].setUpdater( 
  +                                                                    adder.getValueUpdater()
);
  +                                                grandchildren[n].setSingularPropertyType(

  +                                                                    types[1] );
  +                                                if ( log.isTraceEnabled() ) {
  +                                                    log.trace(
  +                                                        "Value descriptor: " + grandchildren[n]);
  +                                                }
  +                                            }
  +                                        }
  +                                    }
  +                                }
  +                            } else {
  +                                if ( log.isDebugEnabled() ) {
  +                                    log.debug( 
  +                                        "Could not find an ElementDescriptor with property
name: " 
  +                                        + propertyName + " to attach the add method: "
+ method 
  +                                    );
                                   }
  -                            }
  -                        } else {
  -                            if ( log.isDebugEnabled() ) {
  -                                log.debug( 
  -                                    "Could not find an ElementDescriptor with property
name: " 
  -                                    + propertyName + " to attach the add method: " + method

  -                                );
                               }
                           }
  -                    }
  +                    } 
                   }
               }
           }
  
  
  
  1.1                  jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/expression/MapEntryAdder.java
  
  Index: MapEntryAdder.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/expression/MapEntryAdder.java,v
1.1 2003/04/11 21:27:42 rdonkin Exp $
   * $Revision: 1.1 $
   * $Date: 2003/04/11 21:27:42 $
   *
   * ====================================================================
   *
   * 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: MapEntryAdder.java,v 1.1 2003/04/11 21:27:42 rdonkin Exp $
   */
  package org.apache.commons.betwixt.expression;
  
  import java.lang.reflect.Method;
  
  import org.apache.commons.beanutils.ConvertUtils;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /** <p><code>MapEntryAdder</code> is used to add entries to a map.</p>
    *
    * <p>
    * <code>MapEntryAdder</code> supplies two updaters:
    * <ul>
    *   <li>{@link #getKeyUpdater()} which allows the entry key to be updated</li>
    *   <li>{@link #getValueUpdater()} which allows the entry value to be updated</li>
    * </ul>
    * When both of these updaters have been called, the entry adder method is called.
    * Once this has happened then the values can be updated again.
    * Note that only the <code>Context</code> passed by the last update will be
used.
    * </p>
    *
    * @author <a href="mailto:rdonkin@apache.org">Robert Burrell Donkin</a>
    * @version $Revision: 1.1 $
    */
  public class MapEntryAdder {
  
      
      // Class Attributes
      //-------------------------------------------------------------------------   
      
      /** Log used by this class */
      private static Log log = LogFactory.getLog( MapEntryAdder.class );
      
      
      // Class Methods
      //-------------------------------------------------------------------------      
      
      /** 
       * Sets the logger used by this class.
       *
       * @param newLog log to this
       */
      public static void setLog(Log newLog) {
          log = newLog;
      }
      
      // Attributes
      //-------------------------------------------------------------------------    
  
      /** The method to be called to add a new map entry */
      private Method adderMethod;
      
      /** Has the entry key been updated? */
      private boolean keyUpdated = false;
      /** The entry key */
      private Object key;
      
      /** Has the entry value been updated? */
      private boolean valueUpdated = false;
      /** The entry value */
      private Object value;
      
          
      // Constructors
      //-------------------------------------------------------------------------    
      
      /**
       * Construct a <code>MapEntryAdder</code> which adds entries to given method.
       *
       * @param method the <code>Method</code> called to add a key-value entry
       * @throws IllegalArgumentException if the given method does not take two parameters

       */
      public MapEntryAdder(Method method) {
          
          Class[] types = method.getParameterTypes();
          if ( types == null || types.length != 2) {
              throw new IllegalArgumentException(
                  "Method used to add entries to maps must have two parameter.");
          }
          this.adderMethod = method;
      }
      
      // Properties
      //-------------------------------------------------------------------------    
      
      /**
       * Gets the entry key <code>Updater</code>.
       * This is used to update the entry key value to the read value.
       * If {@link #getValueUpdater} has been called previously, 
       * then this trigger the updating of the adder method.
       *
       * @return the <code>Updater</code> which should be used to populate the
entry key
       */
      public Updater getKeyUpdater() {
          
          return new Updater() {
              public void update( Context context, Object keyValue ) {
                  // might as well make sure that his can only be set once
                  if ( !keyUpdated ) {
                      keyUpdated = true;
                      key = keyValue;
                      if ( log.isTraceEnabled() ) {
                          log.trace( "Setting entry key to " + key );
                          log.trace( "Current entry value is " + value );
                      }
                      if ( valueUpdated ) {
                          callAdderMethod( context );
                      }
                  }
              }
          };
      }
      
      /**
       * Gets the entry value <code>Updater</code>.
       * This is used to update the entry key value to the read value.
       * If {@link #getKeyUpdater} has been called previously, 
       * then this trigger the updating of the adder method.
       *
       * @return the <code>Updater</code> which should be used to populate the
entry value
       */
      public Updater getValueUpdater() {
          
          return new Updater() {
              public void update( Context context, Object valueValue ) {
                  // might as well make sure that his can only be set once
                  if ( !valueUpdated ) {
                      valueUpdated = true;
                      value = valueValue;
                      if ( log.isTraceEnabled() ) {
                          log.trace( "Setting entry value to " + value);
                          log.trace( "Current entry key is " + key );
                      }
                      if ( keyUpdated ) {
                          callAdderMethod( context );
                      }
                  }
              }
          };
      }
      
      
      
      // Implementation methods
      //-------------------------------------------------------------------------    
  
      /**
       * Call the adder method on the bean associated with the <code>Context</code>
       * with the key, value entry values stored previously.
       *
       * @param context the Context against whose bean the adder method will be invoked
       */
      private void callAdderMethod(Context context) {
          log.trace("Calling adder method");
          
          // this allows the same instance to be used multiple times.
          keyUpdated = false;
          valueUpdated = false;
          
          //
          // XXX This is (basically) cut and pasted from the MethodUpdater code
          // I haven't abstracted this code just yet since I think that adding
          // handling for non-beans will mean adding quite a lot more structure
          // and only once this is added will the proper position for this method 
          // become clear.
          //
          
          Class[] types = adderMethod.getParameterTypes();
          // key is first parameter
          Class keyType = types[0];
          // value is the second
          Class valueType = types[1];
          
          Object bean = context.getBean();
          if ( bean != null ) {
              if ( key instanceof String ) {
                  // try to convert into primitive types
                  key = ConvertUtils.convert( (String) key, keyType );
              }
              
              if ( value instanceof String ) {
                  // try to convert into primitive types
                  value = ConvertUtils.convert( (String) value, keyType );
              }
                   
              Object[] arguments = { key, value };
              try {
                  if ( log.isTraceEnabled() ) {
                      log.trace( 
                          "Calling adder method: " + adderMethod.getName() + " on bean: "
+ bean 
                          + " with key: " + key + " and value: " + value
                      );
                  }
                  adderMethod.invoke( bean, arguments );
                  
              } catch (Exception e) {
                  log.warn( 
                      "Cannot evaluate adder method: " + adderMethod.getName() + " on bean:
" + bean 
                      + " of type: " + bean.getClass().getName() + " with value: " + value

                      + " of type: " + valueType + " and key: " + key
                      + " of type: " + keyType 
                  );
                  log.debug(e);
              }
          }
      }
  }
  
  
  
  1.5       +15 -8     jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanRuleSet.java
  
  Index: BeanRuleSet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/betwixt/src/java/org/apache/commons/betwixt/io/BeanRuleSet.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- BeanRuleSet.java	20 Mar 2003 19:29:00 -0000	1.4
  +++ BeanRuleSet.java	11 Apr 2003 21:27:42 -0000	1.5
  @@ -284,7 +284,10 @@
                           continue;
                       }
                       if ( childDescriptor.getUpdater() != null ) {
  -                        if (log.isTraceEnabled()) {
  +                        if (
  +                            log.isTraceEnabled() 
  +                            && childDescriptor.getUpdater() instanceof MethodUpdater)
{
  +                            
                               log.trace("Element has updater "
                               + ((MethodUpdater) childDescriptor.getUpdater()).getMethod().getName());
                           }
  @@ -319,7 +322,9 @@
                               }
                           }
                       } else {
  -                        log.trace("Element does not have updater");
  +                        if ( log.isTraceEnabled() ) {
  +                            log.trace("Element does not have updater: " + childDescriptor);
  +                        }
                       }
       
                       ElementDescriptor[] grandChildren = childDescriptor.getElementDescriptors();
  @@ -328,6 +333,8 @@
                               log.trace("Adding grand children @path:" + path);
                           }
                           addChildRules( path + '/', childDescriptor, context );
  +                    } else if ( log.isTraceEnabled() ) {
  +                        log.trace( "No children for " + childDescriptor);
                       }
                   }
               }
  @@ -345,7 +352,7 @@
           */
           ElementDescriptor getElementDescriptor( ElementDescriptor propertyDescriptor )
{
               Class beanClass = propertyDescriptor.getSingularPropertyType();
  -            if ( beanClass != null ) {
  +            if ( beanClass != null && !Map.class.isAssignableFrom( beanClass )
) {
                   try {
                       XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
                       return xmlInfo.getElementDescriptor();
  
  
  

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


Mime
View raw message