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.construction;
028:
029: import java.sql.Connection;
030: import java.sql.DriverManager;
031: import java.sql.ResultSet;
032: import java.sql.SQLException;
033: import java.sql.Statement;
034: import java.util.Enumeration;
035: import java.util.Hashtable;
036: import java.util.Vector;
037:
038: import org.cougaar.core.blackboard.IncrementalSubscription;
039: import org.cougaar.core.mts.MessageAddress;
040: import org.cougaar.glm.ldm.Constants;
041: import org.cougaar.glm.ldm.asset.ClassIVConstructionMaterial;
042: import org.cougaar.glm.ldm.asset.NewSupplyClassPG;
043: import org.cougaar.glm.ldm.asset.Organization;
044: import org.cougaar.glm.ldm.asset.ScheduledContentPG;
045: import org.cougaar.glm.plugins.AssetUtils;
046: import org.cougaar.glm.plugins.BasicProcessor;
047: import org.cougaar.glm.plugins.GLMDecorationPlugin;
048: import org.cougaar.glm.plugins.ScheduleUtils;
049: import org.cougaar.glm.plugins.TimeUtils;
050: import org.cougaar.glm.plugins.projection.ConsumerSpec;
051: import org.cougaar.planning.ldm.asset.Asset;
052: import org.cougaar.planning.ldm.asset.NewTypeIdentificationPG;
053: import org.cougaar.planning.ldm.measure.Count;
054: import org.cougaar.planning.ldm.measure.CountRate;
055: import org.cougaar.planning.ldm.measure.Duration;
056: import org.cougaar.planning.ldm.plan.AspectType;
057: import org.cougaar.planning.ldm.plan.NewTask;
058: import org.cougaar.planning.ldm.plan.Preference;
059: import org.cougaar.planning.ldm.plan.Schedule;
060: import org.cougaar.planning.ldm.plan.Task;
061: import org.cougaar.planning.plugin.util.PluginHelper;
062: import org.cougaar.util.Parameters;
063: import org.cougaar.util.UnaryPredicate;
064:
065: /*
066: * Construction (ClassIV) plugin that takes construction tasks and
067: * creates GenerateProjection tasks.
068: *
069: **/
070:
071: public class ConstructionGenerateDemandProjector extends BasicProcessor {
072:
073: // 86400000 msec/day = 1000msec/sec * 60sec/min *60min/hr * 24 hr/day
074: protected static final long MSEC_PER_DAY = 86400000;
075:
076: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
077:
078: private MessageAddress meCluster = null;
079: private GLMDecorationPlugin this Plugin_ = null;
080:
081: protected IncrementalSubscription constructionDemandSub;
082: protected IncrementalSubscription generateConstructionProjectionSub;
083: protected IncrementalSubscription taskMaterielPolicySub;
084:
085: private String className = "ConstructionGenerateDemandProjector";
086: private Organization myOrganization = null;
087:
088: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
089:
090: public ConstructionGenerateDemandProjector(
091: GLMDecorationPlugin glmPlugin, Organization myOrg) {
092:
093: super (glmPlugin, myOrg);
094: this Plugin_ = glmPlugin;
095: this .myOrganization = myOrg;
096:
097: initializeSubscriptions();
098:
099: } // constructor
100:
101: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
102:
103: protected void initializeSubscriptions() {
104: constructionDemandSub = subscribe(constructionDemandPred);
105:
106: constructionDemandSub = subscribe(constructionDemandPred);
107:
108: generateConstructionProjectionSub = subscribe(generateConstructionProjectionPred);
109:
110: } // initializeSubscriptions
111:
112: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
113:
114: public void update() {
115:
116: //debug("In update method......");
117: // This isn't really replan, this means need to plan
118: boolean replan = false;
119:
120: if (constructionDemandSub.getChangedList().hasMoreElements()) {
121: // How would this happen???
122: replan = true;
123: } // if
124:
125: //debug("replan is " + replan);
126: // At this point we have OPlan and ORG activities
127: if (replan) {
128: //debug("replan is true....");
129: // Will do first process tasks
130: // replan, reprocess everything
131: processTasks(constructionDemandSub.elements());
132:
133: } else {
134: //debug("in the else of the if, addedList.hasmore is " +
135: if (constructionDemandSub.getAddedList().hasMoreElements()) {
136: // Will do second process tasks
137: // expand, create and publish new tasks
138: processTasks(constructionDemandSub.getAddedList());
139: }
140: } // if
141: } // update
142:
143: public boolean processTasks(Enumeration tasks) {
144:
145: //debug (" in processTasks");
146: if (!tasks.hasMoreElements()) {
147: return false;
148: } // if
149: //debug (" <1>");
150:
151: // Project Demand
152: Hashtable consumerSchedules_;
153: consumerSchedules_ = createConsumerSchedules();
154: if (consumerSchedules_.isEmpty()) {
155: return false;
156: } // if
157: //debug (" <2>");
158:
159: // this should only be one element - a single constructionDemand task
160: // of a particular type
161: while (tasks.hasMoreElements()) {
162: if (processTask((Task) tasks.nextElement(),
163: consumerSchedules_)) {
164: return true;
165: } // if
166: } // while
167: return false;
168: } // processTasks
169:
170: public boolean processTask(Task task, Hashtable consumerSchedules_) {
171: //debug (" in processTask");
172:
173: Vector demand_tasks = createDemandTasks(task,
174: consumerSchedules_);
175: if ((demand_tasks == null) || (demand_tasks.size() == 0)) {
176: return true;
177: } // if
178: publishExpansion(task, demand_tasks);
179: return false;
180: } // processTask
181:
182: protected Vector createDemandTasks(Task parent_task,
183: Hashtable consumerSchedules_) {
184:
185: //debug (" in createDemandTasks");
186:
187: Asset consumer;
188: String consumer_id;
189: ConstructionDemandSpec spec;
190: Schedule consumer_sched;
191: //create materiel_sched off start and end preferences off of parent task
192: long start = 0;
193: long end = 0;
194: Enumeration parentprefs = parent_task.getPreferences();
195: while (parentprefs.hasMoreElements()) {
196: Preference apref = (Preference) parentprefs.nextElement();
197: if (apref.getAspectType() == AspectType.START_TIME) {
198: start = (long) apref.getScoringFunction().getBest()
199: .getValue();
200: } else if (apref.getAspectType() == AspectType.END_TIME) {
201: end = (long) apref.getScoringFunction().getBest()
202: .getValue();
203: }
204: }
205: Schedule materiel_sched = ScheduleUtils
206: .buildSimpleQuantitySchedule(1, start, end);
207:
208: //System.out.println("&&& parent task is: " + parent_task);
209: //System.out.println("\n &&&&&&& materiel_sched is "+materiel_sched);
210:
211: // Project demand for each consumer in the cluster.
212: Enumeration assets = consumerSchedules_.keys();
213: Vector tasks = new Vector();
214: //Vector glm_oplans = thisPlugin_.getOPlans();
215: //debug (" glm_oplans is " + glm_oplans);
216: while (assets.hasMoreElements()) {
217:
218: consumer = (Asset) assets.nextElement();
219: //debug (" working with asset " + consumer);
220: consumer_sched = (Schedule) consumerSchedules_
221: .get(consumer);
222: spec = new ConstructionDemandSpec(consumer, consumer_sched,
223: materiel_sched, ldmFactory_);
224:
225: addAssetsToConsumerSpec(parent_task, spec);
226:
227: Task dTask = newDemandTask(parent_task, consumer, spec);
228: tasks.add(dTask);
229: } // while
230: return tasks;
231: } // createDemandTasks
232:
233: /**
234: * Looks up the required assets from the asset table and adds these assets to
235: * the demand spec. The rates a calculated and added also.
236: */
237: private void addAssetsToConsumerSpec(Task task,
238: ConstructionDemandSpec spec) {
239:
240: String taskVerb = task.getVerb().toString();
241:
242: //Collection subtasks = new ArrayList();
243:
244: try {
245: String rawdb = Parameters
246: .replaceParameters("${construction.database}");
247: int colonIndex1 = rawdb.indexOf(':');
248: int colonIndex2 = rawdb.indexOf(':', colonIndex1 + 1);
249: String dbType = rawdb.substring(colonIndex1 + 1,
250: colonIndex2);
251: Class.forName(Parameters.findParameter("driver." + dbType));
252: Connection conn = null;
253: ResultSet rset = null;
254:
255: try {
256:
257: // Connect to the database
258: // You must put a database name after the @ sign in the connection URL.
259: // You can use either the fully specified SQL*net syntax or a short cut
260: // syntax as <host>:<port>:<sid>. The example uses the short cut syntax.
261: //get the db info out of the cougaarrc file
262: String dbinfo = Parameters.replaceParameters(rawdb);
263: String rawuser = "${construction.user}";
264: String dbuser = Parameters.replaceParameters(rawuser);
265: String rawpasswd = "${construction.password}";
266: String dbpasswd = Parameters
267: .replaceParameters(rawpasswd);
268:
269: conn = DriverManager.getConnection(dbinfo, dbuser,
270: dbpasswd);
271:
272: String parentverb = task.getVerb().toString();
273: // Create a Statement
274: Statement stmt = conn.createStatement();
275:
276: //First get the first order leaf tasks
277: StringBuffer query = new StringBuffer(
278: "select NSN, NOMENCLATURE, MATERIEL_QTY, MATERIEL_UOM from CONSTR_TASK_MATERIEL where TASK_NAME = ");
279: query.append("'" + taskVerb + "'");
280:
281: //System.out.println("\n About to execute query: "+ query);
282: rset = stmt.executeQuery(query.toString());
283:
284: while (rset.next()) {
285: String nsn = rset.getString(1);
286: String nomenclature = rset.getString(2);
287: double quantity = rset.getDouble(3);
288: String units = rset.getString(4);
289:
290: //System.out.println("\n Got a result set for the query: " +
291: // nsn + ", " + nomenclature + ", " + quantity + ", " + units);
292:
293: long dayDuration = (PluginHelper.getEndTime(task) - PluginHelper
294: .getStartTime(task))
295: / MSEC_PER_DAY;
296: //System.out.println("task duration is " + dayDuration);
297:
298: // just average out the total task count over the time period
299: CountRate rate = new CountRate(new Count(quantity,
300: Count.UNITS), new Duration(dayDuration,
301: Duration.DAYS));
302: //System.out.println("calculated rate of " + rate);
303:
304: //Asset theAsset = new ClassIVConstructionMaterial();
305: ClassIVConstructionMaterial theAsset = (ClassIVConstructionMaterial) ldmFactory_
306: .createPrototype(
307: "ClassIVConstructionMaterial",
308: nomenclature);
309: NewSupplyClassPG pg = (NewSupplyClassPG) org.cougaar.glm.ldm.asset.PropertyGroupFactory
310: .newSupplyClassPG();
311: pg.setSupplyClass("ClassIVConstructionMaterial");
312: pg.setSupplyType("ClassIVConstructionMaterial");
313: theAsset.setPropertyGroup(pg);
314:
315: String fullnsn = new String("NSN/");
316: fullnsn = fullnsn.concat(nsn);
317: NewTypeIdentificationPG tipg = (NewTypeIdentificationPG) org.cougaar.glm.ldm.asset.PropertyGroupFactory
318: .newTypeIdentificationPG();
319: tipg.setTypeIdentification(fullnsn);
320: tipg.setNomenclature(nomenclature);
321: theAsset.setPropertyGroup(tipg);
322:
323: spec.addAsset(theAsset, rate);
324:
325: }
326:
327: // close this round of queries
328: stmt.close();
329:
330: } catch (SQLException e) {
331: System.err.println("Query failed: " + e);
332: } finally {
333: if (conn != null)
334: conn.close();
335: }
336: } catch (Exception e) {
337: System.err
338: .println("Caught exception while executing a query: "
339: + e);
340: e.printStackTrace();
341: }
342:
343: //System.out.println("\n About to return: " + subtasks.size() + "Subtasks for Workflow");
344: //return subtasks;
345:
346: }
347:
348: protected Task newDemandTask(Task parent_task, Asset consumer,
349: ConsumerSpec spec) {
350:
351: // create prepositions for the new Supply task
352: Vector pp_vector = new Vector();
353:
354: pp_vector
355: .addElement(newPrepositionalPhrase("DemandSpec", spec));
356:
357: pp_vector.addElement(newPrepositionalPhrase(
358: Constants.Preposition.OFTYPE,
359: "ClassIVConstructionMaterial"));
360:
361: NewTask t = (NewTask) buildTask(parent_task,
362: Constants.Verb.GENERATEPROJECTIONS,
363: //ConstructionConstants.Verb.GENERATE_CONSTRUCTION_DEMAND,
364: consumer, pp_vector);
365:
366: return t;
367: } // newDemandTask
368:
369: /**
370: * Create a quantity schedule for each type of consumer
371: * representing the number of that type of consumer over time.
372: **/
373: private Hashtable createConsumerSchedules() {
374: Hashtable consumerSchedules_ = new Hashtable();
375: consumerSchedules_.clear();
376:
377: ScheduledContentPG scp;
378: int qty;
379: Asset consumer, asset;
380:
381: asset = myOrganization;
382:
383: scp = null;
384: qty = 1;
385: consumer = asset.getPrototype();
386: if (consumer == null) {
387: // don't expect this to happen
388: //debug("asset: "+asset+" has null prototype");
389: consumer = asset;
390: } // if
391:
392: // CDW - The previous error message probably displayed.
393: // So what? I'll set it myself, thank you very much.
394: consumer = myOrganization;
395:
396: Schedule role_sched = asset.getRoleSchedule()
397: .getAvailableSchedule();
398: if (role_sched == null) {
399: // error
400: debug("createConsumerSchedule no available schedule for asset "
401: + AssetUtils.assetDesc(asset));
402: //continue;
403: } // if
404:
405: // Start and end time of the consumers in the cluster
406: long start = role_sched.getStartTime();
407: long end = role_sched.getEndTime();
408: if (start >= end - 1) {
409: // error
410: debug("createConsumerSchedule bad times "
411: + TimeUtils.dateString(start) + " to "
412: + TimeUtils.dateString(end));
413: //continue;
414: } // if
415: Schedule sched = (Schedule) consumerSchedules_.get(consumer);
416: // ScheduleUtils schedule methods have a granularity - so 1000 = 1 sec
417: // so everything is scheduled on an even second
418: if (sched != null) {
419: sched = ScheduleUtils.adjustSchedule(sched, start, end,
420: qty, 1000);
421: } else {
422: sched = ScheduleUtils.buildSimpleQuantitySchedule(qty,
423: start, end, 1000);
424: } // if
425:
426: consumerSchedules_.put(consumer, sched);
427:
428: return consumerSchedules_;
429: } // createConsumerSchedules
430: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
431:
432: private UnaryPredicate constructionDemandPred = new UnaryPredicate() {
433: public boolean execute(Object o) {
434: if (o instanceof Task) {
435: Task t = (Task) o;
436: if ((t.getVerb()
437: .equals(ConstructionConstants.Verb.Lay_Gravel))
438: || (t.getVerb()
439: .equals(ConstructionConstants.Verb.Lay_Mesh))
440: || (t.getVerb()
441: .equals(ConstructionConstants.Verb.Pour_Concrete))
442: || (t.getVerb()
443: .equals(ConstructionConstants.Verb.Cut_Trees))
444: || (t.getVerb()
445: .equals(ConstructionConstants.Verb.Remove_Stumps))
446: || (t.getVerb()
447: .equals(ConstructionConstants.Verb.Doze_Area))
448: || (t.getVerb()
449: .equals(ConstructionConstants.Verb.Scrape_Area))
450: || (t.getVerb()
451: .equals(ConstructionConstants.Verb.Steam_Roll_Area))
452: || (t.getVerb()
453: .equals(ConstructionConstants.Verb.Compact_Area))
454: || (t.getVerb()
455: .equals(ConstructionConstants.Verb.Spray_Sealer))
456: || (t.getVerb()
457: .equals(ConstructionConstants.Verb.Build_Frames))
458: || (t.getVerb()
459: .equals(ConstructionConstants.Verb.Establish_Sanitation))
460: || (t.getVerb()
461: .equals(ConstructionConstants.Verb.Establish_Power))
462: || (t.getVerb()
463: .equals(ConstructionConstants.Verb.Build_Walls))
464: || (t.getVerb()
465: .equals(ConstructionConstants.Verb.Construct_Roofing))) {
466:
467: //debug ("Found an input task to process: " + t.getVerb());
468: return true;
469: }
470: }
471: return false;
472: }
473: };
474:
475: private UnaryPredicate generateConstructionProjectionPred = new UnaryPredicate() {
476: public boolean execute(Object o) {
477: if (o instanceof Task) {
478: Task t = (Task) o;
479: if (t.getVerb().equals("GENERATECONSTRUCTIONDEMAND")) {
480: return true;
481: } // if
482: } // if
483: return false;
484: } // execute
485: }; // generateConstructionProjectionPred
486:
487: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
488:
489: public void debug(String msg) {
490: System.out.println("\n" + className + ": " + msg);
491: } // debug
492:
493: } // ConstructionGenerateDemandProjector
|