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.logistics.ldm.Constants;
032: import org.cougaar.planning.ldm.asset.Asset;
033: import org.cougaar.planning.ldm.plan.Allocation;
034: import org.cougaar.planning.ldm.plan.AllocationResult;
035: import org.cougaar.planning.ldm.plan.Role;
036: import org.cougaar.planning.ldm.plan.Task;
037: import org.cougaar.planning.plugin.util.AllocationResultHelper;
038: import org.cougaar.planning.plugin.util.PluginHelper;
039:
040: import java.util.*;
041:
042: public class ExternalAllocator extends InventoryModule implements
043: AllocatorModule {
044:
045: private static int WARNING_SUPPRESSION_INTERVAL = 2;
046: private long warningCutoffTime = 0;
047:
048: Role providerRole;
049: /** list of nsn's with no resupply point */
050: private Vector noResupply;
051:
052: public ExternalAllocator(InventoryManager imPlugin, Role provider) {
053: super (imPlugin);
054: providerRole = provider;
055: noResupply = new Vector();
056: }
057:
058: // allocate our new refill tasks
059: public void allocateRefillTasks(Collection newRefills) {
060: Task refill;
061: Iterator refillIT = newRefills.iterator();
062: while (refillIT.hasNext()) {
063: refill = (Task) refillIT.next();
064: if (logger.isDebugEnabled()) {
065: logger.debug("Agent: "
066: + inventoryPlugin.getClusterId().toString()
067: + "ExtAlloc" + inventoryPlugin.getSupplyType()
068: + "]" + "trying to allocate refill task: "
069: + refill.getUID());
070: }
071: allocateTask(refill);
072: }
073: }
074:
075: protected boolean allocateTask(Task task) {
076: Organization provider = findBestSource(task);
077: if (provider != null) {
078: if (verifyBeforeAllocation(task, provider)) {
079: AllocationResult estAR = createPredictedAllocationResult(task);
080: Allocation alloc;
081: //either make an allocation or reset the estimated AR on the
082: // already existing pe - mostly likely to happen if a task's prefs
083: // changed.
084: if (task.getPlanElement() == null) {
085: alloc = buildAllocation(task, provider,
086: providerRole);
087: if (estAR != null) {
088: alloc.setEstimatedResult(estAR);
089: inventoryPlugin.publishAdd(alloc);
090: }
091: } else {
092: alloc = (Allocation) task.getPlanElement();
093: if (estAR != null) {
094: alloc.setEstimatedResult(estAR);
095: inventoryPlugin.publishChange(alloc);
096: }
097: }
098: }
099: }
100: return false;
101: }
102:
103: /** Figure out which organization supplying item is best for us. */
104: private Organization findBestSource(Task task) {
105: Enumeration support_orgs;
106: if (getTaskUtils().isProjection(task)) {
107: /* For a projection, should be time-phased as support
108: changes over time. We try for one provider for the whole task, if that doesn't work
109: we try to split it.*/
110: support_orgs = getAssetUtils().getSupportingOrgs(
111: inventoryPlugin.getMyOrganization(), providerRole,
112: getTaskUtils().getStartTime(task),
113: TaskUtils.getEndTime(task));
114: // if we have no providers that cover the whole projection, split it and try again
115: if (!support_orgs.hasMoreElements()) {
116: //HashMap provSchedMap = inventoryPlugin.relationshipScheduleMap();
117: List howToSplit = inventoryPlugin
118: .getNewTaskSplitTimes(task);
119: // if we can split it, do it, if not warn that we have no provider
120: if (!howToSplit.isEmpty()) {
121: Collection newPartialTasks = getTaskUtils()
122: .splitProjection(task, howToSplit,
123: inventoryPlugin);
124: allocateRefillTasks(newPartialTasks);
125: return null;
126: } else {
127: stagedMessageLog("No "
128: + providerRole
129: + " for projection task "
130: + task.getUID()
131: + ", during ["
132: + getTimeUtils().dateString(
133: getTaskUtils().getStartTime(task))
134: + "-"
135: + getTimeUtils().dateString(
136: TaskUtils.getEndTime(task)) + "]"
137: + ". Will retry.");
138: return null;
139: }
140: }
141: } else {
142: support_orgs = getAssetUtils().getSupportingOrgs(
143: inventoryPlugin.getMyOrganization(), providerRole,
144: getTaskUtils().getEndTime(task));
145: if (!support_orgs.hasMoreElements()) {
146: stagedMessageLog("No "
147: + providerRole
148: + " for task "
149: + task.getUID()
150: + ", during "
151: + getTimeUtils().dateString(
152: getTaskUtils().getEndTime(task))
153: + ". Will retry.");
154: return null;
155: }
156: }
157: // For now, returning the first supporting org during the time span
158: if (support_orgs.hasMoreElements()) {
159: return (Organization) support_orgs.nextElement();
160: } else {
161: return null;
162: }
163: }
164:
165: /** build Allocation with an estimated alloc result */
166: private Allocation buildAllocation(Task t, Asset a, Role r) {
167: return inventoryPlugin.getPlanningFactory().createAllocation(
168: t.getPlan(), t, a, null, r);
169: }
170:
171: private AllocationResult createPredictedAllocationResult(Task task) {
172: //MWD in the future this will have to generate the expected result
173: //from the predictor.
174: return new AllocationResultHelper(task, null)
175: .getAllocationResult(Constants.Confidence.DISPATCHED,
176: true);
177: }
178:
179: protected Collection findSingleSource(Task task, long endTime) {
180: Vector tasksAndProviders = new Vector();
181: Enumeration supportOrgs = getAssetUtils().getSupportingOrgs(
182: inventoryPlugin.getMyOrganization(), providerRole,
183: endTime);
184: if (supportOrgs.hasMoreElements()) {
185: // For now, returning the first supporting org during the time span
186: tasksAndProviders.add(task);
187: tasksAndProviders.add((Organization) supportOrgs
188: .nextElement());
189: return (tasksAndProviders);
190: } else {
191: findSourcesWarning(task);
192: return (null);
193: }
194: }
195:
196: protected class SupportOrg {
197: Organization org;
198: long startTime;
199: long endTime;
200:
201: public SupportOrg(Organization org, long startTime, long endTime) {
202: this .org = org;
203: this .startTime = startTime;
204: this .endTime = endTime;
205: }
206:
207: public Organization getOrg() {
208: return org;
209: }
210:
211: public long getEndTime() {
212: return endTime;
213: }
214:
215: public long getStartTime() {
216: return startTime;
217: }
218: };
219:
220: private long getWarningCutOffTime() {
221: if (warningCutoffTime == 0) {
222: // WARNING_SUPPRESSION_INTERVAL = Integer.getInteger(QUERY_GRACE_PERIOD_PROPERTY,
223: // WARNING_SUPPRESSION_INTERVAL).intValue();
224: warningCutoffTime = System.currentTimeMillis()
225: + WARNING_SUPPRESSION_INTERVAL * 60000;
226: }
227:
228: return warningCutoffTime;
229: }
230:
231: private void stagedMessageLog(String message) {
232: stagedMessageLog(message, null);
233: }
234:
235: private void stagedMessageLog(String message, Throwable e) {
236:
237: if (System.currentTimeMillis() > getWarningCutOffTime()) {
238: if (e == null)
239: logger.warn(inventoryPlugin.getClusterId().toString()
240: + message);
241: else
242: logger.warn(inventoryPlugin.getClusterId().toString()
243: + message, e);
244: } else if (logger.isInfoEnabled()) {
245: if (e == null)
246: logger.info(inventoryPlugin.getClusterId().toString()
247: + message);
248: else
249: logger.info(inventoryPlugin.getClusterId().toString()
250: + message, e);
251: }
252: }
253:
254: private boolean verifyBeforeAllocation(Task task, Organization org) {
255: // Do not allocate tasks after they have taken place-AF does this make sense?
256: if (!(task.beforeCommitment(new Date(inventoryPlugin
257: .getCurrentTimeMillis())))) {
258: logger
259: .warn("verifyBeforeAllocation: return ... after commitment "
260: + task.getCommitmentDate()
261: + " task:"
262: + task + " to Asset " + org);
263: // too late to change
264: return false;
265: }
266: return true;
267: }
268:
269: public HashSet updateAllocationResult(Collection sub) {
270: // System.out.println("ex alloc update ARs being called in" + inventoryPlugin.getClusterId());
271: HashSet backwardFlowInventories = new HashSet();
272: // Set up the affected inventories for the AllocationAssessor
273: Task refill;
274: Asset asset;
275: Allocation alloc;
276: Inventory inventory;
277: LogisticsInventoryPG logInvPG = null;
278: Iterator refill_list = sub.iterator(); // ###
279: while (refill_list.hasNext()) {
280: alloc = (Allocation) refill_list.next();
281: refill = alloc.getTask();
282: asset = refill.getDirectObject();
283: inventory = inventoryPlugin.findOrMakeInventory(asset);
284:
285: if (PluginHelper.updatePlanElement(alloc)) {
286: inventoryPlugin.publishChange(alloc);
287: if (logger.isDebugEnabled()) {
288: logger
289: .debug("Agent: "
290: + inventoryPlugin.getClusterId()
291: .toString()
292: + "ExtAlloc["
293: + inventoryPlugin.getSupplyType()
294: + "]"
295: + "publist Changing allocation due to AR change: "
296: + alloc.getUID()
297: + " parent task is: "
298: + alloc.getTask().getUID());
299: }
300: //System.out.println("ex all publish changing and added to AA's inventory list " + logInvPG.getResource());
301: backwardFlowInventories.add(inventory);
302:
303: logInvPG = (LogisticsInventoryPG) inventory
304: .searchForPropertyGroup(LogisticsInventoryPG.class);
305: if (refill.getVerb().equals(
306: Constants.Verb.PROJECTSUPPLY)) {
307: logInvPG.updateRefillProjection(refill);
308: } else {
309: logInvPG.updateRefillRequisition(refill);
310: }
311: }
312: }
313: return backwardFlowInventories;
314: }
315:
316: protected void findSourcesWarning(Task task) {
317: //String itemId = task.getDirectObject().getTypeIdentificationPG().getTypeIdentification();
318: if (getTaskUtils().isProjection(task)) {
319: logger.error("No "
320: + providerRole
321: + " for task "
322: + task.getUID()
323: + ", during ["
324: + getTimeUtils().dateString(
325: getTaskUtils().getStartTime(task))
326: + "-"
327: + getTimeUtils().dateString(
328: getTaskUtils().getEndTime(task)) + "]"
329: + ". Will retry.");
330: } else {
331: logger.error("No "
332: + providerRole
333: + " for task "
334: + task.getUID()
335: + ", during "
336: + getTimeUtils().dateString(
337: getTaskUtils().getEndTime(task))
338: + ". Will retry.");
339: }
340: }
341:
342: public void rescindTaskAllocations(Collection tasks) {
343: Task task;
344: Allocation alloc;
345: Iterator taskIt = tasks.iterator();
346: while (taskIt.hasNext()) {
347: task = (Task) taskIt.next();
348: alloc = (Allocation) task.getPlanElement();
349: inventoryPlugin.publishRemove(alloc);
350: }
351: }
352: }
|