3bff0564b2829901633520e9138de98746e95be2
[utils] / system / general / src / main / java / org / wamblee / system / SystemAssembler.java
1 package org.wamblee.system;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 /**
12  * Assembler to control multiple subsystems. It makes sure that
13  * all dependencies are met and controls the order in which systems
14  * are initialized. 
15  */
16 public class SystemAssembler {
17
18         private static final Log LOG = LogFactory.getLog(SystemAssembler.class);
19
20         private static final String ROOT_CONTEXT_NAME = "root";
21         private String _context;
22         private SubSystem[] _systems;
23
24         /**
25          * Constructs the assembler. 
26          * @param aSystems Systems that must be assembled.
27          * @param aAvailableServices Available services from other systems
28          *  outside of the systems that this assembler manages.
29          */
30         public SystemAssembler(SubSystem[] aSystems, ServiceDescriptor[] aAvailableServices) {
31                 this(ROOT_CONTEXT_NAME, aSystems, aAvailableServices);
32         }
33
34         /**
35          * Constructs the assembler. 
36          * @param aContext Context (unique name) of the assembler. 
37          * @param aSystems Systems that must be assembled. 
38          * @param aAvailableServices Available services from other systems
39          *  outside of the systems that this assembler manages.
40          */
41         public SystemAssembler(String aContext, SubSystem[] aSystems, 
42                         ServiceDescriptor[] aAvailableServices) {
43                 _context = aContext;
44                 _systems = aSystems;
45                 validate(aAvailableServices);
46         }
47
48         /**
49          * Determines if the systems are ordered appropriately so that all
50          * dependencies are met.
51          */
52         private void validate(ServiceDescriptor[] aDescriptors) throws SystemAssemblyException {
53
54                 List<ServiceDescriptor> allProvided = new ArrayList<ServiceDescriptor>();
55                 for (ServiceDescriptor descriptor: aDescriptors) { 
56                         allProvided.add(descriptor);
57                 }
58                 for (SubSystem system : _systems) {
59                         // Check if all required services are already provided by earlier
60                         // systems.
61                         ServiceDescriptor[] required = system.getRequiredServices();
62                         for (ServiceDescriptor descriptor : required) {
63                                 if (!(allProvided.contains(descriptor))) {
64                                         throw new SystemAssemblyException(
65                                                         "Service '"
66                                                                         + descriptor
67                                                                         + "' required by system '"
68                                                                         + system
69                                                                         + "' is not provided by systems that are started earlier");
70                                 }
71                         }
72
73                         // add all provided services
74                         ServiceDescriptor[] provided = system.getProvidedServices();
75                         for (ServiceDescriptor descriptor : provided) {
76                                 allProvided.add(descriptor);
77                         }
78                 }
79         }
80
81         /**
82          * Starts the subsystems.
83          * @param aRequiredServices Services that are available from
84          *  other systems that have been started before. 
85          */
86         public void start(Service[] aRequiredServices) {
87                 LOG.info("Starting '" + _context + "'");
88                 Map<ServiceDescriptor, Service> allProvided = new HashMap<ServiceDescriptor, Service>();
89
90                 for (Service service : aRequiredServices) {
91                         allProvided.put(service.getDescriptor(), service);
92                 }
93                 for (SubSystem system : _systems) {
94                         ServiceDescriptor[] descriptors = system.getRequiredServices();
95                         List<Service> services = new ArrayList<Service>();
96                         for (ServiceDescriptor descriptor : descriptors) {
97                                 Service required = allProvided.get(descriptor);
98                                 if (required == null) {
99                                         throw new SystemAssemblyException("Service '" + descriptor
100                                                         + "' required by '" + system + "' is null.");
101                                 }
102                                 services.add(required);
103                         }
104                         Service[] provided = system.initialize(_context, services
105                                         .toArray(new Service[0]));
106                         for (Service service : provided) {
107                                 allProvided.put(service.getDescriptor(), service);
108                         }
109
110                 }
111         }
112
113 }