001: /**
002: * <copyright>
003: *
004: * Copyright 1997-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: */package org.cougaar.logistics.plugin.inventory;
026:
027: import org.cougaar.planning.ldm.plan.*;
028: import org.cougaar.planning.ldm.PlanningFactory;
029: import org.cougaar.core.service.DomainService;
030:
031: import org.cougaar.util.UnaryPredicate;
032: import org.cougaar.core.component.Component;
033: import org.cougaar.core.service.LoggingService;
034: import org.cougaar.core.component.ServiceBroker;
035: import org.cougaar.core.plugin.ComponentPlugin;
036: import org.cougaar.planning.service.LDMService;
037: import org.cougaar.core.component.ServiceRevokedListener;
038: import org.cougaar.core.component.ServiceRevokedEvent;
039: import org.cougaar.core.mts.MessageAddress;
040: import org.cougaar.core.blackboard.IncrementalSubscription;
041: import org.cougaar.glm.ldm.oplan.OrgActivity;
042: import org.cougaar.glm.ldm.asset.Organization;
043: import org.cougaar.glm.ldm.oplan.Oplan;
044: import org.cougaar.core.util.UID;
045: import org.cougaar.util.DynamicUnaryPredicate;
046: import java.io.Serializable;
047: import java.util.*;
048:
049: /** The LogisticsOPlanPlugin collects the OPlans and OrgActivities
050: * in the cluster and creates an oplan object with the information
051: * pertinent to the InventoryPlugin.
052: **/
053:
054: public class LogisticsOPlanPlugin extends ComponentPlugin {
055:
056: public IncrementalSubscription oplans;
057: /** Map keyed by OPlan UID to an org activity subscription **/
058: private Map orgActivitySubscriptionOfOPlanUID = new HashMap();
059: /** Hash of oplans **/
060: private HashMap oplanHash = new HashMap();
061: /** Subscription for the Organization(s) in which this plugin resides **/
062: private IncrementalSubscription selfOrganizations;
063: private LoggingService logger;
064: private Organization myOrganization;
065: protected MessageAddress clusterId;
066:
067: // oplan
068: static class OplanPredicate implements UnaryPredicate {
069: public boolean execute(Object o) {
070: return (o instanceof Oplan);
071: }
072: }
073:
074: static class OplanOrgActivitiesPredicate implements UnaryPredicate {
075: UID oplanUID_;
076:
077: public OplanOrgActivitiesPredicate(UID uid) {
078: oplanUID_ = uid;
079: }
080:
081: public boolean execute(Object o) {
082: if (o instanceof OrgActivity) {
083: if (oplanUID_.equals(((OrgActivity) o).getOplanUID())) {
084: return true;
085: }
086: }
087: return false;
088: }
089: }
090:
091: private static UnaryPredicate orgsPredicate = new UnaryPredicate() {
092: public boolean execute(Object o) {
093: if (o instanceof Organization) {
094: return ((Organization) o).isSelf();
095: }
096: return false;
097: }
098: };
099:
100: private static UnaryPredicate logisticsOPlanPredicate = new UnaryPredicate() {
101: public boolean execute(Object o) {
102: return o instanceof LogisticsOPlan;
103: }
104: };
105:
106: public void load() {
107: super .load();
108: logger = getLoggingService(this );
109: }
110:
111: public synchronized void execute() {
112: if (myOrganization == null) {
113: myOrganization = getMyOrganization(selfOrganizations
114: .elements());
115: if (myOrganization == null) {
116: return;
117: } else {
118: clusterId = myOrganization.getClusterPG()
119: .getMessageAddress();
120: }
121: }
122: updateOplans();
123: updateOrgActivities();
124: publishLogOplanObjects();
125: }
126:
127: protected void setupSubscriptions() {
128: selfOrganizations = (IncrementalSubscription) getBlackboardService()
129: .subscribe(orgsPredicate);
130:
131: // If we are rehydrating then this subscription will have things on it
132: // So restore our private variables
133: if (myOrganization == null && !selfOrganizations.isEmpty()) {
134: myOrganization = getMyOrganization(selfOrganizations
135: .elements());
136: if (myOrganization != null) {
137: clusterId = myOrganization.getClusterPG()
138: .getMessageAddress();
139: }
140: }
141:
142: oplans = (IncrementalSubscription) getBlackboardService()
143: .subscribe(new OplanPredicate());
144:
145: // If there are oplans on our subscription, then restore the
146: // private hashes / subscriptions
147: // Note the assumption that there will be an Oplan object before or
148: // at least at same time as there are OrgActivities and therefore
149: // LogOplans.
150: if (!oplans.isEmpty()) {
151: if (logger.isInfoEnabled())
152: logger.info(getAgentIdentifier()
153: + ".setupSub: have oplans. Restoring hashes.");
154: // Restore org activities subscriptions / hash
155: Enumeration en = oplans.elements();
156: while (en.hasMoreElements()) {
157: Oplan oplan = (Oplan) en.nextElement();
158: UID oplanUID = oplan.getUID();
159: IncrementalSubscription oplanActivities = (IncrementalSubscription) orgActivitySubscriptionOfOPlanUID
160: .get(oplanUID);
161: if (oplanActivities == null) {
162: oplanActivities = (IncrementalSubscription) getBlackboardService()
163: .subscribe(
164: new OplanOrgActivitiesPredicate(
165: oplanUID));
166: orgActivitySubscriptionOfOPlanUID.put(oplanUID,
167: oplanActivities);
168: }
169: // publish code was here
170: }
171:
172: // Restore LogOplan hash
173: // If there are none on the blackboard, then wait for the execute
174: // method of this Plugin to fire on new OrgActivities,
175: // and create one.
176: Collection c = getBlackboardService().query(
177: logisticsOPlanPredicate);
178: for (Iterator i = c.iterator(); i.hasNext();) {
179: LogisticsOPlan loplan = (LogisticsOPlan) i.next();
180: oplanHash.put(loplan.getOplanUID(), loplan);
181: }
182:
183: // If there already are OrgActivities on the subscriptions we just
184: // restored above, but we have not yet created the LogOplans
185: // to got with them, then create them here.
186: // This may not strictly be necessary, but it doesn't hurt
187: publishLogOplanObjects();
188: } // end of check for oplans on subscription
189:
190: }
191:
192: private boolean updateOplans() {
193: boolean oplanChange = false;
194: if (logger.isDebugEnabled()) {
195: logger.debug("starting updateOplans");
196: }
197: if (oplans.hasChanged()) {
198: doUpdateOplans();
199: oplanChange = true;
200: }
201: return oplanChange;
202: }
203:
204: // Process Oplan subscription
205: private void doUpdateOplans() {
206: if (logger.isDebugEnabled()) {
207: logger.debug("Updating the Oplans!");
208: }
209: Enumeration en;
210: // Create new LogisticsOPlan objects for each added Oplan
211: if (oplans.getAddedList().hasMoreElements()) {
212: en = oplans.getAddedList();
213: while (en.hasMoreElements()) {
214: Oplan oplan = (Oplan) en.nextElement();
215: UID oplanUID = oplan.getUID();
216: IncrementalSubscription oplanActivities = (IncrementalSubscription) orgActivitySubscriptionOfOPlanUID
217: .get(oplanUID);
218: if (oplanActivities == null) {
219: oplanActivities = (IncrementalSubscription) getBlackboardService()
220: .subscribe(
221: new OplanOrgActivitiesPredicate(
222: oplanUID));
223: orgActivitySubscriptionOfOPlanUID.put(oplanUID,
224: oplanActivities);
225: }
226: // publish code was here
227: }
228: }
229: // Remove LogisticsOPlan objects that are no longer relevant
230: if (oplans.getRemovedList().hasMoreElements()) {
231: en = oplans.getRemovedList();
232: while (en.hasMoreElements()) {
233: Oplan oplan = (Oplan) en.nextElement();
234: UID oplanUID = oplan.getUID();
235: LogisticsOPlan loplan = (LogisticsOPlan) oplanHash
236: .get(oplanUID);
237: // Remove LogisticsOPlan from array
238: oplanHash.remove(oplanUID);
239: // Cancel subscription
240: IncrementalSubscription s = (IncrementalSubscription) orgActivitySubscriptionOfOPlanUID
241: .remove(oplanUID);
242: if (s != null)
243: getBlackboardService().unsubscribe(s);
244: getBlackboardService().publishRemove(loplan);
245: break;
246: }
247: }
248: }
249:
250: // Each LogisticsOPlan updates its own OrgActivities if needed
251: private boolean updateOrgActivities() {
252: Iterator en = oplanHash.values().iterator();
253: boolean update = false;
254: while (en.hasNext()) {
255: LogisticsOPlan loplan = (LogisticsOPlan) en.next();
256: IncrementalSubscription s = (IncrementalSubscription) orgActivitySubscriptionOfOPlanUID
257: .get(loplan.getOplanUID());
258: if ((!s.getChangedCollection().isEmpty())
259: || (!s.getAddedCollection().isEmpty())
260: || (!s.getRemovedCollection().isEmpty())) {
261: update = update || loplan.updateOrgActivities(s);
262: getBlackboardService().publishChange(loplan);
263: }
264: }
265: return update;
266: }
267:
268: /** The publishLogOplanObjects() method publishes the LogisticsOPlan objects for
269: * oplans that also have orgactivities.
270: * The updateOPlans() method associates the Oplan with its OrgActivities by placing
271: * them in the orgActivitySubscriptionOfOPlanUID map. At the end of the execute the
272: * publishLogOplanObjects() looks through the map to find oplans with orgActivities
273: * that have not been published (do not appear in the oplanHash) and creates and
274: * publishes the LogOplan object.
275: **/
276: private void publishLogOplanObjects() {
277: Oplan oplan;
278: UID oplanUID;
279: LogisticsOPlan loplan;
280: Iterator oplanUIDset = orgActivitySubscriptionOfOPlanUID
281: .keySet().iterator();
282: while (oplanUIDset.hasNext()) {
283: oplanUID = (UID) oplanUIDset.next();
284: oplan = findOplan(oplanUID);
285: if (oplan == null) {
286: logger.error("Cannot find matching oplan " + oplanUID);
287: continue;
288: }
289: loplan = (LogisticsOPlan) oplanHash.get(oplanUID);
290: IncrementalSubscription s = (IncrementalSubscription) orgActivitySubscriptionOfOPlanUID
291: .get(oplanUID);
292: if (loplan == null) {
293: if (logger.isInfoEnabled())
294: logger.info(getAgentIdentifier()
295: + ".publishLogOplan: no loplan for uid "
296: + oplanUID + ". OrgActivity sub.isEmpty? "
297: + s.isEmpty());
298: if (!s.isEmpty()) {
299: loplan = new LogisticsOPlan(clusterId, oplan);
300: loplan.updateOrgActivities(s);
301: oplanHash.put(oplanUID, loplan);
302: getBlackboardService().publishAdd(loplan);
303: if (logger.isDebugEnabled()) {
304: logger.debug("Published LogisticsOPlan "
305: + loplan + " for " + clusterId);
306: }
307: }
308: }
309: }
310: }
311:
312: private Oplan findOplan(UID oplanUID) {
313: Iterator oplanIt = oplans.iterator();
314: Oplan oplan;
315: while (oplanIt.hasNext()) {
316: oplan = (Oplan) oplanIt.next();
317: if (oplan.getUID().equals(oplanUID)) {
318: return oplan;
319: }
320: }
321: return null;
322: }
323:
324: public LoggingService getLoggingService(Object requestor) {
325: return (LoggingService) getServiceBroker().getService(
326: requestor, LoggingService.class, null);
327: }
328:
329: private Organization getMyOrganization(Enumeration orgs) {
330: Organization myOrg = null;
331: // look for this organization
332: if (orgs.hasMoreElements()) {
333: myOrg = (Organization) orgs.nextElement();
334: }
335: return myOrg;
336: }
337:
338: }
|