package org.wamblee.system.container;
import java.util.ArrayList;
-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;
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;
private static final Log LOG = LogFactory.getLog(Container.class);
private List<Component> _components;
- private Set<String> _componentNames;
private CompositeEdgeFilter _edgeFilter;
private boolean _sealed;
* Required services by the container.
*/
public Container(String aName, Component[] aComponents,
- ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
+ List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
super(aName, aProvided, aRequired);
_components = new ArrayList<Component>();
- _componentNames = new HashSet<String>();
_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],
+ 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;
}
public void connectRequiredProvided(String aClientComponent, String aRequiredInterface,
String aServerComponent, String aProvidedInterface) {
checkSealed();
- // TODO validate
+ 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));
}
public void connectExternalRequired(String aComponent, String aRequiredInterface,
String aExternalRequiredInterface) {
checkSealed();
- // TODO validate
+ 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();
- // TODO validate
+ 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
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();
private ComponentGraph doStartOptionalDryRun(Scope aScope, boolean aDryRun) {
ComponentGraph graph = createComponentGraph();
graph.validate();
- if (!aDryRun) {
- graph.link();
- }
+ graph.link();
LOG.info("Starting '" + getQualifiedName() + "'");
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 extends NamedInterface> T findInterface(List<T> aInterfaces, String aInterfaceName) {
+ for (T intf: aInterfaces) {
+ if ( intf.getName().equals(aInterfaceName)) {
+ return intf;
+ }
+ }
+ return null;
+ }
}