Implemented restrictions on component connections in the Container.
[utils] / system / general / src / main / java / org / wamblee / system / core / Container.java
index 1eaebf432a0e1c239189e621e3d0a35b9275f1ed..8075abab3c7fcc703b5cbcdc9a22c2e105a58096 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.wamblee.general.Pair;
 
 /**
  * Container consisting of multiple components.
@@ -37,29 +38,23 @@ public class Container extends AbstractComponent<Scope> {
 
     private List<Component> _components;
     private Set<String> _componentNames;
+    private CompositeInterfaceRestriction _restriction; 
     private boolean _sealed;
 
-    public static RequiredInterface[] filterRequiredServices(
-            ProvidedInterface aProvided,
-            Collection<RequiredInterface> aDescriptors) {
-        List<RequiredInterface> required = new ArrayList<RequiredInterface>();
-        for (RequiredInterface descriptor : aDescriptors) {
-            if (descriptor.implementedBy(aProvided)) {
-                required.add(descriptor);
-            }
-        }
-        return required.toArray(new RequiredInterface[0]);
-    }
 
     public static ProvidedInterface[] filterProvidedServices(
-            RequiredInterface aRequired, Collection<ProvidedInterface> aProvided) {
-        List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
-        for (ProvidedInterface descriptor : aProvided) {
-            if (aRequired.implementedBy(descriptor)) {
-                provided.add(descriptor);
+            Component aClient, RequiredInterface aRequired, Collection<Pair<ProvidedInterface,Component>> aProvided,
+            InterfaceRestriction aRestriction) {
+        List<ProvidedInterface> result = new ArrayList<ProvidedInterface>();
+        for (Pair<ProvidedInterface,Component> descriptor : aProvided) {
+            ProvidedInterface provided = descriptor.getFirst();
+            Component server = descriptor.getSecond();
+            if (aRequired.implementedBy(provided) && 
+                    !aRestriction.isViolated(aClient, aRequired, server, provided)) {
+                result.add(provided);
             }
         }
-        return provided.toArray(new ProvidedInterface[0]);
+        return result.toArray(new ProvidedInterface[0]);
     }
 
     /**
@@ -80,6 +75,7 @@ public class Container extends AbstractComponent<Scope> {
         _components = new ArrayList<Component>();
 
         _componentNames = new HashSet<String>();
+        _restriction = new CompositeInterfaceRestriction();
         _sealed = false;
         for (Component component : aComponents) {
             addComponent(component);
@@ -108,6 +104,18 @@ public class Container extends AbstractComponent<Scope> {
         aComponent.addContext(getQualifiedName());
         return this;
     }
+    
+    /**
+     * Adds an interface restriction for explicitly configuring the 
+     * relations between components. 
+     * @param aRestriction Restriction to add. 
+     * @return Reference to this to allow call chaining. 
+     */
+    public Container addRestriction(InterfaceRestriction aRestriction) {
+        checkSealed(); 
+        _restriction.add(aRestriction);
+        return this; 
+    }
 
     @Override
     public Container addProvidedInterface(ProvidedInterface aProvided) {
@@ -235,8 +243,8 @@ public class Container extends AbstractComponent<Scope> {
 
         Scope scope = new DefaultScope(getProvidedInterfaces(), aExternalScope);
 
-        List<ProvidedInterface> allProvided = new ArrayList<ProvidedInterface>();
-
+        List<Pair<ProvidedInterface,Component>> allProvided = new ArrayList<Pair<ProvidedInterface,Component>>();
+        
         addProvidersOfRequiredInterfaces(allProvided);
 
         List<Component> started = new ArrayList<Component>();
@@ -255,7 +263,9 @@ public class Container extends AbstractComponent<Scope> {
                 // add all provided services
                 ProvidedInterface[] provided = component
                         .getProvidedInterfaces();
-                allProvided.addAll(Arrays.asList(provided));
+                for (ProvidedInterface prov: provided) { 
+                    allProvided.add(new Pair<ProvidedInterface,Component>(prov, component));
+                }
             } catch (SystemAssemblyException e) {
                 throw e;
             } catch (RuntimeException e) {
@@ -269,14 +279,14 @@ public class Container extends AbstractComponent<Scope> {
     }
 
     private void addProvidersOfRequiredInterfaces(
-            List<ProvidedInterface> allProvided) {
+            List<Pair<ProvidedInterface,Component>> 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);
+                allProvided.add(new Pair<ProvidedInterface,Component>(provider, null));
             } else {
                 if (!intf.isOptional()) {
                     throw new SystemAssemblyException(getQualifiedName()
@@ -314,15 +324,15 @@ public class Container extends AbstractComponent<Scope> {
      *            interfaces.
      */
     private void initializeProvidersForRequiredInterfaces(
-            List<ProvidedInterface> aAllProvided, Component aComponent,
+            List<Pair<ProvidedInterface,Component>> aAllProvided, Component aComponent,
             boolean aValidateOnly) {
         // Check if all required services are already provided by
         // earlier
         // systems.
 
         for (RequiredInterface descriptor : aComponent.getRequiredInterfaces()) {
-            ProvidedInterface[] filtered = filterProvidedServices(descriptor,
-                    aAllProvided);
+            ProvidedInterface[] filtered = filterProvidedServices(aComponent, descriptor,
+                    aAllProvided, _restriction);
             if (filtered.length == 1) {
                 if (!aValidateOnly) {
                     descriptor.setProvider(filtered[0]);