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.logistics.plugin.inventory;
028:
029: import org.cougaar.glm.ldm.asset.Inventory;
030: import org.cougaar.glm.ldm.asset.Organization;
031: import org.cougaar.glm.ldm.plan.AlpineAspectType;
032: import org.cougaar.glm.ldm.plan.GeolocLocation;
033: import org.cougaar.logistics.ldm.Constants;
034: import org.cougaar.planning.ldm.asset.TypeIdentificationPG;
035: import org.cougaar.planning.ldm.measure.*;
036: import org.cougaar.planning.ldm.plan.*;
037:
038: import java.util.*;
039:
040: /** The Refill Projection Generator Module is responsible for generating
041: * projection refill tasks. These projections will be calculated by
042: * time shifting the projections from each customer and summing the
043: * results.
044: * Called by the Inventory Plugin when there is new projection demand.
045: * Uses the InventoryBG module to gather projected demand.
046: * Generates Refill Projection tasks
047: * NOTE: Right now this module assumes that all customers have the
048: * same VTH boundaries as we do. This means that Level 2 demand is
049: * calculated soley from Level 2 incoming demand. In the future we will
050: * need to account for differing level2 boundaries and calculate level 2
051: * projections by summing the tonnage across level 6 projections for all
052: * inventories.
053: **/
054:
055: public class RefillProjectionGenerator extends InventoryLevelGenerator
056: implements RefillProjectionGeneratorModule {
057:
058: private transient Organization myOrg = null;
059: private transient String myOrgName = null;
060: private transient GeolocLocation homeGeoloc = null;
061: LevelOfDetailInventoryManager detailInventoryManager;
062:
063: /** Need to pass in the IM Plugin for now to get services
064: * and util classes.
065: **/
066: public RefillProjectionGenerator(InventoryManager imPlugin,
067: LevelOfDetailInventoryManager detailInventoryManager) {
068: super (imPlugin);
069: this .detailInventoryManager = detailInventoryManager;
070: }
071:
072: /** Called by the InventoryPlugin to calculate new Refills.
073: * We only want to calculate new Refills for inventories that have changed
074: * because of projection changes.
075: * @param touchedInventories Inventories that have changed
076: * @param daysOnHand Number of DaysOnHand from the InventoryPolicy
077: * @param endOfLevelSix The day representing the end of the Level 6 window
078: * from the VariableTimeHorizon OperatingMode (knob)
079: * @param endOfLevelTwo The day representing the end of the Level 2 window
080: * from the VariableTimeHorizon OperatingMode (knob)
081: **/
082: public void calculateRefillProjections(
083: Collection touchedInventories, int daysOnHand,
084: long endOfLevelSix, long endOfLevelTwo,
085: ComparatorModule theComparator) {
086:
087: // NOTE!!!!
088: // For now since we aren't doing anything special for the level 2 time window like
089: // translating level 6 to level 2 or vice versa - just use the level 6 method to
090: // calculate everything. This means the end time used by that method will
091: // be the end of the level 2 window as we don't want to process anything after that.
092:
093: if (!touchedInventories.isEmpty()) {
094: calculateLevelSixProjections(touchedInventories,
095: daysOnHand, endOfLevelTwo, theComparator);
096: }
097:
098: // get the demand projections for each customer from bg
099: // time shift the demand for each customer
100: // sum the each customer's time shifted demand
101:
102: // ArrayList level6Inventories = new ArrayList();
103: // Inventory level2Inv = null;
104:
105: // Iterator touchedIter = touchedInventories.iterator();
106: // while (touchedIter.hasNext()) {
107: // Inventory inv = (Inventory) touchedIter.next();
108: // LogisticsInventoryPG thePG = (LogisticsInventoryPG)inv.
109: // searchForPropertyGroup(LogisticsInventoryPG.class);
110: // if (thePG.getIsLevel2()) {
111: // level2Inv = inv;
112: // } else {
113: // level6Inventories.add(inv);
114: // }
115: // }
116:
117: // if (! level6Inventories.isEmpty()) {
118: // calculateLevelSixProjections(level6Inventories, daysOnHand,
119: // endOfLevelSix, theComparator);
120: // }
121: // // if the level 2 and level 6 boundaries are = don't process
122: // // and just for safety make sure the end of level 2 doesn't fall before
123: // // the end of the level 6 window
124: // if ((level2Inv != null) && ( endOfLevelTwo > endOfLevelSix)) {
125: // if (inventoryPlugin.getClusterId().toString().equals("1-35-ARBN")) {
126: // System.out.println("RPG calling calculate level 2 projections");
127: // }
128: // calculateLevelTwoProjections(level2Inv, daysOnHand,
129: // getTimeUtils().addNDays(endOfLevelSix, 1),
130: // endOfLevelTwo, theComparator);
131: // }
132: // }
133: }
134:
135: /** Calculate Projection Refills in level Six detail until the end of the
136: * Level 6 VTH window.
137: * @param touchedInventories The Inventories that have changed wrt projections.
138: * We will only recalculate refill projections for these.
139: * @param daysOnHand DaysOnHand policy.
140: * @param endOfLevelSix The date representing the end of the Level 6 VTH window.
141: **/
142: protected void calculateLevelSixProjections(
143: Collection touchedInventories, int daysOnHand,
144: long endOfLevelSix, ComparatorModule myComparator) {
145:
146: ArrayList refillProjections = new ArrayList();
147: ArrayList oldProjections = new ArrayList();
148:
149: //temp mwd
150: // inventoryPlugin.updateStartAndEndTimes();
151:
152: Iterator tiIter = touchedInventories.iterator();
153: while (tiIter.hasNext()) {
154: // clear out the old and new projections for the last Inventory
155: refillProjections.clear();
156: oldProjections.clear();
157: Inventory anInventory = (Inventory) tiIter.next();
158: LogisticsInventoryPG thePG = (LogisticsInventoryPG) anInventory
159: .searchForPropertyGroup(LogisticsInventoryPG.class);
160:
161: //start time is the start time of the inventorybg
162: long startDay = thePG.getStartTime();
163: if (startDay < detailInventoryManager.getRefillStartTime()) {
164: startDay = detailInventoryManager.getRefillStartTime();
165: }
166:
167: long now = inventoryPlugin.getCurrentTimeMillis();
168:
169: //Bug fix for 13464
170: long cutoffTime = now
171: + ((detailInventoryManager.getOrderShipTime()) * thePG
172: .getBucketMillis());
173: //round up if need be (not exactly on the zero mark)
174: cutoffTime = thePG.convertBucketToTime(thePG
175: .convertTimeToBucket(cutoffTime, true));
176:
177: if (cutoffTime > startDay) {
178: startDay = cutoffTime;
179: }
180:
181: int startBucket = thePG.convertTimeToBucket(startDay, true);
182:
183: // clear all of the projections
184: oldProjections.addAll(thePG
185: .clearRefillProjectionTasks(cutoffTime));
186: //grab the overlapping tasks and change their end time
187: ArrayList projectionsToCut = (ArrayList) thePG
188: .getOverlappingRefillProjections();
189: Iterator toCut = projectionsToCut.iterator();
190: while (toCut.hasNext()) {
191: Task taskToCut = (Task) toCut.next();
192: if (taskToCut != null) {
193: Preference new_end = getTaskUtils()
194: .createTimePreference(
195: cutoffTime,
196: inventoryPlugin
197: .getOPlanArrivalInTheaterTime(),
198: inventoryPlugin.getOPlanEndTime(),
199: AspectType.END_TIME,
200: inventoryPlugin.getClusterId(),
201: inventoryPlugin
202: .getPlanningFactory(),
203: thePG);
204: ((NewTask) taskToCut).setPreference(new_end);
205: inventoryPlugin.publishChange(taskToCut);
206: thePG.updateRefillProjection(taskToCut);
207: }
208: }
209:
210: int currentBucket = startBucket;
211: // int customerDemandBucket = thePG.convertTimeToBucket(getTimeUtils().
212: // addNDays(startDay, daysOnHand), true);
213: //int customerDemandBucket = thePG.convertTimeToBucket(startDay, false) + daysOnHand;
214:
215: //Bug fix for #13464
216: int customerDemandBucket = startBucket + daysOnHand;
217:
218: double projDemand = 0;
219: double nextProjDemand = 0;
220: int endOfLevelSixBucket = thePG.convertTimeToBucket(
221: endOfLevelSix, false);
222: thePG.setEndOfLevelSixBucket(endOfLevelSixBucket);
223:
224: //get the initial demand for the customer for startBucket + daysOnHand
225: //Is there a better way to do this to avoid the duplication?
226: projDemand = thePG.getProjectedDemand(customerDemandBucket);
227:
228: //move forward a bucket
229: currentBucket = currentBucket + 1;
230: customerDemandBucket = customerDemandBucket + 1;
231:
232: int refillCtr = 0;
233:
234: //Begin looping through currentBucket forward until you hit the end of
235: // the level six boundary
236: //possible boundary issue... is it '<' or '<=' ??
237: while (currentBucket < endOfLevelSixBucket) {
238: nextProjDemand = thePG
239: .getProjectedDemand(customerDemandBucket);
240: if (projDemand != nextProjDemand) {
241: //if there's a change in the demand, create a refill projection
242: //BUT only if demand is non-zero
243: if (projDemand > 0.0) {
244:
245: Task refill = createProjectionRefill(
246: thePG.convertBucketToTime(startBucket),
247: thePG
248: .convertBucketToTime(currentBucket),
249: projDemand, thePG);
250: if (startBucket >= currentBucket) {
251: logger.error("Invalid task : "
252: + getTaskUtils().taskDesc(refill)
253: + ", startDay: "
254: + getTimeUtils().dateString(
255: startDay)
256: + ", startBucket: " + startBucket
257: + ", currentBucket: "
258: + currentBucket);
259: } else {
260: refillProjections.add(refill);
261: }
262: }
263: //then reset the start bucket and the new demand
264: startBucket = currentBucket;
265: projDemand = nextProjDemand;
266: }
267: //in either case bump current and customer forward a bucket.
268: currentBucket = currentBucket + 1;
269: customerDemandBucket = customerDemandBucket + 1;
270: }
271: // when we get to the end of the level six window create the last
272: // projection task (if there is one)
273: if (startBucket != currentBucket) {
274: // HERE LIES A BUG. We should never generate zero demand projection tasks
275: // and never generate projection tasks that go beyond the end of the war
276: if (projDemand > 0.0) {
277: Task lastRefill = createProjectionRefill(thePG
278: .convertBucketToTime(startBucket), thePG
279: .convertBucketToTime(currentBucket),
280: projDemand, thePG);
281: if (startBucket >= currentBucket) {
282: logger.error("Invalid task : "
283: + getTaskUtils().taskDesc(lastRefill)
284: + ", startDay: "
285: + getTimeUtils().dateString(startDay)
286: + ", startBucket: " + startBucket
287: + ", currentBucket: " + currentBucket);
288: } else {
289: refillProjections.add(lastRefill);
290: }
291: }
292: }
293: // send the new projections and the old projections to the Comparator
294: // the comparator will rescind the old and publish the new projections
295: myComparator.compareRefillProjections(refillProjections,
296: oldProjections, anInventory);
297:
298: if (thePG.getIsLevel2()) {
299: setTargetForProjectionPeriod(thePG, 0, thePG
300: .getInitialLevel());
301: }
302: }
303:
304: }
305:
306: /** Calculate the Projection Refills in Level 2
307: * Right now we assume that all of our customers have the same
308: * VTH boundaries as we do - so all of our level refills are based
309: * on customer level 2 demand.
310: * In the future we will want to enhance this code to deal with
311: * customers having different VTH boundaries then us, meaning that we
312: * need to take into account customer level 2 demand and calculate level 2
313: * demand from customer level 6 demand if our level 2 window is earlier than the
314: * customer's level2 window.
315: * @param level2Inv The level 2 inventory for this supply type.
316: * @param daysOnHand The DaysOnHand value from the InventoryPolicy
317: * @param start The start time of the Level 2 VTH window
318: * @param endOfLevelTwo The end time of the Level 2 VTH window
319: * @param theComparator The Comparator instance to compare old and new level 2 projections
320: **/
321: // private void calculateLevelTwoProjections(Inventory level2Inv, int daysOnHand,
322: // long start, long endOfLevelTwo,
323: // RefillComparator theComparator) {
324: // ArrayList newProjections = new ArrayList();
325: // ArrayList oldProjections = new ArrayList();
326: // LogisticsInventoryPG level2PG = (LogisticsInventoryPG) level2Inv.
327: // searchForPropertyGroup(LogisticsInventoryPG.class);
328: // // for now clear all the level 2 projections and only create
329: // // new ones for the current level2 window
330: // // this will have to change once we have mismatched level 2 windows
331: // oldProjections.addAll(level2PG.clearRefillProjectionTasks());
332: // int startBucket = level2PG.convertTimeToBucket(start, true);
333: // // int currentBucket = startBucket;
334: // // int customerDemandBucket = level2PG.convertTimeToBucket(getTimeUtils().
335: // // addNDays(start, daysOnHand));
336: // // We need to time shift refills by days on hand. So if level 2 demand starts the
337: // // day the level 2 window starts then we actually need to order outside of the level 2
338: // // window. Perhaps this is wrong - and we should order the first 3 days in level 6
339: // // but right now we don't have the data to do this.
340: // int currentBucket = startBucket - daysOnHand;
341: // //reset startBucket
342: // startBucket = currentBucket;
343: // int customerDemandBucket = startBucket;
344: // int endOfLevelTwoBucket = level2PG.convertTimeToBucket(endOfLevelTwo, true);
345: // // get intital demand level
346: // double projDemand = level2PG.getProjectedDemand(customerDemandBucket);
347: // double nextProjDemand = 0;
348: // // move ahead one day
349: // currentBucket = currentBucket + 1;
350: // customerDemandBucket = customerDemandBucket + 1;
351: // //In the future with varying customer level 2 windows we will have to
352: // //loop through all of our Inventories and sum the tonnage of demand
353: // // for a level 2 combined demand per bucket.
354: // //loop through the buckets until we reach the end of level two
355: // while (currentBucket < endOfLevelTwoBucket) {
356: // nextProjDemand = level2PG.getProjectedDemand(customerDemandBucket);
357: // //check the results for the Day.
358: // if (projDemand != nextProjDemand) {
359: // //if there's a change in the demand, create a refill projection
360: // //BUT only if demand is non-zero
361: // if (projDemand > 0.0) {
362: // old
363: // Task newLevel2Refill =
364: // createAggregateProjectionRefill(level2PG.convertBucketToTime(startBucket),
365: // level2PG.convertBucketToTime(currentBucket),
366: // level2PG.getStartTime(), projDemand, level2PG,
367: // level2Inv);
368: // new (can't have earliest arrive before we get to theatre
369: // Task newLevel2Refill =
370: // createAggregateProjectionRefill(level2PG.convertBucketToTime(startBucket),
371: // level2PG.convertBucketToTime(currentBucket),
372: // inventoryPlugin.getOPlanArrivalInTheaterTime(), projDemand,
373: // level2PG,
374: // level2Inv);
375: // newProjections.add(newLevel2Refill);
376: // }
377: // //then reset the start bucket and the new demand
378: // startBucket = currentBucket;
379: // projDemand = nextProjDemand;
380: // }
381: // // bump forward a bucket.
382: // currentBucket = currentBucket + 1;
383: // customerDemandBucket = customerDemandBucket + 1;
384: // }
385: // // when we get to the end of the level two window create the last
386: // // projection task (if there is one)
387: // if (startBucket != currentBucket) {
388: // if (projDemand > 0.0) {
389: // old
390: // Task lastLevel2Refill =
391: // createAggregateProjectionRefill(level2PG.convertBucketToTime(startBucket),
392: // level2PG.convertBucketToTime(currentBucket),
393: // level2PG.getStartTime(), projDemand, level2PG,
394: // level2Inv);
395: // new (can't have earliest arrive before we get to theatre
396: // Task lastLevel2Refill =
397: // createAggregateProjectionRefill(level2PG.convertBucketToTime(startBucket),
398: // level2PG.convertBucketToTime(currentBucket),
399: // inventoryPlugin.getOPlanArrivalInTheaterTime(),
400: // projDemand, level2PG,
401: // level2Inv);
402: // newProjections.add(lastLevel2Refill);
403: // }
404: // }
405: // // send the new projections and the old projections to the Comparator
406: // // the comparator will rescind the old and publish the new projections
407: // theComparator.compareRefillProjections(newProjections, oldProjections,
408: // level2Inv);
409: // setTargetForProjectionPeriod(level2PG, 1, level2PG.getInitialLevel());
410: // }
411:
412: /** Make a Projection Refill Task and publish it to the InventoryPlugin.
413: * The InventoryPlugin will hook the task in to the proper workflow
414: * and publish it to the blackboard.
415: * @param start The start time for the Task
416: * @param end The end time for the Task
417: * @param demand The demandrate value of the task
418: * @param thePG The Property Group of the Inventory Asset
419: * @return Task The new Projection Refill
420: **/
421: protected Task createProjectionRefill(long start, long end,
422: double demand, LogisticsInventoryPG thePG) {
423: //create a projection refill task
424: NewTask newRefill = inventoryPlugin.getPlanningFactory()
425: .newTask();
426: newRefill.setVerb(Constants.Verb.ProjectSupply);
427: newRefill.setDirectObject(thePG.getResource());
428: // newRefill = fillInTask(newRefill, start, end, thePG.getStartTime(),
429: // demand, thePG);
430: newRefill = fillInTask(newRefill, start, end, inventoryPlugin
431: .getOPlanArrivalInTheaterTime(), demand, thePG);
432: return newRefill;
433: }
434:
435: /** Create a Level 2 Projection Refill
436: * @param start The start time of the Task
437: * @param end The end time of the Task
438: * @param earliest The earliest delivery time.
439: * @param demand The total demand in terms of tons or volume
440: * @param level2PG The PropertyGroup of the Level 2 Inventory
441: * @param level2Inv The Level 2 Inventory
442: * @return Task The new Level 2 Projection Task
443: **/
444: private Task createAggregateProjectionRefill(long start, long end,
445: long earliest, double demand,
446: LogisticsInventoryPG level2PG, Inventory level2Inv) {
447: //create a level two projection refill task
448: NewTask newAggRefill = inventoryPlugin.getPlanningFactory()
449: .newTask();
450: newAggRefill.setVerb(Constants.Verb.ProjectSupply);
451: //TODO - for now physical pg can stay the same as the demand task
452: //physical pg needs to represent demand
453: // level2Asset.setPhysicalPG(demand);
454: newAggRefill.setDirectObject(level2Inv);
455: newAggRefill = fillInTask(newAggRefill, start, end, earliest,
456: demand, level2PG);
457: return newAggRefill;
458: }
459:
460: /** Utility method to fill in task details
461: * @param newRefill The task to fill in
462: * @param start Start time for Task
463: * @param end End Time for Task
464: * @param qty Quantity Pref for Task
465: * @param thePG The property group attached to the Inventory
466: * @return NewTask the filled in Task
467: **/
468: protected NewTask fillInTask(NewTask newRefill, long start,
469: long end, long earliest, double qty,
470: LogisticsInventoryPG thePG) {
471: // create preferences
472: Vector prefs = new Vector();
473: Preference p_start, p_end, p_qty;
474: p_start = getTaskUtils().createTimePreference(start, earliest,
475: inventoryPlugin.getOPlanEndTime(),
476: AspectType.START_TIME, inventoryPlugin.getClusterId(),
477: inventoryPlugin.getPlanningFactory(), thePG);
478: p_end = getTaskUtils().createTimePreference(end, earliest,
479: inventoryPlugin.getOPlanEndTime(), AspectType.END_TIME,
480: inventoryPlugin.getClusterId(),
481: inventoryPlugin.getPlanningFactory(), thePG);
482: p_qty = createRefillRatePreference(qty, thePG.getBucketMillis());
483: prefs.add(p_start);
484: prefs.add(p_end);
485: prefs.add(p_qty);
486: newRefill.setPreferences(prefs.elements());
487:
488: //create Prepositional Phrases
489: Vector pp_vector = new Vector();
490: pp_vector.add(createPrepPhrase(Constants.Preposition.FOR,
491: getOrgName()));
492: pp_vector.add(createPrepPhrase(Constants.Preposition.OFTYPE,
493: inventoryPlugin.getSupplyType()));
494:
495: Object io;
496: Enumeration geolocs = getAssetUtils().getGeolocLocationAtTime(
497: getMyOrganization(), (end - 1000));
498: if (geolocs.hasMoreElements()) {
499: io = (GeolocLocation) geolocs.nextElement();
500: } else {
501: io = getHomeLocation();
502: }
503: pp_vector.addElement(createPrepPhrase(Constants.Preposition.TO,
504: io));
505: TypeIdentificationPG tip = thePG.getResource()
506: .getTypeIdentificationPG();
507: MaintainedItem itemID = MaintainedItem
508: .findOrMakeMaintainedItem("Inventory", tip
509: .getTypeIdentification(), null, tip
510: .getNomenclature(),
511: (UtilsProvider) inventoryPlugin);
512: pp_vector.add(createPrepPhrase(
513: Constants.Preposition.MAINTAINING, itemID));
514: pp_vector.add(createPrepPhrase(Constants.Preposition.REFILL,
515: null));
516:
517: newRefill.setPrepositionalPhrases(pp_vector.elements());
518: return newRefill;
519: }
520:
521: /** Utility method to create Refill Projection Rate preference
522: * We use a V scoring function for this preference.
523: * @param refill_qty The quantity we want for this Refill Task
524: * @return Preference The new demand rate preference for the Refill Task
525: **/
526: protected Preference createRefillRatePreference(double refill_qty,
527: long bucketMillis) {
528: AspectValue bestAV;
529: Duration dur = new Duration(bucketMillis, Duration.MILLISECONDS);
530: //highAV could be bumped to more than refill_qty + 1 if needed
531: if (inventoryPlugin.getSupplyType().equals("BulkPOL")) {
532: Volume vol = new Volume(refill_qty, Volume.GALLONS);
533: bestAV = AspectValue
534: .newAspectValue(AlpineAspectType.DEMANDRATE,
535: new FlowRate(vol, dur));
536: } else {
537: Count cnt = new Count(refill_qty, Count.EACHES);
538: bestAV = AspectValue.newAspectValue(
539: AlpineAspectType.DEMANDRATE,
540: new CountRate(cnt, dur));
541: }
542: ScoringFunction qtySF = ScoringFunction
543: .createStrictlyAtValue(bestAV);
544: return inventoryPlugin.getPlanningFactory().newPreference(
545: AlpineAspectType.DEMANDRATE, qtySF);
546: }
547:
548: /** Utility method to create a Refill Projection Prepositional Phrase
549: * @param prep The preposition
550: * @param io The indirect object
551: * @return PrepositionalPhrase A new prep phrase for the task
552: **/
553: protected PrepositionalPhrase createPrepPhrase(String prep,
554: Object io) {
555: NewPrepositionalPhrase newpp = inventoryPlugin
556: .getPlanningFactory().newPrepositionalPhrase();
557: newpp.setPreposition(prep);
558: newpp.setIndirectObject(io);
559: return newpp;
560: }
561:
562: /** Utility method to get and keep organization info from the InventoryPlugin. **/
563: protected Organization getMyOrganization() {
564: if (myOrg == null) {
565: myOrg = inventoryPlugin.getMyOrganization();
566: // if we still don't have it after we ask the inventory plugin, throw an error!
567: if (myOrg == null) {
568: logger
569: .error("RefillProjectionGenerator can not get MyOrganization "
570: + "from the InventoryPlugin");
571: }
572: }
573: return myOrg;
574: }
575:
576: /** Utility accessor to get the Org Name from my organization and keep it around **/
577: protected String getOrgName() {
578: if (myOrgName == null) {
579: myOrgName = getMyOrganization().getItemIdentificationPG()
580: .getItemIdentification();
581: }
582: return myOrgName;
583: }
584:
585: /** Utility method to get the default (home) location of the Org **/
586: protected GeolocLocation getHomeLocation() {
587: if (homeGeoloc == null) {
588: Organization org = getMyOrganization();
589: if (org.getMilitaryOrgPG() != null) {
590: GeolocLocation geoloc = (GeolocLocation) org
591: .getMilitaryOrgPG().getHomeLocation();
592: if (geoloc != null) {
593: homeGeoloc = geoloc;
594: } else {
595: //if we can't find the home loc either print an error
596: logger
597: .error("RefillProjectionGenerator can not generate a "
598: + "Home Geoloc for org: " + org);
599: }
600: }
601: }
602: return homeGeoloc;
603: }
604:
605: }
|