donaldp     02/03/22 20:56:24

  Modified:    
proposal/myrmidon/src/java/org/apache/myrmidon/components/converter
                        DefaultMasterConverter.java
  Added:       proposal/myrmidon/src/java/org/apache/aut/converter
                        AbstractMasterConverter.java
  Removed:     
proposal/myrmidon/src/java/org/apache/myrmidon/components/converter
                        AbstractMasterConverter.java
  Log:
  Move AbstractMasterConverter from
  
  org.apache.myrmidon.components.converter
  
  to
  
  org.apache.aut.converter
  
  Revision  Changes    Path
  1.28      +2 -1      
jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/converter/DefaultMasterConverter.java
  
  Index: DefaultMasterConverter.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/converter/DefaultMasterConverter.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- DefaultMasterConverter.java       23 Mar 2002 04:54:21 -0000      1.27
  +++ DefaultMasterConverter.java       23 Mar 2002 04:56:24 -0000      1.28
  @@ -8,6 +8,7 @@
   package org.apache.myrmidon.components.converter;
   
   import org.apache.aut.converter.Converter;
  +import org.apache.aut.converter.AbstractMasterConverter;
   import org.apache.avalon.framework.service.ServiceException;
   import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.avalon.framework.service.Serviceable;
  @@ -19,7 +20,7 @@
    * Converter engine to handle converting between types.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
  - * @version $Revision: 1.27 $ $Date: 2002/03/23 04:54:21 $
  + * @version $Revision: 1.28 $ $Date: 2002/03/23 04:56:24 $
    */
   public class DefaultMasterConverter
       extends AbstractMasterConverter
  
  
  
  1.1                  
jakarta-ant/proposal/myrmidon/src/java/org/apache/aut/converter/AbstractMasterConverter.java
  
  Index: AbstractMasterConverter.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.aut.converter;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Map;
  import org.apache.aut.converter.Converter;
  import org.apache.aut.converter.ConverterException;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.myrmidon.components.converter.DefaultMasterConverter;
  
  /**
   * This is an abstract implementation of a <code>MasterConverter</code>.
   * A MasterConverter is capable of converting between many different
   * source and destination types. The <code>MasterConverter</code>
   * delegates to other converters that do the actual work.
   *
   * <p>To use this class you must subclass it, overide the
   * (@link #createConverter(String)) method and register some
   * converters using the (@link #registerConverter(String,String,String))
   * method.</p>
   *
   * <p>The reason this class deals with strings rather than Class objects
   * is because dealing with strings allows us to implement alternative
   * mechanisms for defining Converters in the future, only defining converter
   * when it is first used.</p>
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2002/03/23 04:56:24 $
   */
  public class AbstractMasterConverter
      implements Converter
  {
      private final static Resources REZ =
          ResourceManager.getPackageResources( DefaultMasterConverter.class );
  
      /**
       * Map from converter classname to instance of converter.
       */
      private final Map m_converters = new HashMap();
  
      /**
       * This holds the mapping between source/destination
       * and converter name.
       */
      private final HashMap m_mapping = new HashMap();
  
      /**
       * Convert object to destination type.
       *
       * @param destination the destination type
       * @param original the original object
       * @param context the context in which to convert
       * @return the converted object
       * @exception org.apache.aut.converter.ConverterException if an error 
occurs
       */
      public Object convert( final Class destination,
                             final Object original,
                             final Object context )
          throws ConverterException
      {
          final Class originalClass = original.getClass();
  
          if( destination.isAssignableFrom( originalClass ) )
          {
              return original;
          }
  
          try
          {
              // Search inheritance hierarchy for converter
              final String name = findConverter( originalClass, destination );
  
              // Create the converter
              Converter converter = (Converter)m_converters.get( name );
              if( converter == null )
              {
                  converter = createConverter( name );
                  m_converters.put( name, converter );
              }
  
              // Convert
              final Object object = converter.convert( destination, original, 
context );
              if( destination.isInstance( object ) )
              {
                  return object;
              }
  
              final String message =
                  REZ.getString( "bad-return-type.error",
                                 object.getClass().getName(),
                                 destination.getName() );
              throw new ConverterException( message );
          }
          catch( final Exception e )
          {
              final String message = REZ.getString( "convert.error",
                                                    originalClass.getName(),
                                                    destination.getName() );
              throw new ConverterException( message, e );
          }
      }
  
      /**
       * Register a converter
       *
       * @param classname the className of converter
       * @param source the source classname
       * @param destination the destination classname
       */
      protected void registerConverter( final String classname,
                                        final String source,
                                        final String destination )
      {
          HashMap map = (HashMap)m_mapping.get( source );
          if( null == map )
          {
              map = new HashMap();
              m_mapping.put( source, map );
          }
  
          map.put( destination, classname );
  
          //Remove instance of converter if it has already been created
          m_converters.remove( classname );
      }
  
      /**
       * Create an instance of converter with specified name.
       *
       * @param name the name of converter
       * @return the created converter instance
       * @throws java.lang.Exception if converter can not be created.
       */
      protected abstract Converter createConverter( final String name )
          throws Exception;
  
      /**
       * Determine the name of the converter to use to convert between
       * original and destination classes.
       */
      private String findConverter( final Class originalClass,
                                    final Class destination )
          throws ConverterException
      {
          //TODO: Maybe we should search the destination classes hierarchy as 
well
  
          // Recursively iterate over the super-types of the original class,
          // looking for a converter from source type -> destination type.
          // If more than one is found, choose the most specialised.
  
          Class match = null;
          String converterName = null;
          ArrayList queue = new ArrayList();
          queue.add( originalClass );
  
          while( !queue.isEmpty() )
          {
              Class clazz = (Class)queue.remove( 0 );
  
              // Add superclass and all interfaces
              if( clazz.getSuperclass() != null )
              {
                  queue.add( clazz.getSuperclass() );
              }
              final Class[] interfaces = clazz.getInterfaces();
              for( int i = 0; i < interfaces.length; i++ )
              {
                  queue.add( interfaces[ i ] );
              }
  
              // Check if we can convert from current class to destination
              final String name = getConverterClassname( clazz.getName(),
                                                         destination.getName() 
);
              if( name == null )
              {
                  continue;
              }
  
              // Choose the more specialised source class
              if( match == null || match.isAssignableFrom( clazz ) )
              {
                  match = clazz;
                  converterName = name;
              }
              else if( clazz.isAssignableFrom( clazz ) )
              {
                  continue;
              }
              else
              {
                  // Duplicate
                  final String message = REZ.getString( 
"ambiguous-converter.error" );
                  throw new ConverterException( message );
              }
          }
  
          // TODO - should cache the (src, dest) -> converter mapping
          if( match != null )
          {
              return converterName;
          }
  
          // Could not find a converter
          final String message = REZ.getString( "no-converter.error" );
          throw new ConverterException( message );
      }
  
      /**
       * Retrieve name of ConverterInfo that describes converter that converts
       * from source to destination.
       *
       * @param source the source classname
       * @param destination the destination classname
       * @return the className of converter or null if none available
       */
      private String getConverterClassname( final String source, final String 
destination )
      {
          final HashMap map = (HashMap)m_mapping.get( source );
          if( null == map )
          {
              return null;
          }
          return (String)map.get( destination );
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to