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: */
026:
027: package org.cougaar.mlm.plugin.ldm;
028:
029: import java.awt.LayoutManager;
030: import java.awt.event.ActionEvent;
031: import java.awt.event.ActionListener;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.Enumeration;
035: import java.util.HashMap;
036: import java.util.HashSet;
037: import java.util.Iterator;
038:
039: import javax.swing.JButton;
040: import javax.swing.JFrame;
041: import javax.swing.JLabel;
042: import javax.swing.JPanel;
043:
044: import org.cougaar.core.blackboard.IncrementalSubscription;
045: import org.cougaar.core.service.UIDService;
046: import org.cougaar.core.util.UID;
047: import org.cougaar.glm.ldm.oplan.Oplan;
048: import org.cougaar.glm.ldm.oplan.OplanContributor;
049: import org.cougaar.glm.ldm.oplan.OplanCoupon;
050: import org.cougaar.glm.ldm.oplan.OrgActivity;
051: import org.cougaar.glm.ldm.plan.GeolocLocation;
052: import org.cougaar.glm.ldm.plan.NamedPosition;
053: import org.cougaar.mlm.plugin.UICoordinator;
054: import org.cougaar.util.UnaryPredicate;
055:
056: /**
057: * The SQLOplanPlugin instantiates the Oplan and adds it to the LogPlan. Essentially
058: * a copy of OplanPlugin.java except that it uses QueryHandlers to load Oplan info from
059: * a database.
060: *
061: **/
062: public class SQLOplanPlugin extends LDMSQLPlugin implements
063: SQLOplanBase {
064: public static final String OPLAN_ID_PARAMETER = "oplanid";
065: /** frame for 1-button UI **/
066: private JFrame frame;
067:
068: /** for feedback to user on whether root GLS was successful **/
069: private JLabel oplanLabel;
070: protected JButton oplanButton;
071:
072: private IncrementalSubscription oplanSubscription;
073:
074: private IncrementalSubscription stateSubscription;
075: private IncrementalSubscription publishTheOplanSubscription;
076:
077: private ArrayList contributors;
078:
079: private boolean readyToPublishOplan = false;
080:
081: private boolean UTBPublishOplan() {
082: if (!readyToPublishOplan) {
083: if (log.isWarnEnabled())
084: log.warn("OPLAN CANNOT BE PUBLISHED AGAIN.");
085: return false;
086: } else {
087: readyToPublishOplan = false;
088: publishOplanFromInsideTx();
089: return true;
090: }
091: }
092:
093: private ArrayList oplans = new ArrayList();
094: private HashMap locations = new HashMap();
095:
096: // Additions/Modifications/Deletions which have not yet been published
097: private HashSet newObjects = new HashSet();
098: private HashSet modifiedObjects = new HashSet();
099: private HashSet removedObjects = new HashSet();
100:
101: private JLabel updateLabel;
102: protected JButton updateButton;
103:
104: protected long myOplanTime;
105:
106: UIDService uidService = null;
107:
108: private static class MyPrivateState implements java.io.Serializable {
109: boolean oplanExists = false;
110: boolean unpublishedChanges = false;
111: boolean errorOccurred = false;
112: }
113:
114: private MyPrivateState myPrivateState;
115:
116: private static UnaryPredicate oplanPredicate = new UnaryPredicate() {
117: public boolean execute(Object o) {
118: return (o instanceof Oplan);
119: }
120: };
121:
122: private static UnaryPredicate publishTheOplanPredicate = new UnaryPredicate() {
123: public boolean execute(Object o) {
124: if (o instanceof java.lang.String)
125: return (o.toString()
126: .equalsIgnoreCase("publishTheOplan"));
127: return false;
128: }
129: };
130:
131: private static UnaryPredicate statePredicate = new UnaryPredicate() {
132: public boolean execute(Object o) {
133: return (o instanceof MyPrivateState);
134: }
135: };
136:
137: private static class OrgActivityPredicate implements UnaryPredicate {
138: private Oplan myOplan = null;
139: private String myOrgId = "";
140:
141: public void setOplan(Oplan oplan) {
142: myOplan = oplan;
143: }
144:
145: public void setOrgId(String orgId) {
146: myOrgId = orgId;
147: }
148:
149: public boolean execute(Object o) {
150: if ((myOplan == null) || (myOrgId.equals(""))) {
151: return false;
152: }
153:
154: return ((o instanceof OrgActivity)
155: && (((OrgActivity) o).getOrgID().equals(myOrgId)) && (((OrgActivity) o)
156: .getOplanUID().equals(myOplan.getUID())));
157: }
158: }
159:
160: private static OrgActivityPredicate orgActivityPredicate = new OrgActivityPredicate();
161:
162: /**
163: * Executes Plugin functionality.
164: */
165: public void execute() {
166: if (stateSubscription.hasChanged()) {
167: checkForPrivateState(stateSubscription.getAddedList());
168: }
169: if (oplanSubscription.hasChanged()) {
170: Collection adds = oplanSubscription.getAddedCollection();
171: if (adds != null) {
172: processOplanAdds(adds);
173: }
174: Collection changes = oplanSubscription
175: .getChangedCollection();
176: if (changes != null) {
177: processChanges(changes);
178: }
179: Collection deletes = oplanSubscription
180: .getRemovedCollection();
181: if (deletes != null) {
182: processOplanDeletes(deletes);
183: }
184: }
185:
186: for (Iterator it = contributors.iterator(); it.hasNext();) {
187: IncrementalSubscription is = (IncrementalSubscription) it
188: .next();
189:
190: // we don't care about adds, just deletes and changes
191: if (is.hasChanged()) {
192: Collection changes = is.getChangedCollection();
193: if (changes != null) {
194: processChanges(changes);
195: }
196:
197: // Deletes of OplanContributors are treated as changes to the Oplan
198: changes = is.getRemovedCollection();
199: if (changes != null) {
200: processChanges(changes);
201: }
202: }
203: }
204: Collection publishIt = publishTheOplanSubscription
205: .getAddedCollection();
206: if (publishIt != null && publishIt.size() > 0) {
207: for (Iterator iterator = publishIt.iterator(); iterator
208: .hasNext();) {
209: Object object = iterator.next();
210: getBlackboardService().publishRemove(object);
211: }
212: UTBPublishOplan();
213: }
214: }
215:
216: public Oplan getOplan(String oplanID) {
217:
218: synchronized (oplans) {
219: for (Iterator iterator = oplans.iterator(); iterator
220: .hasNext();) {
221: Oplan oplan = (Oplan) iterator.next();
222: if ((oplan.getOplanId().equals(oplanID))) {
223: return oplan;
224: }
225: }
226: return null;
227: }
228: }
229:
230: public void updateOplanInfo(Oplan update) {
231: synchronized (oplans) {
232: String oplanID = update.getOplanId();
233: Oplan oplan = getOplan(oplanID);
234:
235: if (oplan == null) {
236: oplan = addOplan(oplanID);
237: }
238:
239: oplan.setOperationName(update.getOperationName());
240: oplan.setPriority(update.getPriority());
241: oplan.setCday(update.getCday());
242: oplan.setEndDay(update.getEndDay());
243:
244: boolean found = false;
245: if (oplanSubscription != null) {
246: Collection published = oplanSubscription
247: .getCollection();
248: for (Iterator iterator = published.iterator(); iterator
249: .hasNext();) {
250: if (((Oplan) iterator.next()).getOplanId().equals(
251: oplanID)) {
252: found = true;
253: break;
254: }
255: }
256: }
257:
258: if (found) {
259: modifiedObjects.add(oplan);
260:
261: if (myPrivateState != null) {
262: myPrivateState.unpublishedChanges = true;
263: }
264: } else {
265: newObjects.add(oplan);
266: }
267: }
268: }
269:
270: // Replace org activies for Org.
271: public void updateOrgActivities(Oplan update, String orgId,
272: Collection orgActivities) {
273: synchronized (oplans) {
274: String oplanID = update.getOplanId();
275: Oplan oplan = getOplan(oplanID);
276:
277: if (oplan == null) {
278: log
279: .error("In "
280: + getMessageAddress()
281: + "updateOrgActivities(): can't find referenced Oplan "
282: + oplanID);
283: return;
284: }
285:
286: // Execute a query to get all existing org activities associated with
287: // the oplan
288: orgActivityPredicate.setOplan(oplan);
289: orgActivityPredicate.setOrgId(orgId);
290: Collection existingOrgActivities = getBlackboardService()
291: .query(orgActivityPredicate);
292: for (Iterator iterator = existingOrgActivities.iterator(); iterator
293: .hasNext();) {
294: OrgActivity orgActivity = (OrgActivity) iterator.next();
295:
296: if (orgActivity.getOrgID().equals(orgId)) {
297: removedObjects.add(orgActivity);
298: }
299: }
300:
301: for (Iterator iterator = orgActivities.iterator(); iterator
302: .hasNext();) {
303: OrgActivity orgActivity = (OrgActivity) iterator.next();
304: newObjects.add(orgActivity);
305: }
306:
307: if (myPrivateState != null) {
308: myPrivateState.unpublishedChanges = true;
309: }
310: }
311: }
312:
313: // Used by query handlers to get location info
314: public NamedPosition getLocation(String locCode) {
315: return (NamedPosition) locations.get(locCode);
316: }
317:
318: // Used by query handlers to update location info
319: public void updateLocation(GeolocLocation location) {
320: String locName = location.getGeolocCode();
321: locations.put(locName, location);
322: }
323:
324: /*
325: * Creates a subscription.
326: */
327: protected void setupSubscriptions() {
328: super .setupSubscriptions();
329:
330: // get the UIDService
331: // uidService = (UIDService) getBindingSite().getServiceBroker().getService(this, UIDService.class, null);
332:
333: getBlackboardService().getSubscriber().setShouldBePersisted(
334: false);
335: oplanSubscription = (IncrementalSubscription) getBlackboardService()
336: .subscribe(oplanPredicate);
337: stateSubscription = (IncrementalSubscription) getBlackboardService()
338: .subscribe(statePredicate);
339:
340: contributors = new ArrayList(13);
341: // refill contributors Collection on rehydrate
342: processOplanAdds(oplanSubscription.getCollection());
343:
344: createGUI();
345: readyToPublishOplan = true;
346: publishTheOplanSubscription = (IncrementalSubscription) getBlackboardService()
347: .subscribe(publishTheOplanPredicate);
348:
349: if (getBlackboardService().didRehydrate()) {
350: checkForPrivateState(stateSubscription.elements());
351: } else {
352: getBlackboardService().publishAdd(new MyPrivateState());
353: }
354: }
355:
356: protected void initProperties() {
357: // default package for QueryHandler
358: super .initProperties();
359: String exptid = System.getProperty("org.cougaar.experiment.id");
360:
361: if (exptid != null) {
362: globalParameters.put("exptid", exptid);
363: }
364: }
365:
366: private Oplan addOplan(String oplanID) {
367: Oplan oplan;
368:
369: synchronized (oplans) {
370: oplan = getOplan(oplanID);
371:
372: if (oplan != null) {
373: if (log.isWarnEnabled())
374: log.warn("In " + getMessageAddress()
375: + "addOplan(): " + oplanID
376: + " already exists.");
377: return oplan;
378: } else {
379: oplan = new Oplan();
380: //getCluster().getUID...
381: getUIDServer().registerUniqueObject(oplan);
382: //uidService.registerUniqueObject(oplan);
383: oplan.setOwner(getMessageAddress());
384: oplan.setOplanId(oplanID);
385:
386: oplans.add(oplan);
387: }
388: } // end syncronization on oplans
389: return oplan;
390: }
391:
392: private void checkForPrivateState(Enumeration e) {
393: if (myPrivateState == null) {
394: while (e.hasMoreElements()) {
395: myPrivateState = (MyPrivateState) e.nextElement();
396: checkButtonEnable();
397: }
398: }
399: }
400:
401: private void createGUI() {
402: frame = new JFrame("OplanPlugin");
403: JPanel panel = new JPanel((LayoutManager) null);
404: // Create the button
405: oplanButton = new JButton("Publish Oplan");
406: oplanLabel = new JLabel("No Oplan has been published.");
407:
408: // Register a listener for the check box
409: OplanButtonListener myOplanListener = new OplanButtonListener();
410: oplanButton.addActionListener(myOplanListener);
411: oplanButton.setEnabled(false);
412: UICoordinator.layoutButtonAndLabel(panel, oplanButton,
413: oplanLabel);
414: frame.getRootPane().setDefaultButton(oplanButton); // hitting return sends the oplan
415:
416: // Create the button
417: updateButton = new JButton("Update Oplan");
418: updateLabel = new JLabel("No Oplan has been published.");
419:
420: // Register a listener for the check box
421: UpdateButtonListener myUpdateListener = new UpdateButtonListener();
422: updateButton.addActionListener(myUpdateListener);
423: updateButton.setEnabled(false);
424: UICoordinator.layoutButtonAndLabel(panel, updateButton,
425: updateLabel);
426:
427: frame.setContentPane(panel);
428: frame.pack();
429: UICoordinator.setBounds(frame);
430: frame.setVisible(true);
431: }
432:
433: /** An ActionListener that listens to the GLS buttons. */
434: class OplanButtonListener implements ActionListener {
435: public void actionPerformed(ActionEvent ae) {
436: publishOplan();
437: }
438: }
439:
440: /** An ActionListener that listens to the update button. */
441: class UpdateButtonListener implements ActionListener {
442: public void actionPerformed(ActionEvent ae) {
443: refreshOplan();
444: }
445: }
446:
447: private void checkButtonEnable() {
448: // Log status
449: oplanButton.setEnabled(!myPrivateState.oplanExists
450: || myPrivateState.unpublishedChanges);
451: if (myPrivateState.oplanExists) {
452: oplanLabel.setText("Published successfully");
453: } else if (myPrivateState.errorOccurred) {
454: oplanLabel
455: .setText("ERROR::Unable to add the Oplan to the LogPlan.");
456: } else {
457: oplanLabel.setText("No Oplan has been published.");
458: }
459:
460: updateButton.setEnabled(myPrivateState.oplanExists);
461: if (myPrivateState.oplanExists) {
462: updateLabel.setText("Oplan can be updated.");
463: } else {
464: updateLabel.setText("No Oplan to update.");
465: }
466:
467: }
468:
469: /*
470: protected void addOplan(Oplan oplan) {
471: if (oplans == null) {
472: oplans = new ArrayList();
473: } else {
474: // verify oplan not already on the list
475: }
476:
477: oplans.add(oplan);
478: }
479: */
480: private void publishOplanObjects() {
481: for (Iterator iterator = newObjects.iterator(); iterator
482: .hasNext();) {
483: Object object = iterator.next();
484: getBlackboardService().publishAdd(object);
485:
486: if (object instanceof Oplan) {
487: OplanCoupon ow = new OplanCoupon(((Oplan) object)
488: .getUID(), getMessageAddress());
489: getUIDServer().registerUniqueObject(ow);
490: getBlackboardService().publishAdd(ow);
491:
492: myPrivateState.oplanExists = true;
493: }
494: }
495:
496: for (Iterator iterator = modifiedObjects.iterator(); iterator
497: .hasNext();) {
498: Object object = iterator.next();
499: getBlackboardService().publishChange(object);
500: }
501:
502: for (Iterator iterator = removedObjects.iterator(); iterator
503: .hasNext();) {
504: Object object = iterator.next();
505: getBlackboardService().publishRemove(object);
506: }
507:
508: getBlackboardService().publishChange(myPrivateState);
509: }
510:
511: private void publishOplanPostProcessing() {
512: newObjects.clear();
513: modifiedObjects.clear();
514: removedObjects.clear();
515:
516: myPrivateState.unpublishedChanges = false;
517:
518: checkButtonEnable();
519: }
520:
521: private void publishOplan() {
522: // Need to make separate add/remove/modify lists
523: getBlackboardService().openTransaction();
524: publishOplanObjects();
525: getBlackboardService().closeTransactionDontReset();
526: publishOplanPostProcessing();
527: }
528:
529: private void publishOplanFromInsideTx() {
530: // Need to make separate add/remove/modify lists
531: publishOplanObjects();
532: publishOplanPostProcessing();
533: }
534:
535: private void refreshOplan() {
536: for (Enumeration e = queries.elements(); e.hasMoreElements();) {
537: SQLOplanQueryHandler qh = (SQLOplanQueryHandler) e
538: .nextElement();
539: qh.update();
540: }
541: checkButtonEnable();
542: }
543:
544: private void processOplanAdds(Collection adds) {
545: for (Iterator it = adds.iterator(); it.hasNext();) {
546: Oplan oplan = (Oplan) it.next();
547:
548: IncrementalSubscription is = (IncrementalSubscription) getBlackboardService()
549: .subscribe(new ContributorPredicate(oplan.getUID()));
550: contributors.add(is);
551: }
552: }
553:
554: private void processChanges(Collection changes) {
555: HashSet changedOplans = new HashSet();
556:
557: for (Iterator iterator = changes.iterator(); iterator.hasNext();) {
558: UID oplanUID = null;
559: Object o = iterator.next();
560: if (o instanceof Oplan) {
561: oplanUID = ((Oplan) o).getUID();
562: } else if (o instanceof OplanContributor) {
563: oplanUID = ((OplanContributor) o).getOplanUID();
564: } else
565: continue;
566:
567: changedOplans.add(oplanUID);
568: }
569:
570: // Publish once for each changed oplan
571: for (Iterator iterator = changedOplans.iterator(); iterator
572: .hasNext();) {
573: Collection coupons = getBlackboardService().query(
574: new CouponPredicate((UID) iterator.next()));
575: for (Iterator couponIt = coupons.iterator(); couponIt
576: .hasNext();) {
577: if (log.isInfoEnabled())
578: log.info("In " + getMessageAddress()
579: + " publishChanging OplanCoupon");
580: getBlackboardService().publishChange(couponIt.next());
581: }
582: }
583: }
584:
585: private void processOplanDeletes(Collection deletes) {
586: for (Iterator it = deletes.iterator(); it.hasNext();) {
587: Oplan oplan = (Oplan) it.next();
588: Collection coupons = getBlackboardService().query(
589: new CouponPredicate(oplan.getUID()));
590: for (Iterator couponIt = coupons.iterator(); couponIt
591: .hasNext();) {
592: getBlackboardService().publishRemove(couponIt.next());
593: }
594: }
595: }
596:
597: private class CouponPredicate implements UnaryPredicate {
598: UID _oplanUID;
599:
600: public CouponPredicate(UID oplanUID) {
601: _oplanUID = oplanUID;
602: }
603:
604: public boolean execute(Object o) {
605: if (o instanceof OplanCoupon) {
606: if (((OplanCoupon) o).getOplanUID().equals(_oplanUID)) {
607: return true;
608: }
609: }
610: return false;
611: }
612: }
613:
614: private class ContributorPredicate implements UnaryPredicate {
615: UID _oplanUID;
616:
617: public ContributorPredicate(UID oplanUID) {
618: _oplanUID = oplanUID;
619: }
620:
621: public boolean execute(Object o) {
622: if (o instanceof OplanContributor) {
623: if (((OplanContributor) o).getOplanUID().equals(
624: _oplanUID)) {
625: return true;
626: }
627: }
628: return false;
629: }
630: }
631: }
|