donaldp 02/03/22 20:54:21
Modified:
proposal/myrmidon/src/java/org/apache/myrmidon/components/converter
DefaultMasterConverter.java
Added:
proposal/myrmidon/src/java/org/apache/myrmidon/components/converter
AbstractMasterConverter.java
Log:
Separate and document the myrmidon agnostic part of MasterConverter into an
abstract class. This will make it easier to reuse in other projects.
Revision Changes Path
1.27 +6 -177
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.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- DefaultMasterConverter.java 23 Mar 2002 04:38:09 -0000 1.26
+++ DefaultMasterConverter.java 23 Mar 2002 04:54:21 -0000 1.27
@@ -7,46 +7,27 @@
*/
package org.apache.myrmidon.components.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.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
+import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;
-import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
/**
* Converter engine to handle converting between types.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
- * @version $Revision: 1.26 $ $Date: 2002/03/23 04:38:09 $
+ * @version $Revision: 1.27 $ $Date: 2002/03/23 04:54:21 $
*/
public class DefaultMasterConverter
- implements Converter, ConverterRegistry, Serviceable
+ extends AbstractMasterConverter
+ implements ConverterRegistry, Serviceable
{
- private final static Resources REZ =
- ResourceManager.getPackageResources( DefaultMasterConverter.class );
-
private TypeManager m_typeManager;
/**
- * 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();
-
- /**
* Retrieve relevent services needed to deploy.
*
* @param serviceManager the ServiceManager
@@ -69,70 +50,7 @@
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 );
- }
-
- /**
- * 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 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 );
- }
+ super.registerConverter( className, source, destination );
}
/**
@@ -142,99 +60,10 @@
* @return the created converter instance
* @throws Exception if converter can not be created.
*/
- private Converter createConverter( final String name )
+ protected Converter createConverter( final String name )
throws Exception
{
final TypeFactory factory = m_typeManager.getFactory( Converter.ROLE
);
return (Converter)factory.create( name );
- }
-
- /**
- * 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 );
}
}
1.1
jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/components/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.myrmidon.components.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;
/**
* 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:54:21 $
*/
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 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 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]>