001: /*
002: *
003: * <copyright>
004: *
005: * Copyright 1997-2004 BBNT Solutions, LLC
006: * under sponsorship of the Defense Advanced Research Projects
007: * Agency (DARPA).
008: *
009: * You can redistribute this software and/or modify it under the
010: * terms of the Cougaar Open Source License as published on the
011: * Cougaar Open Source Website (www.cougaar.org).
012: *
013: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
014: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
015: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
016: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
017: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
018: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
019: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
020: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
021: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
022: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
023: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
024: *
025: * </copyright>
026: */
027:
028: package org.cougaar.servicediscovery.servlet;
029:
030: import java.io.IOException;
031: import java.io.PrintWriter;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.Collections;
035: import java.util.HashMap;
036: import java.util.Iterator;
037: import java.util.Vector;
038:
039: import javax.servlet.ServletException;
040: import javax.servlet.http.HttpServlet;
041: import javax.servlet.http.HttpServletRequest;
042: import javax.servlet.http.HttpServletResponse;
043:
044: import org.cougaar.core.service.LoggingService;
045: import org.cougaar.core.servlet.SimpleServletSupport;
046: import org.cougaar.planning.ldm.PlanningFactory;
047: import org.cougaar.servicediscovery.description.MMQuery;
048: import org.cougaar.servicediscovery.description.ScoredServiceDescription;
049: import org.cougaar.servicediscovery.description.ServiceClassification;
050: import org.cougaar.servicediscovery.transaction.MMQueryRequest;
051: import org.cougaar.servicediscovery.transaction.NewMMQueryRequest;
052: import org.cougaar.util.UnaryPredicate;
053:
054: /**
055: * A <code>Servlet</code>, loaded by the
056: * <code>SimpleServletComponent</code>, that generates
057: * an HTML view of MatchMakerQuery data.
058: *
059: * @see org.cougaar.core.servlet.SimpleServletComponent
060: */
061: public class MatchMakerQueryServlet extends HttpServlet {
062: private SimpleServletSupport support;
063: private LoggingService logger;
064: private PlanningFactory ldmFactory;
065:
066: public void setSimpleServletSupport(SimpleServletSupport support) {
067: this .support = support;
068: }
069:
070: public void setLoggingService(LoggingService loggingService) {
071: this .logger = loggingService;
072: }
073:
074: public void setRootFactory(PlanningFactory rootFactory) {
075: this .ldmFactory = rootFactory;
076: }
077:
078: public void doGet(HttpServletRequest request,
079: HttpServletResponse response) throws IOException,
080: ServletException {
081: // create a new "MMQueryPrinter" context per request
082: MMQueryPrinter ct = new MMQueryPrinter(support, ldmFactory,
083: logger, request, response);
084: ct.execute();
085: }
086:
087: public void doPost(HttpServletRequest request,
088: HttpServletResponse response) throws IOException,
089: ServletException {
090: // create a new "MMQueryPrinter" context per request
091: MMQueryPrinter ct = new MMQueryPrinter(support, ldmFactory,
092: logger, request, response);
093: ct.execute();
094: }
095:
096: /**
097: * Inner-class to hold state and generate the response.
098: */
099: protected static class MMQueryPrinter {
100:
101: // since "MMQueryPrinter" is a static inner class, here
102: // we hold onto the support API.
103: //
104: // this makes it clear that MMQueryPrinter only uses
105: // the "support" from the outer class.
106: private SimpleServletSupport support;
107: private HttpServletRequest request;
108: private HttpServletResponse response;
109: private LoggingService logger;
110: private PlanningFactory ldmFactory;
111:
112: // writer from the request for HTML output
113: private PrintWriter out;
114:
115: public MMQueryPrinter(SimpleServletSupport support,
116: PlanningFactory ldmFactory, LoggingService logger,
117: HttpServletRequest request, HttpServletResponse response) {
118: this .support = support;
119: this .request = request;
120: this .response = response;
121: this .ldmFactory = ldmFactory;
122: this .logger = logger;
123: }
124:
125: public void execute() throws IOException, ServletException {
126: this .out = response.getWriter();
127:
128: String viewType = request.getParameter("viewType");
129: if ("viewSpecificQuery".equals(viewType)) {
130: // single query w/ matching UID
131: String queryUID = request.getParameter("UID");
132: MMQueryRequest result = getSpecificMMQueryRequest(queryUID);
133: printMatchMakerQueryAsHTML(result);
134: } else if ("viewAllQueries".equals(viewType)) {
135: // all
136: Collection col = getMMQueryRequests();
137: printQueriesAsHTML(col);
138: } else if ("viewDefault".equals(viewType)) {
139: Collection col = getMMQueryRequests();
140: if (col.isEmpty()) {
141: // none
142: printMatchMakerQueryAsHTML(null);
143: } else if (col.size() == 1) {
144: // single query
145: MMQueryRequest request = (MMQueryRequest) col
146: .iterator().next();
147: printMatchMakerQueryAsHTML(request);
148: } else {
149: // all
150: printQueriesAsHTML(col);
151: }
152: } else {
153: // frame
154: printFrame();
155: }
156: }
157:
158: protected void printFrame() {
159: // generate outer frame page:
160: // top: select "/agent"
161: // bottom: query frame
162: out
163: .print("<html><head>"
164: + "<title>MatchMakerQuery Data</title></head>"
165: + "<frameset rows=\"10%,90%\">\n"
166: + "<frame src=\""
167: + "/agents?format=select&suffix="
168: + support.getEncodedAgentName()
169: + "\" name=\"agentFrame\">\n"
170: + "<frame src=\"/$"
171: + support.getEncodedAgentName()
172: + support.getPath()
173: + "?viewType=viewDefault"
174: + "\" name=\"queryFrame\">\n"
175: + "</frameset>\n"
176: + "<noframes>Please enable frame support</noframes>"
177: + "</html>\n");
178: }
179:
180: private static String formatFloat(float n) {
181: return formatFloat(n, 6);
182: }
183:
184: private static String formatFloat(float n, int w) {
185: String r = String.valueOf(n);
186: return " ".substring(0, w - r.length()) + r;
187: }
188:
189: protected static final UnaryPredicate MATCH_MAKER_REQUEST_PRED = new UnaryPredicate() {
190: public boolean execute(Object o) {
191: return (o instanceof NewMMQueryRequest);
192: }
193: };
194:
195: protected class SpecificMatchMakerQuery implements
196: UnaryPredicate {
197: private String queryUID;
198:
199: SpecificMatchMakerQuery(String aQueryUID) {
200: super ();
201: this .queryUID = aQueryUID;
202: }
203:
204: public boolean execute(Object o) {
205: if (o instanceof NewMMQueryRequest) {
206: MMQueryRequest q = (MMQueryRequest) o;
207: return (queryUID.equals(q.getUID().toString()));
208: }
209: return false;
210: }
211: }
212:
213: protected MMQueryRequest getSpecificMMQueryRequest(
214: String queryUID) {
215: Collection col = support
216: .queryBlackboard(new SpecificMatchMakerQuery(
217: queryUID));
218: if ((col == null) || (col.size() < 1)) {
219: System.out
220: .println("Null Collection returned from blackboard");
221: return null;
222: } else {
223: if ((col.size() > 1) && (logger.isErrorEnabled())) {
224: logger.error("More than one NewMMQueryRequest at "
225: + support.getEncodedAgentName());
226: }
227: Iterator it = col.iterator();
228: return ((MMQueryRequest) it.next());
229: }
230: }
231:
232: protected Collection getMMQueryRequests() {
233: Collection col = support
234: .queryBlackboard(MATCH_MAKER_REQUEST_PRED);
235: return col;
236: }
237:
238: protected void printClusterSelectionComboBox() {
239: // javascript based on PlanViewServlet
240: out
241: .print("<html><head>"
242: + "<script language=\"JavaScript\">\n"
243: + "<!--\n"
244: + "function mySubmit() {\n"
245: + " var obj = top.agentFrame.document.agent.name;\n"
246: + " var encAgent = obj.value;\n"
247: + " if (encAgent.charAt(0) == '.') {\n"
248: + " alert(\"Please select an agent name\")\n"
249: + " return false;\n"
250: + " }\n"
251: + " document.myForm.target=\"queryFrame\"\n"
252: + " document.myForm.action=\"/$\"+encAgent+\""
253: + support.getPath()
254: + "\"\n"
255: + " return true\n"
256: + "}\n"
257: + "// -->\n"
258: + "</script>\n"
259: + "</head><body>\n"
260: + "<h2><center>MatchMakerQuery Data at "
261: + support.getEncodedAgentName()
262: + "</center></h2>\n"
263: + "<form name=\"myForm\" method=\"get\" "
264: + "onSubmit=\"return mySubmit()\">\n"
265: + "<input type=hidden name=\"viewType\" value=\"");
266: String viewType = request.getParameter("viewType");
267: if (viewType != null) {
268: out.print(viewType);
269: }
270: out
271: .print("\">"
272: + "<input type=submit name=\"formSubmit\" value=\"Reload\">"
273: + "<br>\n</form>");
274: }
275:
276: /**
277: * Write the given <code>MatchMakerQueryRequest</code> as formatted HTML.
278: */
279: protected void printMatchMakerQueryAsHTML(MMQueryRequest result) {
280: printClusterSelectionComboBox();
281: printTableAsHTML(result);
282: if (result != null) {
283: out.print("\n<a href=\"" + support.getPath()
284: + "?viewType=viewAllQueries\""
285: + " target=\"queryFrame\">"
286: + "View all Queries</a>\n");
287: }
288: out.print("</body></html>");
289: out.flush();
290: }
291:
292: protected void printTableAsHTML(MMQueryRequest request) {
293: if (request != null) {
294: printQueryAsHTMLTable(request.getQuery());
295: printResultAsHTMLTable(request);
296: } else {
297: out
298: .print("<pre>No Match Maker query requests at this Agent</b></pre>");
299: }
300: }
301:
302: protected void printQueryAsHTMLTable(MMQuery query) {
303: QueryToHTMLTranslator qt = QueryToHTMLTranslator
304: .createTranslatorForQuery(query);
305:
306: if (qt == null) {
307: logger.error("Unknown query type:" + query);
308: } else {
309: printQueryAsHTMLTable(qt);
310: }
311: }
312:
313: protected void printQueryAsHTMLTable(QueryToHTMLTranslator qt) {
314: qt.setRootFactory(ldmFactory);
315: out.print(qt.beginHTMLQueryTable("Query", null));
316: out.print(qt.toHTMLQueryTableRow());
317: out.print(qt.endHTMLQueryTable());
318: }
319:
320: protected void printQueriesAsHTML(Collection col) {
321: printClusterSelectionComboBox();
322: printQueriesAsHTMLTable(col);
323: out.print("</body></html>");
324: out.flush();
325: }
326:
327: protected void printQueriesAsHTMLTable(Collection col) {
328:
329: HashMap transMap = sortQueries(col);
330:
331: Collection transKeys = transMap.keySet();
332: Iterator keyIT = transKeys.iterator();
333:
334: while (keyIT.hasNext()) {
335:
336: String aKey = (String) keyIT.next();
337:
338: Collection requests = (Collection) transMap.get(aKey);
339:
340: Iterator requestsIT = requests.iterator();
341: int ctr = 0;
342:
343: ArrayList uids = new ArrayList();
344: HashMap mmRequests = new HashMap();
345:
346: //sort the requests by UID
347: while (requestsIT.hasNext()) {
348:
349: MMQueryRequest mmqr = (MMQueryRequest) requestsIT
350: .next();
351: String queryUID = mmqr.getUID().toString();
352:
353: uids.add(queryUID);
354: mmRequests.put(queryUID, mmqr);
355: }
356: Collections.sort(uids);
357: Collections.reverse(uids);
358:
359: Iterator uidIT = uids.iterator();
360:
361: while (uidIT.hasNext()) {
362: String queryUID = (String) uidIT.next();
363: MMQueryRequest mmqr = (MMQueryRequest) mmRequests
364: .get(queryUID);
365:
366: QueryToHTMLTranslator qt = QueryToHTMLTranslator
367: .createTranslatorForQuery(mmqr.getQuery());
368: if (qt == null) {
369: logger.error("Unknown query class type:"
370: + mmqr.getQuery());
371: continue;
372: }
373:
374: qt.setRootFactory(ldmFactory);
375:
376: if (ctr == 0) {
377: out.print(qt.beginHTMLQueriesTable("Queries"));
378: }
379: out.print(qt.toHTMLQueriesTableRow(queryUID, mmqr));
380: ctr++;
381: if (ctr == requests.size()) {
382: out.print(qt.endHTMLQueriesTable());
383: }
384:
385: }
386: }
387: }
388:
389: protected HashMap sortQueries(Collection col) {
390: Iterator requestsIT = col.iterator();
391: HashMap map = new HashMap();
392:
393: while (requestsIT.hasNext()) {
394:
395: MMQueryRequest mmqr = (MMQueryRequest) requestsIT
396: .next();
397:
398: String queryType = QueryToHTMLTranslator
399: .getQueryType(mmqr.getQuery());
400: if (queryType == null) {
401: logger.error("Unknown query type:"
402: + mmqr.getQuery());
403: }
404:
405: Vector requests = (Vector) map.get(queryType);
406:
407: if (requests == null) {
408: requests = new Vector();
409: map.put(queryType, requests);
410: }
411: requests.add(mmqr);
412: }
413:
414: return map;
415: }
416:
417: protected void printResultAsHTMLTable(MMQueryRequest request) {
418: Collection scoredDescriptions = request.getResult();
419: if (scoredDescriptions != null) {
420: String statusString = null;
421: if (scoredDescriptions.size() < 1) {
422: statusString = "Failed to find any providers";
423: //out.print(" <br>Result Returned is empty</br>");
424: } else if (scoredDescriptions.size() == 1) {
425: statusString = "1 provider successfully found";
426: } else {
427: statusString = "" + scoredDescriptions.size()
428: + " providers successfully found";
429: }
430: beginResultHTMLTable("Results:", statusString);
431: Iterator sdIT = scoredDescriptions.iterator();
432:
433: while (sdIT.hasNext()) {
434: ScoredServiceDescription sdd = (ScoredServiceDescription) sdIT
435: .next();
436: beginServiceDescriptionAsHTML(sdd);
437: printServiceDescriptionAsHTML(sdd);
438: }
439: endHTMLTable();
440: } else {
441: out
442: .print(" <br>No Result at this Time</br>");
443: }
444: }
445:
446: /**
447: * Begin a table of <tt>printQueryAsHTMLTable</tt> entries.
448: */
449: protected void beginQueryHTMLTable(String title,
450: String subTitle, QueryToHTMLTranslator example) {
451: out
452: .print("<table border=1 cellpadding=3 cellspacing=1 width=\"100%\">\n"
453: + "<tr bgcolor=lightblue><th align=left colspan=3>");
454: out.print(title);
455: if (subTitle != null) {
456: out
457: .print(" <tt><i>");
458: out.print(subTitle);
459: out.print("</i></tt>");
460: }
461: out.print(example.beginHTMLQueryTable(title, subTitle));
462: }
463:
464: protected void beginQueriesHTMLTable(String title,
465: String subTitle) {
466: out
467: .print("<table border=1 cellpadding=3 cellspacing=1 width=\"100%\">\n"
468: + "<tr bgcolor=lightblue><th align=left colspan=5>");
469: out.print(title);
470: if (subTitle != null) {
471: out
472: .print(" <tt><i>");
473: out.print(subTitle);
474: out.print("</i></tt>");
475: }
476: out.print("</th></tr>\n" + "<tr>" + "<th>UID</th>"
477: + "<th>Minimum Echelon</th>"
478: + "<th>Class Code</th>" + "<th>Class Scheme</th>"
479: + "<th>Has Result?</th>" + "</tr>\n");
480: }
481:
482: /**
483: * Begin a table of <tt>printQueryAsHTMLTable</tt> entries.
484: */
485: protected void beginResultHTMLTable(String title,
486: String subTitle) {
487: out
488: .print("<table border=1 cellpadding=3 cellspacing=1 width=\"100%\">\n"
489: + "<tr bgcolor=lightblue><th align=left colspan=3>");
490: out.print(title);
491: if (subTitle != null) {
492: out.print(" ");
493: out.print(subTitle);
494: //out.print("</i></tt>");
495: }
496: out.print("</th></tr>\n");
497: }
498:
499: protected void beginServiceDescriptionAsHTML(
500: ScoredServiceDescription sdd) {
501:
502: out
503: .print("<tr bgcolor=lightgrey> <td align=center colspan=3><b> Provider:");
504: out.print(sdd.getProviderName());
505: out
506: .print("   Penalty Score=");
507: out.print(formatFloat(sdd.getScore()));
508: out.print("</b></td></tr>\n");
509: out.print("<tr>" + "<th>Scheme</th>" + "<th>Code</th>"
510: + "<th>Name</th>" + "</tr>\n");
511: }
512:
513: /**
514: * End a table of <tt>printQueryAsHTMLTable & printResultAsHTMLTable</tt> entries.
515: */
516: protected void endHTMLTable() {
517: out.print("</table>\n" + "<p>\n");
518: }
519:
520: /**
521: * Write the given <code>AbstractTask</code> as formatted HTML.
522: */
523: protected void printServiceDescriptionAsHTML(
524: ScoredServiceDescription sdd) {
525: Iterator scIT = sdd.getServiceClassifications().iterator();
526:
527: while (scIT.hasNext()) {
528: ServiceClassification sc = (ServiceClassification) scIT
529: .next();
530: out.print("<tr align=left><td>");
531: out.print(sc.getClassificationSchemeName());
532: out.print("</td><td>");
533: out.print(sc.getClassificationCode());
534: out.print("</td><td>");
535: out.print(sc.getClassificationName());
536: out.print("</td></tr>\n");
537: }
538:
539: }
540: }
541: }
|