Less duplication of validation and start. Validation should be a dry-run
authorErik Brakkee <erik@brakkee.org>
Sun, 20 Apr 2008 21:54:37 +0000 (21:54 +0000)
committerErik Brakkee <erik@brakkee.org>
Sun, 20 Apr 2008 21:54:37 +0000 (21:54 +0000)
of starting.

system/general/src/main/java/org/wamblee/system/core/Container.java
system/general/src/test/java/org/wamblee/system/core/ContainerTest.java

index b9056971136787a59fd09fc6f5de558ee6ed2fd6..8e98755b5e7b02b8d8c33c2243150fac045660a5 100644 (file)
@@ -78,13 +78,12 @@ public class Container extends AbstractComponent<Scope> {
             ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
         super(aName, aProvided, aRequired);
         _components = new ArrayList<Component>();
-       
+
         _componentNames = new HashSet<String>();
         _sealed = false;
         for (Component component : aComponents) {
             addComponent(component);
         }
-        validate();
     }
 
     public Container(String aName) {
@@ -144,46 +143,28 @@ public class Container extends AbstractComponent<Scope> {
             required.addAll(Arrays.asList(component.getRequiredInterfaces()));
         }
 
-        validateProvidedInterfaces(provided);
+        validateProvidedInterfacesArePresent(provided);
 
         validateRequiredInterfaces(required);
 
-        List<RequiredInterface> reallyRequired = validateRequiredProvidedMatch(
-                provided, required);
-
-        String missingRequired = "";
-        for (RequiredInterface service : reallyRequired) {
-            missingRequired += service + "\n";
-        }
-        if (missingRequired.length() > 0) {
-            throw new SystemAssemblyException(getName()
-                    + ": missing required services\n" + missingRequired);
-        }
+        addProvidersOfRequiredInterfaces(provided);
+        validateRequiredProvidedMatch(provided, required);
     }
 
-    private List<RequiredInterface> validateRequiredProvidedMatch(
+    /**
+     * 
+     * @param aProvided
+     *            All provided interfaces.
+     * @param aRequired
+     *            All required interfaces.
+     * @return
+     */
+    private void validateRequiredProvidedMatch(
             List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
-        List<RequiredInterface> reallyRequired = new ArrayList<RequiredInterface>(
-                aRequired);
-        // Compute all required interfaces that are not provided
-
-        for (ProvidedInterface service : aProvided) {
-            List<RequiredInterface> fulfilled = Arrays
-                    .asList(filterRequiredServices(service, reallyRequired));
-            reallyRequired.removeAll(fulfilled);
-        }
-        // Now remove all optional interfaces from the list.
-        for (Iterator<RequiredInterface> i = reallyRequired.iterator(); i
-                .hasNext();) {
-            RequiredInterface req = i.next();
-            if (req.isOptional()) {
-                i.remove();
-            }
+
+        for (Component component : _components) {
+            initializeProvidersForRequiredInterfaces(aProvided, component, true);
         }
-        // Now the remaining interfaces should be covered by the required
-        // list.
-        reallyRequired.removeAll(Arrays.asList(getRequiredInterfaces()));
-        return reallyRequired;
     }
 
     private void validateRequiredInterfaces(List<RequiredInterface> aRequired) {
@@ -216,7 +197,8 @@ public class Container extends AbstractComponent<Scope> {
         }
     }
 
-    private void validateProvidedInterfaces(List<ProvidedInterface> aProvided) {
+    private void validateProvidedInterfacesArePresent(
+            List<ProvidedInterface> aProvided) {
         for (ProvidedInterface service : getProvidedInterfaces()) {
             // TODO provided interfaces by components could be
             // provide subclasses or implementations of the
@@ -270,26 +252,13 @@ public class Container extends AbstractComponent<Scope> {
 
         List<ProvidedInterface> allProvided = new ArrayList<ProvidedInterface>();
 
-        // all interfaces from the required list of this container are
-        // provided to the components inside it.
-        RequiredInterface[] required = getRequiredInterfaces();
-        for (RequiredInterface intf : required) {
-            ProvidedInterface provider = intf.getProvider();
-            if (provider != null) {
-                allProvided.add(provider);
-            } else {
-                if (!intf.isOptional()) {
-                    throw new SystemAssemblyException(getQualifiedName()
-                            + ": required interface '" + intf
-                            + "' is not provided");
-                }
-            }
-        }
+        addProvidersOfRequiredInterfaces(allProvided);
 
         List<Component> started = new ArrayList<Component>();
         for (Component component : _components) {
             try {
-                checkAllRequiredServicesAlreadyProvided(allProvided, component);
+                initializeProvidersForRequiredInterfaces(allProvided,
+                        component, false);
 
                 // Start the service.
                 Object runtime = component.start(scope);
@@ -312,6 +281,25 @@ public class Container extends AbstractComponent<Scope> {
         return scope;
     }
 
+    private void addProvidersOfRequiredInterfaces(
+            List<ProvidedInterface> allProvided) {
+        // all interfaces from the required list of this container are
+        // provided to the components inside it.
+        RequiredInterface[] required = getRequiredInterfaces();
+        for (RequiredInterface intf : required) {
+            ProvidedInterface provider = intf.getProvider();
+            if (provider != null) {
+                allProvided.add(provider);
+            } else {
+                if (!intf.isOptional()) {
+                    throw new SystemAssemblyException(getQualifiedName()
+                            + ": required interface '" + intf
+                            + "' is not provided");
+                }
+            }
+        }
+    }
+
     private void stopAlreadyStartedComponents(List<Component> aStarted,
             Scope aScope) {
         // an exception occurred, stop the successfully started
@@ -326,8 +314,20 @@ public class Container extends AbstractComponent<Scope> {
         }
     }
 
-    private void checkAllRequiredServicesAlreadyProvided(
-            List<ProvidedInterface> aAllProvided, Component aComponent) {
+    /**
+     * Sets the provided interface or a component.
+     * 
+     * @param aAllProvided
+     *            All available provided interfaces.
+     * @param aComponent
+     *            Component whose required interfaces we are looking at.
+     * @param aValidateOnly
+     *            If true then the provider will not be set for required
+     *            interfaces.
+     */
+    private void initializeProvidersForRequiredInterfaces(
+            List<ProvidedInterface> aAllProvided, Component aComponent,
+            boolean aValidateOnly) {
         // Check if all required services are already provided by
         // earlier
         // systems.
@@ -336,7 +336,9 @@ public class Container extends AbstractComponent<Scope> {
             ProvidedInterface[] filtered = filterProvidedServices(descriptor,
                     aAllProvided);
             if (filtered.length == 1) {
-                descriptor.setProvider(filtered[0]);
+                if (!aValidateOnly) {
+                    descriptor.setProvider(filtered[0]);
+                }
             } else if (filtered.length > 1) {
                 throw new SystemAssemblyException(
                         "Service '"
index 8b6c61e85fbe873feb02034a55154ed87d2b6efe..90723ed1c93c4f6271448cf19622ed0eb8166dbe 100644 (file)
@@ -84,7 +84,6 @@ public class ContainerTest extends TestCase {
                Container container = new Container("root", new Component[] {
                                environment, application }, new ProvidedInterface[0],
                                new RequiredInterface[0]);
-
                Scope scope = container.start();
                assertTrue(container.isSealed());
                AssertionUtils.assertEquals(new String[] { "start.environment",
@@ -164,6 +163,7 @@ public class ContainerTest extends TestCase {
                                        new ProvidedInterface[] { new DefaultProvidedInterface(
                                                        "float", Float.class) },
                                        new DefaultRequiredInterface[0]);
+                       system.validate(); 
                } catch (SystemAssemblyException e) {
                        return;
                }