FELIX-593 change accepted and default values for immediate attribute
with respect to the factory attribute

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@662680 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
index f8ca2d1..35fdee5 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
@@ -188,29 +188,20 @@
     private ComponentManager createComponentManager( Dictionary configuration, boolean synchronous )
     {
         long componentId = m_componentRegistry.createComponentId();
-        ComponentManager cm = ManagerFactory.createManager( getActivator(), getComponentMetadata(), componentId );
-
+        ImmediateComponentManager cm = new ImmediateComponentManager( getActivator(), getComponentMetadata(),
+            componentId );
+        
         // add the new component to the activators instances
         getActivator().getInstanceReferences().add( cm );
 
         // register with the internal set of created components
         m_createdComponents.put( cm, cm );
 
-        // inject configuration if possible
-        if ( cm instanceof ImmediateComponentManager )
-        {
-            ( ( ImmediateComponentManager ) cm ).setFactoryProperties( configuration );
-        }
+        // inject configuration
+        cm.setFactoryProperties( configuration );
 
         // enable synchronously or asynchronously depending on the flag
-        if ( cm instanceof AbstractComponentManager )
-        {
-            ( ( AbstractComponentManager ) cm ).enable( synchronous );
-        }
-        else
-        {
-            cm.enable();
-        }
+        cm.enable( synchronous );
 
         return cm;
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentMetadata.java
index 07613e7..ccc1d28 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ComponentMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ComponentMetadata.java
@@ -201,9 +201,9 @@
      * This method may only be trusted after this instance has been validated
      * by the {@link #validate()} call. Else it will either return the value
      * of an explicitly set "immediate" attribute or return false if a service
-     * element is set or true otherwise. This latter default value deduction
-     * may be unsafe while the descriptor has not been completely read.
-     * 
+     * element or the factory attribute is set or true otherwise. This latter
+     * default value deduction may be unsafe while the descriptor has not been
+     * completely read.
      * 
      * @return a boolean that defines the activation policy
      */
@@ -213,8 +213,8 @@
             return m_immediate.booleanValue();
         }
 
-        // deduce default value from service element presence
-        return m_service == null;
+        // deduce default from service element and factory attribute presence 
+        return m_service == null && m_factory == null;
     }
     
     /**
@@ -265,60 +265,90 @@
     /**
      * Method used to verify if the semantics of this metadata are correct
      */
-    void validate() {
-    	
-        // First check if the properties are valid (and extract property values)
-        Iterator propertyIterator = m_propertyMetaData.iterator();
-    	while ( propertyIterator.hasNext() ) {
-    	    PropertyMetadata propMeta = (PropertyMetadata) propertyIterator.next();
-            propMeta.validate();
-            m_properties.put(propMeta.getName(), propMeta.getValue());
+    void validate()
+    {
+
+        // 112.10 The name of the component is required
+        if ( m_name == null )
+        {
+            throw new ComponentException( "The component name has not been set" );
         }
-    	m_propertyMetaData.clear();
-    	
-    	// Check that the provided services are valid too
-    	if(m_service != null) {
-    		m_service.validate();
-    	}
-    	
-    	// Check that the references are ok
-    	Iterator referenceIterator = m_references.iterator();
-    	while ( referenceIterator.hasNext() ) {
-    		((ReferenceMetadata)referenceIterator.next()).validate();
-    	}
-    	    	
-    	// 112.10 The name of the component is required
-    	if( m_name == null ) {
-    		throw new ComponentException("The component name has not been set");
-    	}
-    	
-    	// 112.10 There must be one implementation element and the class atribute is required
-    	if ( m_implementationClassName == null ) {
-    		throw new ComponentException("The implementation class name has not been set for this component");
-    	}
-    	
-    	// 112.2.3 A delayed component specifies a service, is not specified to be a factory component
-    	// and does not have the immediate attribute of the component element set to true.
-    	if ( m_immediate != null && isImmediate() == false && m_service == null ) {
-            throw new ComponentException( "Component '" + m_name
-                + "' is specified as being delayed but does not provide any service." );
-        }    	
-    	
-    	if ( m_factory != null && isImmediate() == false) {
-    		throw new ComponentException("A factory cannot be a delayed component");
-    	}
-    	
-    	// 112.4.6 The serviceFactory attribute (of a provided service) must not be true if 
-    	// the component is a factory component or an immediate component
-    	if ( m_service != null ) {
-            if ( m_service.isServiceFactory() && ( isFactory() || isImmediate() ) ) {
-                throw new ComponentException( "A ServiceFactory service cannot be a factory or immediate component" );
+
+        // 112.10 There must be one implementation element and the class atribute is required
+        if ( m_implementationClassName == null )
+        {
+            throw validationFailure( "Implementation class name missing" );
+        }
+
+        // Next check if the properties are valid (and extract property values)
+        Iterator propertyIterator = m_propertyMetaData.iterator();
+        while ( propertyIterator.hasNext() )
+        {
+            PropertyMetadata propMeta = ( PropertyMetadata ) propertyIterator.next();
+            propMeta.validate( this );
+            m_properties.put( propMeta.getName(), propMeta.getValue() );
+        }
+        m_propertyMetaData.clear();
+
+        // Check that the provided services are valid too
+        if ( m_service != null )
+        {
+            m_service.validate( this );
+        }
+
+        // Check that the references are ok
+        Iterator referenceIterator = m_references.iterator();
+        while ( referenceIterator.hasNext() )
+        {
+            ( ( ReferenceMetadata ) referenceIterator.next() ).validate( this );
+        }
+
+        // verify value of immediate attribute if set
+        if ( m_immediate != null )
+        {
+            if ( isImmediate() )
+            {
+                // FELIX-593: 112.4.3 clarification, immediate is false for factory
+                if ( isFactory() )
+                {
+                    throw validationFailure( "Factory cannot be immediate" );
+                }
+            }
+            else
+            {
+                // 112.2.3 A delayed component specifies a service, is not specified to be a factory component
+                // and does not have the immediate attribute of the component element set to true.
+                // FELIX-593: 112.4.3 clarification, immediate may be true for factory
+                if ( m_service == null && !isFactory() )
+                {
+                    throw validationFailure( "Delayed must provide a service or be a factory" );
+                }
             }
         }
 
-    	
-    	m_validated = true;
-    	// TODO: put a similar flag on the references and the services
+        // 112.4.6 The serviceFactory attribute (of a provided service) must not be true if 
+        // the component is a factory component or an immediate component
+        if ( m_service != null )
+        {
+            if ( m_service.isServiceFactory() && ( isFactory() || isImmediate() ) )
+            {
+                throw validationFailure( "ServiceFactory cannot be factory or immediate" );
+            }
+        }
+
+        m_validated = true;
+        // TODO: put a similar flag on the references and the services
     }
 
+
+    /**
+     * Returns a <code>ComponentException</code> for this compeonent with the
+     * given explanation for failure.
+     * 
+     * @param reason The explanation for failing to validate this component.
+     */
+    ComponentException validationFailure( String reason )
+    {
+        return new ComponentException( "Component " + getName() + " validation failed: " + reason );
+    }
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/PropertyMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/PropertyMetadata.java
index ab8068e..f30ea0e 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/PropertyMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/PropertyMetadata.java
@@ -195,11 +195,12 @@
     /**
      * Method used to verify if the semantics of this metadata are correct
      */
-    public void validate(){
-    	if(m_name == null)
-    	{
-    		throw new ComponentException("Property name attribute is mandatory");
-    	}
+    public void validate( ComponentMetadata componentMetadata )
+    {
+        if ( m_name == null )
+        {
+            throw componentMetadata.validationFailure( "Property name attribute is mandatory" );
+        }
     }
     
     private Object toType(String value) {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ReferenceMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/ReferenceMetadata.java
index 2378642..75b243f 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ReferenceMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ReferenceMetadata.java
@@ -330,16 +330,16 @@
      *  Method used to verify if the semantics of this metadata are correct
      *
      */
-    void validate()
+    void validate( ComponentMetadata componentMetadata )
     {
         if ( m_name == null )
         {
-            throw new ComponentException( "the name for the reference must be set" );
+            throw componentMetadata.validationFailure( "A name must be declared for the reference" );
         }
 
         if ( m_interface == null )
         {
-            throw new ComponentException( "the interface for the reference must be set" );
+            throw componentMetadata.validationFailure( "An interface must be declared for the reference" );
         }
     }
 
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ServiceMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/ServiceMetadata.java
index 665a400..1d97d34 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ServiceMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ServiceMetadata.java
@@ -1,103 +1,106 @@
-/* 

- * Licensed to the Apache Software Foundation (ASF) under one

- * or more contributor license agreements.  See the NOTICE file

- * distributed with this work for additional information

- * regarding copyright ownership.  The ASF licenses this file

- * to you under the Apache License, Version 2.0 (the

- * "License"); you may not use this file except in compliance

- * with the License.  You may obtain a copy of the License at

- *

- *   http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing,

- * software distributed under the License is distributed on an

- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

- * KIND, either express or implied.  See the License for the

- * specific language governing permissions and limitations

- * under the License.

- */

-package org.apache.felix.scr.impl;

-

-import java.util.ArrayList;

-import java.util.Iterator;

-import java.util.List;

-

-import org.osgi.service.component.ComponentException;

-

-/**

- * This class contains the metadata associated to a service that is provided

- * by a component

- *

- */

-public class ServiceMetadata {

-	

-	// 112.4.6 Flag that indicates if the service is a ServiceFactory 

-	private boolean m_serviceFactory = false;

-	

-	// List of provided interfaces

-	private List m_provides = new ArrayList();

-	

-	// Flag that indicates if this metadata has been validated and has become immutable

-	private boolean m_validated = false;

-	

-	/**

-	 * Setter for the servicefactory attribute of the service element

-	 * 

-	 * @param serviceFactory

-	 */

-	public void setServiceFactory(boolean serviceFactory) {

-		if(m_validated) {

-			return;

-		}			

-		

-		m_serviceFactory = serviceFactory;

-	}

-	

-	/**

-	 * Add a provided interface to this service

-	 * 

-	 * @param provide a String containing the name of the provided interface

-	 */

-	public void addProvide(String provide) {

-		if(m_validated) {

-			return;

-		}			

-

-		m_provides.add(provide);

-	}

-	

-	/**

-	 * Return the flag that defines if it is a service factory or not

-	 * 

-	 * @return a boolean flag

-	 */

-	public boolean isServiceFactory() {

-		return m_serviceFactory; 

-	}

-	

-	/**

-     * Returns the implemented interfaces

-     *

-     * @return the implemented interfaces as a string array

-     */

-    public String [] getProvides() {

-        String provides[] = new String[m_provides.size()];

-        Iterator it = m_provides.iterator();

-        int count = 0;

-        while (it.hasNext())

-        {

-            provides[count++] = it.next().toString();

-        }

-        return provides;

-    }

-    

-    /**

-     * Verify if the semantics of this metadata are correct

-     *

-     */

-    void validate() {

-    	if(m_provides.size() == 0) {

-    		throw new ComponentException("At least one provided interface must be given");

-    	}

-    }

-}

+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.osgi.service.component.ComponentException;
+
+/**
+ * This class contains the metadata associated to a service that is provided
+ * by a component
+ *
+ */
+public class ServiceMetadata {
+	
+	// 112.4.6 Flag that indicates if the service is a ServiceFactory 
+	private boolean m_serviceFactory = false;
+	
+	// List of provided interfaces
+	private List m_provides = new ArrayList();
+	
+	// Flag that indicates if this metadata has been validated and has become immutable
+	private boolean m_validated = false;
+	
+	/**
+	 * Setter for the servicefactory attribute of the service element
+	 * 
+	 * @param serviceFactory
+	 */
+	public void setServiceFactory(boolean serviceFactory) {
+		if(m_validated) {
+			return;
+		}			
+		
+		m_serviceFactory = serviceFactory;
+	}
+	
+	/**
+	 * Add a provided interface to this service
+	 * 
+	 * @param provide a String containing the name of the provided interface
+	 */
+	public void addProvide(String provide) {
+		if(m_validated) {
+			return;
+		}			
+
+		m_provides.add(provide);
+	}
+	
+	/**
+	 * Return the flag that defines if it is a service factory or not
+	 * 
+	 * @return a boolean flag
+	 */
+	public boolean isServiceFactory() {
+		return m_serviceFactory; 
+	}
+	
+	/**
+     * Returns the implemented interfaces
+     *
+     * @return the implemented interfaces as a string array
+     */
+    public String [] getProvides() {
+        String provides[] = new String[m_provides.size()];
+        Iterator it = m_provides.iterator();
+        int count = 0;
+        while (it.hasNext())
+        {
+            provides[count++] = it.next().toString();
+        }
+        return provides;
+    }
+    
+    /**
+     * Verify if the semantics of this metadata are correct
+     *
+     */
+    void validate( ComponentMetadata componentMetadata )
+    {
+        if ( m_provides.size() == 0 )
+        {
+            throw componentMetadata
+                .validationFailure( "At least one provided interface must be declared in the service element" );
+        }
+    }
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/ComponentMetadataTest.java b/scr/src/test/java/org/apache/felix/scr/impl/ComponentMetadataTest.java
new file mode 100644
index 0000000..10dd3a2
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/ComponentMetadataTest.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl;
+
+
+import junit.framework.TestCase;
+
+import org.osgi.service.component.ComponentException;
+
+
+public class ComponentMetadataTest extends TestCase
+{
+
+    // test various combinations of component metadata with respect to
+    //  -- immediate: true, false, unset
+    //  -- factory: set, unset
+    //  -- service: set, unset
+    //  -- servicefactory: true, false, unset
+
+    public void testImmediate()
+    {
+        // immediate is default true if no service element is defined
+        final ComponentMetadata cm0 = createComponentMetadata( null, null );
+        cm0.validate();
+        assertTrue( "Component without service must be immediate", cm0.isImmediate() );
+
+        // immediate is explicit true
+        final ComponentMetadata cm1 = createComponentMetadata( Boolean.TRUE, null );
+        cm1.validate();
+        assertTrue( "Component must be immediate", cm1.isImmediate() );
+
+        // immediate is explicit true
+        final ComponentMetadata cm2 = createComponentMetadata( Boolean.TRUE, null );
+        cm2.setService( createServiceMetadata( null ) );
+        cm2.validate();
+        assertTrue( "Component must be immediate", cm2.isImmediate() );
+
+        // immediate is explicit true
+        final ComponentMetadata cm3 = createComponentMetadata( Boolean.TRUE, null );
+        cm3.setService( createServiceMetadata( Boolean.FALSE ) );
+        cm3.validate();
+        assertTrue( "Component must be immediate", cm3.isImmediate() );
+
+        // validation failure of immediate with service factory
+        final ComponentMetadata cm4 = createComponentMetadata( Boolean.TRUE, null );
+        cm4.setService( createServiceMetadata( Boolean.TRUE ) );
+        try
+        {
+            cm4.validate();
+            fail( "Expect validation failure for immediate service factory" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+    }
+
+
+    public void testDelayed()
+    {
+        // immediate is default false if service element is defined
+        final ComponentMetadata cm0 = createComponentMetadata( null, null );
+        cm0.setService( createServiceMetadata( null ) );
+        cm0.validate();
+        assertFalse( "Component with service must be delayed", cm0.isImmediate() );
+
+        // immediate is default false if service element is defined
+        final ComponentMetadata cm1 = createComponentMetadata( null, null );
+        cm1.setService( createServiceMetadata( Boolean.TRUE ) );
+        cm1.validate();
+        assertFalse( "Component with service must be delayed", cm1.isImmediate() );
+
+        // immediate is default false if service element is defined
+        final ComponentMetadata cm2 = createComponentMetadata( null, null );
+        cm2.setService( createServiceMetadata( Boolean.FALSE ) );
+        cm2.validate();
+        assertFalse( "Component with service must be delayed", cm2.isImmediate() );
+
+        // immediate is false if service element is defined
+        final ComponentMetadata cm3 = createComponentMetadata( Boolean.FALSE, null );
+        cm3.setService( createServiceMetadata( null ) );
+        cm3.validate();
+        assertFalse( "Component with service must be delayed", cm3.isImmediate() );
+
+        // immediate is false if service element is defined
+        final ComponentMetadata cm4 = createComponentMetadata( Boolean.FALSE, null );
+        cm4.setService( createServiceMetadata( Boolean.TRUE ) );
+        cm4.validate();
+        assertFalse( "Component with service must be delayed", cm4.isImmediate() );
+
+        // immediate is false if service element is defined
+        final ComponentMetadata cm5 = createComponentMetadata( Boolean.FALSE, null );
+        cm5.setService( createServiceMetadata( Boolean.FALSE ) );
+        cm5.validate();
+        assertFalse( "Component with service must be delayed", cm5.isImmediate() );
+
+        // explicit delayed fails when there is no service
+        final ComponentMetadata cm6 = createComponentMetadata( Boolean.FALSE, null );
+        try
+        {
+            cm6.validate();
+            fail( "Expect validation failure for delayed component without service" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+    }
+
+
+    public void testFactory()
+    {
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm0 = createComponentMetadata( null, "factory" );
+        cm0.validate();
+        assertFalse( "Component with factory must be delayed", cm0.isImmediate() );
+
+        // immediate is false if factory is defined
+        final ComponentMetadata cm1 = createComponentMetadata( Boolean.FALSE, "factory" );
+        cm1.validate();
+        assertFalse( "Component with factory must be delayed", cm1.isImmediate() );
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm2 = createComponentMetadata( Boolean.TRUE, "factory" );
+        try
+        {
+            cm2.validate();
+            fail( "Expect validation failure for immediate factory component" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm10 = createComponentMetadata( null, "factory" );
+        cm10.setService( createServiceMetadata( null ) );
+        cm10.validate();
+        assertFalse( "Component with factory must be delayed", cm10.isImmediate() );
+
+        // immediate is false if factory is defined
+        final ComponentMetadata cm11 = createComponentMetadata( Boolean.FALSE, "factory" );
+        cm11.setService( createServiceMetadata( null ) );
+        cm11.validate();
+        assertFalse( "Component with factory must be delayed", cm11.isImmediate() );
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm12 = createComponentMetadata( Boolean.TRUE, "factory" );
+        cm12.setService( createServiceMetadata( null ) );
+        try
+        {
+            cm12.validate();
+            fail( "Expect validation failure for immediate factory component" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm20 = createComponentMetadata( null, "factory" );
+        cm20.setService( createServiceMetadata( Boolean.FALSE ) );
+        cm20.validate();
+        assertFalse( "Component with factory must be delayed", cm20.isImmediate() );
+
+        // immediate is false if factory is defined
+        final ComponentMetadata cm21 = createComponentMetadata( Boolean.FALSE, "factory" );
+        cm21.setService( createServiceMetadata( Boolean.FALSE ) );
+        cm21.validate();
+        assertFalse( "Component with factory must be delayed", cm21.isImmediate() );
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm22 = createComponentMetadata( Boolean.TRUE, "factory" );
+        cm22.setService( createServiceMetadata( Boolean.FALSE ) );
+        try
+        {
+            cm22.validate();
+            fail( "Expect validation failure for immediate factory component" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm30 = createComponentMetadata( null, "factory" );
+        cm30.setService( createServiceMetadata( Boolean.TRUE ) );
+        try
+        {
+            cm30.validate();
+            fail( "Expect validation failure for factory component with service factory" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+
+        // immediate is false if factory is defined
+        final ComponentMetadata cm31 = createComponentMetadata( Boolean.FALSE, "factory" );
+        cm31.setService( createServiceMetadata( Boolean.TRUE ) );
+        try
+        {
+            cm31.validate();
+            fail( "Expect validation failure for factory component with service factory" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+
+        // immediate is default false if factory is defined
+        final ComponentMetadata cm32 = createComponentMetadata( Boolean.TRUE, "factory" );
+        cm32.setService( createServiceMetadata( Boolean.TRUE ) );
+        try
+        {
+            cm32.validate();
+            fail( "Expect validation failure for immediate factory component with service factory" );
+        }
+        catch ( ComponentException ce )
+        {
+            // expect
+        }
+
+    }
+
+
+    private ComponentMetadata createComponentMetadata( Boolean immediate, String factory )
+    {
+        ComponentMetadata meta = new ComponentMetadata();
+        meta.setName( "place.holder" );
+        meta.setImplementationClassName( "place.holder.implementation" );
+        if ( immediate != null )
+        {
+            meta.setImmediate( immediate.booleanValue() );
+        }
+        if ( factory != null )
+        {
+            meta.setFactoryIdentifier( factory );
+        }
+        return meta;
+    }
+
+
+    private ServiceMetadata createServiceMetadata( Boolean serviceFactory )
+    {
+        ServiceMetadata meta = new ServiceMetadata();
+        meta.addProvide( "place.holder.service" );
+        if ( serviceFactory != null )
+        {
+            meta.setServiceFactory( serviceFactory.booleanValue() );
+        }
+        return meta;
+    }
+}