+ /**
+ * Creates a new AbstractComponent object.
+ *
+ */
+ 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;
+ }
+
+ @Override
+ public void addContext(String aContext) {
+ if (context == null) {
+ context = aContext;
+ } else {
+ context = aContext + "." + context;
+ }
+ }
+
+ @Override
+ public String getContext() {
+ return context;
+ }
+
+ @Override
+ public String getQualifiedName() {
+ if (context == null) {
+ return getName();
+ }
+
+ return context + "." + getName();
+ }
+
+ @Override
+ public final List<ProvidedInterface> getProvidedInterfaces() {
+ return Collections.unmodifiableList(provided);
+ }
+
+ @Override
+ public final List<RequiredInterface> getRequiredInterfaces() {
+ return Collections.unmodifiableList(required);
+ }
+
+ @Override
+ 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 #addInterface(ProvidedInterface, Object, Scope)} for
+ * each service that is started.
+ *
+ *
+ * @return Returns the runtime of the component.
+ */
+ 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
+ * Implementation of the interface.
+ * @param aScope
+ * scope in which to publish the implementation.
+ *
+ */
+ 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 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;
+ }