d9dc29be471126bdfeba4f818c4b2e859e5d6ff4
[utils] / system / general / src / main / java / org / wamblee / system / Container.java
1 package org.wamblee.system;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
9
10 import sun.util.LocaleServiceProviderPool.LocalizedObjectGetter;
11
12 /**
13  * Composite system consisting of multiple subsystems. 
14  *
15  * @author Erik Brakkee
16  */
17 public class Container extends AbstractComponent {
18
19         private static final Log LOG = LogFactory.getLog(Container.class);
20
21         private Component[] _systems;
22
23         /**
24          * Construcst the composite system. 
25          * @param aName Name of the system. 
26          * @param aRegistry Service registry.
27          * @param aSystems Subsystems. 
28          * @param aProvided Provided services of the system. 
29          * @param aRequired Required services by the system. 
30          */
31         public Container(String aName, Component[] aSystems,
32                         ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
33                 super(aName, aProvided, aRequired);
34                 _systems = aSystems;
35                 validate(aRequired);
36         }
37
38         /**
39          * Validates the subsystems together to check that there are
40          * no required services not in the required list and 
41          * no services in the provided list that cannot be provided. 
42          * Also logs a warning in case of superfluous requirements.  
43          */
44         private void validate(RequiredInterface[] aRequired) {
45                 List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
46                 for (Component system : _systems) {
47                         provided.addAll(Arrays.asList(system.getProvidedServices()));
48                 }
49
50                 List<RequiredInterface> required = new ArrayList<RequiredInterface>();
51                 for (Component system : _systems) {
52                         required.addAll(Arrays.asList(system.getRequiredServices()));
53                 }
54
55                 for (ProvidedInterface service : getProvidedServices()) {
56                         if (!(provided.contains(service))) {
57                                 throw new SystemAssemblyException(getName() + ": Service '" + service
58                                                 + "' is not provided by any of the subsystems");
59                         }
60                 }
61
62                 for (RequiredInterface service : getRequiredServices()) {
63                         if (!(required.contains(service))) {
64                                 info("Service '"
65                                                 + service
66                                                 + "' indicated as required is not actually required by any of the subsystems");
67                         }
68                 }
69
70                 List<RequiredInterface> reallyRequired = new ArrayList<RequiredInterface>(
71                                 required);
72                 // Compute all required interfaces that are not provided
73                 for (ProvidedInterface service : provided) {
74                         List<RequiredInterface> fulfilled = 
75                                 Arrays.asList(SystemAssembler.filterRequiredServices(service, 
76                                         reallyRequired));
77                         reallyRequired.removeAll(fulfilled); 
78                 }
79                 // Now the remaining interfaces should be covered by the required
80                 // list. 
81                 reallyRequired.removeAll(Arrays.asList(aRequired));
82                 
83                 String missingRequired = "";
84                 for (RequiredInterface service: reallyRequired) {
85                         missingRequired += service + "\n";
86                 }
87                 if ( missingRequired.length() > 0 ) { 
88                         throw new SystemAssemblyException(getName() + ": missing required services\n" + missingRequired);
89                 }
90         }
91
92         @Override
93         protected void doStart(String aContext) {
94                 List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
95                 
96                 // all interfaces from the required list of this container are
97                 // provided to the components inside it.
98                 RequiredInterface[] required = getRequiredServices();
99                 for (RequiredInterface intf: required) { 
100                     ProvidedInterface provider = intf.getProvider(); 
101                     if ( provider == null ) { 
102                         throw new SystemAssemblyException(aContext + ": required interface '" + intf +"' is not provided");
103                     }
104                         provided.add(intf.getProvider());
105                 }
106                 
107                 SystemAssembler assembler = new SystemAssembler( _systems, 
108                                 provided.toArray(new ProvidedInterface[0]));
109                 assembler.start();
110         }
111         
112         @Override
113         protected void doStop() {
114                 for (int i = _systems.length-1; i >= 0; i--) { 
115                         _systems[i].stop();
116                 }
117         }
118
119         private void info(String aMsg) {
120                 LOG.info(getName() + ": " + aMsg);
121         }
122
123 }