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.Iterator;
033:
034: import org.cougaar.core.blackboard.IncrementalSubscription;
035: import org.cougaar.core.component.ServiceBroker;
036: import org.cougaar.core.service.OperatingModeService;
037: import org.cougaar.core.service.PlaybookConstrainService;
038: import org.cougaar.util.UnaryPredicate;
039:
040: /**
041: * A PolicyManager that handles OperatingModePolicies
042: * For now, it listens for OperatingModePolicies and uses the
043: * PlaybookConstrainService to constrain the playbook with the OMPolicies.
044: * It also sets the values of OperatingModes for non-adaptive OMPolicies.
045: * In the future, it will forward InterAgentOperatingModePolicies to
046: * other entities.
047: */
048:
049: public class OperatingModePolicyManager extends ServiceUserPluginBase {
050: private PlaybookConstrainService playbookConstrainService;
051: private OperatingModeService operatingModeService;
052:
053: private static final Class[] requiredServices = {
054: PlaybookConstrainService.class, OperatingModeService.class };
055:
056: private static UnaryPredicate policyPredicate = new UnaryPredicate() {
057: public boolean execute(Object o) {
058: if (o instanceof OperatingModePolicy) {
059: if (o instanceof InterAgentOperatingModePolicy) {
060: InterAgentOperatingModePolicy iaomp = (InterAgentOperatingModePolicy) o;
061: return iaomp.appliesToThisAgent();
062: }
063: return true;
064: }
065: return false;
066: }
067: };
068:
069: private IncrementalSubscription policySubscription;
070:
071: private class OMPredicate implements UnaryPredicate {
072: private HashSet omnames;
073:
074: public OMPredicate() {
075: omnames = new HashSet(13);
076: }
077:
078: public void addOM(String om) {
079: omnames.add(om);
080: }
081:
082: public void removeOM(String om) {
083: omnames.remove(om);
084: }
085:
086: public boolean execute(Object o) {
087: if (o instanceof OperatingMode) {
088: OperatingMode om = (OperatingMode) o;
089: String bbOM = om.getName();
090: for (Iterator it = omnames.iterator(); it.hasNext();) {
091: String storedName = (String) it.next();
092: if (bbOM.equals(storedName)) {
093: return true;
094: }
095: }
096: }
097: return false;
098: }
099: }
100:
101: private IncrementalSubscription omSubscription;
102: private OMPredicate omPred;
103:
104: public OperatingModePolicyManager() {
105: super (requiredServices);
106: }
107:
108: public void setupSubscriptions() {
109: }
110:
111: private void reallySetupSubscriptions() {
112:
113: policySubscription = (IncrementalSubscription) blackboard
114: .subscribe(policyPredicate);
115:
116: omPred = new OMPredicate();
117: omSubscription = (IncrementalSubscription) blackboard
118: .subscribe(omPred);
119: }
120:
121: private boolean haveServices() {
122: if (playbookConstrainService != null)
123: return true;
124: if (acquireServices()) {
125: ServiceBroker sb = getServiceBroker();
126: playbookConstrainService = (PlaybookConstrainService) sb
127: .getService(this , PlaybookConstrainService.class,
128: null);
129: operatingModeService = (OperatingModeService) getServiceBroker()
130: .getService(this , OperatingModeService.class, null);
131: reallySetupSubscriptions();
132: return true;
133: }
134: return false;
135: }
136:
137: public void execute() {
138: if (haveServices()) {
139: if (policySubscription.hasChanged()) {
140: removePolicies(policySubscription
141: .getRemovedCollection());
142: changePolicies(policySubscription
143: .getChangedCollection());
144: addPolicies(policySubscription.getAddedCollection());
145: }
146:
147: // Missing OperatingModes may have shown up
148: if (omSubscription.hasChanged()) {
149: checkOMSubs();
150: }
151: }
152: }
153:
154: /**
155: * Constrain the playbook with the new policies
156: */
157: private void addPolicies(Collection newPolicies) {
158: if (logger.isInfoEnabled())
159: logger.info("Adding policy");
160: for (Iterator it = newPolicies.iterator(); it.hasNext();) {
161: OperatingModePolicy omp = (OperatingModePolicy) it.next();
162: if (nonAdaptive(omp)) {
163: playbookConstrainService.constrain(omp);
164: }
165: }
166: }
167:
168: /**
169: * Unconstrain the playbook with the removed policies
170: */
171: private void removePolicies(Collection removedPolicies) {
172: if (logger.isInfoEnabled())
173: logger.info("Removing policy");
174: for (Iterator it = removedPolicies.iterator(); it.hasNext();) {
175: playbookConstrainService
176: .unconstrain((OperatingModePolicy) it.next());
177: }
178: }
179:
180: /**
181: * Unconstrain, then reconstrain the playbook with the
182: * changed policies.
183: */
184: private void changePolicies(Collection changedPolicies) {
185: if (logger.isInfoEnabled())
186: logger.info("Changing policy");
187: for (Iterator it = changedPolicies.iterator(); it.hasNext();) {
188: OperatingModePolicy omp = (OperatingModePolicy) it.next();
189: if (nonAdaptive(omp)) {
190: playbookConstrainService.unconstrain(omp);
191: playbookConstrainService.constrain(omp);
192: }
193: }
194: }
195:
196: /**
197: * If any missing OperatingModes have been published run through
198: * all the policies again
199: **/
200: private void checkOMSubs() {
201: if (logger.isInfoEnabled())
202: logger.info("checking for wanted Operating Modes");
203:
204: // for (Iterator subIt = omSubscription.getAddedCollection().iterator();
205: // subIt.hasNext();) {
206: // System.out.println("Found OM: " + subIt.next());
207: // }
208:
209: // If anyone of the missing OMs has shown up, run through ALL of policies
210: for (Iterator policyIt = policySubscription.iterator(); policyIt
211: .hasNext();) {
212: OperatingModePolicy omp = (OperatingModePolicy) policyIt
213: .next();
214: nonAdaptive(omp);
215: }
216: }
217:
218: /**
219: * This methods sets the values of OperatingModes of NonAdaptive Policies.
220: * A non adaptivie policies is defined as one that has a TRUE ifClause and
221: * only single point ranges as values of the OperatingModeConstraints.
222: * @return true if the policy always restricts its OMs to a single point and has a TRUE ifClause
223: *
224: **/
225: private boolean nonAdaptive(OperatingModePolicy policy) {
226: PolicyKernel pk = policy.getPolicyKernel();
227: ConstrainingClause ifClause = pk.getIfClause();
228: ArrayList keepers = new ArrayList(13);
229:
230: if (ifClause.equals(ConstrainingClause.TRUE_CLAUSE)) {
231: ConstraintPhrase[] cps = pk.getOperatingModeConstraints();
232:
233: for (int i = 0; i < cps.length; i++) {
234: OMCRangeList rl = cps[i].getAllowedValues();
235: OMCRange[] ranges = rl.getAllowedValues();
236:
237: if (ranges.length > 1) {
238: return false;
239: }
240: if (!(ranges[0] instanceof OMCPoint)) {
241: return false;
242: }
243:
244: ConstraintOperator op = cps[i].getOperator();
245: if (op.equals(ConstraintOperator.EQUAL)
246: || op.equals(ConstraintOperator.ASSIGN)
247: || op.equals(ConstraintOperator.IN)) {
248: keepers.add(cps[i]);
249: } else {
250: return false;
251: }
252: }
253: }
254:
255: if (keepers.size() == 0) {
256: return false;
257: }
258:
259: for (Iterator it = keepers.iterator(); it.hasNext();) {
260: ConstraintPhrase cp = (ConstraintPhrase) it.next();
261:
262: /* lookup and set operating mode corresponding to this phrase */
263: OperatingMode om = findOM(cp.getProxyName());
264: if (om != null) {
265: OMCRange theValue = cp.getAllowedValues()
266: .getAllowedValues()[0];
267: om.setValue(theValue.getMin());
268: blackboard.publishChange(om);
269:
270: // Remove this om from the predicate, in case it's there.
271: omPred.removeOM(cp.getProxyName());
272: } else {
273: // didn't find operating mode we expected
274: // add it to the om predicate, and hope it shows up later
275: omPred.addOM(cp.getProxyName());
276: }
277: }
278: return true;
279: }
280:
281: /**
282: * Lookup an OperatingMode first using the OperatingModeService,
283: * then by searching the local subscription
284: **/
285: private OperatingMode findOM(String omName) {
286: // first try to find the om using the OMService
287: OperatingMode om = operatingModeService
288: .getOperatingModeByName(omName);
289: if (om == null) {
290: // Not in OMService, maybe in our subscription
291: for (Iterator subIt = omSubscription.iterator(); subIt
292: .hasNext();) {
293: OperatingMode subOM = (OperatingMode) subIt.next();
294: if (omName.equals(subOM.getName())) {
295: return subOM;
296: }
297: }
298: }
299: return om;
300: }
301: }
|