X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fcontainer%2FContainer.java;h=9669cb216dd65a28e0f75670e3f0a9d106b2efb0;hb=e1975449f1bf16ccb441632d68e440f3e3704a79;hp=349e59782cee2eae1251ab216d1648a82f12d815;hpb=aa78ce0aeaa36871bd926eefa1eabf9cb3254c7a;p=utils diff --git a/system/general/src/main/java/org/wamblee/system/container/Container.java b/system/general/src/main/java/org/wamblee/system/container/Container.java index 349e5978..9669cb21 100644 --- a/system/general/src/main/java/org/wamblee/system/container/Container.java +++ b/system/general/src/main/java/org/wamblee/system/container/Container.java @@ -16,10 +16,8 @@ package org.wamblee.system.container; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; +import java.util.Arrays; import java.util.List; -import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -27,11 +25,16 @@ import org.wamblee.general.Pair; import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.Component; import org.wamblee.system.core.DefaultScope; +import org.wamblee.system.core.NamedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; +import org.wamblee.system.graph.CompositeEdgeFilter; import org.wamblee.system.graph.component.ComponentGraph; +import org.wamblee.system.graph.component.ConnectExternalProvidedProvidedFilter; +import org.wamblee.system.graph.component.ConnectRequiredExternallyRequiredEdgeFilter; +import org.wamblee.system.graph.component.ConnectRequiredProvidedEdgeFilter; /** * Container consisting of multiple components. @@ -43,8 +46,7 @@ public class Container extends AbstractComponent { private static final Log LOG = LogFactory.getLog(Container.class); private List _components; - private Set _componentNames; - private CompositeInterfaceRestriction _restriction; + private CompositeEdgeFilter _edgeFilter; private boolean _sealed; /** @@ -60,17 +62,33 @@ public class Container extends AbstractComponent { * Required services by the container. */ public Container(String aName, Component[] aComponents, - ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { + List aProvided, List aRequired) { super(aName, aProvided, aRequired); _components = new ArrayList(); - _componentNames = new HashSet(); - _restriction = new CompositeInterfaceRestriction(); + _edgeFilter = new CompositeEdgeFilter(); _sealed = false; for (Component component : aComponents) { addComponent(component); } } + + /** + * Constructs the container + * + * @param aName + * Name of the container + * @param aComponents + * Components. + * @param aProvided + * Provided services of the container + * @param aRequired + * Required services by the container. + */ + public Container(String aName, Component[] aComponents, + ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { + this(aName, aComponents, Arrays.asList(aProvided), Arrays.asList(aRequired)); + } public Container(String aName) { this(aName, new Component[0], new ProvidedInterface[0], @@ -85,30 +103,109 @@ public class Container extends AbstractComponent { + aComponent.getName() + "' is already part of another hierarchy"); } - if (_componentNames.contains(aComponent.getName())) { + if ( findComponent(aComponent.getName()) != null ) { throw new SystemAssemblyException("Duplicate component '" + aComponent.getName() + "'"); } _components.add(aComponent); - _componentNames.add(aComponent.getName()); 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. + * Explictly connects required and provided interfaces. + * @param aClientComponent Client component, may not be null. + * @param aRequiredInterface Required interface. If null it means all required interfaces. + * @param aServerComponent Server component to connect to. If null, it means that no server components + * may be connected to and the provider of the required interface will be null. + * @param aProvidedInterface Provided interface. If null, it means that there is no restriction on the + * name of the provided interface and that it is automatically selected. */ - public Container addRestriction(InterfaceRestriction aRestriction) { + public void connectRequiredProvided(String aClientComponent, String aRequiredInterface, + String aServerComponent, String aProvidedInterface) { checkSealed(); - _restriction.add(aRestriction); - return this; + Component client = findComponent(aClientComponent); + Component server = findComponent(aServerComponent); + if ( client == null ) { + throw new SystemAssemblyException(getQualifiedName() + ": No component '" + aClientComponent + "' in the container"); + } + if ( aRequiredInterface != null ) { + if ( findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null ) { + throw new SystemAssemblyException( + getQualifiedName() + ": Component '" + aClientComponent + "' does not have a required interface named '" + + aRequiredInterface + "'"); + } + } + if ( server == null ) { + throw new SystemAssemblyException("No component '" + aClientComponent + "' in the container"); + } + if ( aProvidedInterface != null ) { + if ( findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { + throw new SystemAssemblyException( + getQualifiedName() + ": Component '" + aServerComponent + "' does not have a provided interface named '" + + aProvidedInterface + "'"); + } + } + _edgeFilter.add(new ConnectRequiredProvidedEdgeFilter(aClientComponent, aRequiredInterface, aServerComponent, aProvidedInterface)); + } + + /** + * Explicitly connects a externally required interface to an internally required interface. + * @param aComponent Component requiring the interface (must be non-null). + * @param aRequiredInterface Required interface of the component (must be non-null). + * @param aExternalRequiredInterface Externally required interface (must be non-null). + */ + public void connectExternalRequired(String aComponent, String aRequiredInterface, + String aExternalRequiredInterface) { + checkSealed(); + Component client = findComponent(aComponent); + if ( client == null ) { + throw new SystemAssemblyException(getQualifiedName() + ": No component '" + aComponent + "' in the container"); + } + if ( aRequiredInterface != null ) { + if ( findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null ) { + throw new SystemAssemblyException( + getQualifiedName() + ": Component '" + aComponent + "' does not have a required interface named '" + + aRequiredInterface + "'"); + } + } + if ( aExternalRequiredInterface != null) { + if ( findInterface(getRequiredInterfaces(), aExternalRequiredInterface) == null ) { + throw new SystemAssemblyException( + getQualifiedName() + ": container does not have a required interface named '" + + aExternalRequiredInterface + "'"); + } + } + _edgeFilter.add(new ConnectRequiredExternallyRequiredEdgeFilter( + aComponent, aRequiredInterface, aExternalRequiredInterface)); + } + + public void connectExternalProvided(String aExternalProvided, String aComponent, String aProvidedInterface) { + checkSealed(); + Component server = findComponent(aComponent); + + + if ( server == null ) { + throw new SystemAssemblyException("No component '" + aComponent + "' in the container"); + } + if ( aProvidedInterface != null ) { + if ( findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { + throw new SystemAssemblyException( + getQualifiedName() + ": Component '" + aComponent + "' does not have a provided interface named '" + + aProvidedInterface + "'"); + } + } + if ( aExternalProvided != null ) { + if ( findInterface(getProvidedInterfaces(), aExternalProvided) == null) { + throw new SystemAssemblyException( + getQualifiedName() + ": Container does not have a provided interface named '" + + aExternalProvided + "'"); + } + } + _edgeFilter.add(new ConnectExternalProvidedProvidedFilter(aExternalProvided, aComponent, aProvidedInterface)); } + @Override public Container addProvidedInterface(ProvidedInterface aProvided) { checkSealed(); @@ -174,9 +271,8 @@ public class Container extends AbstractComponent { @Override protected Scope doStart(Scope aExternalScope) { - checkSealed(); validate(); - Scope scope = new DefaultScope(getProvidedInterfaces(), aExternalScope); + Scope scope = new DefaultScope(getProvidedInterfaces().toArray(new ProvidedInterface[0]), aExternalScope); ComponentGraph graph = doStartOptionalDryRun(scope, false); exposeProvidedInterfaces(graph, aExternalScope, scope); seal(); @@ -195,9 +291,7 @@ public class Container extends AbstractComponent { private ComponentGraph doStartOptionalDryRun(Scope aScope, boolean aDryRun) { ComponentGraph graph = createComponentGraph(); graph.validate(); - if (!aDryRun) { - graph.link(); - } + graph.link(); LOG.info("Starting '" + getQualifiedName() + "'"); @@ -225,16 +319,16 @@ public class Container extends AbstractComponent { private ComponentGraph createComponentGraph() { ComponentGraph graph = new ComponentGraph(); for (RequiredInterface req : getRequiredInterfaces()) { - graph.addRequiredInterface(req); + graph.addRequiredInterface(this, req); } for (Component comp : _components) { graph.addComponent(comp); } for (ProvidedInterface prov: getProvidedInterfaces()) { - graph.addProvidedInterface(prov); + graph.addProvidedInterface(this, prov); } - graph.addRestriction(_restriction); + graph.addEdgeFilter(_edgeFilter); return graph; } @@ -267,4 +361,27 @@ public class Container extends AbstractComponent { throw new SystemAssemblyException("Container is sealed"); } } + + /** + * Finds a component based on the non-qualified name of the component. + * @param aName Component name. + * @return Component or null if not found. + */ + public Component findComponent(String aName) { + for (Component component: _components) { + if ( component.getName().equals(aName)) { + return component; + } + } + return null; + } + + private static T findInterface(List aInterfaces, String aInterfaceName) { + for (T intf: aInterfaces) { + if ( intf.getName().equals(aInterfaceName)) { + return intf; + } + } + return null; + } }