(no commit message)
[utils] / system / general / src / main / java / org / wamblee / system / core / AbstractComponent.java
1 /*
2  * Copyright 2007 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */ 
16 package org.wamblee.system.core;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Set;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 /**
28  * Abstract subsystem class making it easy to implement new subsystems.
29  */
30 public abstract class AbstractComponent implements Component {
31
32         private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
33
34         private String _context; 
35         private String _name; 
36         private List<ProvidedInterface> _provided;
37         private List<RequiredInterface> _required;
38         private Set<ProvidedInterface> _running;
39         
40         /**
41          * Constructs the subsystem.
42          *
43          * @param aName
44          *            Name of the system.
45          * @param aProvided
46          *            Provided services.
47          * @param aRequired
48          *            Required services.
49          */
50         protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
51                         RequiredInterface[] aRequired) {
52                 _context = null; 
53                 _name = aName;
54                 _provided = new ArrayList<ProvidedInterface>();
55                 _provided.addAll(Arrays.asList(aProvided));
56                 _required = new ArrayList<RequiredInterface>();
57                 _required.addAll(Arrays.asList(aRequired));
58                 _running = new HashSet<ProvidedInterface>();
59         }
60
61         @Override
62         public final String getName() {
63                 return _name;
64         }
65         
66         @Override
67         public void addContext(String aContext) {
68                 if (_context == null ) { 
69                         _context = aContext; 
70                 }
71                 else { 
72                         _context = aContext + "." + _context;
73                 }
74         }
75         
76         @Override
77         public String getQualifiedName() {
78                 if ( _context == null ) { 
79                         return getName(); 
80                 }
81                 return _context + "." + getName(); 
82         }
83
84         @Override
85         public final ProvidedInterface[] getProvidedInterfaces() {
86                 return _provided.toArray(new ProvidedInterface[0]);
87         }
88
89         @Override
90         public final RequiredInterface[] getRequiredInterfaces() {
91                 return _required.toArray(new RequiredInterface[0]);
92         }
93
94         @Override
95         public final void start() {
96                 LOG.info("Initializing '" + getQualifiedName() + "'");
97                 doStart();
98                 if ( _running.size() != _provided.size()) { 
99                         List<ProvidedInterface> remaining = 
100                                 new ArrayList<ProvidedInterface>(_provided);
101                         remaining.removeAll(_running);
102                         throw new SystemAssemblyException(getQualifiedName() + ": not all services were started, missing " + remaining);
103                 }
104         }
105
106         /**
107          * Must be implemented for initializing the subsystem. The implementation
108          * must call {@link #addService(Service)} for each service that is started.
109          */
110         protected abstract void doStart();
111
112         /**
113          * Implementations must call this method to indicate that a new service has
114          * been started.
115          * 
116          * @param aService
117          *            Service.
118          */
119         protected final void addInterface(
120                         ProvidedInterface aDescriptor, Object aService) {
121                 LOG.info("Interface '" + getQualifiedName() + "." + aDescriptor.getName() + "' started.");
122                 _running.add(aDescriptor);
123                 aDescriptor.publish(aService);
124         }
125
126         @Override
127         public ProvidedInterface[] getRunningInterfaces() {
128                 return _running.toArray(new ProvidedInterface[0]);
129         }
130         
131         @Override
132         public void stop() {
133                 doStop();
134                 if ( _running.size() > 0 ) { 
135                         // programming error.
136                         throw new RuntimeException(getQualifiedName() + ": still services running after the stop call.");
137                 }
138         }
139         
140         protected abstract void doStop();
141         
142         /**
143          * Implementations must call this method to indicate that a running service has
144          * been stopped.
145          * 
146          * @param aService
147          *            Service.
148          */
149         protected final void removeInterface(
150                         ProvidedInterface aDescriptor) {
151                 LOG.info("Interface '" + getQualifiedName() + "." + aDescriptor.getName() + "' stopped.");
152                 _running.remove(aDescriptor);
153                 aDescriptor.publish(null);
154         }
155
156         @Override
157         public String toString() {
158                 return getQualifiedName();
159         }
160
161 }