001: /*
002: * <copyright>
003: *
004: * Copyright 2002-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.core.adaptivity;
028:
029: import java.util.ArrayList;
030: import java.util.Collection;
031: import java.util.HashSet;
032: import java.util.List;
033: import java.util.Set;
034:
035: import org.cougaar.core.blackboard.IncrementalSubscription;
036: import org.cougaar.core.component.ServiceBroker;
037: import org.cougaar.core.component.ServiceProvider;
038: import org.cougaar.core.plugin.ComponentPlugin;
039: import org.cougaar.core.service.LoggingService;
040: import org.cougaar.core.service.OperatingModeService;
041: import org.cougaar.util.Collectors;
042: import org.cougaar.util.KeyedSet;
043: import org.cougaar.util.Thunk;
044: import org.cougaar.util.UnaryPredicate;
045:
046: /**
047: * This Plugin serves as an OperatingModeServiceProvider. It
048: * subscribes to {@link OperatingMode}s using a subscription allowing
049: * immediate access to individual OperatingModes by name. Provides
050: * OperatingModeService to components needing name-based access to
051: * OperatingModes.
052: **/
053: public class OperatingModeServiceProvider extends ComponentPlugin
054: implements ServiceProvider {
055: /**
056: * A {@link KeyedSet} for sets of OperatingModes keyed by name.
057: **/
058: private static class OperatingModeSet extends KeyedSet {
059: public OperatingModeSet() {
060: super ();
061: makeSynchronized();
062: }
063:
064: protected Object getKey(Object o) {
065: OperatingMode om = (OperatingMode) o;
066: return om.getName();
067: }
068:
069: public OperatingMode getOperatingMode(String name) {
070: return (OperatingMode) inner.get(name);
071: }
072: }
073:
074: /**
075: * An implementation of OperatingModeService in terms of the
076: * information in the OperatingModeSet.
077: **/
078: private class OperatingModeServiceImpl implements
079: OperatingModeService {
080: public void addListener(OperatingModeService.Listener l) {
081: synchronized (listeners) {
082: listeners.add(l);
083: }
084: }
085:
086: public void removeListener(OperatingModeService.Listener l) {
087: synchronized (listeners) {
088: listeners.remove(l);
089: }
090: }
091:
092: public OperatingMode getOperatingModeByName(String knobName) {
093: synchronized (omSet) {
094: return omSet.getOperatingMode(knobName);
095: }
096: }
097:
098: public Set getAllOperatingModeNames() {
099: synchronized (omSet) {
100: return new HashSet(omSet.keySet());
101: }
102: }
103: }
104:
105: private static UnaryPredicate operatingModePredicate = new UnaryPredicate() {
106: public boolean execute(Object o) {
107: return o instanceof OperatingMode;
108: }
109: };
110:
111: LoggingService logger;
112: private OperatingModeSet omSet = new OperatingModeSet();
113: private IncrementalSubscription operatingModes;
114: private List listeners = new ArrayList(2);
115: private Thunk listenerAddThunk = new Thunk() {
116: public void apply(Object o) {
117: OperatingModeService.Listener l = (OperatingModeService.Listener) o;
118: if (l.wantAdds())
119: blackboard.publishChange(o);
120: }
121: };
122: private Thunk listenerChangeThunk = new Thunk() {
123: public void apply(Object o) {
124: OperatingModeService.Listener l = (OperatingModeService.Listener) o;
125: if (l.wantChanges())
126: blackboard.publishChange(o);
127: }
128: };
129: private Thunk listenerRemoveThunk = new Thunk() {
130: public void apply(Object o) {
131: OperatingModeService.Listener l = (OperatingModeService.Listener) o;
132: if (l.wantRemoves())
133: blackboard.publishChange(o);
134: }
135: };
136:
137: /**
138: * Override base class method to register our service with the
139: * service broker.
140: **/
141: public void load() {
142: super .load();
143: getServiceBroker().addService(OperatingModeService.class, this );
144: logger = (LoggingService) getServiceBroker().getService(this ,
145: LoggingService.class, null);
146: }
147:
148: /**
149: * Override base class method to unregister our service with the
150: * service broker.
151: **/
152: public void unload() {
153: getServiceBroker().revokeService(OperatingModeService.class,
154: this );
155: super .unload();
156: }
157:
158: /**
159: * Standard setupSubscriptions subscribes to all OperatingModes.
160: **/
161: public void setupSubscriptions() {
162: synchronized (omSet) {
163: operatingModes = (IncrementalSubscription) getBlackboardService()
164: .subscribe(operatingModePredicate);
165: omSet.addAll(operatingModes);
166: }
167: }
168:
169: /**
170: * Standard execute method does nothing. Our subscription
171: * automatically maintains the information of interest in omSet
172: * where it is referenced directly by the service API.
173: **/
174: public void execute() {
175: synchronized (omSet) {
176: if (operatingModes.hasChanged()) {
177: Collection c;
178: c = operatingModes.getAddedCollection();
179: if (c.size() > 0) {
180: omSet.addAll(c);
181: if (logger.isDebugEnabled())
182: logger.debug("OM Added");
183: Collectors.apply(listenerAddThunk, listeners);
184: }
185: c = operatingModes.getChangedCollection();
186: if (c.size() > 0) {
187: if (logger.isDebugEnabled())
188: logger.debug("OM Changed");
189: Collectors.apply(listenerChangeThunk, listeners);
190: }
191: c = operatingModes.getRemovedCollection();
192: if (c.size() > 0) {
193: omSet.removeAll(c);
194: if (logger.isDebugEnabled())
195: logger.debug("OM Removed");
196: Collectors.apply(listenerRemoveThunk, listeners);
197: }
198: }
199: }
200: }
201:
202: /**
203: * Gets (creates) an implementation of the OperatingModeService.
204: * This is part of our implementation of the ServiceProvider API.
205: **/
206: public Object getService(ServiceBroker sb, Object requestor,
207: Class serviceClass) {
208: if (serviceClass == OperatingModeService.class) {
209: return new OperatingModeServiceImpl();
210: }
211: throw new IllegalArgumentException(getClass()
212: + " does not furnish " + serviceClass);
213: }
214:
215: /**
216: * Releases an implementation of the OperatingModeService.
217: * This is part of our implementation of the ServiceProvider API.
218: **/
219: public void releaseService(ServiceBroker sb, Object requestor,
220: Class serviceClass, Object svc) {
221: if (serviceClass != OperatingModeService.class
222: || svc.getClass() != OperatingModeServiceImpl.class) {
223: throw new IllegalArgumentException(getClass()
224: + " did not furnish " + svc);
225: }
226: }
227: }
|