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.tools.csmart.ui.servlet;
028:
029: import org.cougaar.core.mts.MessageAddress;
030: import org.cougaar.core.servlet.ServletUtil;
031: import org.cougaar.core.servlet.SimpleServletSupport;
032: import org.cougaar.core.util.UID;
033: import org.cougaar.core.util.UniqueObject;
034: import org.cougaar.planning.ldm.asset.Asset;
035: import org.cougaar.planning.ldm.asset.AssetGroup;
036: import org.cougaar.planning.ldm.plan.*;
037: import org.cougaar.util.UnaryPredicate;
038: import org.cougaar.util.log.Logger;
039:
040: import javax.servlet.http.HttpServlet;
041: import javax.servlet.http.HttpServletRequest;
042: import javax.servlet.http.HttpServletResponse;
043: import java.io.IOException;
044: import java.io.InputStream;
045: import java.io.ObjectInputStream;
046: import java.io.ObjectOutputStream;
047: import java.io.OutputStream;
048: import java.io.PrintWriter;
049: import java.io.UnsupportedEncodingException;
050: import java.net.URLEncoder;
051: import java.util.ArrayList;
052: import java.util.Collection;
053: import java.util.Enumeration;
054: import java.util.HashMap;
055: import java.util.HashSet;
056: import java.util.Iterator;
057: import java.util.List;
058: import java.util.Map;
059: import java.util.Set;
060:
061: /**
062: * Servlet that searches the Blackboard for all <code>UniqueObjects</code> that
063: * are connected to a given <code>Set</code> of <code>UID</code>s.
064: * <p>
065: * The user specifies:<ul>
066: * <li>a "?limit=.." is an integer limit for the number of object
067: * to find. FIXME over-limit action</li>
068: * <li>a "?format=.." of "html" or "data" (the default is html)</li>
069: * <li>a "?find=.." of "up" or "down" (the default is "down"). "Up" links
070: * are all the "parent" Objects (<i>causes</i>), and "down" links are
071: * all the "child" Objects (<i>effects</i>)</li>
072: * <li>a starting Set of UID Strings (either POSTed as a
073: * serialized Java <code>List</code> or, if not POSTed, sent as a
074: * single "?uid=.." URL parameter)</li>
075: * </ul>
076: * The result is a List of <code>PropertyTree</code>s for all the
077: * related UniqueObjects.
078: *
079: * <p>
080: * Can be loaded manually by including this line in an agent's .ini configuration file: <br>
081: * plugin = org.cougaar.core.servlet.SimpleServletComponent(org.cougaar.tools.csmart.ui.servlet.SearchServlet,
082: * /CSMART_SearchServlet)
083: *
084: * <p>
085: * Is loaded from a URL on a CSMART machine, on agent 'Agent': <br>
086: * http://localhost:port/$Agent/CSMART_SearchServlet
087: *
088: * @see TranslateUtils
089: */
090: public class SearchServlet extends HttpServlet {
091: // cougaar hook
092: SimpleServletSupport support;
093:
094: public void setSimpleServletSupport(SimpleServletSupport support) {
095: this .support = support;
096:
097: if (!("/CSMART_SearchServlet".equals(support.getPath()))) {
098: System.out.println("Error in servlet path: "
099: + support.getPath());
100: }
101: }
102:
103: /* Reponds to the GET http method call
104: * @param request HttpServletRequest
105: * @param response HttpServletResponse
106: */
107: public void doGet(HttpServletRequest request,
108: HttpServletResponse response) throws IOException {
109: // create a new "SearchProvider" context per request
110: SearchProvider sp = new SearchProvider(support);
111: sp.execute(request, response);
112: }
113:
114: /* Reponds to the PUT http method call
115: * @param request HttpServletRequest
116: * @param response HttpServletResponse
117: */
118: public void doPut(HttpServletRequest request,
119: HttpServletResponse response) throws IOException {
120: // create a new "SearchProvider" context per request
121: SearchProvider sp = new SearchProvider(support);
122: sp.execute(request, response);
123: }
124:
125: /**
126: * Used to parse the URL and set parameters
127: */
128: private static class SearchProvider {
129:
130: /**
131: * Set to "true" to see debug-level messages.
132: */
133: public static final boolean VERBOSE = false;
134:
135: /*
136: * Support class
137: */
138: private SimpleServletSupport support;
139:
140: /* parameter and method variables */
141: private Set startUIDs = null;
142: private boolean isDown = true;
143: private boolean returnAsData;
144: private int limit = Integer.MAX_VALUE;
145: private String uid;
146: private PrintWriter htmlout;
147:
148: /* Inner class constructor
149: * @param support Cougaar hook
150: */
151: public SearchProvider(SimpleServletSupport support) {
152: this .support = support;
153: }
154:
155: /**
156: * Make the GET and POST passing of parameters transparent to
157: * the user.
158: * <p>
159: * Determine either GET or POST methods, call with respective
160: * ServletUtil methods.
161: * <p>
162: * Creates a ParamVisitor instance to set the parameters.
163: * Set the parameters, store the map of (name, value) pairs for getting UIDs.
164: */
165: public void parseParams(HttpServletRequest req)
166: throws IOException, ClassNotFoundException {
167: // always read "format=..", "limit=..", etc
168: ServletUtil.ParamVisitor vis = new ServletUtil.ParamVisitor() {
169: public void setParam(String name, String value) {
170: if ("find".equalsIgnoreCase(name)) {
171: if ("down".equalsIgnoreCase(value)) {
172: isDown = true;
173: } else if ("up".equalsIgnoreCase(value)) {
174: isDown = false;
175: }
176: } else if ("format".equalsIgnoreCase(name)) {
177: if ("data".equalsIgnoreCase(value)) {
178: returnAsData = true;
179: } else if ("html".equalsIgnoreCase(value)) {
180: returnAsData = false;
181: }
182: } else if ("limit".equalsIgnoreCase(name)) {
183: try {
184: limit = Integer.parseInt(value);
185: if (limit < 0) {
186: limit = Integer.MAX_VALUE;
187: }
188: } catch (NumberFormatException nfe) {
189: }
190: } else if ("uid".equalsIgnoreCase(name)) {
191: uid = value;
192: }
193: }
194: };
195: ServletUtil.parseParams(vis, req);
196:
197: // read attached data if there (e.g. from PUT)
198: int len = req.getContentLength();
199: if (len > 0) {
200: InputStream in = req.getInputStream();
201: // read List of Strings
202: try {
203: Object data;
204: try {
205: ObjectInputStream obStream = new ObjectInputStream(
206: in);
207: data = obStream.readObject();
208: } catch (IOException e) {
209: System.out
210: .println("Expecting a POSTED Serialized \"Object\": "
211: + e.getMessage());
212: data = null;
213: }
214: if (data != null) {
215: startUIDs = getSearchUIDs(data);
216: }
217: } catch (RuntimeException e) {
218: System.out.println("zero UIDs posted?: "
219: + e.getMessage());
220: }
221: }
222: }
223:
224: /**
225: * Main Servlet Method. Parses parameters, searches through them, returning
226: * either data or html.
227: *
228: * @param request HttpServletRequest
229: * @param response HttpServletResponse
230: */
231: public void execute(HttpServletRequest request,
232: HttpServletResponse response) throws IOException {
233:
234: // parse the URL parameters and attached (binary) data
235: try {
236: parseParams(request);
237:
238: // if zero UIDs were posted then look for a "?uid=" parameter
239: if ((startUIDs == null) &&
240: //(optUID != null)) {
241: (uid != null)) {
242: startUIDs = new HashSet(1);
243: //UID uid = UID.toUID(optUID);
244: UID tmpuid = UID.toUID(uid);
245: startUIDs.add(tmpuid);
246: }
247: } catch (Exception e) {
248: System.err
249: .println("SearchServlet: Unable to parse parameters:");
250: e.printStackTrace();
251:
252: // handle as "null" search set
253: startUIDs = null;
254: }
255:
256: // search
257: List l;
258: try {
259: l = search(support, startUIDs, isDown, limit);
260: } catch (RuntimeException e) {
261: System.err
262: .println("SearchServlet: Unable to search for data:");
263: e.printStackTrace();
264:
265: // send back a null
266: l = null;
267: }
268:
269: /* Obtain <code>MessageAddress</code> */
270: MessageAddress cid = support.getAgentIdentifier();
271:
272: // send back the results
273: try {
274: if (returnAsData) {
275: OutputStream dataOut = response.getOutputStream();
276: replyWithData(dataOut, cid, l);
277: } else {
278: PrintWriter htmlOut = response.getWriter();
279: replyWithHTML(htmlOut, cid, startUIDs, isDown, l);
280: }
281: } catch (Exception e) {
282: System.err
283: .println("SearchServlet: Unable to send response back:");
284: e.printStackTrace();
285: }
286:
287: // done!
288: }
289:
290: /**
291: * Reply with a serialized List of PropertyTrees.
292: * @param out OutputStream
293: * @param cid MessageAddress
294: * @param l List of UIDs
295: */
296: private static void replyWithData(OutputStream out,
297: MessageAddress cid, List l) throws IOException {
298:
299: // convert to PropertyTrees, all tagged with this agent's name
300: List retL = TranslateUtils.toPropertyTrees(l, cid
301: .toString());
302:
303: try {
304: if (retL != null) {
305: // serialize back to the user
306: ObjectOutputStream p = new ObjectOutputStream(out);
307: p.writeObject(retL);
308: //System.out.println("SearchServlet: Sent Objects");
309: }
310: } catch (Exception e) {
311: System.out.println("SearchServlet Exception: " + e);
312: e.printStackTrace();
313: }
314: }
315:
316: /**
317: * Reply with an HTML document.
318: * @param out PrintWriter out
319: * @param cid MessageAddress
320: * @param startUIDs starting set of UIDs
321: * @param isDown search guidlines
322: * @param l List of UIDs
323: */
324: private static void replyWithHTML(PrintWriter out,
325: MessageAddress cid, Set startUIDs, boolean isDown,
326: List l) {
327: int nStartUIDs = ((startUIDs != null) ? startUIDs.size()
328: : 0);
329: out
330: .print("<html><head><title>Search results</title></head><body>\n"
331: + "<h2>Search "
332: + cid
333: + "</h2><p>\n"
334: + "<h3>Direction: <b>"
335: + (isDown ? "Down" : "Up")
336: + "</b></h3>\n"
337: + "<h3>Start with UIDs["
338: + nStartUIDs
339: + "]:</h3>");
340: if (nStartUIDs > 0) {
341: out.print("<ol>");
342: Iterator iter = startUIDs.iterator();
343: for (int i = 0; i < nStartUIDs; i++) {
344: out.print("<li>" + iter.next() + "</li>");
345: }
346: out.print("</ol>");
347: } else {
348: out.print("<i>Use \"?uid=...\" or POST a serialized "
349: + "List of UID Strings</i>");
350: }
351: int n = ((l != null) ? l.size() : 0);
352: out
353: .print("\n<h3>Found UniqueObjects["
354: + n
355: + "]:</h3><p>"
356: + "<i>Note: links will appear in the task servlet's lower-left frame</i>"
357: + "<p><ol>\n");
358: String hrefBase = null;
359: try {
360: hrefBase = "<a" + " target=\"itemFrame\""
361: + " href=\"/$"
362: + URLEncoder.encode(cid.toString(), "UTF-8")
363: + "/tasks?uid=";
364: } catch (UnsupportedEncodingException e) {
365: // should never happen -- UTF-8 is always valid.
366: System.err.println("Exception Encoding: "
367: + e.getMessage());
368: }
369:
370: // print objs
371: for (int i = 0; i < n; i++) {
372: UniqueObject ui = (UniqueObject) l.get(i);
373: String href;
374: UID uid = ui.getUID();
375: if (uid != null) {
376: String suid = ui.getUID().toString();
377: // mode must match tasks servlet
378: int mode = ((ui instanceof Task) ? 3
379: : (ui instanceof PlanElement) ? 5
380: : (ui instanceof Asset) ? 7 : 10);
381: href = hrefBase + suid + "?mode=" + mode + "\">"
382: + suid + "</a>";
383: } else {
384: href = "<font color=\"red\">null UID</font>";
385: }
386: out.print("\n<li>" + href + " == "
387: + ui.getClass().getName() + "</li>");
388: }
389:
390: out.print("\n</ol>\n<h3>As PropertyTrees[");
391: // convert to PropertyTrees
392: List retL = TranslateUtils.toPropertyTrees(l, cid
393: .toString());
394: int nRetL = ((retL != null) ? retL.size() : 0);
395: out.print(nRetL + "]:</h3><ol>");
396: for (int i = 0; i < nRetL; i++) {
397: out.print("\n<li>" + retL.get(i) + "</li>");
398: }
399: out.print("\n</ol></body></html>");
400:
401: out.flush();
402: }
403:
404: /**
405: * Get the Set of UIDs specified by the POSTed data.
406: * @param postObj List of objects
407: */
408: private static Set getSearchUIDs(Object postObj) {
409:
410: // make sure that a List was posted
411: if (!(postObj instanceof List)) {
412: throw new IllegalArgumentException(
413: "POSTED Object is not a \"java.util.List\": "
414: + ((postObj != null) ? postObj
415: .getClass().getName() : "null"));
416: }
417:
418: // parse vector of params into a set of uids
419: List postUIDs = (List) postObj;
420: int nPostUIDs = postUIDs.size();
421:
422: // parse Strings to a Set of UIDs
423: Set toSet = new HashSet(nPostUIDs);
424: for (int i = 0; i < nPostUIDs; i++) {
425: Object oi = postUIDs.get(i);
426: if (!(oi instanceof String)) {
427: throw new IllegalArgumentException("POSTED List["
428: + i
429: + "] contains a non-String:"
430: + ((oi != null) ? oi.getClass().getName()
431: : "null"));
432: }
433: UID ui = UID.toUID((String) oi);
434: toSet.add(ui);
435: }
436:
437: // return the Set of UIDs
438: return toSet;
439: }
440:
441: /**
442: * Find all the UniqueObjects that have UIDs in the given Set.
443: * @param support Cougaar hook
444: * @param uids UID set
445: */
446: private static Collection findUniqueObjects(
447: SimpleServletSupport support, final Set uids) {
448:
449: Collection resultCol;
450:
451: int nuids = ((uids != null) ? uids.size() : 0);
452: if (nuids <= 0) {
453: // find nothing?
454: resultCol = new ArrayList(0);
455: } else if (nuids == 1) {
456: // get the single UID
457: final UID uid = (UID) uids.iterator().next();
458: // create a predicate
459: UnaryPredicate pred = new UnaryPredicate() {
460: public boolean execute(Object o) {
461: return ((o instanceof UniqueObject) && (uid
462: .equals(((UniqueObject) o).getUID())));
463: }
464: };
465: // query
466: resultCol = support.queryBlackboard(pred);
467: // resultCol = querySupport.query(pred);
468: } else {
469: // find multiple UniqueObjects
470: // create a predicate
471: UnaryPredicate pred = new UnaryPredicate() {
472: public boolean execute(Object o) {
473: return ((o instanceof UniqueObject) && (uids
474: .contains(((UniqueObject) o).getUID())));
475: }
476: };
477: // query
478: resultCol = support.queryBlackboard(pred);
479: }
480:
481: return resultCol;
482: }
483:
484: /**
485: * Search a UID set, to a certain limit
486: * @param support Cougaar support
487: * @param startUIDset UID set
488: * @param isDown search direction
489: * @param limit limit of search recursion
490: */
491: private static List search(SimpleServletSupport support,
492: Set startUIDSet, boolean isDown, int limit) {
493: return (isDown ? searchDown(support, startUIDSet, limit)
494: : searchUp(support, startUIDSet, limit));
495: }
496:
497: /**
498: * Search down a UID set
499: * @param support Cougaar hook
500: * @param startUIDSet start UID set
501: * @param limit limit of search recursion
502: */
503: private static List searchDown(SimpleServletSupport support,
504: Set startUIDSet, int limit) {
505:
506: if (VERBOSE) {
507: System.out
508: .println("\n****************************************************"
509: + "\nSEARCH DOWN"
510: + "\nStart with ["
511: + ((startUIDSet != null) ? startUIDSet
512: .size() : 0)
513: + "]: "
514: + startUIDSet
515: + ((limit >= 0) ? ("\nLimit: " + limit)
516: : "\nNo limit"));
517: }
518:
519: // find the starting objects
520: Collection startCol = findUniqueObjects(support,
521: startUIDSet);
522:
523: if (VERBOSE) {
524: System.out.println("Found "
525: + startCol.size()
526: + " of "
527: + ((startUIDSet != null) ? startUIDSet.size()
528: : 0));
529: }
530:
531: // make a list of Objs to search
532: WorkStack ws = new WorkStack();
533: ws.pushAll(startCol);
534:
535: while (ws.hasWork()) {
536: UniqueObject uo = ws.take();
537: //
538: int type = getItemType(uo);
539: switch (type) {
540: case ITEM_TYPE_ALLOCATION: {
541: Allocation alloc = (Allocation) uo;
542: // asset
543: ws.push(alloc.getAsset());
544: // FIXME: what about the task?
545: ws.push(alloc.getTask());
546: // if remote then remote task UID is a property
547: }
548: break;
549: case ITEM_TYPE_EXPANSION: {
550: Expansion ex = (Expansion) uo;
551: ws.push(ex.getWorkflow());
552: }
553: break;
554: case ITEM_TYPE_AGGREGATION: {
555: Aggregation agg = (Aggregation) uo;
556: Composition comp = agg.getComposition();
557: if (comp != null) {
558: // "^" ignore comp.getParentTasks
559: // child MPTask
560: ws.push(comp.getCombinedTask());
561: }
562: }
563: break;
564: case ITEM_TYPE_ASSET_TRANSFER: {
565: AssetTransfer atrans = (AssetTransfer) uo;
566: // asset moved
567: ws.push(atrans.getAsset());
568: // destination asset
569: ws.push(atrans.getAssignee());
570: // task
571: ws.push(atrans.getTask());
572: }
573: break;
574: case ITEM_TYPE_TASK: {
575: Task t = (Task) uo;
576: // direct object (Asset)
577: ws.push(t.getDirectObject());
578: // plan element
579: ws.push(t.getPlanElement());
580: }
581: break;
582: case ITEM_TYPE_ASSET: {
583: Asset asset = (Asset) uo;
584: // asset group?
585: if (asset instanceof AssetGroup) {
586: // assets
587: ws.pushAll(((AssetGroup) asset).getAssets());
588: }
589: }
590: break;
591: case ITEM_TYPE_WORKFLOW: {
592: Workflow wf = (Workflow) uo;
593: // tasks
594: ws.pushAll(wf.getTasks());
595: }
596: break;
597: case ITEM_TYPE_DISPOSITION: {
598: // FIXME: What about the Task?
599: PlanElement pe = (PlanElement) uo;
600: // task
601: ws.push(pe.getTask());
602: break;
603: }
604: default:
605: // ignore
606: break;
607: }
608:
609: if (ws.sizePushed() > limit) {
610: // we've exceeded our limit
611: //
612: // FIXME: trim "ws" to just (limit + 1)
613: break;
614: }
615: }
616:
617: if (VERBOSE) {
618: System.out
619: .println("done."
620: + "\n**********************************************\n");
621: }
622:
623: List toL = new ArrayList(ws.sizePushed());
624: ws.toCollection(toL);
625: return toL;
626: }
627:
628: /**
629: * search up.
630: */
631: private static List searchUp(SimpleServletSupport support,
632: Set startUIDSet, int limit) {
633:
634: // get this Agent's identifier
635: MessageAddress localCID = support.getAgentIdentifier();
636:
637: if (VERBOSE) {
638: System.out
639: .println("\n*****************************************************"
640: + "\nSEARCH UP"
641: + ((limit >= 0) ? ("\nLimit: " + limit)
642: : "\nNo limit"));
643: }
644:
645: // make a list of Objs to search
646: WorkStack ws = new WorkStack();
647: Set findUIDSet = new HashSet(startUIDSet);
648:
649: search_up_loop: while (!(findUIDSet.isEmpty())) {
650:
651: if (VERBOSE) {
652: System.out.println("\nFind [" + findUIDSet.size()
653: + "]: " + findUIDSet);
654: }
655:
656: // find the starting objects
657: Collection foundCol = findUniqueObjects(support,
658: findUIDSet);
659: findUIDSet.clear();
660:
661: if (VERBOSE) {
662: System.out.println("Found " + foundCol.size()
663: + " of " + findUIDSet.size());
664: }
665:
666: ws.pushAll(foundCol);
667:
668: while (ws.hasWork()) {
669: UniqueObject uo = ws.take();
670: //
671: if (uo instanceof PlanElement) {
672:
673: PlanElement pe = (PlanElement) uo;
674: // task
675: ws.push(pe.getTask());
676:
677: } else if (uo instanceof Task) {
678:
679: // task parent(s)
680: if (uo instanceof MPTask) {
681: MPTask mpt = (MPTask) uo;
682: // parent tasks
683: ws.pushAll(mpt.getParentTasks());
684: } else {
685: Task t = (Task) uo;
686: // only have a UID for the parent
687: MessageAddress tCID = t.getSource();
688: if ((tCID == null)
689: || (localCID.equals(tCID))) {
690: // local Task, must search by UID
691: UID uid = t.getParentTaskUID();
692: if ((uid != null)
693: && (!(ws.hasPushedKey(uid)))) {
694: // add the UID to next search pass.
695: //
696: // note that this "find" Task may be found in
697: // this pass indirectly, which will waste a query,
698: // but it's a rare and harmless situation
699: findUIDSet.add(uid);
700: }
701: } else {
702: // remote up!
703: }
704: }
705:
706: } else if (uo instanceof Workflow) {
707:
708: Workflow wf = (Workflow) uo;
709: // task
710: ws.push(wf.getParentTask());
711:
712: } else {
713: // ignore
714: }
715:
716: if (ws.sizePushed() > limit) {
717: // we've exceeded our limit
718: //
719: // FIXME: trim "ws" to just (limit + 1)
720: break search_up_loop;
721: }
722: }
723: }
724:
725: if (VERBOSE) {
726: System.out
727: .println("done."
728: + "\n****************************************************\n");
729: }
730:
731: List toL = new ArrayList(ws.sizePushed());
732: ws.toCollection(toL);
733: return toL;
734: }
735:
736: /**
737: * Search "worklist" data structure to traverse a UniqueObject graph.
738: */
739: private static final class WorkStack {
740:
741: private List l;
742: private HashMap m;
743:
744: public WorkStack() {
745: this .l = new ArrayList();
746: this .m = new HashMap(89);
747: }
748:
749: public int sizeWork() {
750: return l.size();
751: }
752:
753: public int sizePushed() {
754: return m.size();
755: }
756:
757: public boolean hasWork() {
758: return (!(l.isEmpty()));
759: }
760:
761: public UniqueObject take() {
762: UniqueObject uo = (UniqueObject) l.remove(l.size() - 1);
763: if (VERBOSE) {
764: System.out.println("----take["
765: + l.size()
766: + "]: "
767: + ((uo != null) ? uo.getClass().getName()
768: : "null"));
769: }
770: return uo;
771: }
772:
773: public boolean push(UniqueObject uo) {
774: if (uo != null) {
775: UID uid = uo.getUID();
776: if (m.put(uid, uo) == null) {
777: // add if new
778: l.add(uo);
779: if (VERBOSE) {
780: System.out
781: .println("++++pushed UID: " + uid
782: + " for "
783: + uo.getClass().getName());
784: }
785: return true;
786: } else {
787: if (VERBOSE) {
788: System.out
789: .println(" ignore UID: " + uid
790: + " for "
791: + uo.getClass().getName());
792: }
793: }
794: } else {
795: if (VERBOSE) {
796: System.out.println(" ignore null");
797: }
798: }
799: return false;
800: }
801:
802: public boolean push(Object o) {
803: if (o instanceof UniqueObject) {
804: return push((UniqueObject) o);
805: } else {
806: if (VERBOSE) {
807: System.out.println(" ignore "
808: + ((o != null) ? o.getClass().getName()
809: : "null"));
810: }
811: return false;
812: }
813: }
814:
815: public int pushAll(Collection fromCol) {
816: int t = 0;
817: int n = ((fromCol != null) ? fromCol.size() : 0);
818: if (n > 0) {
819: Iterator iter = fromCol.iterator();
820: do {
821: if (this .push(iter.next())) {
822: t++;
823: }
824: } while (--n > 0);
825: }
826: return t;
827: }
828:
829: public int pushAll(Enumeration fromEn) {
830: int t = 0;
831: if (fromEn != null) {
832: while (fromEn.hasMoreElements()) {
833: if (this .push(fromEn.nextElement())) {
834: t++;
835: }
836: }
837: }
838: return t;
839: }
840:
841: public boolean hasPushed(UniqueObject uo) {
842: return ((uo != null) && (hasPushedKey(uo.getUID())));
843: }
844:
845: public boolean hasPushed(Object o) {
846: return ((o instanceof UniqueObject) && (this
847: .hasPushed((UniqueObject) o)));
848: }
849:
850: public boolean hasPushedKey(UID uid) {
851: return ((uid != null) && (m.containsKey(uid)));
852: }
853:
854: public void toCollection(Collection toCol) {
855: /// add all the values in the Map to the given collection
856: toCol.addAll(m.values());
857: }
858:
859: public void toMap(Map toMap) {
860: toMap.putAll(m);
861: }
862:
863: public String toString() {
864: return toString(false);
865: }
866:
867: public String toString(boolean verbose) {
868: String s = "WorkStack {" + "\n work[" + l.size() + "]";
869: if (verbose) {
870: s += ": " + l;
871: }
872: s += "\n found[" + m.size() + "]";
873: if (verbose) {
874: s += ": " + m;
875: }
876: s += "\n}";
877: return s;
878: }
879: }
880:
881: /* Object Class type variables */
882: private static final int ITEM_TYPE_ALLOCATION = 0;
883: private static final int ITEM_TYPE_EXPANSION = 1;
884: private static final int ITEM_TYPE_AGGREGATION = 2;
885: private static final int ITEM_TYPE_DISPOSITION = 3;
886: private static final int ITEM_TYPE_ASSET_TRANSFER = 4;
887: private static final int ITEM_TYPE_TASK = 5;
888: private static final int ITEM_TYPE_ASSET = 6;
889: private static final int ITEM_TYPE_WORKFLOW = 7;
890: private static final int ITEM_TYPE_OTHER = 8;
891:
892: /**
893: * Big switch statement on Object Class type.
894: * <p>
895: * Replace with synchronized hashmap lookup on obj.getClass()?
896: **/
897: private static int getItemType(Object obj) {
898: if (obj instanceof PlanElement) {
899: if (obj instanceof Allocation) {
900: return ITEM_TYPE_ALLOCATION;
901: } else if (obj instanceof Expansion) {
902: return ITEM_TYPE_EXPANSION;
903: } else if (obj instanceof Aggregation) {
904: return ITEM_TYPE_AGGREGATION;
905: } else if (obj instanceof Disposition) {
906: return ITEM_TYPE_DISPOSITION;
907: } else if (obj instanceof AssetTransfer) {
908: return ITEM_TYPE_ASSET_TRANSFER;
909: } else {
910: return ITEM_TYPE_OTHER;
911: }
912: } else if (obj instanceof Task) {
913: return ITEM_TYPE_TASK;
914: } else if (obj instanceof Asset) {
915: return ITEM_TYPE_ASSET;
916: } else if (obj instanceof Workflow) {
917: return ITEM_TYPE_WORKFLOW;
918: } else {
919: return ITEM_TYPE_OTHER;
920: }
921: }
922: }
923: }
|