diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java
index a3775f8f6..f5f71b9e3 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java
@@ -28,6 +28,8 @@ import org.apache.myrmidon.interfaces.converter.MasterConverter;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;
+import org.apache.myrmidon.interfaces.role.RoleManager;
+import org.apache.myrmidon.framework.DataType;
/**
* Class used to configure tasks.
@@ -48,6 +50,9 @@ public class DefaultConfigurer
//TypeManager to use to create types in typed adders
private TypeManager m_typeManager;
+ //RoleManager to use to map from type names -> role shorthand
+ private RoleManager m_roleManager;
+
///Cached object configurers. This is a map from Class to the
///ObjectConfigurer for that class.
private Map m_configurerCache = new HashMap();
@@ -57,6 +62,7 @@ public class DefaultConfigurer
{
m_converter = (MasterConverter)componentManager.lookup( MasterConverter.ROLE );
m_typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE );
+ m_roleManager = (RoleManager)componentManager.lookup( RoleManager.ROLE );
}
/**
@@ -122,7 +128,6 @@ public class DefaultConfigurer
}
catch( final ConfigurationException ce )
{
- ce.fillInStackTrace();
throw ce;
}
catch( final CascadingException ce )
@@ -151,7 +156,6 @@ public class DefaultConfigurer
}
catch( final ConfigurationException ce )
{
- ce.fillInStackTrace();
throw ce;
}
catch( final CascadingException ce )
@@ -180,13 +184,12 @@ public class DefaultConfigurer
}
catch( final ConfigurationException ce )
{
- ce.fillInStackTrace();
throw ce;
}
catch( final CascadingException ce )
{
final String message =
- REZ.getString( "bad-set-element.error", name );
+ REZ.getString( "bad-set-element.error", elemName, name );
throw new ConfigurationException( message, ce );
}
}
@@ -269,8 +272,8 @@ public class DefaultConfigurer
final String name = element.getName();
// Locate the configurer for the child element
- final PropertyConfigurer childConfigurer =
- state.getConfigurer().getProperty( name );
+ final PropertyConfigurer childConfigurer
+ = getConfigurerFromName( state.getConfigurer(), name, true );
// Create & configure the child element
final Object child =
@@ -288,9 +291,6 @@ public class DefaultConfigurer
final Context context )
throws CascadingException
{
- // Adjust the name
- final String elementName = element.getName();
- final String name = elementName.substring( 0, elementName.length() - 4 );
// Extract the id
final String id = element.getAttribute( "id" );
@@ -302,6 +302,7 @@ public class DefaultConfigurer
}
// Set the property
+ final String name = element.getName();
setReference( state, name, id, context );
}
@@ -309,13 +310,17 @@ public class DefaultConfigurer
* Sets a property using a reference.
*/
private void setReference( final ConfigurationState state,
- final String name,
+ final String refName,
final String unresolvedId,
final Context context )
throws CascadingException
{
- // Locate the configurer for the child element
- final PropertyConfigurer childConfigurer = state.getConfigurer().getProperty( name );
+ // Adjust the name
+ final String name = refName.substring( 0, refName.length() - 4 );
+
+ // Locate the configurer for the property
+ final PropertyConfigurer childConfigurer
+ = getConfigurerFromName( state.getConfigurer(), name, false );
// Resolve any props in the id
Object id = PropertyUtil.resolveProperty( unresolvedId, context, false );
@@ -356,14 +361,13 @@ public class DefaultConfigurer
if( name.toLowerCase().endsWith( "-ref" ) )
{
// A reference
- final String refName = name.substring( 0, name.length() - 4 );
- setReference( state, refName, value, context );
+ setReference( state, name, value, context );
}
else
{
// Set the value
- final PropertyConfigurer propConfigurer =
- state.getConfigurer().getProperty( name );
+ PropertyConfigurer propConfigurer
+ = getConfigurerFromName( state.getConfigurer(), name, false );
setValue( propConfigurer, state, value, context );
}
}
@@ -424,7 +428,7 @@ public class DefaultConfigurer
}
else if( null == child )
{
- // Create an instance using the default constructor
+ // Create an instance
if( type.isInterface() )
{
child = createdTypedObject( name, type );
@@ -439,18 +443,62 @@ public class DefaultConfigurer
return child;
}
+ /**
+ * Determines the property configurer to use for a particular element
+ * or attribute. If the supplied name matches a property of the
+ * class being configured, that property configurer is returned. If
+ * the supplied name matches the role shorthand for the class' typed
+ * property, then the typed property configurer is used.
+ *
+ * @param configurer The configurer for the class being configured.
+ * @param name The attribute/element name.
+ */
+ private PropertyConfigurer getConfigurerFromName( final ObjectConfigurer configurer,
+ final String name,
+ boolean ignoreRoleName )
+ throws NoSuchPropertyException
+ {
+ // Try a named property
+ final NoSuchPropertyException exc;
+ try
+ {
+ return configurer.getProperty( name );
+ }
+ catch( NoSuchPropertyException e )
+ {
+ // Keep for later
+ exc = e;
+ }
+
+ // Try a typed property
+ final PropertyConfigurer propertyConfigurer = configurer.getTypedProperty();
+ if( ! ignoreRoleName )
+ {
+ final String roleShorthand = m_roleManager.getNameForRole( propertyConfigurer.getType().getName() );
+ if( ! name.equalsIgnoreCase(roleShorthand) )
+ {
+ // Rethrow the original exception
+ throw exc;
+ }
+ }
+
+ return propertyConfigurer;
+ }
+
/**
* Utility method to create an instance of the
- * specified type that satisfied supplied interface.
+ * specified type that satisfies supplied interface.
*/
private Object createdTypedObject( final String name,
final Class type )
throws ConfigurationException
{
- final TypeFactory factory = getTypeFactory( type );
+ // Attempt to create the object
+ final Object obj;
try
{
- return factory.create( name );
+ final TypeFactory factory = getTypeFactory( DataType.class );
+ obj = factory.create( name );
}
catch( final Exception e )
{
@@ -460,6 +508,16 @@ public class DefaultConfigurer
type.getName() );
throw new ConfigurationException( message, e );
}
+
+ // Check the types
+ if( ! type.isInstance( obj ) )
+ {
+ final String message =
+ REZ.getString( "mismatched-typed-object.error", name, type.getName() );
+ throw new ConfigurationException( message );
+ }
+
+ return obj;
}
/**
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java
index 00d836eb4..fe4ab3ddc 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java
@@ -46,6 +46,11 @@ class DefaultObjectConfigurer
*/
private final List m_allProps = new ArrayList();
+ /**
+ * The typed property configurer.
+ */
+ private PropertyConfigurer m_typedPropConfigurer;
+
/**
* Content configurer.
*/
@@ -67,15 +72,15 @@ class DefaultObjectConfigurer
public void enableAll()
throws ConfigurationException
{
- // TODO - get rid of creators, and either setter or adders
- enableAdders();
+ // TODO - get rid of creators
+ enableProperties();
enableContent();
}
/**
* Enables all creators + adders.
*/
- public void enableAdders()
+ private void enableProperties()
throws ConfigurationException
{
final Map creators = findCreators();
@@ -119,6 +124,16 @@ class DefaultObjectConfigurer
type = addMethod.getParameterTypes()[ 0 ];
}
+ final boolean isTypedProp = (propName.length() == 0);
+ if( isTypedProp && !type.isInterface() )
+ {
+ final String message =
+ REZ.getString( "typed-adder-non-interface.error",
+ m_class.getName(),
+ type.getName() );
+ throw new ConfigurationException( message );
+ }
+
// Determine the max count for the property
int maxCount = Integer.MAX_VALUE;
if( addMethod != null && addMethod.getName().startsWith( "set" ) )
@@ -132,8 +147,15 @@ class DefaultObjectConfigurer
createMethod,
addMethod,
maxCount );
- m_props.put( propName, configurer );
m_allProps.add( configurer );
+ if( isTypedProp )
+ {
+ m_typedPropConfigurer = configurer;
+ }
+ else
+ {
+ m_props.put( propName, configurer );
+ }
}
}
@@ -160,19 +182,7 @@ class DefaultObjectConfigurer
continue;
}
- final boolean isTypedAdder = methodName.equals( "add" );
-
- final Class paramType = method.getParameterTypes()[ 0 ];
- if( isTypedAdder && !paramType.isInterface() )
- {
- final String message =
- REZ.getString( "typed-adder-non-interface.error",
- m_class.getName(),
- paramType.getName() );
- throw new ConfigurationException( message );
- }
-
- // TODO - un-hard-code this
+ // Skip the text content method
if( methodName.equals( "addContent" ) )
{
continue;
@@ -180,8 +190,7 @@ class DefaultObjectConfigurer
// Extract property name
final String propName = extractName( 3, methodName );
-
- final Class type = paramType;
+ final Class type = method.getParameterTypes()[0];
// Add to the adders map
if( adders.containsKey( propName ) )
@@ -190,15 +199,7 @@ class DefaultObjectConfigurer
final Class currentType = candidate.getParameterTypes()[ 0 ];
// Ditch the string version, if any
- if( isTypedAdder )
- {
- // Both are string, or both are not string
- final String message =
- REZ.getString( "multiple-typed-adder-methods-for-element.error",
- m_class.getName() );
- throw new ConfigurationException( message );
- }
- else if( currentType != String.class && type == String.class )
+ if( currentType != String.class && type == String.class )
{
// New type is string, and current type is not. Ignore
// the new method
@@ -217,6 +218,7 @@ class DefaultObjectConfigurer
// Else, current type is string, and new type is not, so
// continue below, and overwrite the current method
}
+
adders.put( propName, method );
}
return adders;
@@ -253,7 +255,7 @@ class DefaultObjectConfigurer
final String message =
REZ.getString( "multiple-creator-methods-for-element.error",
m_class.getName(),
- elemName );
+ methodName );
throw new ConfigurationException( message );
}
creators.put( elemName, method );
@@ -264,9 +266,13 @@ class DefaultObjectConfigurer
/**
* Enables content.
*/
- public void enableContent()
+ private void enableContent()
throws ConfigurationException
{
+ // TODO - should be using 'setContent', rather than 'addContent',
+ // to better match the call-at-most-once semantics of the other
+ // setter methods
+
// Locate any 'addContent' methods, which return void, and take
// a single parameter.
final Method[] methods = m_class.getMethods();
@@ -355,16 +361,25 @@ class DefaultObjectConfigurer
return configurer;
}
- //Maybe there is a typed adder??
- configurer = (PropertyConfigurer)m_props.get( "" );
- if( null != configurer )
+ // Unknown property
+ final String message = REZ.getString( "unknown-property.error", m_class.getName(), name );
+ throw new NoSuchPropertyException( message );
+ }
+
+ /**
+ * Returns a configurer for the typed property of this class.
+ */
+ public PropertyConfigurer getTypedProperty()
+ throws NoSuchPropertyException
+ {
+ if( null != m_typedPropConfigurer )
{
- return configurer;
+ return m_typedPropConfigurer;
}
else
{
- // Unknown property
- final String message = REZ.getString( "unknown-property.error", m_class.getName(), name );
+ // No typed property
+ final String message = REZ.getString( "no-typed-property.error", m_class.getName() );
throw new NoSuchPropertyException( message );
}
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java
index de2db8a75..760374e7a 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java
@@ -58,4 +58,14 @@ interface ObjectConfigurer
*/
PropertyConfigurer getContentConfigurer()
throws NoSuchPropertyException;
+
+ /**
+ * Returns a configurer for the typed property of this class.
+ *
+ * @return A configurer for the typed property.
+ * @throws NoSuchPropertyException If the class does not have a typed
+ * property.
+ */
+ PropertyConfigurer getTypedProperty()
+ throws NoSuchPropertyException;
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties
index a26083651..e5a78ffd7 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties
@@ -3,9 +3,8 @@ extra-config-for-ref.error=A reference element can only include an "id" attribut
get-ref.error=Could not locate reference "{0}".
mismatch-ref-types.error=Mismatched type for reference "{0}". Was expecting an object of type {1}, instead found an object of type {2}.
incompatible-element-types.error=Incompatible creator and adder/setter methods found in class {0} for property "{1}".
-multiple-adder-methods-for-element.error=Multiple adder/setter methods found in class {0} for property "{1}".
-multiple-typed-adder-methods-for-element.error=Multiple typed add() methods found in class {0}.
-multiple-creator-methods-for-element.error=Multiple creator methods found in class {0} for property "{1}".
+multiple-adder-methods-for-element.error=Multiple add{1}() or set{1}() methods found in class {0}.
+multiple-creator-methods-for-element.error=Multiple {1}() methods found in class {0}.
multiple-content-setter-methods.error=Multiple content setter methods found in class {0}.
pending-property-value.error=An object created using the creator method has not been set using the adder/setter method.
unknown-property.error=Class {0} does not have a "{1}" property.
@@ -22,4 +21,5 @@ no-content.error=Text content is not allowed for element <{0}>.
bad-set-content.error=Could not set text content for element <{0}>.
typed-adder-non-interface.error=The typed adder for class "{0}" must have a single parameter that is an interface rather than {1} which defines a class.
no-factory-for-role.error=Unable to locate type factory for role "{0}"
-create-typed-object.error=Could not create an object of type "{0}" of class {1}.
\ No newline at end of file
+create-typed-object.error=Could not create an object of type "{0}" of class {1}.
+typed-property-not-supported.error=Class {0} does not have a typed property.
\ No newline at end of file
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
index baf96177d..378c19dde 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
@@ -38,6 +38,9 @@ import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.TypeManager;
+import org.apache.myrmidon.interfaces.type.TypeException;
+import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
+import org.apache.myrmidon.converter.Converter;
/**
* A base class for tests for the default components.
@@ -145,6 +148,21 @@ public abstract class AbstractComponentTest
}
}
+ /**
+ * Utility method to register a Converter.
+ */
+ protected void registerConverter( final Class converterClass,
+ final Class sourceClass,
+ final Class destClass )
+ throws ComponentException, TypeException
+ {
+ ConverterRegistry converterRegistry = (ConverterRegistry)getComponentManager().lookup( ConverterRegistry.ROLE );
+ converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() );
+ DefaultTypeFactory factory = new DefaultTypeFactory( getClass().getClassLoader() );
+ factory.addNameClassMapping( converterClass.getName(), converterClass.getName() );
+ getTypeManager().registerType( Converter.class, converterClass.getName(), factory );
+ }
+
/**
* Asserts that an exception contains the expected message.
*
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/ConfigTest10.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/ConfigTest10.java
new file mode 100644
index 000000000..e7a67f032
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/ConfigTest10.java
@@ -0,0 +1,46 @@
+/*
+ * 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.configurer;
+
+import org.apache.myrmidon.components.AbstractComponentTest;
+
+/**
+ * A class for testing conversion.
+ *
+ * @author Adam Murdoch
+ */
+public class ConfigTest10
+{
+ private int m_intProp;
+ private Integer m_integerProp;
+
+ public void setIntProp( int intProp )
+ {
+ m_intProp = intProp;
+ }
+
+ public void setIntegerProp( Integer integerProp )
+ {
+ m_integerProp = integerProp;
+ }
+
+ public boolean equals( Object obj )
+ {
+ ConfigTest10 test = (ConfigTest10)obj;
+ if( m_intProp != test.m_intProp )
+ {
+ return false;
+ }
+ if ( !AbstractComponentTest.equals( m_integerProp, test.m_integerProp ) )
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
index 9eaf6224e..416ada497 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
@@ -8,7 +8,7 @@
package org.apache.myrmidon.components.configurer;
import java.io.File;
-import junit.framework.AssertionFailedError;
+import org.apache.antlib.core.StringToIntegerConverter;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -16,7 +16,9 @@ import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.components.AbstractComponentTest;
import org.apache.myrmidon.components.workspace.DefaultTaskContext;
+import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
+import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
/**
@@ -80,6 +82,35 @@ public class DefaultConfigurerTest
assertEquals( expected, test );
}
+ /**
+ * Tests attribute conversion.
+ */
+ public void testAttributeConvert()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ config.setAttribute( "int-prop", "90" );
+ config.setAttribute( "integer-prop", "-401" );
+
+ // Register the converter
+ final Class converterClass = StringToIntegerConverter.class;
+ final Class sourceClass = String.class;
+ final Class destClass = Integer.class;
+ registerConverter( converterClass, sourceClass, destClass );
+
+ final ConfigTest10 test = new ConfigTest10();
+
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+
+ // Check result
+ final ConfigTest10 expected = new ConfigTest10();
+ expected.setIntProp( 90 );
+ expected.setIntegerProp( new Integer(-401) );
+ assertEquals( expected, test );
+ }
+
/**
* Tests setting an unknown attribute.
*/
@@ -96,7 +127,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( final ConfigurationException ce )
{
@@ -155,7 +186,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( final ConfigurationException ce )
{
@@ -202,7 +233,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( final ConfigurationException ce )
{
@@ -280,6 +311,34 @@ public class DefaultConfigurerTest
assertEquals( expected, test );
}
+ /**
+ * Tests that extra content is not allowed in a reference element.
+ */
+ public void testReferenceElementExtra()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ final DefaultConfiguration elem = new DefaultConfiguration( "some-prop-ref", "test" );
+ elem.setAttribute( "id", "prop-a" );
+ elem.setAttribute( "extra-attr", "some value" );
+ config.addChild( elem );
+
+ final ConfigTest1 test = new ConfigTest1();
+
+ try
+ {
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+ fail();
+ }
+ catch( ConfigurationException e )
+ {
+ final String message = REZ.getString( "extra-config-for-ref.error" );
+ assertSameMessage( message, e );
+ }
+ }
+
/**
* Tests whether an object with a non-iterface typed adder causes an
* exception.
@@ -326,8 +385,9 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
- final String message = REZ.getString( "multiple-typed-adder-methods-for-element.error",
- ConfigTest5.class.getName() );
+ final String message = REZ.getString( "multiple-adder-methods-for-element.error",
+ ConfigTest5.class.getName(),
+ "");
assertSameMessage( message, ce );
}
}
@@ -349,8 +409,8 @@ public class DefaultConfigurerTest
final DefaultTypeFactory factory = new DefaultTypeFactory( loader );
factory.addNameClassMapping( "my-type1", MyType1.class.getName() );
factory.addNameClassMapping( "my-type2", MyType2.class.getName() );
- getTypeManager().registerType( MyRole1.class, "my-type1", factory );
- getTypeManager().registerType( MyRole1.class, "my-type2", factory );
+ getTypeManager().registerType( DataType.class, "my-type1", factory );
+ getTypeManager().registerType( DataType.class, "my-type2", factory );
final ConfigTest6 test = new ConfigTest6();
@@ -363,6 +423,32 @@ public class DefaultConfigurerTest
assertEquals( expected, test );
}
+ /**
+ * Tests to see if typed adder can be used via an attribute.
+ */
+ public void testTypedAdderAttribute()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ config.setAttribute( "my-role1", "some value" );
+
+ // Set up the converter and role
+ RoleManager roleMgr = (RoleManager)getComponentManager().lookup( RoleManager.ROLE );
+ roleMgr.addNameRoleMapping( "my-role1", MyRole1.ROLE );
+ registerConverter( StringToMyRole1Converter.class, String.class, MyRole1.class );
+
+ final ConfigTest6 test = new ConfigTest6();
+
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+
+ // Check result
+ final ConfigTest6 expected = new ConfigTest6();
+ expected.add( new MyType1() );
+ assertEquals( expected, test );
+ }
+
/**
* Tests to see if typed adder works, with Configuration type.
*/
@@ -388,7 +474,7 @@ public class DefaultConfigurerTest
}
/**
- * Tests to see if typed adder works, with Configuration objects.
+ * Tests to see if adder works, with Configuration objects.
*/
public void testConfigAdder()
throws Exception
@@ -470,7 +556,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( ConfigurationException e )
{
@@ -498,7 +584,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( ConfigurationException e )
{
@@ -510,6 +596,38 @@ public class DefaultConfigurerTest
}
}
+ /**
+ * Tests using a reference with a typed adder. Tests using an attribute
+ * and a nested element.
+ */
+ public void testTypedAdderReference()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ config.setAttribute( "my-role1-ref", "id" );
+ final DefaultConfiguration child = new DefaultConfiguration( "my-role1-ref", "test" );
+ child.setAttribute( "id", "id2" );
+ config.addChild( child );
+
+ // Add role mapping, and add to reference to context
+ final RoleManager roleMgr = (RoleManager)getComponentManager().lookup( RoleManager.ROLE );
+ roleMgr.addNameRoleMapping( "my-role1", MyRole1.class.getName() );
+ m_context.setProperty( "id", new MyType1() );
+ m_context.setProperty( "id2", new MyType2() );
+
+ final ConfigTest6 test = new ConfigTest6();
+
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+
+ // Compare against expected value
+ final ConfigTest6 expected = new ConfigTest6();
+ expected.add( new MyType1() );
+ expected.add( new MyType2() );
+ assertEquals( expected, test );
+ }
+
/**
* Tests reporting of nested errors.
*/
@@ -527,7 +645,7 @@ public class DefaultConfigurerTest
{
// Configure the object
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( ConfigurationException e )
{
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/MyRole1.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/MyRole1.java
index 4e524204d..f62943b3c 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/MyRole1.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/MyRole1.java
@@ -7,6 +7,8 @@
*/
package org.apache.myrmidon.components.configurer;
+import org.apache.myrmidon.framework.DataType;
+
/**
* A basic interface to test configurer.
*
@@ -14,5 +16,7 @@ package org.apache.myrmidon.components.configurer;
* @version $Revision$ $Date$
*/
public interface MyRole1
+ extends DataType
{
+ String ROLE = MyRole1.class.getName();
}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/StringToMyRole1Converter.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/StringToMyRole1Converter.java
new file mode 100644
index 000000000..7d2dfd641
--- /dev/null
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/StringToMyRole1Converter.java
@@ -0,0 +1,32 @@
+/*
+ * 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.configurer;
+
+import org.apache.myrmidon.converter.AbstractConverter;
+import org.apache.myrmidon.converter.ConverterException;
+import org.apache.avalon.framework.context.Context;
+
+/**
+ * Converts from a string to a {@link MyRole1} implementation.
+ *
+ * @author Adam Murdoch
+ */
+public class StringToMyRole1Converter
+ extends AbstractConverter
+{
+ public StringToMyRole1Converter()
+ {
+ super( String.class, MyRole1.class );
+ }
+
+ protected Object convert( Object original, Context context )
+ throws ConverterException
+ {
+ return new MyType1();
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
index baf96177d..378c19dde 100644
--- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
@@ -38,6 +38,9 @@ import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.TypeManager;
+import org.apache.myrmidon.interfaces.type.TypeException;
+import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
+import org.apache.myrmidon.converter.Converter;
/**
* A base class for tests for the default components.
@@ -145,6 +148,21 @@ public abstract class AbstractComponentTest
}
}
+ /**
+ * Utility method to register a Converter.
+ */
+ protected void registerConverter( final Class converterClass,
+ final Class sourceClass,
+ final Class destClass )
+ throws ComponentException, TypeException
+ {
+ ConverterRegistry converterRegistry = (ConverterRegistry)getComponentManager().lookup( ConverterRegistry.ROLE );
+ converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() );
+ DefaultTypeFactory factory = new DefaultTypeFactory( getClass().getClassLoader() );
+ factory.addNameClassMapping( converterClass.getName(), converterClass.getName() );
+ getTypeManager().registerType( Converter.class, converterClass.getName(), factory );
+ }
+
/**
* Asserts that an exception contains the expected message.
*
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/ConfigTest10.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/ConfigTest10.java
new file mode 100644
index 000000000..e7a67f032
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/ConfigTest10.java
@@ -0,0 +1,46 @@
+/*
+ * 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.configurer;
+
+import org.apache.myrmidon.components.AbstractComponentTest;
+
+/**
+ * A class for testing conversion.
+ *
+ * @author Adam Murdoch
+ */
+public class ConfigTest10
+{
+ private int m_intProp;
+ private Integer m_integerProp;
+
+ public void setIntProp( int intProp )
+ {
+ m_intProp = intProp;
+ }
+
+ public void setIntegerProp( Integer integerProp )
+ {
+ m_integerProp = integerProp;
+ }
+
+ public boolean equals( Object obj )
+ {
+ ConfigTest10 test = (ConfigTest10)obj;
+ if( m_intProp != test.m_intProp )
+ {
+ return false;
+ }
+ if ( !AbstractComponentTest.equals( m_integerProp, test.m_integerProp ) )
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
index 9eaf6224e..416ada497 100644
--- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/DefaultConfigurerTest.java
@@ -8,7 +8,7 @@
package org.apache.myrmidon.components.configurer;
import java.io.File;
-import junit.framework.AssertionFailedError;
+import org.apache.antlib.core.StringToIntegerConverter;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -16,7 +16,9 @@ import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.components.AbstractComponentTest;
import org.apache.myrmidon.components.workspace.DefaultTaskContext;
+import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
+import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
/**
@@ -80,6 +82,35 @@ public class DefaultConfigurerTest
assertEquals( expected, test );
}
+ /**
+ * Tests attribute conversion.
+ */
+ public void testAttributeConvert()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ config.setAttribute( "int-prop", "90" );
+ config.setAttribute( "integer-prop", "-401" );
+
+ // Register the converter
+ final Class converterClass = StringToIntegerConverter.class;
+ final Class sourceClass = String.class;
+ final Class destClass = Integer.class;
+ registerConverter( converterClass, sourceClass, destClass );
+
+ final ConfigTest10 test = new ConfigTest10();
+
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+
+ // Check result
+ final ConfigTest10 expected = new ConfigTest10();
+ expected.setIntProp( 90 );
+ expected.setIntegerProp( new Integer(-401) );
+ assertEquals( expected, test );
+ }
+
/**
* Tests setting an unknown attribute.
*/
@@ -96,7 +127,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( final ConfigurationException ce )
{
@@ -155,7 +186,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( final ConfigurationException ce )
{
@@ -202,7 +233,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( final ConfigurationException ce )
{
@@ -280,6 +311,34 @@ public class DefaultConfigurerTest
assertEquals( expected, test );
}
+ /**
+ * Tests that extra content is not allowed in a reference element.
+ */
+ public void testReferenceElementExtra()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ final DefaultConfiguration elem = new DefaultConfiguration( "some-prop-ref", "test" );
+ elem.setAttribute( "id", "prop-a" );
+ elem.setAttribute( "extra-attr", "some value" );
+ config.addChild( elem );
+
+ final ConfigTest1 test = new ConfigTest1();
+
+ try
+ {
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+ fail();
+ }
+ catch( ConfigurationException e )
+ {
+ final String message = REZ.getString( "extra-config-for-ref.error" );
+ assertSameMessage( message, e );
+ }
+ }
+
/**
* Tests whether an object with a non-iterface typed adder causes an
* exception.
@@ -326,8 +385,9 @@ public class DefaultConfigurerTest
}
catch( final ConfigurationException ce )
{
- final String message = REZ.getString( "multiple-typed-adder-methods-for-element.error",
- ConfigTest5.class.getName() );
+ final String message = REZ.getString( "multiple-adder-methods-for-element.error",
+ ConfigTest5.class.getName(),
+ "");
assertSameMessage( message, ce );
}
}
@@ -349,8 +409,8 @@ public class DefaultConfigurerTest
final DefaultTypeFactory factory = new DefaultTypeFactory( loader );
factory.addNameClassMapping( "my-type1", MyType1.class.getName() );
factory.addNameClassMapping( "my-type2", MyType2.class.getName() );
- getTypeManager().registerType( MyRole1.class, "my-type1", factory );
- getTypeManager().registerType( MyRole1.class, "my-type2", factory );
+ getTypeManager().registerType( DataType.class, "my-type1", factory );
+ getTypeManager().registerType( DataType.class, "my-type2", factory );
final ConfigTest6 test = new ConfigTest6();
@@ -363,6 +423,32 @@ public class DefaultConfigurerTest
assertEquals( expected, test );
}
+ /**
+ * Tests to see if typed adder can be used via an attribute.
+ */
+ public void testTypedAdderAttribute()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ config.setAttribute( "my-role1", "some value" );
+
+ // Set up the converter and role
+ RoleManager roleMgr = (RoleManager)getComponentManager().lookup( RoleManager.ROLE );
+ roleMgr.addNameRoleMapping( "my-role1", MyRole1.ROLE );
+ registerConverter( StringToMyRole1Converter.class, String.class, MyRole1.class );
+
+ final ConfigTest6 test = new ConfigTest6();
+
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+
+ // Check result
+ final ConfigTest6 expected = new ConfigTest6();
+ expected.add( new MyType1() );
+ assertEquals( expected, test );
+ }
+
/**
* Tests to see if typed adder works, with Configuration type.
*/
@@ -388,7 +474,7 @@ public class DefaultConfigurerTest
}
/**
- * Tests to see if typed adder works, with Configuration objects.
+ * Tests to see if adder works, with Configuration objects.
*/
public void testConfigAdder()
throws Exception
@@ -470,7 +556,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( ConfigurationException e )
{
@@ -498,7 +584,7 @@ public class DefaultConfigurerTest
try
{
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( ConfigurationException e )
{
@@ -510,6 +596,38 @@ public class DefaultConfigurerTest
}
}
+ /**
+ * Tests using a reference with a typed adder. Tests using an attribute
+ * and a nested element.
+ */
+ public void testTypedAdderReference()
+ throws Exception
+ {
+ // Setup test data
+ final DefaultConfiguration config = new DefaultConfiguration( "test", "test" );
+ config.setAttribute( "my-role1-ref", "id" );
+ final DefaultConfiguration child = new DefaultConfiguration( "my-role1-ref", "test" );
+ child.setAttribute( "id", "id2" );
+ config.addChild( child );
+
+ // Add role mapping, and add to reference to context
+ final RoleManager roleMgr = (RoleManager)getComponentManager().lookup( RoleManager.ROLE );
+ roleMgr.addNameRoleMapping( "my-role1", MyRole1.class.getName() );
+ m_context.setProperty( "id", new MyType1() );
+ m_context.setProperty( "id2", new MyType2() );
+
+ final ConfigTest6 test = new ConfigTest6();
+
+ // Configure the object
+ m_configurer.configure( test, config, m_context );
+
+ // Compare against expected value
+ final ConfigTest6 expected = new ConfigTest6();
+ expected.add( new MyType1() );
+ expected.add( new MyType2() );
+ assertEquals( expected, test );
+ }
+
/**
* Tests reporting of nested errors.
*/
@@ -527,7 +645,7 @@ public class DefaultConfigurerTest
{
// Configure the object
m_configurer.configure( test, config, m_context );
- throw new AssertionFailedError();
+ fail();
}
catch( ConfigurationException e )
{
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/MyRole1.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/MyRole1.java
index 4e524204d..f62943b3c 100644
--- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/MyRole1.java
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/MyRole1.java
@@ -7,6 +7,8 @@
*/
package org.apache.myrmidon.components.configurer;
+import org.apache.myrmidon.framework.DataType;
+
/**
* A basic interface to test configurer.
*
@@ -14,5 +16,7 @@ package org.apache.myrmidon.components.configurer;
* @version $Revision$ $Date$
*/
public interface MyRole1
+ extends DataType
{
+ String ROLE = MyRole1.class.getName();
}
diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/StringToMyRole1Converter.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/StringToMyRole1Converter.java
new file mode 100644
index 000000000..7d2dfd641
--- /dev/null
+++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/configurer/StringToMyRole1Converter.java
@@ -0,0 +1,32 @@
+/*
+ * 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.configurer;
+
+import org.apache.myrmidon.converter.AbstractConverter;
+import org.apache.myrmidon.converter.ConverterException;
+import org.apache.avalon.framework.context.Context;
+
+/**
+ * Converts from a string to a {@link MyRole1} implementation.
+ *
+ * @author Adam Murdoch
+ */
+public class StringToMyRole1Converter
+ extends AbstractConverter
+{
+ public StringToMyRole1Converter()
+ {
+ super( String.class, MyRole1.class );
+ }
+
+ protected Object convert( Object original, Context context )
+ throws ConverterException
+ {
+ return new MyType1();
+ }
+}