updated coding rules.
[utils] / system / general / src / main / java / org / wamblee / system / core / AbstractComponent.java
index b202f285412040a8a42b13bc9aba4a3684f26636..579fd27435907d4ee9c0db8466fb1bb12db71270 100644 (file)
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- */ 
+ */
 package org.wamblee.system.core;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.List;
-import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -27,20 +26,20 @@ import org.apache.commons.logging.LogFactory;
 /**
  * Abstract subsystem class making it easy to implement new subsystems.
  */
-public abstract class AbstractComponent implements Component {
+public abstract class AbstractComponent<Type> implements Component<Type> {
 
        private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
 
-       private Status _status;
-       private String _context; 
-       private String _name; 
-       private List<ProvidedInterface> _provided;
-       private List<RequiredInterface> _required;
-       private Set<ProvidedInterface> _running;
-       
+       private ThreadLocal<List<ProvidedInterface>> remaining;
+
+       private String context;
+       private String name;
+       private List<ProvidedInterface> provided;
+       private List<RequiredInterface> required;
+
        /**
         * Constructs the subsystem.
-        *
+        * 
         * @param aName
         *            Name of the system.
         * @param aProvided
@@ -48,123 +47,167 @@ public abstract class AbstractComponent implements Component {
         * @param aRequired
         *            Required services.
         */
-       protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
-                       RequiredInterface[] aRequired) {
-               _status = Status.NOT_STARTED;
-               _context = null; 
-               _name = aName;
-               _provided = new ArrayList<ProvidedInterface>();
-               _provided.addAll(Arrays.asList(aProvided));
-               _required = new ArrayList<RequiredInterface>();
-               _required.addAll(Arrays.asList(aRequired));
-               _running = new HashSet<ProvidedInterface>();
+       protected AbstractComponent(String aName, List<ProvidedInterface> aProvided,
+                       List<RequiredInterface> aRequired) {
+               remaining = new ThreadLocal<List<ProvidedInterface>>();
+               context = null;
+               name = aName;
+               provided = new ArrayList<ProvidedInterface>(aProvided);
+               required = new ArrayList<RequiredInterface>(aRequired); 
        }
        
-       @Override
-       public Status getStatus() {
-               return _status; 
+       /**
+     * Constructs the subsystem.
+     * 
+     * @param aName
+     *            Name of the system.
+     * @param aProvided
+     *            Provided services.
+     * @param aRequired
+     *            Required services.
+     */
+    protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
+            RequiredInterface[] aRequired) {
+        this(aName, Arrays.asList(aProvided), Arrays.asList(aRequired));
+    }
+       
+       protected AbstractComponent(String aName) {
+               this(aName, new ProvidedInterface[0], new RequiredInterface[0]);
        }
-
+       
+       public AbstractComponent<Type> addProvidedInterface(ProvidedInterface aProvided) { 
+               provided.add(aProvided);
+               return this; 
+       }
+       
+       public AbstractComponent<Type> addRequiredInterface(RequiredInterface aRequired) { 
+               required.add(aRequired);
+               return this;
+       }
+       
        @Override
        public final String getName() {
-               return _name;
+               return name;
        }
-       
+
        @Override
        public void addContext(String aContext) {
-               if (_context == null ) { 
-                       _context = aContext; 
-               }
-               else { 
-                       _context = aContext + "." + _context;
+               if (context == null) {
+                       context = aContext;
+               } else {
+                       context = aContext + "." + context;
                }
        }
        
+       @Override
+       public String getContext() {
+               return context;
+       }
+
        @Override
        public String getQualifiedName() {
-               if ( _context == null ) { 
-                       return getName(); 
+               if (context == null) {
+                       return getName();
                }
-               return _context + "." + getName(); 
+               return context + "." + getName();
        }
 
        @Override
-       public final ProvidedInterface[] getProvidedInterfaces() {
-               return _provided.toArray(new ProvidedInterface[0]);
+       public final List<ProvidedInterface> getProvidedInterfaces() {
+               return Collections.unmodifiableList(provided);
        }
 
        @Override
-       public final RequiredInterface[] getRequiredInterfaces() {
-               return _required.toArray(new RequiredInterface[0]);
+       public final List<RequiredInterface> getRequiredInterfaces() {
+               return Collections.unmodifiableList(required);
        }
 
        @Override
-       public final void start() {
-               LOG.info("Initializing '" + getQualifiedName() + "'");
-               doStart();
-               _status = Status.RUNNING;
-               if ( _running.size() != _provided.size()) { 
-                       List<ProvidedInterface> remaining = 
-                               new ArrayList<ProvidedInterface>(_provided);
-                       remaining.removeAll(_running);
-                       throw new SystemAssemblyException(getQualifiedName() + ": not all services were started, missing " + remaining);
+       public final Type start(Scope aScope) {
+               LOG.info("Initialization starting '" + getQualifiedName() + "'");
+               List<ProvidedInterface> oldRemaining = remaining.get();
+               remaining.set(new ArrayList<ProvidedInterface>(getProvidedInterfaces()));
+               try {
+                       Type runtime = doStart(aScope);
+                       checkNotStartedInterfaces();
+                       LOG.info("Initialization finished '" + getQualifiedName() + "'");
+                       return runtime;
+               } finally {
+                       remaining.set(oldRemaining);
+               }
+       }
+
+       private void checkNotStartedInterfaces() {
+               if (remaining.get().size() > 0) {
+                       String notProvided = "";
+                       for (ProvidedInterface provided : remaining.get()) {
+                               notProvided += "\nComponent " + getQualifiedName()
+                                               + " did not start interface " + provided;
+                       }
+                       throw new SystemAssemblyException(notProvided);
                }
        }
 
        /**
         * Must be implemented for initializing the subsystem. The implementation
-        * must call {@link #addService(Service)} for each service that is started.
+        * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for each service that is started.
+        * 
+        * @return Returns the runtime of the component.
         */
-       protected abstract void doStart();
+       protected abstract Type doStart(Scope aScope);
 
        /**
         * Implementations must call this method to indicate that a new service has
         * been started.
         * 
+        * @param aDescriptor
+        *            Provided interface.
         * @param aService
-        *            Service.
+        *            Implementation of the interface.
+        * @param aScope
+        *            scope in which to publish the implementation.
         */
-       protected final void addInterface(
-                       ProvidedInterface aDescriptor, Object aService) {
-               LOG.info("Interface '" + getQualifiedName() + "." + aDescriptor.getName() + "' started.");
-               _running.add(aDescriptor);
-               aDescriptor.publish(aService);
+       protected final void addInterface(ProvidedInterface aDescriptor,
+                       Object aService, Scope aScope) {
+               LOG.info("Interface '" + getQualifiedName() + "."
+                               + aDescriptor.getName() + "' started.");
+               if ( !remaining.get().remove(aDescriptor) ) { 
+                   throw new SystemAssemblyException("Component '" + getQualifiedName() + "' started an unexpected interface '" + 
+                           aDescriptor + "' that was not registerd as a provided interface before");
+               }
+               aScope.publishInterface(aDescriptor, aService);
        }
 
        @Override
-       public ProvidedInterface[] getRunningInterfaces() {
-               return _running.toArray(new ProvidedInterface[0]);
-       }
-       
-       @Override
-       public void stop() {
-               doStop();
-               if ( _running.size() > 0 ) { 
-                       // programming error.
-                       throw new RuntimeException(getQualifiedName() + ": still services running after the stop call.");
-               }
-               _status = Status.STOPPED;
-       }
-       
-       protected abstract void doStop();
-       
-       /**
-        * Implementations must call this method to indicate that a running service has
-        * been stopped.
-        * 
-        * @param aService
-        *            Service.
-        */
-       protected final void removeInterface(
-                       ProvidedInterface aDescriptor) {
-               LOG.info("Interface '" + getQualifiedName() + "." + aDescriptor.getName() + "' stopped.");
-               _running.remove(aDescriptor);
-               aDescriptor.publish(null);
+       public void stop(Type aRuntime) {
+           LOG.info("Stopping initiated '" + getQualifiedName() + "'");
+               doStop(aRuntime);
+               LOG.info("Stopping completed '" + getQualifiedName() + "'");
        }
 
+       protected abstract void doStop(Type aRuntime);
+
        @Override
        public String toString() {
                return getQualifiedName();
        }
+       
+       public ProvidedInterface findProvidedInterface(String aName) { 
+           for (ProvidedInterface provided: getProvidedInterfaces()) { 
+               if ( provided.getName().equals(aName)) { 
+                   return provided; 
+               }
+           }
+           return null; 
+       }
+       
+       public RequiredInterface findRequiredInterface(String aName) { 
+           for (RequiredInterface required: getRequiredInterfaces()) { 
+               if ( required.getName().equals(aName)) { 
+                   return required; 
+               }
+           }
+           return null; 
+       }
 
 }