Source Code Cross Referenced for AmmoProjectionExpanderPlugin.java in  » Science » Cougaar12_4 » org » cougaar » logistics » plugin » trans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » Cougaar12_4 » org.cougaar.logistics.plugin.trans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * <copyright>
0003:         *  
0004:         *  Copyright 2001-2004 BBNT Solutions, LLC
0005:         *  under sponsorship of the Defense Advanced Research Projects
0006:         *  Agency (DARPA).
0007:         * 
0008:         *  You can redistribute this software and/or modify it under the
0009:         *  terms of the Cougaar Open Source License as published on the
0010:         *  Cougaar Open Source Website (www.cougaar.org).
0011:         * 
0012:         *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013:         *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014:         *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015:         *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016:         *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017:         *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018:         *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019:         *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020:         *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021:         *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022:         *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023:         *  
0024:         * </copyright>
0025:         */
0026:        package org.cougaar.logistics.plugin.trans;
0027:
0028:        import org.cougaar.core.service.LoggingService;
0029:        import org.cougaar.core.util.UID;
0030:        import org.cougaar.glm.ldm.asset.*;
0031:        import org.cougaar.glm.ldm.asset.PropertyGroupFactory;
0032:        import org.cougaar.glm.ldm.plan.AlpineAspectType;
0033:        import org.cougaar.lib.callback.UTILExpandableTaskCallback;
0034:        import org.cougaar.lib.callback.UTILFilterCallback;
0035:        import org.cougaar.lib.callback.UTILFilterCallbackAdapter;
0036:        import org.cougaar.lib.callback.UTILGenericListener;
0037:        import org.cougaar.lib.util.UTILAllocate;
0038:        import org.cougaar.logistics.ldm.Constants;
0039:        import org.cougaar.logistics.plugin.inventory.TaskUtils;
0040:        import org.cougaar.planning.ldm.asset.*;
0041:        import org.cougaar.planning.ldm.measure.Area;
0042:        import org.cougaar.planning.ldm.measure.Mass;
0043:        import org.cougaar.planning.ldm.measure.Volume;
0044:        import org.cougaar.planning.ldm.plan.*;
0045:        import org.cougaar.util.UnaryPredicate;
0046:
0047:        import java.util.*;
0048:
0049:        /**
0050:         * Takes PROJECT_SUPPLY tasks 
0051:         * and converts them into TRANSPORT tasks with a RESERVATION prep. <p>
0052:         *
0053:         */
0054:        public class AmmoProjectionExpanderPlugin extends
0055:                AmmoLowFidelityExpanderPlugin {
0056:            public long CHUNK_DAYS = 30;
0057:            protected boolean FIND_FOR_UNIT_PREP_ON_TASK = false;
0058:            public static long MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
0059:            public static double SECS_PER_DAY = 60.0d * 60.0d * 24.0d;
0060:            public static final String AMMO_CATEGORY_CODE = "MBB";
0061:            public static final String MILVAN_NSN = "NSN/8115001682275";
0062:            public static final double PACKING_LIMIT = 13.9; /* short tons */
0063:            public static final long TASK_TRANSMISSION_DELAY = 1000 * 60 * 60;
0064:            private static Asset MILVAN_PROTOTYPE = null;
0065:            public static String START = "Start";
0066:            protected Map childToParent = new HashMap();
0067:            protected Map uidToTask = new HashMap();
0068:            protected Map typeToTasks = new HashMap();
0069:            protected UTILFilterCallback myTaskCallback;
0070:            protected List defaultUnit;
0071:            public TaskUtils taskUtils;
0072:
0073:            /**
0074:             * rely upon load-time introspection to set these services - 
0075:             * don't worry about revokation.
0076:             */
0077:            public void setLoggingService(LoggingService bs) {
0078:                super .setLoggingService(bs);
0079:                taskUtils = new TaskUtils(logger);
0080:            }
0081:
0082:            public void localSetup() {
0083:                super .localSetup();
0084:
0085:                try {
0086:                    if (getMyParams().hasParam("CHUNK_DAYS"))
0087:                        CHUNK_DAYS = getMyParams().getLongParam("CHUNK_DAYS");
0088:                    if (getMyParams().hasParam("FIND_FOR_UNIT_PREP_ON_TASK"))
0089:                        FIND_FOR_UNIT_PREP_ON_TASK = getMyParams()
0090:                                .getBooleanParam("FIND_FOR_UNIT_PREP_ON_TASK");
0091:                } catch (Exception e) {
0092:                    if (isWarnEnabled()) {
0093:                        warn("got unexpected exception " + e);
0094:                    }
0095:                }
0096:            }
0097:
0098:            /**
0099:             * Uses a special callback that maintains two maps :
0100:             *
0101:             * a uidToTask map so we can do parent task lookup efficiently AND
0102:             * a typeToTasks map so we can look up a list of tasks by what ammo type they are
0103:             *
0104:             * @see #getMatchingTasksByType
0105:             */
0106:            public void setupFilters() {
0107:                super .setupFilters();
0108:
0109:                addFilter(myTaskCallback = new UTILFilterCallbackAdapter(this ,
0110:                        logger) {
0111:                    protected UnaryPredicate getPredicate() {
0112:                        return new UnaryPredicate() {
0113:                            public boolean execute(Object o) {
0114:                                return (o instanceof  Task);
0115:                            }
0116:                        };
0117:                    }
0118:
0119:                    public void reactToChangedFilter() {
0120:                        Enumeration addedtasks = getSubscription()
0121:                                .getAddedList();
0122:                        while (addedtasks.hasMoreElements()) {
0123:                            Task task = (Task) addedtasks.nextElement();
0124:
0125:                            if (!(task instanceof  Task))
0126:                                error("huh? " + task + " is not an MPTask??");
0127:
0128:                            if (isInfoEnabled()) {
0129:                                info("uidToTask - mapping task "
0130:                                        + task.getUID());
0131:                            }
0132:
0133:                            uidToTask.put(task.getUID(), task);
0134:
0135:                            // keep a ammo type to tasks map so we can later compare
0136:                            // an actual task with a reserved or vice versa by just examining 
0137:                            // tasks with the same ammo type
0138:                            // see #getMatchingTasksByType
0139:
0140:                            if (task.getVerb().equals(Constants.Verb.TRANSPORT)) {
0141:                                Collection types = getTypesInContainer(task);
0142:
0143:                                for (Iterator iter = types.iterator(); iter
0144:                                        .hasNext();) {
0145:                                    String type = (String) iter.next();
0146:                                    List tasksForType = (List) typeToTasks
0147:                                            .get(type);
0148:                                    if (tasksForType == null) {
0149:                                        typeToTasks.put(type,
0150:                                                tasksForType = new ArrayList());
0151:                                        if (isInfoEnabled()) {
0152:                                            info("adding type " + type
0153:                                                    + " to map.");
0154:                                        }
0155:                                    }
0156:                                    tasksForType.add(task);
0157:                                }
0158:                            }
0159:                        }
0160:
0161:                        if (getSubscription().getRemovedList()
0162:                                .hasMoreElements()) {
0163:                            Set uniqueTasks = new HashSet();
0164:                            Enumeration removedtasks = getSubscription()
0165:                                    .getRemovedList();
0166:                            while (removedtasks.hasMoreElements()) {
0167:                                Task task = (Task) removedtasks.nextElement();
0168:
0169:                                if (uniqueTasks.contains(task)) { // skip duplicate entries in removed list, if any
0170:                                    if (isWarnEnabled()) {
0171:                                        warn("duplicate entries in removed list, skipping "
0172:                                                + task.getUID());
0173:                                    }
0174:                                    continue;
0175:                                } else {
0176:                                    uniqueTasks.add(task);
0177:                                }
0178:
0179:                                if (uidToTask.remove(task.getUID()) == null) {
0180:                                    if (isWarnEnabled()) {
0181:                                        warn("no task in uidToTask map with uid "
0182:                                                + task.getUID());
0183:                                    }
0184:                                } else {
0185:                                    if (isInfoEnabled()) {
0186:                                        info("uidToTask - removing task uid "
0187:                                                + task.getUID() + " from map.");
0188:                                    }
0189:                                }
0190:
0191:                                // keep a ammo type to tasks map so we can later compare
0192:                                // an actual task with a reserved or vice versa by just examining 
0193:                                // tasks with the same ammo type
0194:                                // see #getMatchingTasksByType
0195:                                if (task.getVerb().equals(
0196:                                        Constants.Verb.TRANSPORT)) {
0197:                                    Collection types = getTypesInContainer(task);
0198:
0199:                                    for (Iterator iter = types.iterator(); iter
0200:                                            .hasNext();) {
0201:                                        String type = (String) iter.next();
0202:                                        List tasksForType = (List) typeToTasks
0203:                                                .get(type);
0204:                                        if (tasksForType != null) { // might have been removed already
0205:                                            if (!tasksForType.remove(task)) {
0206:                                                if (isWarnEnabled()) {
0207:                                                    warn("no task "
0208:                                                            + task.getUID()
0209:                                                            + " in typeToTasks.");
0210:                                                }
0211:                                            }
0212:                                        }
0213:                                    }
0214:                                }
0215:                            }
0216:                        }
0217:                    }
0218:                });
0219:            }
0220:
0221:            protected UTILFilterCallback createThreadCallback(
0222:                    UTILGenericListener bufferingThread) {
0223:                if (isInfoEnabled())
0224:                    info(getName() + " : Filtering for Expandable Tasks...");
0225:
0226:                myInputTaskCallback = new UTILExpandableTaskCallback(
0227:                        bufferingThread, logger) {
0228:                    protected UnaryPredicate getPredicate() {
0229:                        return new UnaryPredicate() {
0230:                            protected TaskUtils myTaskUtils = new TaskUtils(
0231:                                    logger);
0232:
0233:                            public boolean execute(Object o) {
0234:                                if (o instanceof  Task) {
0235:                                    Task task = (Task) o;
0236:                                    boolean hasTransport = task.getVerb()
0237:                                            .equals(Constants.Verb.TRANSPORT);
0238:                                    boolean isReserved = (task
0239:                                            .getPrepositionalPhrase(START) != null);
0240:                                    if (hasTransport && isReserved)
0241:                                        return true;
0242:
0243:                                    if (// (task.getPlanElement() == null ) &&  ** Now dealing with changed tasks **
0244:                                    (task.getVerb()
0245:                                            .equals(Constants.Verb.PROJECTSUPPLY))
0246:                                            && (myTaskUtils.isLevel2(task))) {
0247:                                        boolean isReadyForTransport = (myTaskUtils
0248:                                                .isReadyForTransport(task));
0249:                                        //TODO: MWD delete this debug line
0250:                                        if ((isReadyForTransport)
0251:                                                && logger.isDebugEnabled()) {
0252:                                            logger
0253:                                                    .debug("AmmoProjectionExpanderPlugin:isLevel2 ReadyForTransport="
0254:                                                            + isReadyForTransport);
0255:                                        }
0256:                                        return isReadyForTransport;
0257:                                    }
0258:
0259:                                    return (// (task.getWorkflow() == null )  &&   ** Now dealing with changed tasks **
0260:                                    // (task.getPlanElement() == null ) &&
0261:                                    ((UTILGenericListener) myListener)
0262:                                            .interestingTask(task));
0263:                                }
0264:                                return false;
0265:                            }
0266:                        };
0267:                    }
0268:                };
0269:
0270:                return myInputTaskCallback;
0271:            }
0272:
0273:            /**
0274:             * State that we are interested in all transport tasks
0275:             * @param task the task to test.
0276:             * @return true if the tasks verb is SUPPLY, false otherwise
0277:             */
0278:            public boolean interestingTask(Task task) {
0279:                boolean hasSupply = task.getVerb().equals(
0280:                        Constants.Verb.PROJECTSUPPLY);
0281:                boolean hasTransport = task.getVerb().equals(
0282:                        Constants.Verb.TRANSPORT);
0283:
0284:                if (isDebugEnabled() && hasSupply)
0285:                    debug(".interestingTask - processing PROJECT_SUPPLY task "
0286:                            + task.getUID());
0287:                if (isDebugEnabled() && hasTransport)
0288:                    debug(".interestingTask - processing TRANSPORT task "
0289:                            + task.getUID());
0290:
0291:                return (hasSupply || hasTransport);
0292:            }
0293:
0294:            int total = 0;
0295:
0296:            /**
0297:             * Implemented for UTILExpanderPlugin interface
0298:             *
0299:             * Break up project supply tasks into reserved transport tasks for 
0300:             * discrete periods of time.  Takes the (demand rate X period) of the project
0301:             * supply task and breaks this up total ammo up across several subtasks, one
0302:             * per month.
0303:             *
0304:             * Called from handleTask, which is called from HandleProjectSupplyTask
0305:             * @see #handleProjectSupplyTask
0306:             * @return transport subtasks for the parent project supply
0307:             */
0308:            public Vector getSubtasks(Task parentTask) {
0309:                if (!(parentTask.getVerb().equals(Constants.Verb.PROJECTSUPPLY)))
0310:                    error("Expecting a project supply task, got " + parentTask);
0311:
0312:                Vector childTasks = new Vector();
0313:
0314:                // create the d.o.
0315:
0316:                Asset supplyAsset = parentTask.getDirectObject();
0317:
0318:                Preference pref = prefHelper.getPrefWithAspectType(parentTask,
0319:                        AlpineAspectType.DEMANDRATE);
0320:                double ratePerSec = prefHelper.getPreferenceBestValue(pref); // base number is in tons per second!
0321:                double ratePerDay = ratePerSec * SECS_PER_DAY;
0322:
0323:                Date readyAt = prefHelper.getReadyAt(parentTask);
0324:                Date early = getEarlyDate(parentTask);
0325:                Date best = prefHelper.getBestDate(parentTask);
0326:                Date late = getLateDate(parentTask);
0327:
0328:                if (early.getTime() < readyAt.getTime())
0329:                    early = readyAt;
0330:                if (best.getTime() < readyAt.getTime())
0331:                    best = readyAt;
0332:
0333:                long window = best.getTime() - readyAt.getTime();
0334:                long originalWindowInDays = window / MILLIS_PER_DAY;
0335:                long numSubtasks = window / (CHUNK_DAYS * MILLIS_PER_DAY);
0336:                if (window - (numSubtasks * CHUNK_DAYS * MILLIS_PER_DAY) != 0)
0337:                    numSubtasks++;
0338:
0339:                if (numSubtasks < 1) {
0340:                    error(getName() + ".getSubtasks - task "
0341:                            + parentTask.getUID()
0342:                            + " will create no subtasks?  Window was "
0343:                            + originalWindowInDays + " days");
0344:                }
0345:
0346:                if (isInfoEnabled()) {
0347:                    info(getName() + ".getSubtasks - task "
0348:                            + parentTask.getUID() + " from " + readyAt + " to "
0349:                            + best + " will produce " + numSubtasks
0350:                            + " subtasks.");
0351:                }
0352:
0353:                String unit;
0354:                if (FIND_FOR_UNIT_PREP_ON_TASK) {
0355:                    unit = (prepHelper.hasPrepNamed(parentTask,
0356:                            Constants.Preposition.FOR)) ? (String) prepHelper
0357:                            .getIndirectObject(parentTask,
0358:                                    Constants.Preposition.FOR) : "null";
0359:                } else {
0360:                    unit = getClusterName();
0361:                }
0362:
0363:                // create one subtask for every chunk set of days, with an asset that is the total
0364:                // delivered over the period = days*ratePerDay
0365:                long daysSoFar = 0;
0366:                double totalQuantity = 0;
0367:                double targetQuantity = ((double) (window / 1000l))
0368:                        * ratePerSec;
0369:                Date lastBestDate = readyAt;
0370:
0371:                if (isInfoEnabled()) {
0372:                    info(getName() + ".getSubtasks - task "
0373:                            + parentTask.getUID() + " target quantity "
0374:                            + targetQuantity + " windowInSec " + window / 1000l
0375:                            + " rate/sec " + ratePerSec);
0376:                }
0377:
0378:                for (int i = 0; i < (int) numSubtasks; i++) {
0379:                    boolean onLastTask = (window / MILLIS_PER_DAY) < CHUNK_DAYS;
0380:                    long daysToChunk = (onLastTask) ? window / MILLIS_PER_DAY
0381:                            : CHUNK_DAYS;
0382:
0383:                    if (isInfoEnabled() && onLastTask)
0384:                        info("on last task - days " + daysToChunk + " since "
0385:                                + window / MILLIS_PER_DAY + " < " + CHUNK_DAYS);
0386:
0387:                    daysSoFar += daysToChunk;
0388:                    window -= daysToChunk * MILLIS_PER_DAY;
0389:                    double quantity = ((double) daysToChunk) * ratePerDay;
0390:                    if (onLastTask
0391:                            && ((totalQuantity + quantity) != targetQuantity)) {
0392:                        if (isInfoEnabled())
0393:                            info(" task " + parentTask.getUID()
0394:                                    + " adjusting quantity from " + quantity
0395:                                    + " to " + (targetQuantity - totalQuantity)
0396:                                    + " total is " + totalQuantity);
0397:                        quantity = targetQuantity - totalQuantity;
0398:                    } else if (isInfoEnabled()) {
0399:                        info(".getSubtasks - task " + parentTask.getUID()
0400:                                + " quantity is " + quantity + " chunk days "
0401:                                + daysToChunk + " rate " + ratePerDay);
0402:                    }
0403:
0404:                    if (quantity < 0.00001) {
0405:                        if (isInfoEnabled()) {
0406:                            info(".getSubtasks - task "
0407:                                    + parentTask.getUID()
0408:                                    + " gets a quantity of zero, ratePerDay was "
0409:                                    + ratePerDay + " chunk days " + daysToChunk);
0410:                        }
0411:                    }
0412:
0413:                    //      double massInKGs = ((GLMAsset)supplyAsset).getPhysicalPG().getMass().getKilograms()*quantity;
0414:                    double massInSTons = quantity;
0415:                    totalQuantity += quantity;
0416:
0417:                    //  CHANGE to JUST Grab the d.o.?
0418:
0419:                    // set item id pg to show it's a reservation, and not a normal task's asset
0420:
0421:                    ItemIdentificationPG itemIDPG = (ItemIdentificationPG) supplyAsset
0422:                            .getItemIdentificationPG();
0423:                    String itemID = itemIDPG.getItemIdentification();
0424:                    String itemNomen = itemIDPG.getNomenclature();
0425:
0426:                    if (itemID == null) {
0427:                        TypeIdentificationPG typeID = supplyAsset
0428:                                .getTypeIdentificationPG();
0429:                        itemID = typeID.getTypeIdentification();
0430:                    }
0431:
0432:                    if (itemNomen == null) {
0433:                        TypeIdentificationPG typeID = supplyAsset
0434:                                .getTypeIdentificationPG();
0435:                        itemNomen = typeID.getNomenclature();
0436:                    }
0437:
0438:                    Asset directObject = getMilvanDirectObject(itemNomen,
0439:                            itemID, unit, massInSTons);
0440:
0441:                    long bestTime = getBestTime(early, best, daysSoFar);
0442:
0443:                    Task subTask = createSubtask(parentTask, directObject,
0444:                            early, best, late, bestTime, daysSoFar,
0445:                            lastBestDate, itemNomen, massInSTons);
0446:
0447:                    lastBestDate = new Date(bestTime);
0448:                    childTasks.addElement(subTask);
0449:                }
0450:
0451:                // post condition
0452:                if (totalQuantity > targetQuantity + 0.001
0453:                        || totalQuantity < targetQuantity - 0.001) {
0454:                    if (isWarnEnabled()) {
0455:                        warn(getName() + " total quantity " + totalQuantity
0456:                                + " != original total " + targetQuantity
0457:                                + " = window " + originalWindowInDays
0458:                                + " * ratePerDay " + ratePerDay);
0459:                    }
0460:                }
0461:
0462:                if (isInfoEnabled())
0463:                    info(getName() + " returning " + childTasks.size()
0464:                            + " subtasks for " + parentTask.getUID());
0465:
0466:                return childTasks;
0467:            }
0468:
0469:            /** 
0470:             * make sure best time is before or equal to best time on task 
0471:             */
0472:            protected long getBestTime(Date early, Date best, long daysSoFar) {
0473:                long bestTime = early.getTime() + ((long) daysSoFar)
0474:                        * MILLIS_PER_DAY;
0475:                if (bestTime > best.getTime()) {
0476:                    if (isInfoEnabled()) {
0477:                        info(getName()
0478:                                + ".getSubtasks - had to correct bestTime, was "
0479:                                + new Date(bestTime) + " now " + best);
0480:                    }
0481:
0482:                    bestTime = best.getTime();
0483:                }
0484:
0485:                return bestTime;
0486:            }
0487:
0488:            /**
0489:             * Create the transport reservation subtask of the parent.
0490:             */
0491:            protected Task createSubtask(Task parentTask, Asset directObject,
0492:                    Date early, Date best, Date late, long bestTime,
0493:                    long daysSoFar, Date lastBestDate, String itemNomen,
0494:                    double massInSTons) {
0495:                Task subTask = makeTask(parentTask, directObject);//deliveredAsset);
0496:                Date startDate = new Date(getAlarmService().currentTimeMillis()
0497:                        + TASK_TRANSMISSION_DELAY);
0498:                if (isInfoEnabled())
0499:                    info(getName() + ".getSubtasks - making task "
0500:                            + subTask.getUID() + " with best arrival "
0501:                            + new Date(bestTime) + " and start " + startDate);
0502:
0503:                // prevent earliest arrival being before start date
0504:                if (early.getTime() < startDate.getTime()) {
0505:                    early = startDate;
0506:                }
0507:
0508:                prefHelper.replacePreference((NewTask) subTask, prefHelper
0509:                        .makeEndDatePreference(ldmf, early, new Date(bestTime),
0510:                                late));
0511:
0512:                prefHelper.replacePreference((NewTask) subTask, prefHelper
0513:                        .makeStartDatePreference(ldmf, startDate));
0514:
0515:                prefHelper.removePrefWithAspectType(subTask,
0516:                        AlpineAspectType.DEMANDRATE); // we've included it in the d.o.
0517:
0518:                prepHelper.removePrepNamed(subTask,
0519:                        Constants.Preposition.MAINTAINING);
0520:                prepHelper.removePrepNamed(subTask,
0521:                        Constants.Preposition.REFILL);
0522:                prepHelper.addPrepToTask(subTask, prepHelper
0523:                        .makePrepositionalPhrase(ldmf, "Start", lastBestDate));
0524:
0525:                if (!FIND_FOR_UNIT_PREP_ON_TASK) {
0526:                    prepHelper.replacePrepOnTask(subTask,
0527:                            prepHelper
0528:                                    .makePrepositionalPhrase(ldmf,
0529:                                            Constants.Preposition.FOR,
0530:                                            getClusterName()));
0531:                }
0532:
0533:                if (isInfoEnabled()) {
0534:                    info(getName() + " publishing reservation "
0535:                            + subTask.getUID() + " for " + itemNomen + " from "
0536:                            + lastBestDate + " to " + new Date(bestTime)
0537:                            + " weight " + massInSTons + " short tons.");
0538:                }
0539:
0540:                return subTask;
0541:            }
0542:
0543:            private static final double MAX_IN_MILVAN = 13.9;
0544:
0545:            protected Asset getMilvanDirectObject(String itemNomen,
0546:                    String itemID, String unit, double massInSTons) {
0547:                int numMilvans = (int) Math.ceil(massInSTons / MAX_IN_MILVAN);
0548:                if (numMilvans == 0) {
0549:                    numMilvans++;
0550:                    if (isWarnEnabled())
0551:                        warn("Got mass that was zero : " + massInSTons);
0552:                    massInSTons += 0.1;
0553:                }
0554:                double tonsLeft = massInSTons;
0555:
0556:                if (numMilvans == 1) {
0557:                    GLMAsset milvan = makeMilvan();
0558:                    addContentsInfo(milvan, itemNomen, itemID, unit,
0559:                            massInSTons);
0560:                    return milvan;
0561:                } else {
0562:                    Vector milvans = new Vector();
0563:                    for (int i = 0; i < numMilvans; i++) {
0564:                        GLMAsset milvan = makeMilvan();
0565:                        double amount = Math.min(tonsLeft, MAX_IN_MILVAN);
0566:                        addContentsInfo(milvan, itemNomen, itemID, unit, amount);
0567:                        tonsLeft -= amount;
0568:                        milvans.add(milvan);
0569:                    }
0570:                    if ((tonsLeft > 0.0000001) || (tonsLeft < -0.0000001)) {
0571:                        error("Tons left is not zero = " + tonsLeft);
0572:                    }
0573:                    return assetHelper.makeAssetGroup(getLDMService().getLDM()
0574:                            .getFactory(), milvans);
0575:                }
0576:            }
0577:
0578:            public Date getEarlyDate(Task t) {
0579:                Preference endDatePref = prefHelper.getPrefWithAspectType(t,
0580:                        AspectType.END_TIME);
0581:                AspectScoreRange range = endDatePref.getScoringFunction()
0582:                        .getDefinedRange();
0583:                return new Date(((AspectScorePoint) range.getRangeStartPoint())
0584:                        .getAspectValue().longValue());
0585:            }
0586:
0587:            public Date getLateDate(Task t) {
0588:                Preference endDatePref = prefHelper.getPrefWithAspectType(t,
0589:                        AspectType.END_TIME);
0590:                AspectScoreRange range = endDatePref.getScoringFunction()
0591:                        .getDefinedRange();
0592:                return new Date(((AspectScorePoint) range.getRangeEndPoint())
0593:                        .getAspectValue().longValue());
0594:            }
0595:
0596:            protected Enumeration getValidEndDateRanges(Preference endDatePref) {
0597:                Calendar cal = java.util.Calendar.getInstance();
0598:                cal.set(2200, 0, 0, 0, 0, 0);
0599:                cal.set(Calendar.MILLISECOND, 0);
0600:                Date endOfRange = (Date) cal.getTime();
0601:
0602:                Enumeration validRanges = endDatePref
0603:                        .getScoringFunction()
0604:                        .getValidRanges(
0605:                                TimeAspectValue.create(AspectType.END_TIME, 0l),
0606:                                TimeAspectValue.create(AspectType.END_TIME,
0607:                                        endOfRange));
0608:                return validRanges;
0609:            }
0610:
0611:            /** create aggregate asset aggregating the direct object's prototype **/
0612:            protected AggregateAsset createDeliveredAsset(Task originalTask,
0613:                    Asset originalAsset, int quantity) {
0614:                Asset prototype = originalAsset.getPrototype();
0615:
0616:                if (prototype == null) {
0617:                    prototype = originalAsset;
0618:                    GLMAsset glmProto = (GLMAsset) prototype;
0619:                    if (!glmProto.hasPhysicalPG()) {
0620:                        warn("createDeliveredAsset - task "
0621:                                + originalTask.getUID() + "'s d.o. "
0622:                                + prototype.getUID() + " - " + prototype
0623:                                + " doesn't have a physical PG - "
0624:                                + glmProto.getPhysicalPG());
0625:                        if (!(prototype instanceof  PhysicalAsset))
0626:                            error("createDeliveredAsset - task "
0627:                                    + originalTask.getUID() + "'s d.o. "
0628:                                    + prototype + " is not a physical asset?.");
0629:                        else if (isInfoEnabled()) {
0630:                            info("createDeliveredAsset - task "
0631:                                    + originalTask.getUID() + "'s d.o. "
0632:                                    + prototype.getUID()
0633:                                    + " is a physical asset.");
0634:                        }
0635:                    } else {
0636:                        if (glmProto.getPhysicalPG().getFootprintArea() == null) {
0637:                            ((NewPhysicalPG) glmProto.getPhysicalPG())
0638:                                    .setFootprintArea(new Area(
0639:                                            Area.SQUARE_FEET, 1));
0640:                            if (isWarnEnabled()) {
0641:                                warn("createDeliveredAsset - task "
0642:                                        + originalTask.getUID()
0643:                                        + "'s d.o. "
0644:                                        + prototype.getUID()
0645:                                        + " doesn't have an area slot on its physical pg.");
0646:                            }
0647:                        }
0648:                        if (glmProto.getPhysicalPG().getVolume() == null) {
0649:                            ((NewPhysicalPG) glmProto.getPhysicalPG())
0650:                                    .setVolume(new Volume(Volume.CUBIC_FEET, 1));
0651:                            if (isWarnEnabled()) {
0652:                                warn("createDeliveredAsset - task "
0653:                                        + originalTask.getUID()
0654:                                        + "'s d.o. "
0655:                                        + prototype.getUID()
0656:                                        + " doesn't have a volume slot on its physical pg.");
0657:                            }
0658:                        }
0659:                    }
0660:                    if (!glmProto.hasPackagePG()) {
0661:                        warn("createDeliveredAsset - task "
0662:                                + originalTask.getUID() + "'s d.o. "
0663:                                + prototype.getUID() + " - " + prototype
0664:                                + " doesn't have a package PG.");
0665:                    }
0666:                }
0667:
0668:                AggregateAsset deliveredAsset = (AggregateAsset) ldmf
0669:                        .createAggregate(prototype, quantity);
0670:
0671:                return deliveredAsset;
0672:            }
0673:
0674:            /**
0675:             * <pre>
0676:             * Report to superior that the expansion has changed. 
0677:             * 
0678:             * An override is needed here for two reasons :
0679:             *
0680:             * 1) to add the DEMANDRATE preference value into the allocation result, 
0681:             *    since downstream plugins won't set this aspect.
0682:             * 2) echo the start time preference in the allocation result (why?)
0683:             *
0684:             * No allocation results flow upward unless reported confidence reaches 100%.
0685:             *
0686:             * </pre>
0687:             * @param cpe Expansion that has changed.
0688:             * @see org.cougaar.lib.filter.UTILPluginAdapter#updateAllocationResult
0689:             */
0690:            public void reportChangedExpansion(Expansion cpe) {
0691:                if (isDebugEnabled())
0692:                    debug(getName() + " : Received changed pe " + cpe.getUID()
0693:                            + " for task " + cpe.getTask().getUID());
0694:                AllocationResult reportedresult = cpe.getReportedResult();
0695:                if (reportedresult != null) {
0696:                    // compare entire allocationresults.
0697:                    AllocationResult estimatedresult = cpe.getEstimatedResult();
0698:                    double confidence = reportedresult.getConfidenceRating();
0699:                    boolean nullEstimated = (estimatedresult == null);
0700:                    // if we are not ignoring low confidence reported values
0701:                    boolean highConfidence = (!skipLowConfidence || confidence > HIGH_CONFIDENCE);
0702:
0703:                    if (nullEstimated
0704:                            || (highConfidence && (!isEqual(estimatedresult,
0705:                                    reportedresult)))) {
0706:                        if (isDebugEnabled())
0707:                            debug(getName()
0708:                                    + " : Swapping Alloc Results for task "
0709:                                    + cpe.getTask().getUID());
0710:                        if (isWarnEnabled() && !reportedresult.isSuccess())
0711:                            warn(getName() + " : " + cpe.getTask().getUID()
0712:                                    + " failed to allocate.");
0713:
0714:                        cpe.setEstimatedResult(reportedresult);
0715:
0716:                        //        double prefValue = getScaledRate (cpe);
0717:                        Task task = cpe.getTask();
0718:                        AspectValue prefRate = task.getPreference(
0719:                                AlpineAspectType.DEMANDRATE)
0720:                                .getScoringFunction().getBest()
0721:                                .getAspectValue();
0722:
0723:                        AspectValue[] aspectValues = cpe.getEstimatedResult()
0724:                                .getAspectValueResults();
0725:
0726:                        AspectValue[] copy = new AspectValue[aspectValues.length + 1];
0727:                        System.arraycopy(aspectValues, 0, copy, 0,
0728:                                aspectValues.length);
0729:                        copy[aspectValues.length] = prefRate;
0730:
0731:                        // fix start time to echo start time preference
0732:                        for (int i = 0; i < copy.length; i++) {
0733:                            AspectValue value = copy[i];
0734:                            if (value.getAspectType() == AspectType.START_TIME) {
0735:                                Date preferredStart = prefHelper
0736:                                        .getReadyAt(task);
0737:                                copy[i] = AspectValue.newAspectValue(
0738:                                        AspectType.START_TIME, preferredStart);
0739:                                break;
0740:                            }
0741:                        }
0742:
0743:                        AllocationResult correctedAR = new AllocationResult(
0744:                                reportedresult.getConfidenceRating(),
0745:                                reportedresult.isSuccess(), copy);
0746:
0747:                        cpe.setEstimatedResult(correctedAR);
0748:
0749:                        if (isInfoEnabled())
0750:                            info(getName() + " : publish changing task "
0751:                                    + cpe.getTask().getUID());
0752:
0753:                        blackboard.publishChange(cpe);
0754:                    }
0755:                } else if (!cpe.getTask().getSource().equals(
0756:                        getAgentIdentifier())) {
0757:                    error("ERROR! " + getName() + " : "
0758:                            + cpe.getTask().getUID()
0759:                            + " has a null reported allocation.");
0760:                }
0761:            }
0762:
0763:            /**
0764:             * <pre>
0765:             * scale the rate to make it the rate over the time of the performance of the 
0766:             * task, so that when the inventory does days*rate, they come up with the original
0767:             * requested quantity.
0768:             *
0769:             * The problem is that we're translating from one meaning of start and end date to another.
0770:             * The start->end date window on a project supply task means "I need X widgets per day, each
0771:             * day, over this period."  The transportation start->end window means "The move started on this
0772:             * day and ended on this other day."  So they mean different things.
0773:             * </pre>
0774:             */
0775:            protected double getScaledRate(PlanElement planElement) {
0776:                Task task = planElement.getTask();
0777:                double prefRate = task.getPreference(
0778:                        AlpineAspectType.DEMANDRATE).getScoringFunction()
0779:                        .getBest().getAspectValue().getValue();
0780:
0781:                Date preferredStart = prefHelper.getReadyAt(task);
0782:                Date preferredEnd = prefHelper.getBestDate(task);
0783:
0784:                Date reportedStart = prefHelper.getReportedReadyAt(planElement);
0785:                Date reportedEnd = prefHelper.getReportedEndDate(planElement);
0786:
0787:                long preferredWindow = preferredEnd.getTime()
0788:                        - preferredStart.getTime();
0789:                long reportedWindow = reportedEnd.getTime()
0790:                        - reportedStart.getTime();
0791:
0792:                double ratio = (double) preferredWindow
0793:                        / (double) reportedWindow;
0794:
0795:                return prefRate * ratio;
0796:            }
0797:
0798:            /** 
0799:             * checks to see if the AllocationResult is equal to this one.
0800:             *
0801:             * We have to use this copy of the AllocationResult.isEqual because we want to
0802:             * to skip equals comparison of DEMANDRATE and START_TIME aspects. (why?)
0803:             *
0804:             * Mainly we need our own version of AspectValue.nearlyEquals
0805:             *
0806:             * @param thisAR
0807:             * @param that
0808:             * @return boolean
0809:             */
0810:            public boolean isEqual(AllocationResult this AR,
0811:                    AllocationResult that) {
0812:                if (this AR == that)
0813:                    return true; // quick success
0814:                if (that == null)
0815:                    return false; // quick fail
0816:                if (!(this AR.isSuccess() == that.isSuccess()
0817:                        && this AR.isPhased() == that.isPhased() && this AR
0818:                        .getConfidenceRating() == that.getConfidenceRating())) {
0819:                    if (isInfoEnabled())
0820:                        info("AspectValues - success/phased/confidence this AR "
0821:                                + this AR + " != " + that);
0822:                    return false;
0823:                }
0824:
0825:                //check the real stuff now!
0826:                //check the aspect types
0827:                //check the summary results
0828:                synchronized (this AR.getAspectValueResults()) {
0829:                    if (!nearlyEquals(this AR.getAspectValueResults(), that
0830:                            .getAspectValueResults())) {
0831:                        if (isDebugEnabled())
0832:                            debug("AspectValues - this AR " + this AR + " != "
0833:                                    + that);
0834:                        return false;
0835:                    }
0836:                    // check the phased results
0837:                    if (this AR.isPhased()) {
0838:                        Iterator i1 = that.getPhasedAspectValueResults()
0839:                                .iterator();
0840:                        Iterator i2 = this AR.getPhasedAspectValueResults()
0841:                                .iterator();
0842:                        while (i1.hasNext()) {
0843:                            if (!i2.hasNext())
0844:                                return false;
0845:                            if (!nearlyEquals((AspectValue[]) i1.next(),
0846:                                    (AspectValue[]) i2.next())) {
0847:                                if (isDebugEnabled())
0848:                                    debug("phased AspectValues - this AR "
0849:                                            + this AR + " != " + that);
0850:                                return false;
0851:                            }
0852:                        }
0853:                        if (i2.hasNext())
0854:                            return false;
0855:                    }
0856:                }
0857:
0858:                // check the aux queries
0859:
0860:                // AUX QUERIES are not used in this plugin - honestly, where are they used?
0861:
0862:                /*
0863:                String[] taux = that.auxqueries;
0864:                if (auxqueries != taux) {
0865:                if (!Arrays.equals(taux, auxqueries)) return false;
0866:                }
0867:                 */
0868:
0869:                // must be equals...
0870:                return true;
0871:            }
0872:
0873:            /** 
0874:             * checks to see that two aspect value arrays are equal
0875:             *
0876:             * skips comparison of DEMANDRATE and START_TIME aspects.
0877:             *
0878:             * We have to skip start time, since it doesn't mean the same in the inventory world
0879:             * as in the transportation world.
0880:             *
0881:             * @param avs1 first set
0882:             * @param avs2 second set
0883:             * @return true if the same
0884:             */
0885:            public boolean nearlyEquals(AspectValue[] avs1, AspectValue[] avs2) {
0886:                int len = avs1.length;
0887:                // if (len != avs2.length) return false; // Can't be equal if different length
0888:                outer: for (int i = 0; i < len; i++) {
0889:                    AspectValue av1 = avs1[i];
0890:                    int type1 = av1.getAspectType();
0891:                    if (type1 == AlpineAspectType.DEMANDRATE)
0892:                        continue; // ignore DEMAND RATE!
0893:                    if (type1 == AspectType.START_TIME)
0894:                        continue; // ignore Start time, since it doesn't mean the same in the inventory world
0895:                    inner: for (int j = 0; j < len; j++) {
0896:                        int k = (i + j) % len;
0897:                        AspectValue av2 = avs2[k];
0898:                        int type2 = av2.getAspectType();
0899:                        if (type1 == type2) {
0900:                            if (av1.nearlyEquals(av2))
0901:                                continue outer;
0902:                            break inner;
0903:                        }
0904:                    }
0905:                    return false; // Found no match
0906:                }
0907:                return true; // Found a match for every aspect
0908:            }
0909:
0910:            /**
0911:             * An ancillary method that creates an asset that represents a MILVAN 
0912:             * (military container) carrying ammunition
0913:             */
0914:            protected GLMAsset makeMilvan() {
0915:
0916:                if (MILVAN_PROTOTYPE == null) {
0917:                    MILVAN_PROTOTYPE = getLDMService().getLDM().getPrototype(
0918:                            MILVAN_NSN);
0919:
0920:                    if (MILVAN_PROTOTYPE == null) {
0921:                        error("AmmoTransport: Error! Unable to get prototype for"
0922:                                + " milvan NSN -" + MILVAN_NSN);
0923:                        return null;
0924:                    }
0925:                }
0926:
0927:                String itemID = makeMilvanID();
0928:                Container milvan = (Container) getLDMService().getLDM()
0929:                        .getFactory().createInstance(MILVAN_PROTOTYPE, itemID);
0930:
0931:                // AMMO Cargo Code
0932:                NewMovabilityPG movabilityPG = PropertyGroupFactory
0933:                        .newMovabilityPG(milvan.getMovabilityPG());
0934:                movabilityPG.setCargoCategoryCode(AMMO_CATEGORY_CODE);
0935:                milvan.setMovabilityPG(movabilityPG);
0936:
0937:                // Milvan Contents
0938:                NewContentsPG contentsPG = PropertyGroupFactory.newContentsPG();
0939:                milvan.setContentsPG(contentsPG);
0940:
0941:                // Unique Item Identification
0942:                NewItemIdentificationPG itemIdentificationPG = PropertyGroupFactory
0943:                        .newItemIdentificationPG();
0944:
0945:                //    String itemID = makeMilvanID();
0946:                itemIdentificationPG.setItemIdentification(itemID); // redundant?
0947:                itemIdentificationPG.setNomenclature("Milvan");
0948:                itemIdentificationPG.setAlternateItemIdentification(itemID);
0949:                milvan.setItemIdentificationPG(itemIdentificationPG);
0950:
0951:                return milvan;
0952:            }
0953:
0954:            protected String makeMilvanID() {
0955:                return new String("Reserved_" + getCounter());
0956:            }
0957:
0958:            private static int COUNTER = 0;
0959:
0960:            private static synchronized long getCounter() {
0961:                return COUNTER++;
0962:            }
0963:
0964:            protected void addContentsInfo(GLMAsset container, String nomen,
0965:                    String typeID, String unit, double massInSTons) {
0966:                List typeIDs = new ArrayList();
0967:                List nomenclatures = new ArrayList();
0968:                List weights = new ArrayList();
0969:                List receivers = new ArrayList();
0970:
0971:                typeIDs.add(typeID);
0972:                nomenclatures.add(nomen);
0973:
0974:                Mass mass = Mass.newMass(massInSTons, Mass.SHORT_TONS);
0975:                weights.add(mass);
0976:
0977:                receivers.add(unit);
0978:
0979:                // Contents
0980:                NewContentsPG contentsPG = PropertyGroupFactory.newContentsPG();
0981:                contentsPG.setNomenclatures(nomenclatures);
0982:                contentsPG.setTypeIdentifications(typeIDs);
0983:                contentsPG.setWeights(weights);
0984:                contentsPG.setReceivers(receivers);
0985:                container.setContentsPG(contentsPG);
0986:            }
0987:
0988:            /**
0989:             * Implemented for UTILBufferingPlugin interface
0990:             *
0991:             * @param tasks that have been buffered up to this point
0992:             * @see org.cougaar.lib.filter.UTILBufferingPlugin#processTasks
0993:             */
0994:            public void processTasks(List tasks) {
0995:                if (isInfoEnabled()) {
0996:                    info(getName() + ".processTasks - processing "
0997:                            + tasks.size() + " tasks.");
0998:                }
0999:
1000:                Map reservedToActual = new HashMap();
1001:                for (int i = 0; i < tasks.size(); i++) {
1002:                    Task task = (Task) tasks.get(i);
1003:
1004:                    if (task.getVerb().equals(Constants.Verb.TRANSPORT))
1005:                        handleTransportTask(task, reservedToActual);
1006:                    else
1007:                        handleProjectSupplyTask(task);
1008:                }
1009:
1010:                for (Iterator iter = reservedToActual.keySet().iterator(); iter
1011:                        .hasNext();) {
1012:                    Task reserved = (Task) iter.next();
1013:                    Task actual = (Task) reservedToActual.get(reserved);
1014:                    Task reservedParent = getParentTask(reserved);
1015:                    if (reservedParent == null) {
1016:                        if (isInfoEnabled()) {
1017:                            info("skipping reserved task " + reserved.getUID()
1018:                                    + " with no parent on blackboard.");
1019:                        }
1020:                    } else if (reserved.getWorkflow() == null) {
1021:                        if (isInfoEnabled()) {
1022:                            info("skipping reserved task " + reserved.getUID()
1023:                                    + " with no workflow.");
1024:                        }
1025:                    } else {
1026:                        synchronized (reserved.getWorkflow()) {
1027:                            if (ownWorkflow(reserved)) {
1028:                                dealWithReservedTask(actual, reserved,
1029:                                        reservedParent);
1030:                            } else if (isInfoEnabled()) {
1031:                                info("reserved task " + reserved.getUID()
1032:                                        + " not a member of it's own workflow "
1033:                                        + reserved.getWorkflow()
1034:                                        + "\nworkflow task uids : "
1035:                                        + uidsWorkflow(reserved)
1036:                                        + " - assuming it will be removed.");
1037:                            }
1038:                        }
1039:                    }
1040:                }
1041:            }
1042:
1043:            /**
1044:             * Handle a task with verb Supply
1045:             */
1046:            public void handleProjectSupplyTask(Task t) {
1047:                wantConfidence = true;
1048:                if (t.getPlanElement() != null) {
1049:                    publishRemove(t.getPlanElement());
1050:                }
1051:                handleTask(t); // expands t with subtasks from getSubtasks
1052:                Preference pref = prefHelper.getPrefWithAspectType(t,
1053:                        AlpineAspectType.DEMANDRATE);
1054:                AspectValue ratePerSec = pref.getScoringFunction().getBest()
1055:                        .getAspectValue();
1056:                if (isInfoEnabled())
1057:                    info(getName() + ".handleTask - task " + t.getUID()
1058:                            + " had p.e. " + t.getPlanElement().getUID());
1059:                if (t.getPlanElement() instanceof  Expansion) {
1060:                    addToEstimatedAR(t.getPlanElement(), ratePerSec);
1061:                    if (isInfoEnabled()) {
1062:                        Workflow tasksWorkflow = t.getWorkflow();
1063:                        Workflow peWorkflow = ((Expansion) t.getPlanElement())
1064:                                .getWorkflow();
1065:                        info(getName()
1066:                                + ".handleTask "
1067:                                + t.getUID()
1068:                                + " in "
1069:                                + ((tasksWorkflow != null) ? tasksWorkflow
1070:                                        .getUID().toString() : "null wf?")
1071:                                + " p.e. "
1072:                                + t.getPlanElement().getUID()
1073:                                + " p.e. wf. "
1074:                                + ((peWorkflow != null) ? peWorkflow.getUID()
1075:                                        .toString() : " null p.e. wf?"));
1076:                    }
1077:                } else if (isWarnEnabled())
1078:                    warn(getName() + ".handleTask - task " + t.getUID()
1079:                            + " had no p.e.???");
1080:            }
1081:
1082:            protected void addToEstimatedAR(PlanElement exp, AspectValue rate) {
1083:                AllocationResult estAR = exp.getEstimatedResult();
1084:                AspectValue[] aspectValues = estAR.getAspectValueResults();
1085:                AspectValue[] copy = new AspectValue[aspectValues.length + 1];
1086:                System.arraycopy(aspectValues, 0, copy, 0, aspectValues.length);
1087:                copy[aspectValues.length] = rate;
1088:
1089:                AllocationResult replacement = ldmf.newAllocationResult(
1090:                        UTILAllocate.MEDIUM_CONFIDENCE, true, copy);
1091:                exp.setEstimatedResult(replacement);
1092:            }
1093:
1094:            /** 
1095:             * Queries the uid->task map for the parent task of the child... 
1096:             * must do this since child task has a uid reference to the parent task not
1097:             * an actual reference.
1098:             */
1099:            protected Task getParentTask(final Task child) {
1100:                Task parent = (Task) uidToTask.get(child.getParentTaskUID());
1101:
1102:                if (parent == null) {
1103:                    logger.warn("huh? no task with " + child.getParentTaskUID()
1104:                            + " in uid->task map.");
1105:                }
1106:
1107:                return parent;
1108:            }
1109:
1110:            /**
1111:             * <pre>
1112:             *
1113:             * find matching reservation transport task
1114:             * see if date overlaps
1115:             * if it does, publish remove it and replace it with one with altered date span and quantity
1116:             *
1117:             * OK - could be MUCH more efficient - blackboard queries are extremely slow!
1118:             *
1119:             * </pre>
1120:             */
1121:            public void handleTransportTask(Task task1, Map reservedToActual) {
1122:                // find matching reservation transport task
1123:                final Task task = task1;
1124:                final Collection units = findForPreps(task);
1125:                final boolean isReserved = isReservedTask(task);
1126:
1127:                if (isReservedTask(task) && !ownWorkflow(task)) {
1128:                    if (isInfoEnabled())
1129:                        info(".handleTransportTask - skipping reserved task "
1130:                                + task.getUID()
1131:                                + " that's not in it's own workflow.");
1132:                    return;
1133:                }
1134:
1135:                if (isInfoEnabled())
1136:                    info(getName()
1137:                            + ".handleTransportTask - looking through blackboard for task to match "
1138:                            + ((isReserved) ? "reserved " : "normal ")
1139:                            + task.getUID());
1140:
1141:                Collection matchingTaskCollection = getMatchingTasksByType(
1142:                        task, units, isReserved);
1143:
1144:                // there can be more than one matching reserved task, e.g. when the actual contains multiple different DODICS:
1145:                //  types [DODIC/C787, DODIC/C380, ] vs [DODIC/C787] (Task 1)
1146:                //  types [DODIC/C787, DODIC/C380, ] vs [DODIC/C380] (Task 2)
1147:
1148:                if (matchingTaskCollection.isEmpty() && isInfoEnabled()) {
1149:                    info(".handleTransportTask - could not find matching task for "
1150:                            + task.getUID());
1151:                    return;
1152:                }
1153:                if (isInfoEnabled()) {
1154:                    info(".handleTransportTask - found "
1155:                            + matchingTaskCollection.size()
1156:                            + " matches for task " + task.getUID());
1157:                }
1158:
1159:                for (Iterator iter = matchingTaskCollection.iterator(); iter
1160:                        .hasNext();) {
1161:                    Task reservedTask, actual;
1162:
1163:                    if (isReserved) {
1164:                        reservedTask = task;
1165:                        actual = (Task) iter.next();
1166:                    } else {
1167:                        reservedTask = (Task) iter.next();
1168:                        actual = task;
1169:                    }
1170:
1171:                    if (!ownWorkflow(reservedTask)) {
1172:                        if (isInfoEnabled()) {
1173:                            info(".handleTransportTask - huh? reserved task "
1174:                                    + reservedTask.getUID()
1175:                                    + " not a member of it's own workflow "
1176:                                    + reservedTask.getWorkflow() + "\nuids "
1177:                                    + uidsWorkflow(reservedTask));
1178:                        }
1179:                    } else {
1180:                        if (isInfoEnabled()) {
1181:                            info(".handleTransportTask - updating map with reserved task "
1182:                                    + reservedTask.getUID()
1183:                                    + " and actual "
1184:                                    + actual.getUID());
1185:                        }
1186:                    }
1187:
1188:                    updateMap(reservedToActual, actual, reservedTask);
1189:                }
1190:            }
1191:
1192:            /**
1193:             * Find those tasks of the same ammo type and try to find tasks that overlap in
1194:             * time with the given task.
1195:             *
1196:             * @param task to look for matching tasks for
1197:             * @param units units the task is for
1198:             * @param isReserved is the task a reserved (project supply child) task
1199:             * @return List of tasks that are for the same type of ammo, same unit, and for an overlapping period of time
1200:             */
1201:            protected List getMatchingTasksByType(Task task, Collection units,
1202:                    boolean isReserved) {
1203:                List matches = new ArrayList();
1204:
1205:                Collection types = getTypesInContainer(task);
1206:
1207:                // reduce set of possible matching tasks to those for the same types of ammo
1208:                List possibleMatches = new ArrayList();
1209:                for (Iterator iter = types.iterator(); iter.hasNext();) {
1210:                    String type = (String) iter.next();
1211:
1212:                    List tasksForType = (List) typeToTasks.get(type);
1213:                    if (tasksForType == null) {
1214:                        if (isWarnEnabled()) {
1215:                            warn("Could not find tasks for type <" + type
1216:                                    + "> for task " + task.getUID()
1217:                                    + " with d.o. " + task.getDirectObject()
1218:                                    + " and types <" + types + ">");
1219:                        }
1220:                    } else {
1221:                        possibleMatches.addAll(tasksForType);
1222:                    }
1223:                }
1224:
1225:                if (isInfoEnabled()) {
1226:                    info("examining " + possibleMatches.size()
1227:                            + " possible matches for task " + task.getUID());
1228:                }
1229:
1230:                for (Iterator iter = possibleMatches.iterator(); iter.hasNext();) {
1231:                    Task examinedTask = (Task) iter.next();
1232:                    if (task.getUID().equals(examinedTask.getUID())) {
1233:                        if (isInfoEnabled()) {
1234:                            info("skipping self " + examinedTask.getUID());
1235:                        }
1236:
1237:                        continue; // don't match yourself
1238:                    }
1239:
1240:                    // better be a transport task
1241:                    /*
1242:                    if (!(examinedTask.getVerb ().equals (Constants.Verb.TRANSPORT))) {
1243:                    if (isDebugEnabled())
1244:                    debug ("skipping non-transport task " + examinedTask.getUID());
1245:                    continue;
1246:                    }
1247:                     */
1248:
1249:                    // is it a reservation task?
1250:                    boolean examinedIsReserved = isReservedTask(examinedTask);
1251:                    if ((!isReserved && !examinedIsReserved)
1252:                            || (isReserved && examinedIsReserved)) {
1253:                        if (isInfoEnabled()) {
1254:                            info("skipping examined transport task because same type "
1255:                                    + examinedTask.getUID()
1256:                                    + " and "
1257:                                    + task.getUID());
1258:                        }
1259:                        continue;
1260:                    }
1261:
1262:                    if (examinedIsReserved) {
1263:                        // has it already been removed from workflow?
1264:                        if (!taskInWorkflow(examinedTask, examinedTask
1265:                                .getWorkflow())) {
1266:                            if (isInfoEnabled())
1267:                                info("skipping reserved transport task "
1268:                                        + examinedTask.getUID()
1269:                                        + " since it's already been removed from it's workflow.");
1270:                            continue;
1271:                        }
1272:                    } else if (!(task instanceof  MPTask)) {
1273:                        if (isInfoEnabled())
1274:                            info("saw transport task " + task.getUID()
1275:                                    + " vs examined " + examinedTask.getUID());
1276:                    }
1277:
1278:                    // is it for the same org?
1279:                    Collection examinedUnits = findForPreps(examinedTask);
1280:                    Collection copy = new ArrayList(examinedUnits);
1281:                    examinedUnits.retainAll(units);
1282:                    if (examinedUnits.isEmpty()) {
1283:                        if (isInfoEnabled())
1284:                            info("skipping transport task where units don't match "
1285:                                    + units + " vs examined " + copy);
1286:                        continue;
1287:                    }
1288:
1289:                    // THIS IS DONE WHEN WE GET POSSIBLE MATCHES
1290:                    // are they for the same type of supply?
1291:                    //      if (!contentTypesOverlap (task, examinedTask)) 
1292:                    //	continue;
1293:
1294:                    // do the dates overlap
1295:                    Task reserved, transport;
1296:                    if (examinedIsReserved) {
1297:                        reserved = examinedTask;
1298:                        transport = task;
1299:                    } else {
1300:                        reserved = task;
1301:                        transport = examinedTask;
1302:                    }
1303:
1304:                    if (transportDateWithinReservedWindow(transport, reserved)) {
1305:                        matches.add(examinedTask);
1306:                    }
1307:                }
1308:
1309:                return matches;
1310:            }
1311:
1312:            /*
1313:            protected boolean contentTypesOverlap (Task task, Task examinedTask){
1314:              Collection typeIDs  = getTypesInContainer (task);
1315:
1316:              Collection examinedTypeIDs  = getTypesInContainer (examinedTask);
1317:              Collection copy = new ArrayList (examinedTypeIDs);
1318:
1319:              copy.retainAll (typeIDs);
1320:              if (copy.isEmpty()) {
1321:                if (isDebugEnabled())
1322:                  debug ("skipping transport task where type ids don't match. " + 
1323:                   "No overlap between examined container " +
1324:                         examinedTypeIDs +
1325:                         " and other container's list " + typeIDs);
1326:                return false;
1327:              }
1328:              else {
1329:                return true;
1330:              }
1331:            }
1332:             */
1333:
1334:            /** 
1335:             * @return all the ammo types inside the task's milvan 
1336:             */
1337:            protected Collection getTypesInContainer(Task task) {
1338:                Container taskDO;
1339:                if (task.getDirectObject() instanceof  AssetGroup) {
1340:                    taskDO = (Container) ((AssetGroup) task.getDirectObject())
1341:                            .getAssets().iterator().next();
1342:                } else {
1343:                    taskDO = (Container) task.getDirectObject();
1344:                }
1345:                ContentsPG contents = taskDO.getContentsPG();
1346:                Collection typeIDs = contents.getTypeIdentifications();
1347:                return typeIDs;
1348:            }
1349:
1350:            /** 
1351:             * @return a report on all the ammo types inside both tasks' milvan 
1352:             */
1353:            protected String reportContentTypes(Task task, Task examinedTask) {
1354:                if (task.getDirectObject() instanceof  Container) {
1355:                    Container taskDO = (Container) task.getDirectObject();
1356:                    Container examinedDO;
1357:                    if (examinedTask.getDirectObject() instanceof  AssetGroup) {
1358:                        examinedDO = (Container) ((AssetGroup) examinedTask
1359:                                .getDirectObject()).getAssets().iterator()
1360:                                .next();
1361:                    } else {
1362:                        examinedDO = (Container) examinedTask.getDirectObject();
1363:                    }
1364:
1365:                    ContentsPG contents = taskDO.getContentsPG();
1366:                    Collection typeIDs = contents.getTypeIdentifications();
1367:
1368:                    ContentsPG examinedContents = examinedDO.getContentsPG();
1369:                    Collection examinedTypeIDs = examinedContents
1370:                            .getTypeIdentifications();
1371:
1372:                    StringBuffer buf = new StringBuffer();
1373:
1374:                    buf.append("[");
1375:                    for (Iterator iter = typeIDs.iterator(); iter.hasNext();)
1376:                        buf.append(iter.next() + ", ");
1377:                    buf.append("]");
1378:                    buf.append(" vs ");
1379:                    buf.append("[");
1380:                    for (Iterator iter = examinedTypeIDs.iterator(); iter
1381:                            .hasNext();)
1382:                        buf.append(iter.next());
1383:                    buf.append("]");
1384:
1385:                    return buf.toString();
1386:                } else
1387:                    return "<not a container>";
1388:            }
1389:
1390:            /** 
1391:             * Must check best dates of Supply task parents. 
1392:             * Fix for bug #12467 and #12468.
1393:             *
1394:             * The problem is that the packer can aggregate supply tasks for two different ammo types
1395:             * into one milvan, and the EARLIER of the two dates becomes the END_TIME best for the
1396:             * MP Transport task.  It was this time I was using to determine overlap of the Transport
1397:             * Reservation that's derived from the ProjectSupply.
1398:             *
1399:             * E.g. the packer can make:
1400:             *
1401:             * Parent #1 : C380 arrive at 10/18
1402:             * Parent #2 : A986 arrive at 10/15
1403:             * -> MPTask with milvan arrive at 10/15 - don't want to make parent #2 be late
1404:             *
1405:             * So when we try to find the overlap with a Reservation:
1406:             * C380 from 9/25->10/20
1407:             * if we use the MPTask's arrival time, the overlap results in a Reservation 
1408:             * from 10/15->10/20 not from 10/18->10/20.
1409:             *
1410:             * Since the packer may do different packings from run-to-run, the quantities of Reserved
1411:             * ammo varies from run to run (and potentially the # of milvans).
1412:             * 
1413:             * @param transport - actual transport task
1414:             * @param reserved projected transport task
1415:             * @return true if transport task overlaps in time with the reserved task 
1416:             */
1417:            protected boolean transportDateWithinReservedWindow(Task transport,
1418:                    Task reserved) {
1419:                Date reservedReady = (Date) prepHelper.getIndirectObject(
1420:                        reserved, START);
1421:
1422:                Date latestDateOfParents = getLatestParentEndDate(transport,
1423:                        reserved);
1424:
1425:                if (reservedReady.getTime() >= latestDateOfParents.getTime()) {
1426:                    if (isDebugEnabled()) {
1427:                        debug("skipping actual transport task where task latest supply parent time "
1428:                                + latestDateOfParents
1429:                                + " before examined ready " + reservedReady);
1430:                    }
1431:
1432:                    return false;
1433:                }
1434:
1435:                if (isInfoEnabled()) {
1436:                    info("transport " + transport.getUID()
1437:                            + " latest supply parent time "
1438:                            + latestDateOfParents + " after reserved "
1439:                            + reserved.getUID() + " ready " + reservedReady);
1440:                }
1441:
1442:                return true;
1443:            }
1444:
1445:            /**
1446:             *  Must check best dates of Supply task parents. 
1447:             *
1448:             *  Remember to round to end of day!  A task arriving at midnight + 1 sec
1449:             *  of a day counts for the whole day against the projection.
1450:             */
1451:            protected Date getLatestParentEndDate(Task transport, Task reserved) {
1452:                Collection types = getTypesInContainer(reserved);
1453:                if (types.isEmpty()) {
1454:                    if (isWarnEnabled()) {
1455:                        warn(getName() + " - huh? no types in container for "
1456:                                + reserved);
1457:                    }
1458:                }
1459:
1460:                // should be only one ammo type in container
1461:                String reservedAmmoType = (String) types.iterator().next();
1462:                Date latest = getLatestParentEndDate(transport,
1463:                        reservedAmmoType);
1464:
1465:                // round to nearest next day boundary
1466:                long round = ((latest.getTime() + MILLIS_PER_DAY) / MILLIS_PER_DAY)
1467:                        * MILLIS_PER_DAY;
1468:
1469:                Date roundDate = new Date(round);
1470:
1471:                if (roundDate.getTime() == latest.getTime()) {
1472:                    if (isWarnEnabled()) {
1473:                        warn("huh? Didn't move date : date was " + latest
1474:                                + " now " + roundDate);
1475:                    }
1476:                } else if (isInfoEnabled()) {
1477:                    info("date was " + latest + " now " + roundDate);
1478:                }
1479:
1480:                return roundDate;
1481:            }
1482:
1483:            /**
1484:             *  Must check best dates of Supply task parents. 
1485:             */
1486:            protected Date getLatestParentEndDate(Task transport,
1487:                    String reservedAmmoType) {
1488:                Date best = prefHelper.getBestDate(transport);
1489:                long latestDateOfParents = best.getTime();
1490:
1491:                if (transport instanceof  MPTask) {
1492:                    MPTask multiParent = (MPTask) transport;
1493:                    for (Enumeration en = multiParent.getParentTasks(); en
1494:                            .hasMoreElements();) {
1495:                        Task supplyParent = (Task) en.nextElement();
1496:
1497:                        // check to see parent is of same ammo type
1498:                        TypeIdentificationPG typePG = supplyParent
1499:                                .getDirectObject().getTypeIdentificationPG();
1500:
1501:                        if (typePG == null) { // never happen
1502:                            if (isWarnEnabled()) {
1503:                                warn("huh? for task "
1504:                                        + supplyParent
1505:                                        + " the direct object is missing its type PG?");
1506:                            }
1507:                        }
1508:
1509:                        String typeName = typePG.getTypeIdentification();
1510:                        if (typeName.equals(reservedAmmoType)) {
1511:                            // check to see if date is later
1512:                            long parentBest = prefHelper.getBestDate(
1513:                                    supplyParent).getTime();
1514:                            if (parentBest > latestDateOfParents) {
1515:                                latestDateOfParents = parentBest;
1516:                            }
1517:                        }
1518:                    }
1519:
1520:                    return new Date(latestDateOfParents);
1521:                } else {
1522:                    // never used
1523:                    if (isWarnEnabled()) {
1524:                        warn("transport task " + transport
1525:                                + " is not an MPTask?");
1526:                    }
1527:
1528:                    return prefHelper.getBestDate(transport);
1529:                }
1530:            }
1531:
1532:            protected void updateMap(Map reservedToActual, Task actual,
1533:                    Task reserved) {
1534:                Task foundActual;
1535:                if ((foundActual = (Task) reservedToActual.get(reserved)) == null) {
1536:                    if (isInfoEnabled()) {
1537:                        info("initally, actual " + actual.getUID()
1538:                                + " matches reserved " + reserved.getUID());
1539:                    }
1540:                    reservedToActual.put(reserved, actual);
1541:                } else {
1542:                    if (isDebugEnabled()) {
1543:                        debug("actual " + actual.getUID()
1544:                                + " matches reserved " + reserved.getUID());
1545:                    }
1546:
1547:                    if (prefHelper.getBestDate(foundActual).getTime() < prefHelper
1548:                            .getBestDate(actual).getTime()) {
1549:                        if (isInfoEnabled()) {
1550:                            info("replacing foundActual "
1551:                                    + foundActual.getUID() + " with actual "
1552:                                    + actual.getUID()
1553:                                    + " which matches reserved "
1554:                                    + reserved.getUID());
1555:                        }
1556:                        reservedToActual.put(reserved, actual); // replace with later date
1557:                    }
1558:                }
1559:            }
1560:
1561:            /**
1562:             * <pre>
1563:             * Called from processTasks. 
1564:             *
1565:             * Compares transport reservation and overlapping actual transport task.
1566:             *
1567:             * Creates a replacement for existing reserved task, if there is any time
1568:             * span left where it doesn't overlap the actual task.  If the actual completely 
1569:             * overlaps the reservation, creates a successful disposition for the task.
1570:             *
1571:             * If there is partial overlap, adjusts the earliest arrival date on the reserved task
1572:             * to be equal to the best date of the actual and updates the contents pg of the direct
1573:             * object to indicate a smaller weight.
1574:             *
1575:             * As a convenience, adds the START prep to the reserved task, indicating the start
1576:             * of the period of the reservation.  This is used in transportDateWithinReservedWindow to
1577:             * determine if an actual falls in the span of a reservation and to indicate whether
1578:             * a transport task is indeed a reservation.
1579:             *
1580:             * </pre>
1581:             * @param task actual transport task
1582:             * @param reservedTask reserved transport task to be replaced
1583:             */
1584:            protected void dealWithReservedTask(Task task, Task reservedTask,
1585:                    Task reservedParent) {
1586:                // preconditions
1587:                if (isReservedTask(task))
1588:                    error("arg - task " + task.getUID()
1589:                            + " is a reserved task.");
1590:
1591:                if (!isReservedTask(reservedTask))
1592:                    error("arg - task " + reservedTask.getUID()
1593:                            + " is not a reserved task.");
1594:
1595:                NewWorkflow tasksWorkflow = (NewWorkflow) reservedTask
1596:                        .getWorkflow();
1597:
1598:                if (tasksWorkflow == null) {
1599:                    error("huh? reservedTask " + reservedTask.getUID()
1600:                            + " workflow is null?");
1601:                    return;
1602:                }
1603:
1604:                int numTasksBefore = numTasksInWorkflow(tasksWorkflow);
1605:
1606:                // real code starts here ---
1607:
1608:                // should be only one ammo type in container
1609:                Date best = getLatestParentEndDate(task, reservedTask);
1610:                Date reservedBest = prefHelper.getBestDate(reservedTask);
1611:                long daysLeft = (reservedBest.getTime() - best.getTime())
1612:                        / MILLIS_PER_DAY;
1613:                Date reservedReady = (Date) prepHelper.getIndirectObject(
1614:                        reservedTask, START);
1615:                long currentDays = (reservedBest.getTime() - reservedReady
1616:                        .getTime())
1617:                        / MILLIS_PER_DAY;
1618:
1619:                if (isInfoEnabled()) {
1620:                    info(getName()
1621:                            + ".dealWithReservedTask - applying actual\n"
1622:                            + task.getUID() + " best " + best
1623:                            + "\nto reserved\n" + reservedTask.getUID()
1624:                            + " reserved ready " + reservedReady + " to best "
1625:                            + reservedBest);
1626:                    info("\t" + reportContentTypes(task, reservedTask));
1627:                }
1628:
1629:                double factor = (double) daysLeft / (double) currentDays;
1630:                if (factor > 0) { // if the actual doesn't completely cover the period of the projection
1631:                    Asset deliveredAsset = getTrimmedDirectObject(reservedTask
1632:                            .getDirectObject(), factor);
1633:
1634:                    NewTask replacement = (NewTask) expandHelper.makeSubTask(
1635:                            ldmf, reservedTask.getPlan(), reservedTask
1636:                                    .getParentTaskUID(),
1637:                            reservedTask.getVerb(), reservedTask
1638:                                    .getPrepositionalPhrases(), deliveredAsset,
1639:                            reservedTask.getPreferences(), reservedTask
1640:                                    .getPriority(), reservedTask.getSource());
1641:                    replacement.setContext(reservedTask.getContext());
1642:
1643:                    if (isInfoEnabled())
1644:                        info("Reserved task " + reservedTask.getUID()
1645:                                + " current days " + currentDays + " daysLeft "
1646:                                + daysLeft + " replacing asset weights.");
1647:
1648:                    if (isInfoEnabled())
1649:                        info("on task " + replacement.getUID()
1650:                                + " replacing start prep date " + reservedReady
1651:                                + " with " + best
1652:                                + " - also becomes early date for task.");
1653:
1654:                    prepHelper.replacePrepOnTask(replacement, prepHelper
1655:                            .makePrepositionalPhrase(ldmf, START, best));
1656:
1657:                    if (!FIND_FOR_UNIT_PREP_ON_TASK) {
1658:                        prepHelper.replacePrepOnTask(replacement, prepHelper
1659:                                .makePrepositionalPhrase(ldmf,
1660:                                        Constants.Preposition.FOR,
1661:                                        getClusterName()));
1662:                    }
1663:
1664:                    prefHelper.replacePreference(replacement, prefHelper
1665:                            .makeEndDatePreference(ldmf, best, reservedBest,
1666:                                    prefHelper.getLateDate(reservedTask)));
1667:
1668:                    replacement.setWorkflow(tasksWorkflow);
1669:                    tasksWorkflow.addTask(replacement);
1670:                    publishAdd(replacement);
1671:                    if (isInfoEnabled()) {
1672:                        info("Publishing replacement " + replacement.getUID()
1673:                                + " in workflow " + tasksWorkflow.getUID()
1674:                                + " start " + best + " best " + reservedBest);
1675:                    }
1676:
1677:                    if (best.getTime() != ((Date) prepHelper.getIndirectObject(
1678:                            replacement, START)).getTime()) {
1679:                        error("replacement start "
1680:                                + prepHelper.getIndirectObject(replacement,
1681:                                        START) + " != " + best);
1682:                    }
1683:
1684:                    if (!taskInWorkflow(replacement, tasksWorkflow)) {
1685:                        error("huh? after adding to workflow, replacement "
1686:                                + replacement.getUID() + " is not in workflow "
1687:                                + tasksWorkflow + "?");
1688:                    }
1689:                } else {
1690:                    if (isInfoEnabled())
1691:                        info("Removing reserved task " + reservedTask.getUID()
1692:                                + " since weight is zero. Days Left was "
1693:                                + daysLeft + ", current days was "
1694:                                + currentDays + " parent was "
1695:                                + reservedTask.getParentTaskUID());
1696:                }
1697:
1698:                tasksWorkflow.removeTask(reservedTask);
1699:                publishRemove(reservedTask);
1700:
1701:                if (taskInWorkflow(reservedTask, tasksWorkflow))
1702:                    error("huh? after removing, reserved task "
1703:                            + reservedTask.getUID()
1704:                            + " is still a member of workflow " + tasksWorkflow);
1705:
1706:                int numTasksAfter = numTasksInWorkflow(tasksWorkflow);
1707:
1708:                if (numTasksAfter == 0) {
1709:                    if (reservedParent != null) { // I guess if the task is being removed, the parent could be missing from the blackboard
1710:                        PlanElement exp = reservedParent.getPlanElement();
1711:                        if (exp == null) {
1712:                            if (isWarnEnabled()) {
1713:                                warn("found task " + reservedParent.getUID()
1714:                                        + " verb " + reservedParent.getVerb()
1715:                                        + " that had no plan element.");
1716:                            }
1717:                        } else {
1718:                            publishRemove(exp);
1719:                            if (isInfoEnabled()) {
1720:                                info("removing expansion of task "
1721:                                        + exp.getTask().getUID());
1722:                            }
1723:                            AllocationResult ar = makeSuccessfulDisposition(reservedParent);
1724:                            Disposition disposition = ldmf.createDisposition(
1725:                                    reservedParent.getPlan(), reservedParent,
1726:                                    ar);
1727:                            publishAdd(disposition);
1728:                            if (isInfoEnabled())
1729:                                info(" task "
1730:                                        + reservedParent.getUID()
1731:                                        + " verb "
1732:                                        + reservedParent.getVerb()
1733:                                        + " - will get a DISPOSITION, since workflow now empty.");
1734:                        }
1735:                    }
1736:                }
1737:
1738:                if (factor < 0.00000001
1739:                        && (numTasksAfter != numTasksBefore - 1))
1740:                    error("Reserved task " + reservedTask.getUID()
1741:                            + "'s workflow had " + numTasksBefore
1742:                            + " should have " + (numTasksBefore - 1)
1743:                            + " but has " + numTasksAfter);
1744:                else if (factor > 0 && (numTasksAfter != numTasksBefore))
1745:                    error("Reserved task " + reservedTask.getUID()
1746:                            + "'s workflow had " + numTasksBefore
1747:                            + " != numTaskAfter, which is " + numTasksAfter);
1748:            }
1749:
1750:            protected boolean isReservedTask(Task task) {
1751:                return (prepHelper.hasPrepNamed(task, START));
1752:            }
1753:
1754:            protected boolean ownWorkflow(Task task) {
1755:                if (task.getWorkflow() == null)
1756:                    return false;
1757:
1758:                return taskInWorkflow(task, task.getWorkflow());
1759:            }
1760:
1761:            protected boolean taskInWorkflow(Task task, Workflow workflow) {
1762:                if (workflow == null)
1763:                    return false;
1764:                String[] uidsInWorkflow = ((WorkflowImpl) workflow)
1765:                        .getTaskIDs();
1766:                boolean found = false;
1767:                for (int i = 0; i < uidsInWorkflow.length && !found; i++)
1768:                    if (uidsInWorkflow[i].equals(task.getUID().toString()))
1769:                        found = true;
1770:
1771:                return found;
1772:            }
1773:
1774:            protected String uidsWorkflow(Task task) {
1775:                if (task.getWorkflow() == null) {
1776:                    return "<null workflow for " + task.getUID() + ">";
1777:                }
1778:
1779:                return uids(((WorkflowImpl) task.getWorkflow()).getTaskIDs());
1780:            }
1781:
1782:            protected String uids(String[] array) {
1783:                StringBuffer buf = new StringBuffer();
1784:                for (int i = 0; i < array.length; i++)
1785:                    buf.append(array[i] + ", ");
1786:                return buf.toString();
1787:            }
1788:
1789:            protected int numTasksInWorkflow(Workflow workflow) {
1790:                int num = 0;
1791:                for (Enumeration en = workflow.getTasks(); en.hasMoreElements(); en
1792:                        .nextElement()) {
1793:                    num++;
1794:                }
1795:                return num;
1796:            }
1797:
1798:            /**
1799:             * Makes allocation result with aspect values that echo the task preferences
1800:             *
1801:             * @param task to dispose
1802:             * @return successful allocation result with aspect values taken from task prefs
1803:             */
1804:            protected AllocationResult makeSuccessfulDisposition(Task task) {
1805:                Enumeration prefEnum;
1806:                synchronized (task) {
1807:                    prefEnum = task.getPreferences();
1808:                } // bug #2125
1809:                List aspectValues = new ArrayList();
1810:                while (prefEnum.hasMoreElements()) {
1811:                    Preference pref = (Preference) prefEnum.nextElement();
1812:                    ScoringFunction sfunc = pref.getScoringFunction();
1813:                    aspectValues.add(sfunc.getBest().getAspectValue());
1814:                }
1815:
1816:                AspectValue[] aspectValueArray = (AspectValue[]) aspectValues
1817:                        .toArray(new AspectValue[aspectValues.size()]);
1818:
1819:                AllocationResult successfulAR = ldmf.newAllocationResult(1.0,
1820:                        true, aspectValueArray);
1821:                return successfulAR;
1822:            }
1823:
1824:            /**
1825:             * Look on task for what unit the ammo is for.  Generally this will be 191-ORDN.
1826:             *
1827:             * If FIND_FOR_UNIT_PREP_ON_TASK is false, just use agent identifier (OSC).
1828:             */
1829:            protected Collection findForPreps(final Task task) {
1830:                List units;
1831:                if (FIND_FOR_UNIT_PREP_ON_TASK) {
1832:                    units = new ArrayList();
1833:                    if (task instanceof  MPTask) {
1834:                        Collection parents = ((MPTask) task).getComposition()
1835:                                .getParentTasks();
1836:                        for (Iterator iter = parents.iterator(); iter.hasNext();) {
1837:                            Task parentTask = (Task) iter.next();
1838:                            if (prepHelper.hasPrepNamed(parentTask,
1839:                                    Constants.Preposition.FOR))
1840:                                units.add(prepHelper.getIndirectObject(
1841:                                        parentTask, Constants.Preposition.FOR));
1842:                        }
1843:                    } else {
1844:                        if (prepHelper.hasPrepNamed(task,
1845:                                Constants.Preposition.FOR)) {
1846:                            units.add(prepHelper.getIndirectObject(task,
1847:                                    Constants.Preposition.FOR));
1848:                        } else {
1849:                            if (isWarnEnabled())
1850:                                warn("no FOR prep on task " + task.getUID()
1851:                                        + " using UID owner ");
1852:                            units.add(task.getUID().getOwner());
1853:                        }
1854:                    }
1855:
1856:                    if (isDebugEnabled())
1857:                        debug("Units for " + task.getUID() + " were " + units);
1858:                } else {
1859:                    if (defaultUnit == null) {
1860:                        defaultUnit = new ArrayList();
1861:                        defaultUnit.add(getClusterName()); // i.e. OSC
1862:                    }
1863:                    units = defaultUnit;
1864:                }
1865:                return units;
1866:            }
1867:
1868:            /**
1869:             * Assumes the direct object is either an asset group or a container (milvan).
1870:             * If it's a container, updates the contentsPG to reflect a new weight that is the
1871:             * old multiplied by factor (0.0 < factor < 1.0).
1872:             *
1873:             * Called from dealWithReservedTask.
1874:             *
1875:             * @param directObject old container or asset group
1876:             * @param factor to reduce container weight by
1877:             * @return new or old milvan with updated contentsPG
1878:             * @see #dealWithReservedTask
1879:             */
1880:            protected Asset getTrimmedDirectObject(Asset directObject,
1881:                    double factor) {
1882:                if (directObject instanceof  AssetGroup) {
1883:                    double total = 0.0;
1884:                    Container last = null;
1885:
1886:                    for (Iterator iter = ((AssetGroup) directObject)
1887:                            .getAssets().iterator(); iter.hasNext();) {
1888:                        last = (Container) iter.next();
1889:                        total += getContainerTons(last);
1890:                    }
1891:
1892:                    if (last == null) {
1893:                        error("Nothing in the asset group of milvans?");
1894:                    }
1895:
1896:                    ContentsPG contents = last.getContentsPG();
1897:
1898:                    String nomen = (String) contents.getNomenclatures()
1899:                            .iterator().next();
1900:                    String type = (String) contents.getTypeIdentifications()
1901:                            .iterator().next();
1902:                    String unit = (String) contents.getReceivers().iterator()
1903:                            .next();
1904:
1905:                    return getMilvanDirectObject(nomen, type, unit, total
1906:                            * factor);
1907:                } else {
1908:                    Container reserved = (Container) directObject;
1909:                    ContentsPG contents = reserved.getContentsPG();
1910:                    Collection weights = contents.getWeights();
1911:                    Mass weight = (Mass) weights.iterator().next();
1912:                    weights.remove(weight);
1913:                    weights.add(new Mass(weight.getKilograms() * factor,
1914:                            Mass.KILOGRAMS));
1915:                    return reserved;
1916:                }
1917:            }
1918:
1919:            /** assumes only one type of ammo in container -- true for reservations */
1920:            protected double getContainerTons(Container container) {
1921:                ContentsPG contents = container.getContentsPG();
1922:                Collection weights = contents.getWeights();
1923:                Mass weight = (Mass) weights.iterator().next();
1924:                return weight.getShortTons();
1925:            }
1926:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.