Source Code Cross Referenced for GLMTransOneToManyExpanderPlugin.java in  » Science » Cougaar12_4 » org » cougaar » logistics » plugin » trans » base » 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.base 
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.base;
0027:
0028:        import org.cougaar.core.adaptivity.OMCRange;
0029:        import org.cougaar.core.adaptivity.OMCRangeList;
0030:        import org.cougaar.core.adaptivity.OperatingMode;
0031:        import org.cougaar.core.adaptivity.OperatingModeImpl;
0032:        import org.cougaar.core.agent.service.alarm.Alarm;
0033:        import org.cougaar.core.service.BlackboardService;
0034:        import org.cougaar.core.service.DomainService;
0035:        import org.cougaar.core.service.ThreadService;
0036:        import org.cougaar.core.thread.Schedulable;
0037:        import org.cougaar.glm.ldm.asset.*;
0038:        import org.cougaar.glm.ldm.plan.GeolocLocation;
0039:        import org.cougaar.glm.util.AssetUtil;
0040:        import org.cougaar.glm.util.GLMPreference;
0041:        import org.cougaar.glm.util.GLMPrepPhrase;
0042:        import org.cougaar.lib.callback.UTILFilterCallback;
0043:        import org.cougaar.lib.callback.UTILFilterCallbackAdapter;
0044:        import org.cougaar.lib.callback.UTILFilterCallbackListener;
0045:        import org.cougaar.lib.filter.UTILExpanderPluginAdapter;
0046:        import org.cougaar.logistics.ldm.Constants;
0047:        import org.cougaar.logistics.plugin.trans.CargoCatCodeDimensionPG;
0048:        import org.cougaar.logistics.plugin.trans.GLMTransConst;
0049:        import org.cougaar.logistics.plugin.trans.LowFidelityAssetPG;
0050:        import org.cougaar.logistics.plugin.trans.NewCargoCatCodeDimensionPG;
0051:        import org.cougaar.logistics.plugin.trans.NewLowFidelityAssetPG;
0052:        import org.cougaar.logistics.plugin.trans.tools.BlackboardPlugin;
0053:        import org.cougaar.logistics.plugin.trans.tools.PortLocatorImpl;
0054:        import org.cougaar.planning.ldm.PlanningFactory;
0055:        import org.cougaar.planning.ldm.asset.AggregateAsset;
0056:        import org.cougaar.planning.ldm.asset.Asset;
0057:        import org.cougaar.planning.ldm.asset.AssetGroup;
0058:        import org.cougaar.planning.ldm.asset.NewItemIdentificationPG;
0059:        import org.cougaar.planning.ldm.asset.PropertyGroup;
0060:        import org.cougaar.planning.ldm.measure.Area;
0061:        import org.cougaar.planning.ldm.measure.Distance;
0062:        import org.cougaar.planning.ldm.measure.Latitude;
0063:        import org.cougaar.planning.ldm.measure.Longitude;
0064:        import org.cougaar.planning.ldm.measure.Mass;
0065:        import org.cougaar.planning.ldm.measure.Volume;
0066:        import org.cougaar.planning.ldm.plan.AspectType;
0067:        import org.cougaar.planning.ldm.plan.Expansion;
0068:        import org.cougaar.planning.ldm.plan.NewTask;
0069:        import org.cougaar.planning.ldm.plan.PlanElement;
0070:        import org.cougaar.planning.ldm.plan.Task;
0071:        import org.cougaar.util.UnaryPredicate;
0072:        import org.cougaar.util.log.Logger;
0073:
0074:        import java.util.ArrayList;
0075:        import java.util.Collection;
0076:        import java.util.Date;
0077:        import java.util.HashSet;
0078:        import java.util.Iterator;
0079:        import java.util.List;
0080:        import java.util.Set;
0081:        import java.util.Vector;
0082:
0083:        /**
0084:         * getSubtasks is filled in.  It justs blows up composite
0085:         * tasks into smaller one unit tasks.  Examines each Task.
0086:         *
0087:         * @see UTILExpanderPluginAdapter
0088:         */
0089:        public class GLMTransOneToManyExpanderPlugin extends
0090:                UTILExpanderPluginAdapter implements  BlackboardPlugin {
0091:            /** VTH operating modes */
0092:            protected transient OperatingMode level2Horizon, level6Horizon;
0093:
0094:            public final Integer LEVEL_2_MIN = new Integer(2); // later, these should be parameters to plugin...
0095:            public final Integer LEVEL_2_MAX = new Integer(365);
0096:            public final Integer LEVEL_6_MIN = new Integer(1);
0097:            public final Integer LEVEL_6_MAX = new Integer(365);
0098:            public final int LEVEL_6_MODE = 0;
0099:            public final int LEVEL_2_MODE = 1;
0100:            /** currently not supported **/
0101:            public final int DONT_PROCESS_MODE = 2;
0102:            public final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
0103:
0104:            public final String LEVEL_2_TIME_HORIZON = "Level2TimeHorizon";
0105:            public final Integer LEVEL_2_TIME_HORIZON_DEFAULT = LEVEL_2_MAX;
0106:            public final String LEVEL_6_TIME_HORIZON = "Level6TimeHorizon";
0107:            public final Integer LEVEL_6_TIME_HORIZON_DEFAULT = LEVEL_6_MAX;
0108:
0109:            public final int NUM_TRANSPORT_CLASSES = 9;
0110:            public final int ASSET_CLASS_UNKNOWN = 0;
0111:            public final int ASSET_CLASS_1 = 1;
0112:            public final int ASSET_CLASS_2 = 2;
0113:            public final int ASSET_CLASS_3 = 3;
0114:            public final int ASSET_CLASS_4 = 4;
0115:            public final int ASSET_CLASS_5 = 5;
0116:            public final int ASSET_CLASS_6 = 6;
0117:            public final int ASSET_CLASS_7 = 7;
0118:            public final int ASSET_CLASS_8 = 8;
0119:            public final int ASSET_CLASS_9 = 9;
0120:            public final int ASSET_CLASS_10 = 10;
0121:            public final int ASSET_CLASS_CONTAINER = 11;
0122:            public final int ASSET_CLASS_PERSON = 12;
0123:            public final long DAY_IN_MILLIS = MILLIS_PER_DAY; //30*1000l;
0124:
0125:            public void localSetup() {
0126:                super .localSetup();
0127:
0128:                try {
0129:                    myExpandAggregates = (getMyParams()
0130:                            .hasParam("ExpandAggregates")) ? getMyParams()
0131:                            .getBooleanParam("ExpandAggregates") : true;
0132:                } catch (Exception e) {
0133:                    warn("got really unexpected exception " + e);
0134:                }
0135:
0136:                glmPrepHelper = new GLMPrepPhrase(logger);
0137:                glmPrefHelper = new GLMPreference(logger);
0138:                glmAssetHelper = new AssetUtil(logger);
0139:
0140:                setupOperatingModes();
0141:                portLocator.setFactory(ldmf); // tell route finder the ldm factory to use
0142:            }
0143:
0144:            /** create the port locator */
0145:            public void setupFilters() {
0146:                super .setupFilters();
0147:                portLocator = new PortLocatorImpl(this , logger);
0148:
0149:                addFilter(modeCallback = new OperatingModeCallback(this , logger));
0150:            }
0151:
0152:            UTILFilterCallback modeCallback;
0153:
0154:            class OperatingModeCallback extends UTILFilterCallbackAdapter {
0155:                public OperatingModeCallback(
0156:                        UTILFilterCallbackListener listener, Logger logger) {
0157:                    super (listener, logger);
0158:                }
0159:
0160:                protected UnaryPredicate getPredicate() {
0161:                    return new UnaryPredicate() {
0162:                        public boolean execute(Object o) {
0163:                            boolean val = (o instanceof  OperatingMode);
0164:                            if (val && logger.isInfoEnabled())
0165:                                logger
0166:                                        .info("GLMTransOneToManyExpanderPlugin.OperatingModeCallback.getPredicate - interested in "
0167:                                                + o);
0168:                            return val;
0169:                        }
0170:                    };
0171:                }
0172:
0173:                public void reactToChangedFilter() {
0174:                    if (isInfoEnabled())
0175:                        info(getName()
0176:                                + " operating modes sub changed "
0177:                                + modeCallback.getSubscription()
0178:                                        .getAddedCollection().size()
0179:                                + " added, "
0180:                                + modeCallback.getSubscription()
0181:                                        .getChangedCollection().size()
0182:                                + " changed, "
0183:                                + modeCallback.getSubscription()
0184:                                        .getRemovedCollection().size()
0185:                                + " removed");
0186:                    if (!modeCallback.getSubscription().getChangedCollection()
0187:                            .isEmpty()) {
0188:                        if (isInfoEnabled())
0189:                            info(getName()
0190:                                    + " operating modes changed, so reviewing level 2 tasks.");
0191:                        reviewLevel2();
0192:                        if (isInfoEnabled())
0193:                            info(getName()
0194:                                    + " operating modes changed, so reviewing deferred tasks.");
0195:                        processTasks(new ArrayList(myInputTaskCallback
0196:                                .getSubscription().getCollection()));
0197:                    }
0198:                }
0199:
0200:            }
0201:
0202:            /** create and publish level-2 and 6 VTH Operating Modes */
0203:            protected void setupOperatingModes() {
0204:                Collection modes = blackboard.query(new UnaryPredicate() {
0205:                    public boolean execute(Object obj) {
0206:                        return (obj instanceof  OperatingMode);
0207:                    }
0208:                });
0209:
0210:                if (modes.size() != 2) {
0211:                    if (isInfoEnabled())
0212:                        info(getName()
0213:                                + " expecting 0 or two operating modes on rehydation - got "
0214:                                + modes.size() + " instead : " + modes);
0215:                }
0216:
0217:                // Find the BBoard value for the OpModes, if we don't already have one
0218:                for (Iterator iter = modes.iterator(); iter.hasNext();) {
0219:                    OperatingMode mode = (OperatingMode) iter.next();
0220:                    if (mode.getName().equals(LEVEL_2_TIME_HORIZON)
0221:                            && (level2Horizon == null || level2Horizon
0222:                                    .getValue() == null)) {
0223:                        if (isInfoEnabled())
0224:                            info(getName()
0225:                                    + " using BBoard value for level2Horizon.");
0226:                        level2Horizon = mode;
0227:                    } else if (mode.getName().equals(LEVEL_6_TIME_HORIZON)
0228:                            && (level6Horizon == null || level6Horizon
0229:                                    .getValue() == null)) {
0230:                        level6Horizon = mode;
0231:                        if (isInfoEnabled())
0232:                            info(getName()
0233:                                    + " using BBoard value for level6Horizon.");
0234:                    }
0235:                }
0236:
0237:                // If we now have an OpMode, but it's value is null, it's junk - discard
0238:                if (level2Horizon != null && level2Horizon.getValue() == null) {
0239:                    error(getName() + " had null value for level2Horizon: "
0240:                            + level2Horizon);
0241:                    level2Horizon = null;
0242:                }
0243:
0244:                if (level6Horizon != null && level6Horizon.getValue() == null) {
0245:                    error(getName() + " had null value for level6Horizon: "
0246:                            + level6Horizon);
0247:                    level6Horizon = null;
0248:                }
0249:
0250:                // If after the BBoard retrieval and error check, we have no OpMode,
0251:                // then create and publishAdd it
0252:                if (level2Horizon == null) {
0253:                    OMCRange level2Range = new IntRange(LEVEL_2_MIN.intValue(),
0254:                            LEVEL_2_MAX.intValue());
0255:                    OMCRangeList rangeList = new OMCRangeList(level2Range);
0256:                    publishAdd(level2Horizon = new OperatingModeImpl(
0257:                            LEVEL_2_TIME_HORIZON, rangeList,
0258:                            LEVEL_2_TIME_HORIZON_DEFAULT));
0259:                    if (isInfoEnabled())
0260:                        info(getAgentIdentifier()
0261:                                + " created operating mode - "
0262:                                + "level 2 time horizon is " + level2Horizon);
0263:                } else {
0264:                    if (isInfoEnabled()) {
0265:                        info(getName()
0266:                                + " skipping creating of level2Horizon operating mode since got it from blackboard.");
0267:                    }
0268:                }
0269:
0270:                if (level6Horizon == null) {
0271:                    OMCRange level6Range = new IntRange(LEVEL_6_MIN.intValue(),
0272:                            LEVEL_6_MAX.intValue());
0273:                    OMCRangeList rangeList = new OMCRangeList(level6Range);
0274:                    publishAdd(level6Horizon = new OperatingModeImpl(
0275:                            LEVEL_6_TIME_HORIZON, rangeList,
0276:                            LEVEL_6_TIME_HORIZON_DEFAULT));
0277:                    if (isInfoEnabled())
0278:                        info(getAgentIdentifier()
0279:                                + " created operating mode - "
0280:                                + " level 6 horizon is " + level6Horizon);
0281:                } else {
0282:                    if (isInfoEnabled()) {
0283:                        info(getName()
0284:                                + " skipping creating of level6Horizon operating mode since got it from blackboard.");
0285:                    }
0286:                }
0287:
0288:            }
0289:
0290:            protected static class IntRange extends OMCRange {
0291:                public IntRange(int a, int b) {
0292:                    super (a, b);
0293:                }
0294:            }
0295:
0296:            /** 
0297:             * Implemented for UTILGenericListener interface
0298:             *
0299:             * Look for tasks that have TRANSPORT as their verb
0300:             *
0301:             * @param t Task to check for interest
0302:             * @return boolean true if task is interesting
0303:             */
0304:
0305:            public boolean interestingTask(Task t) {
0306:                boolean hasTransportVerb = t.getVerb().equals(
0307:                        Constants.Verb.TRANSPORT);
0308:                if (isDebugEnabled() && hasTransportVerb) {
0309:                    debug(getName() + " : interested in expandable task " + t
0310:                            + " with direct obj " + t.getDirectObject());
0311:                }
0312:                if (isDebugEnabled() && !hasTransportVerb)
0313:                    debug(getName() + " : Ignoring task " + t.getUID()
0314:                            + " with verb " + t.getVerb());
0315:
0316:                return hasTransportVerb;
0317:            }
0318:
0319:            /** 
0320:             * <pre>
0321:             * Examines task to see if task looks like what the plugin 
0322:             * expects it to look like.
0323:             *
0324:             * Checks FROM and TO prepositions to see they're all there.
0325:             *
0326:             * </pre>
0327:             * @param taskToCheck Task to check for consistency
0328:             * @return true if task is OK
0329:             */
0330:            public boolean isTaskWellFormed(Task taskToCheck) {
0331:                boolean taskTiming = verifyHelper
0332:                        .isTaskTimingCorrect(taskToCheck);
0333:
0334:                if (!taskTiming) {
0335:                    reportError(taskToCheck.getUID()
0336:                            + " failed timing constraint check - e.g. is earliest arrival before start?");
0337:                    return false;
0338:                }
0339:
0340:                if (glmPrepHelper == null)
0341:                    error(getName()
0342:                            + ".isTaskWellFormed - huh? glmPrepHelper is null??");
0343:
0344:                GeolocLocation start = (GeolocLocation) glmPrepHelper
0345:                        .getIndirectObject(taskToCheck,
0346:                                Constants.Preposition.FROM);
0347:                GeolocLocation end = (GeolocLocation) glmPrepHelper
0348:                        .getIndirectObject(taskToCheck,
0349:                                Constants.Preposition.TO);
0350:
0351:                if (start == null) {
0352:                    reportError(".isTaskWellFormed : Hey! For task "
0353:                            + taskToCheck + " FROM geoloc is null!");
0354:                    return false;
0355:                } else if (end == null) {
0356:                    reportError(".isTaskWellFormed : Hey! For task "
0357:                            + taskToCheck + " TO geoloc is null!");
0358:                    return false;
0359:                } else {
0360:                    Longitude lon = start.getLongitude();
0361:                    Latitude lat = start.getLatitude();
0362:                    if (lon == null) {
0363:                        reportError(".isTaskWellFormed : For task "
0364:                                + taskToCheck + "\n FROM longitude is null!");
0365:                        return false;
0366:                    } else if (isDebugEnabled())
0367:                        debug(".isTaskWellFormed\n\tTask : " + taskToCheck
0368:                                + "\nstart (long, lat) is (" + lon.getDegrees()
0369:                                + "," + lat.getDegrees() + ")");
0370:
0371:                    lon = end.getLongitude();
0372:                    lat = end.getLatitude();
0373:                    if (lon == null) {
0374:                        reportError(".isTaskWellFormed : TO longitude is null!");
0375:                        return false;
0376:                    } else if (isDebugEnabled())
0377:                        debug("end (long, lat) is (" + lon.getDegrees() + ","
0378:                                + lat.getDegrees() + ")");
0379:
0380:                    //      if (isInfoEnabled()) 
0381:                    //	info ("Distance between is : " + 
0382:                    //			    UTILUtil.distanceBetween (start, end).getMiles () + " miles.");
0383:                }
0384:
0385:                return true;
0386:            }
0387:
0388:            public void processTasks(java.util.List tasks) {
0389:                super .processTasks(getPrunedTaskList(tasks));
0390:
0391:                if (logger.isDebugEnabled()) {
0392:                    logger.debug("Finished processing " + tasks.size()
0393:                            + " tasks at "
0394:                            + new Date(alarmService.currentTimeMillis())
0395:                            + " Cougaar Time " + new Date() + " clock time.");
0396:                }
0397:            }
0398:
0399:            protected List getPrunedTaskList(List tasks) {
0400:                java.util.List prunedTasks = new java.util.ArrayList(tasks
0401:                        .size());
0402:
0403:                Collection removed = myInputTaskCallback.getSubscription()
0404:                        .getRemovedCollection();
0405:
0406:                for (Iterator iter = tasks.iterator(); iter.hasNext();) {
0407:                    Task task = (Task) iter.next();
0408:                    if (removed.contains(task)) {
0409:                        if (isInfoEnabled()) {
0410:                            info("ignoring task on removed list "
0411:                                    + task.getUID());
0412:                        }
0413:                    } else
0414:                        prunedTasks.add(task);
0415:                }
0416:                return prunedTasks;
0417:            }
0418:
0419:            public void handleTask(Task parentTask) {
0420:                int mode = getMode(parentTask);
0421:                if (isDebugEnabled()) {
0422:                    debug(".getSubtasks - mode for task "
0423:                            + parentTask.getUID()
0424:                            + " is "
0425:                            + ((mode == LEVEL_6_MODE) ? "LEVEL_6"
0426:                                    : ((mode == LEVEL_2_MODE) ? "LEVEL_2"
0427:                                            : "DONT_PROCESS")));
0428:                }
0429:
0430:                if (parentTask.getPlanElement() != null) { // shouldn't it have been removed from my collection???
0431:                    if (isInfoEnabled()) {
0432:                        info(getName()
0433:                                + ".getSubtasks - skipping previously planned task "
0434:                                + parentTask.getUID() + ".");
0435:                    }
0436:                    return;
0437:                }
0438:
0439:                if (mode != LEVEL_6_MODE) {
0440:                    synchronized (alarmMutex) { // alarm.expire will try to clear currentAlarm so must synchronize on it
0441:                        if (currentAlarm == null) {
0442:                            startAgainIn(DAY_IN_MILLIS);
0443:                        } else {
0444:                            if (isDebugEnabled()) {
0445:                                debug(getName()
0446:                                        + ".getSubtasks - not starting new alarm.");
0447:                            }
0448:                        }
0449:                    }
0450:
0451:                    if (mode == DONT_PROCESS_MODE) {
0452:                        if (isInfoEnabled()) {
0453:                            info(getName()
0454:                                    + ".getSubtasks - not processing "
0455:                                    + parentTask.getUID()
0456:                                    + " for now (= "
0457:                                    + new Date(alarmService.currentTimeMillis())
0458:                                    + "), will revisit at "
0459:                                    + new Date(currentAlarm.getExpirationTime()));
0460:                        }
0461:                    } else {
0462:                        if (isInfoEnabled()) {
0463:                            info(getName()
0464:                                    + ".getSubtasks - processing "
0465:                                    + parentTask.getUID()
0466:                                    + " at level 2 for now (= "
0467:                                    + new Date(alarmService.currentTimeMillis())
0468:                                    + "), will revisit at "
0469:                                    + new Date(currentAlarm.getExpirationTime()));
0470:                        }
0471:                        super .handleTask(parentTask);
0472:                    }
0473:
0474:                    return;
0475:                } else
0476:                    super .handleTask(parentTask);
0477:            }
0478:
0479:            int i = 0;
0480:
0481:            /**
0482:             * <pre>
0483:             * Implemented for UTILExpanderPlugin interface
0484:             *
0485:             * Break up tasks into constituent parts.
0486:             *
0487:             * There are three possible paths a task can take:
0488:             * 
0489:             * 1) If the task is already a LEVEL 2 task, attaches a lowFiAssetPG to the asset and 
0490:             * passes it through.
0491:             * 2) If the task's dates and the operating mode VTH determine it should be handled
0492:             * in level-2 mode, create a level-2 task from the original
0493:             * 3) If the task should be handled in level-6, expand it's d.o. as usual
0494:             * 4) TBD - perhaps, in the future, we'll ignore tasks that are far into the future
0495:             * until the current time advances far enough.  This would require the buffering thread
0496:             * to wake up periodically, however, using the alarm service.  Hmmm...
0497:             *
0498:             * There is also the possibility of rescinding level 2 and replanning as level 6.  
0499:             * That would be real work though.
0500:             * </pre>
0501:             * @return Vector of subtasks of parentTask
0502:             */
0503:            public Vector getSubtasks(Task parentTask) {
0504:                Vector childTasks = new Vector();
0505:
0506:                if (isInfoEnabled())
0507:                    info(".getSubtasks - received task " + (i++) + " total.");
0508:
0509:                int mode = getMode(parentTask);
0510:                if (isDebugEnabled()) {
0511:                    debug(".getSubtasks - mode for task "
0512:                            + parentTask.getUID()
0513:                            + " is "
0514:                            + ((mode == LEVEL_6_MODE) ? "LEVEL_6"
0515:                                    : ((mode == LEVEL_2_MODE) ? "LEVEL_2"
0516:                                            : "DONT_PROCESS")));
0517:                }
0518:
0519:                // if the incoming task is already a low fidelity task, we don't need to do anything to it
0520:                if (prepHelper.hasPrepNamed(parentTask,
0521:                        GLMTransConst.LOW_FIDELITY)) {
0522:                    // pass through
0523:                    Asset lowFiAsset = parentTask.getDirectObject();
0524:                    Task subTask = makeTask(parentTask, lowFiAsset, null);
0525:                    NewLowFidelityAssetPG lowFiPG = (NewLowFidelityAssetPG) ldmf
0526:                            .createPropertyGroup(LowFidelityAssetPG.class);
0527:                    lowFiPG.setOriginalAsset(lowFiAsset);
0528:                    attachPG(lowFiAsset, lowFiPG); // now subobject has pointer back to parent
0529:                    if (isDebugEnabled())
0530:                        debug(".getSubtasks - processing task "
0531:                                + parentTask.getUID()
0532:                                + " by attaching low fi pg to it's d.o. - "
0533:                                + lowFiAsset);
0534:                    childTasks.addElement(subTask);
0535:                } else if ((getMode(parentTask) == LEVEL_2_MODE)
0536:                        && ((parentTask.getDirectObject() instanceof  AssetGroup) || // it doesn't make sense to aggregate an individual item asset
0537:                        (parentTask.getDirectObject() instanceof  AggregateAsset))
0538:                        && !isPersonTask(parentTask)) {
0539:                    if (isDebugEnabled())
0540:                        debug(".getSubtasks - processing task "
0541:                                + parentTask.getUID()
0542:                                + " in LOW fidelity mode. d.o. is "
0543:                                + parentTask.getDirectObject());
0544:
0545:                    Set[] categories = sortAssetsByCategory(expandAsset(
0546:                            parentTask, parentTask.getDirectObject()));
0547:
0548:                    for (int i = 0; i < NUM_TRANSPORT_CLASSES; i++) {
0549:                        if (!categories[i].isEmpty())
0550:                            childTasks.add(getLowFidelityTask(parentTask,
0551:                                    categories[i]));
0552:                    }
0553:                } else {
0554:                    if (isDebugEnabled())
0555:                        debug(".getSubtasks - processing task "
0556:                                + parentTask.getUID()
0557:                                + " in HIGH fidelity mode. d.o. is "
0558:                                + parentTask.getDirectObject());
0559:
0560:                    Vector itemsToMove = expandAsset(parentTask,
0561:                            (Asset) parentTask.getDirectObject());
0562:
0563:                    for (int i = 0; i < itemsToMove.size(); i++) {
0564:                        Task subTask = makeTask(parentTask, (Asset) itemsToMove
0565:                                .elementAt(i), null);
0566:                        childTasks.addElement(subTask);
0567:                    }
0568:                }
0569:
0570:                return childTasks;
0571:            }
0572:
0573:            /** 
0574:             * Decide the mode the task should be processed in, depending on when it asks to be done,
0575:             * and comparing that time against the current time and the level 2 and 6 time horizons
0576:             * 
0577:             * @return either LEVEL_6_MODE, LEVEL_2_MODE, or DONT_PROCESS_MODE (currently not supported)
0578:             */
0579:            protected int getMode(Task parentTask) {
0580:                long bestTime = prefHelper.getBestDate(parentTask).getTime();
0581:                long currentTime = getAlarmService().currentTimeMillis();
0582:
0583:                // Double check -- if we have no good OpModes here, then get them
0584:                if (level6Horizon == null || level2Horizon == null
0585:                        || level6Horizon.getValue() == null
0586:                        || level2Horizon.getValue() == null) {
0587:                    // create them
0588:                    setupOperatingModes();
0589:                }
0590:                long level6Day = ((Integer) level6Horizon.getValue())
0591:                        .longValue();
0592:                long level2Day = ((Integer) level2Horizon.getValue())
0593:                        .longValue();
0594:                if (bestTime < currentTime + level6Day * MILLIS_PER_DAY) {
0595:                    return LEVEL_6_MODE;
0596:                } else if (bestTime < currentTime + level2Day * MILLIS_PER_DAY) {
0597:                    if (isInfoEnabled())
0598:                        info(getName() + ".getMode - got level 2 task ("
0599:                                + parentTask.getUID() + ")\nsince best "
0600:                                + new java.util.Date(bestTime)
0601:                                + " is after current "
0602:                                + new java.util.Date(currentTime)
0603:                                + " + level6 days " + level6Day);
0604:                    return LEVEL_2_MODE;
0605:                }
0606:                return DONT_PROCESS_MODE;
0607:            }
0608:
0609:            protected Set[] sortAssetsByCategory(Collection assets) {
0610:                Set[] categories = new Set[NUM_TRANSPORT_CLASSES];
0611:
0612:                categories[0] = new HashSet();
0613:                categories[1] = new HashSet();
0614:                categories[2] = new HashSet();
0615:                categories[3] = new HashSet();
0616:                categories[4] = new HashSet();
0617:                categories[5] = new HashSet();
0618:                categories[6] = new HashSet();
0619:                categories[7] = new HashSet();
0620:                categories[8] = new HashSet();
0621:
0622:                for (Iterator iter = assets.iterator(); iter.hasNext();) {
0623:                    GLMAsset asset = (GLMAsset) iter.next();
0624:                    String ccc = getCategory(asset);
0625:
0626:                    switch (ccc.charAt(1)) {
0627:                    case '0': // non-air
0628:                        if (ccc.charAt(0) == 'R') {
0629:                            categories[4].add(asset);
0630:                        } else {
0631:                            categories[0].add(asset);
0632:                        }
0633:                        break;
0634:                    case '1': // outsized
0635:                        if (ccc.charAt(0) == 'R') {
0636:                            categories[5].add(asset);
0637:                        } else {
0638:                            categories[1].add(asset);
0639:                        }
0640:                        break;
0641:                    case '2': // oversized
0642:                        if (ccc.charAt(0) == 'R') {
0643:                            categories[6].add(asset);
0644:                        } else {
0645:                            categories[2].add(asset);
0646:                        }
0647:                        break;
0648:                    default: // bulk or unknown
0649:                        if (asset instanceof  Container) {
0650:                            categories[8].add(asset);
0651:                        } else if (ccc.charAt(0) == 'R') {
0652:                            categories[7].add(asset);
0653:                        } else {
0654:                            categories[3].add(asset);
0655:                        }
0656:                        break;
0657:                    }
0658:                }
0659:
0660:                return categories;
0661:            }
0662:
0663:            /** create level 2 task by aggregating the contents of the direct object **/
0664:            protected Task getLowFidelityTask(Task parentTask, Set uniformAssets) {
0665:                Task newTask = null;
0666:
0667:                GLMAsset lowFiAsset = null;
0668:                NewLowFidelityAssetPG lowFiPG = (NewLowFidelityAssetPG) ldmf
0669:                        .createPropertyGroup(LowFidelityAssetPG.class);
0670:                NewMovabilityPG movabilityPG = (NewMovabilityPG) ldmf
0671:                        .createPropertyGroup(MovabilityPG.class);
0672:
0673:                try {
0674:                    NewPhysicalPG newPhysicalPG = PropertyGroupFactory
0675:                            .newPhysicalPG();
0676:                    CargoCatCodeDimensionPG cccd = setDimensions(parentTask,
0677:                            newPhysicalPG, uniformAssets);
0678:                    lowFiPG.setCCCDim(cccd);
0679:
0680:                    lowFiAsset = (GLMAsset) assetHelper.createInstance(
0681:                            getLDMService().getLDM(), "Level2Prototype",
0682:                            "Level2_" + getTransportType(cccd) + "_"
0683:                                    + getNextID());
0684:                    ((NewItemIdentificationPG) lowFiAsset
0685:                            .getItemIdentificationPG())
0686:                            .setNomenclature("Level2Aggregate");
0687:
0688:                    lowFiPG.setOriginalAsset(lowFiAsset); // now subobject can have a pointer back to parent
0689:
0690:                    lowFiAsset.setPhysicalPG(newPhysicalPG);
0691:                    lowFiAsset.addOtherPropertyGroup(lowFiPG);
0692:                    lowFiAsset.setMovabilityPG(movabilityPG);
0693:
0694:                    movabilityPG.setCargoCategoryCode(cccd.getCargoCatCode());
0695:
0696:                    if (!movabilityPG.getCargoCategoryCode().equals(
0697:                            cccd.getCargoCatCode()))
0698:                        logger.error("huh? for asset "
0699:                                + lowFiAsset
0700:                                + " on task "
0701:                                + parentTask.getUID()
0702:                                + " movabilityPG ccc "
0703:                                + lowFiAsset.getMovabilityPG()
0704:                                        .getCargoCategoryCode() + " != "
0705:                                + cccd.getCargoCatCode());
0706:
0707:                } catch (Exception e) {
0708:                    Asset asset = parentTask.getDirectObject();
0709:                    logger.error("problem processing task "
0710:                            + parentTask.getUID() + "'s d.o. asset" + asset, e);
0711:                    return null;
0712:                }
0713:
0714:                if (isDebugEnabled())
0715:                    debug("getLowFidelityTask - created low fi asset "
0716:                            + lowFiAsset.getUID()
0717:                            + " : "
0718:                            + lowFiAsset.getItemIdentificationPG()
0719:                                    .getNomenclature()
0720:                            + " - "
0721:                            + lowFiAsset.getItemIdentificationPG()
0722:                                    .getItemIdentification());
0723:
0724:                newTask = makeTask(parentTask, lowFiAsset,
0725:                        getOriginalOwner(parentTask));
0726:
0727:                // mark the new task as an aggregate low fi task
0728:                prepHelper.addPrepToTask(newTask, prepHelper
0729:                        .makePrepositionalPhrase(ldmf,
0730:                                GLMTransConst.LOW_FIDELITY,
0731:                                GLMTransConst.LOW_FIDELITY));
0732:
0733:                return newTask;
0734:            }
0735:
0736:            /** return a human-readable string to indicate transport type */
0737:            protected String getTransportType(CargoCatCodeDimensionPG cccd) {
0738:                String ccc = cccd.getCargoCatCode();
0739:                String suffix = (ccc.charAt(0) == 'R') ? "_Roadable" : "";
0740:
0741:                switch (ccc.charAt(1)) {
0742:                case '0': // non-air
0743:                    return "Non-air Transport" + suffix;
0744:                case '1': // outsized
0745:                    return "Outsized" + suffix;
0746:                case '2': // oversized
0747:                    return "Oversized" + suffix;
0748:                default: // bulk or unknown
0749:                    if (cccd.getIsContainer()) {
0750:                        return "Container" + suffix;
0751:                    } else {
0752:                        return "Bulk" + suffix;
0753:                    }
0754:                }
0755:            }
0756:
0757:            /** 
0758:             * Recovers owner of task's d.o. from either a FOR prep on the task
0759:             * or the owner part of UID of the d.o.
0760:             * @param parentTask task to examine
0761:             * @return owner of the task = which unit sent the task, owns the asset
0762:             */
0763:            protected String getOriginalOwner(Task parentTask) {
0764:                if (!glmPrepHelper.hasPrepNamed(parentTask,
0765:                        Constants.Preposition.FOR)) {
0766:                    Asset directObject = parentTask.getDirectObject();
0767:                    String owner = directObject.getUID().getOwner();
0768:
0769:                    if (isInfoEnabled()) {
0770:                        info(".getOriginalOwner - WARNING : got task "
0771:                                + parentTask.getUID()
0772:                                + " which has no FOR unit prep, using owner - "
0773:                                + owner + ".");
0774:                    }
0775:
0776:                    return owner;
0777:                } else
0778:                    return (String) glmPrepHelper.getIndirectObject(parentTask,
0779:                            Constants.Preposition.FOR);
0780:            }
0781:
0782:            /** 
0783:             * Since FOR preps are lost a custom property is added to determine unit
0784:             *
0785:             * @param asset to attach PG to
0786:             * @param thisPG pg to attach to asset
0787:             */
0788:            public void attachPG(Asset asset, PropertyGroup this PG) {
0789:                if (asset instanceof  AssetGroup) {
0790:                    Vector assetList = ((AssetGroup) asset).getAssets();
0791:                    for (int i = 0; i < assetList.size(); i++) {
0792:                        attachPG((Asset) assetList.elementAt(i), this PG);
0793:                    }
0794:                } else if (asset instanceof  AggregateAsset) {
0795:                    // Put in both because unsure of behavior
0796:                    asset.addOtherPropertyGroup(this PG);
0797:                    // Don't want to do this, since every aggregate of X
0798:                    //XX asset will then have this pg
0799:                    //	    attachUnitPG(((AggregateAsset)asset).getAsset(),unitPG);
0800:                } else {
0801:                    asset.addOtherPropertyGroup(this PG);
0802:                }
0803:            }
0804:
0805:            /** 
0806:             * <pre>
0807:             * Tries to determine if direct object is a person aggregate.
0808:             * 
0809:             * Can be tricky since sometimes the d.o. is a group of aggregates.
0810:             * </pre>
0811:             */
0812:            protected boolean isPersonTask(Task parentTask) {
0813:                Asset asset = parentTask.getDirectObject();
0814:                if (asset instanceof  AggregateAsset) {
0815:                    GLMAsset itemProto = (GLMAsset) ((AggregateAsset) asset)
0816:                            .getAsset();
0817:                    return itemProto.hasPersonPG();
0818:                }
0819:                // if aggregate assets of people are inside of an asset group
0820:                // it's a person...
0821:                else if (asset instanceof  AssetGroup) {
0822:                    AssetGroup group = (AssetGroup) asset;
0823:                    Vector assetList = group.getAssets();
0824:                    for (int i = 0; i < assetList.size(); i++) {
0825:                        Asset subasset = (Asset) assetList.elementAt(i);
0826:                        if (subasset instanceof  AggregateAsset) {
0827:                            GLMAsset itemProto = (GLMAsset) ((AggregateAsset) subasset)
0828:                                    .getAsset();
0829:                            return itemProto.hasPersonPG();
0830:                        } else
0831:                            return false;
0832:                    }
0833:                }
0834:                return false;
0835:            }
0836:
0837:            protected int id = 0;
0838:
0839:            protected int getNextID() {
0840:                return id++;
0841:            }
0842:
0843:            /**
0844:             * <pre>
0845:             * Takes a collection of assets and sets the dimensions of the physical pg
0846:             * to be their sum, in area, volume, and weight.
0847:             *
0848:             * It doesn't make sense to aggregate length, width, and height, since they
0849:             * wouldn't correspond to area and volume.
0850:             * </pre>
0851:             * @param realAssets to sum
0852:             * @param physicalPG to set with their aggregate dimensions
0853:             **/
0854:            protected CargoCatCodeDimensionPG setDimensions(Task parentTask,
0855:                    NewPhysicalPG physicalPG, Collection realAssets) {
0856:                double area = 0.0;
0857:                double volume = 0.0;
0858:                double mass = 0.0;
0859:
0860:                Object firstItem = realAssets.iterator().next();
0861:
0862:                PhysicalPG cccdPhysicalPG = (PhysicalPG) ldmf
0863:                        .createPropertyGroup(PhysicalPG.class);
0864:                NewCargoCatCodeDimensionPG cccdPG = (NewCargoCatCodeDimensionPG) ldmf
0865:                        .createPropertyGroup(CargoCatCodeDimensionPG.class);
0866:                cccdPG.setDimensions(cccdPhysicalPG);
0867:
0868:                if (firstItem instanceof  AggregateAsset) { // there is only one item...
0869:                    if (realAssets.size() > 1)
0870:                        logger
0871:                                .error(getAgentIdentifier()
0872:                                        + " found aggregate, but skipping some expanded items???");
0873:
0874:                    AggregateAsset aggAsset = (AggregateAsset) firstItem;
0875:                    GLMAsset baseAsset = (GLMAsset) aggAsset.getAsset();
0876:                    PhysicalPG itemPhysicalPG = baseAsset.getPhysicalPG();
0877:                    String ccc = getCategory(baseAsset);
0878:
0879:                    if (itemPhysicalPG == null) {
0880:                        if (!baseAsset.hasPersonPG()) {
0881:                            warn(".setDimensions - for task "
0882:                                    + parentTask.getUID() + " asset "
0883:                                    + firstItem + "'s base asset "
0884:                                    + (GLMAsset) aggAsset.getAsset()
0885:                                    + " has no physical PG.");
0886:                        } else if (isDebugEnabled()) {
0887:                            debug(".setDimensions - NOTE : asset " + firstItem
0888:                                    + "'s base asset "
0889:                                    + (GLMAsset) aggAsset.getAsset()
0890:                                    + " has no physical PG.");
0891:                        }
0892:                    } else {
0893:                        long quantity = aggAsset.getQuantity();
0894:                        double q = (double) quantity;
0895:
0896:                        // it doesn't make sense to display aggregate length, width, height,
0897:                        // since they won't correspond to area and volume
0898:                        area = itemPhysicalPG.getFootprintArea()
0899:                                .getSquareMeters()
0900:                                * q;
0901:                        volume = itemPhysicalPG.getVolume().getCubicMeters()
0902:                                * q;
0903:                        mass = itemPhysicalPG.getMass().getKilograms() * q;
0904:
0905:                        if (area == 0.0d) {
0906:                            area = itemPhysicalPG.getLength().getMeters()
0907:                                    * itemPhysicalPG.getWidth().getMeters() * q;
0908:                            if (isInfoEnabled()) {
0909:                                info(".setDimensions - fixing footprint area, was zero for asset "
0910:                                        + aggAsset
0911:                                        + " on task "
0912:                                        + parentTask.getUID());
0913:                            }
0914:                        }
0915:                        if (area == 0.0d || volume == 0.0d || mass == 0.0d) {
0916:                            if (isWarnEnabled()) {
0917:                                warn(".setDimensions - asset " + firstItem
0918:                                        + " for task " + parentTask.getUID()
0919:                                        + " has a zero dimension.");
0920:                            }
0921:                        }
0922:
0923:                        addToDimension(ccc, q, itemPhysicalPG, cccdPG);
0924:
0925:                        if (baseAsset instanceof  Container)
0926:                            cccdPG.setIsContainer(true);
0927:                        cccdPG.setAssetClass(getAssetClass(baseAsset));
0928:                    }
0929:                } else {
0930:                    Object last = null;
0931:                    for (Iterator iter = realAssets.iterator(); iter.hasNext();) {
0932:                        GLMAsset asset = (GLMAsset) iter.next();
0933:                        last = asset;
0934:                        PhysicalPG itemPhysicalPG = asset.getPhysicalPG();
0935:                        String ccc = getCategory(asset);
0936:
0937:                        if (itemPhysicalPG == null)
0938:                            error("Asset " + asset
0939:                                    + " doesn't have a physical PG.");
0940:                        else {
0941:                            // it doesn't make sense to display aggregate length, width, height,
0942:                            // since they won't correspond to area and volume
0943:                            double itemArea = itemPhysicalPG.getFootprintArea()
0944:                                    .getSquareMeters();
0945:                            double itemVolume = itemPhysicalPG.getVolume()
0946:                                    .getCubicMeters();
0947:                            double itemMass = itemPhysicalPG.getMass()
0948:                                    .getKilograms();
0949:
0950:                            if (itemArea < 0.01d) {
0951:                                itemArea = itemPhysicalPG.getLength()
0952:                                        .getMeters()
0953:                                        * itemPhysicalPG.getWidth().getMeters();
0954:                                if (isInfoEnabled()) {
0955:                                    info(".setDimensions - fixing footprint area, was zero for asset "
0956:                                            + asset
0957:                                            + " on task "
0958:                                            + parentTask.getUID());
0959:                                }
0960:                            }
0961:
0962:                            area += itemArea;
0963:                            volume += itemVolume;
0964:                            mass += itemMass;
0965:
0966:                            if (itemArea == 0.0d || itemVolume == 0.0d
0967:                                    || itemMass == 0.0d) {
0968:                                if (isWarnEnabled()) {
0969:                                    warn(".setDimensions - asset " + asset
0970:                                            + " for task "
0971:                                            + parentTask.getUID()
0972:                                            + " has a zero dimension.");
0973:                                }
0974:                            }
0975:
0976:                            addToDimension(ccc, 1.0, itemPhysicalPG, cccdPG);
0977:                        }
0978:                    }
0979:                    if (last instanceof  Container)
0980:                        cccdPG.setIsContainer(true);
0981:                    cccdPG.setAssetClass(getAssetClass((Asset) last));
0982:                }
0983:
0984:                physicalPG.setMass(new Mass(mass, Mass.KILOGRAMS));
0985:                physicalPG.setFootprintArea(new Area(area, Area.SQUARE_METERS));
0986:                physicalPG.setVolume(new Volume(volume, Volume.CUBIC_METERS));
0987:
0988:                if (isDebugEnabled()) {
0989:                    debug(".setDimensions got " + realAssets.size() + " items.");
0990:                    debug(".setDimensions low fi dimensions : " + " m "
0991:                            + physicalPG.getMass() + " a "
0992:                            + physicalPG.getFootprintArea() + " v "
0993:                            + physicalPG.getVolume());
0994:                }
0995:
0996:                return cccdPG;
0997:            }
0998:
0999:            protected String getCategory(GLMAsset asset) {
1000:                MovabilityPG movabilityPG = asset.getMovabilityPG();
1001:
1002:                String ccc;
1003:
1004:                if (movabilityPG == null) {
1005:                    ccc = "XXX";
1006:                    logger
1007:                            .warn(getAgentIdentifier()
1008:                                    + " "
1009:                                    + asset
1010:                                    + " was missing a movability PG, so could not determine cargo cat code.");
1011:                } else {
1012:                    ccc = movabilityPG.getCargoCategoryCode();
1013:                    if (logger.isDebugEnabled())
1014:                        logger.debug(asset.toString() + " ccc was " + ccc);
1015:                }
1016:
1017:                return ccc;
1018:            }
1019:
1020:            protected void addToDimension(String ccc, double quantity,
1021:                    PhysicalPG itemPhysicalPG, CargoCatCodeDimensionPG cccdPG) {
1022:                NewPhysicalPG whichPG = (NewPhysicalPG) cccdPG.getDimensions();
1023:                NewCargoCatCodeDimensionPG whichCCCDimPG = (NewCargoCatCodeDimensionPG) cccdPG;
1024:
1025:                if (whichPG == null) {
1026:                    logger.error("Could not set physical PG?");
1027:                }
1028:
1029:                String pgCCCString = whichCCCDimPG.getCargoCatCode();
1030:
1031:                if (pgCCCString == null) { // we've never set the cargo cat code
1032:                    whichCCCDimPG.setCargoCatCode(ccc);
1033:                } else if (!pgCCCString.equals(ccc)) {
1034:                    char[] pgCCC = pgCCCString.toCharArray();
1035:                    char[] newCCC = new char[3];
1036:                    char[] cccArray = ccc.toCharArray();
1037:
1038:                    if (isDebugEnabled())
1039:                        debug(".addToDimension old " + new String(pgCCC)
1040:                                + " additional ccc " + ccc);
1041:
1042:                    if (cccArray[0] != pgCCC[0]) {
1043:                        newCCC[0] = 'X';
1044:                    } else {
1045:                        newCCC[0] = pgCCC[0];
1046:                    }
1047:
1048:                    if (cccArray[1] != pgCCC[1]) {
1049:                        newCCC[1] = 'X';
1050:                    } else {
1051:                        newCCC[1] = pgCCC[1];
1052:                    }
1053:
1054:                    if (cccArray[2] != pgCCC[2]) {
1055:                        newCCC[2] = 'X';
1056:                    } else {
1057:                        newCCC[2] = pgCCC[2];
1058:                    }
1059:
1060:                    whichCCCDimPG.setCargoCatCode(new String(newCCC));
1061:                }
1062:
1063:                double area = 0.0d;
1064:                double volume = 0.0d;
1065:                double mass = 0.0d;
1066:
1067:                if (whichPG.getFootprintArea() != null) {
1068:                    area = whichPG.getFootprintArea().getSquareMeters();
1069:                    /*
1070:                    if (area < 0.01d) {
1071:                    area = whichPG.getLength().getMeters() * whichPG.getWidth().getMeters();
1072:                    if (isInfoEnabled ()) {
1073:                    info (".addToDimensions - fixing footprint area, was zero for asset");
1074:                    }
1075:                    }
1076:                     */
1077:                    volume = whichPG.getVolume().getCubicMeters();
1078:                    mass = whichPG.getMass().getKilograms();
1079:                }
1080:
1081:                whichPG.setFootprintArea(new Area(area
1082:                        + itemPhysicalPG.getFootprintArea().getSquareMeters()
1083:                        * quantity, Area.SQUARE_METERS));
1084:                whichPG.setVolume(new Volume(volume
1085:                        + itemPhysicalPG.getVolume().getCubicMeters()
1086:                        * quantity, Volume.CUBIC_METERS));
1087:                whichPG.setMass(new Mass(mass
1088:                        + itemPhysicalPG.getMass().getKilograms() * quantity,
1089:                        Mass.KILOGRAMS));
1090:
1091:                if (isDebugEnabled())
1092:                    debug(".addToDimension final dim for " + ccc + " - "
1093:                            + whichPG.getFootprintArea().getSquareMeters()
1094:                            + " m^2" + whichPG.getVolume().getCubicMeters()
1095:                            + " m^3 " + whichPG.getMass().getShortTons()
1096:                            + " short tons.");
1097:            }
1098:
1099:            private int getAssetClass(Asset a) {
1100:                int value = (a instanceof  ClassISubsistence) ? ASSET_CLASS_1
1101:                        : (a instanceof  ClassIIClothingAndEquipment) ? ASSET_CLASS_2
1102:                                : (a instanceof  ClassIIIPOL) ? ASSET_CLASS_3
1103:                                        : (a instanceof  ClassIVConstructionMaterial) ? ASSET_CLASS_4
1104:                                                : (a instanceof  ClassVAmmunition) ? ASSET_CLASS_5
1105:                                                        : (a instanceof  ClassVIPersonalDemandItem) ? ASSET_CLASS_6
1106:                                                                : (a instanceof  ClassVIIMajorEndItem) ? ASSET_CLASS_7
1107:                                                                        : (a instanceof  ClassVIIIMedical) ? ASSET_CLASS_8
1108:                                                                                : (a instanceof  ClassIXRepairPart) ? ASSET_CLASS_9
1109:                                                                                        : (a instanceof  ClassXNonMilitaryItem) ? ASSET_CLASS_10
1110:                                                                                                : ((a instanceof  Container) || (a instanceof  org.cougaar.glm.ldm.asset.Package)// ||
1111:                                                                                                //       (glmAssetHelper.isPallet(a))) ?
1112:                                                                                                ) ? ASSET_CLASS_CONTAINER
1113:                                                                                                        : ((a instanceof  Person) || ((a instanceof  GLMAsset) && (((GLMAsset) a)
1114:                                                                                                                .hasPersonPG()))) ? ASSET_CLASS_PERSON
1115:                                                                                                                : ASSET_CLASS_UNKNOWN;
1116:
1117:                return value;
1118:            }
1119:
1120:            /** 
1121:             * Makes subtask of parent task, with given direct object.
1122:             *
1123:             * removes OFTYPE prep, since it's not needed by scheduler 
1124:             **/
1125:            protected Task makeTask(Task parentTask, Asset directObject,
1126:                    String originalOwner) {
1127:                if (isDebugEnabled())
1128:                    debug(".makeTask - making subtask of "
1129:                            + parentTask.getUID() + " d.o. " + directObject);
1130:
1131:                Task newtask = expandHelper.makeSubTask(ldmf, parentTask,
1132:                        directObject, getAgentIdentifier());
1133:                ((NewTask) newtask).setContext(parentTask.getContext());
1134:                glmPrepHelper.removePrepNamed(newtask,
1135:                        Constants.Preposition.OFTYPE);
1136:
1137:                // Next four lines create a Property Group for unit and attach it to all assets attached to task
1138:                ForUnitPG unitPG = (ForUnitPG) ldmf
1139:                        .createPropertyGroup(ForUnitPG.class);
1140:                if (!glmPrepHelper.hasPrepNamed(newtask,
1141:                        Constants.Preposition.FOR)) {
1142:                    String owner = (originalOwner != null) ? originalOwner
1143:                            : directObject.getUID().getOwner();
1144:
1145:                    if (isInfoEnabled()) {
1146:                        info(".getSubtasks - NOTE : got task "
1147:                                + parentTask.getUID()
1148:                                + " which has no FOR unit prep, using owner - "
1149:                                + owner + ".");
1150:                    }
1151:
1152:                    ((NewForUnitPG) unitPG).setUnit(owner);
1153:                } else {
1154:                    ((NewForUnitPG) unitPG).setUnit((String) glmPrepHelper
1155:                            .getIndirectObject(newtask,
1156:                                    Constants.Preposition.FOR));
1157:                    glmPrepHelper.removePrepNamed(newtask,
1158:                            Constants.Preposition.FOR);
1159:                }
1160:
1161:                attachPG(directObject, unitPG);
1162:
1163:                // glmtrans doesn't deal with quantity -- only get success or failure
1164:                if (prefHelper.hasPrefWithAspectType(newtask,
1165:                        AspectType.QUANTITY))
1166:                    prefHelper.removePrefWithAspectType(newtask,
1167:                            AspectType.QUANTITY);
1168:
1169:                attachRoute(parentTask, newtask);
1170:
1171:                return newtask;
1172:            }
1173:
1174:            /** 
1175:             * <pre>
1176:             * Attaches two preps to task : SEAROUTE and SEAROUTE_DISTANCE 
1177:             *
1178:             * SEAROUTE will appear in the TPFDD Viewer as the path of the ship, if the 
1179:             * item goes by ship.  SEAROUTE_DISTANCE is used by the TRANSCOM vishnu scheduler
1180:             * to make the sea-vs-air decision.  (Specifically, it decides if at a reasonable
1181:             * ship speed (~15 knots), the task could be completed in the time allowed by ship,
1182:             * and if so, decides to send the item by ship.)
1183:             * </pre>
1184:             * @param parentTask - used to calculate the route (using the from-to pair)
1185:             * @param subtask - task to attach the preps to
1186:             */
1187:            protected void attachRoute(Task parentTask, Task subtask) {
1188:                TransportationRoute route = portLocator.getRoute(parentTask);
1189:
1190:                glmPrepHelper.addPrepToTask(subtask, glmPrepHelper
1191:                        .makePrepositionalPhrase(ldmf, GLMTransConst.SEAROUTE,
1192:                                route));
1193:                Distance distance = route.getLength();
1194:                glmPrepHelper.addPrepToTask(subtask, glmPrepHelper
1195:                        .makePrepositionalPhrase(ldmf,
1196:                                GLMTransConst.SEAROUTE_DISTANCE, distance));
1197:            }
1198:
1199:            /**
1200:             * <pre>
1201:             * Function that breaks up a AssetGroup or AggregateAsset into smaller pieces.
1202:             * Return values should only by Assets and small AggregateAssets (derived classes
1203:             * must determine how big is OK.  By default all Aggregate are broken up).
1204:             *
1205:             * If myExpandAggregates is true, expands both aggregate assets and asset groups.
1206:             * If it's false, only expands asset groups.
1207:             *
1208:             * </pre>
1209:             * @param asset
1210:             * @return A vector of assets that this asset has been broken into.
1211:             **/
1212:            public Vector expandAsset(Task task, Asset asset) {
1213:                if (myExpandAggregates) {
1214:                    if (isDebugEnabled())
1215:                        debug(getName()
1216:                                + ".expandAsset - expanding aggregate asset "
1217:                                + asset);
1218:
1219:                    PlanningFactory ldmf = (PlanningFactory) getDomainService()
1220:                            .getFactory("planning");
1221:                    Vector items = glmAssetHelper.ExpandAsset(ldmf, asset);
1222:                    if (isDebugEnabled())
1223:                        debug(getName() + ".expandAsset - aggregate asset had "
1224:                                + items.size() + " items.");
1225:                    return items;
1226:                } else if (asset instanceof  AssetGroup) {
1227:                    if (isDebugEnabled())
1228:                        debug(getName()
1229:                                + ".expandAsset - expanding asset group "
1230:                                + asset);
1231:                    return glmAssetHelper.expandAssetGroup((AssetGroup) asset);
1232:                } else {
1233:                    if (isDebugEnabled())
1234:                        debug(getName() + ".expandAsset - not expanding "
1235:                                + asset);
1236:                }
1237:
1238:                Vector vector = new Vector();
1239:                vector.add(asset);
1240:
1241:                return vector;
1242:            }
1243:
1244:            /** Buffering runnable wants to restart later */
1245:            public void startAgainIn(long millis) {
1246:                if (isInfoEnabled())
1247:                    info(getName() + " asking to be restarted in " + millis);
1248:
1249:                if (currentAlarm != null)
1250:                    currentAlarm.cancel();
1251:
1252:                alarmService
1253:                        .addAlarm(currentAlarm = new BufferingAlarm(millis));
1254:            }
1255:
1256:            public void setThreadService(ThreadService ts) {
1257:                threadService = ts;
1258:            }
1259:
1260:            /** Alarm for when buffering runnable wants to restart later */
1261:            class BufferingAlarm implements  Alarm {
1262:                long clockExpireTime;
1263:                boolean expired = false;
1264:
1265:                public BufferingAlarm(long ticksToWait) {
1266:                    clockExpireTime = alarmService.currentTimeMillis()
1267:                            + ticksToWait; // based on wall clock time
1268:                }
1269:
1270:                /** @return absolute time (in milliseconds) that the Alarm should
1271:                 * go off.  
1272:                 * This value must be implemented as a fixed value.
1273:                 **/
1274:                public long getExpirationTime() {
1275:                    return clockExpireTime;
1276:                }
1277:
1278:                /** 
1279:                 * Called by the cluster clock when clock-time >= getExpirationTime().
1280:                 * The system will attempt to Expire the Alarm as soon as possible on 
1281:                 * or after the ExpirationTime, but cannot guarantee any specific
1282:                 * maximum latency.
1283:                 * NOTE: this will be called in the thread of the cluster clock.  
1284:                 * Implementations should make certain that this code does not block
1285:                 * for a significant length of time.
1286:                 * If the alarm has been canceled, this should be a no-op.
1287:                 **/
1288:                public synchronized void expire() {
1289:                    if (!expired) {
1290:                        synchronized (alarmMutex) { // getSubtasks will check to see if one exists, so must synchronize
1291:                            currentAlarm = null;
1292:                        }
1293:
1294:                        expired = true;
1295:
1296:                        String name = getName() + "_restartThread";
1297:
1298:                        if (isInfoEnabled())
1299:                            info(getName() + " re-examining unprocessed tasks.");
1300:
1301:                        schedulable = threadService.getThread(this ,
1302:                                new Runnable() {
1303:                                    public void run() {
1304:                                        // review the known task list
1305:                                        try {
1306:                                            blackboard.openTransaction();
1307:                                            reviewLevel2();
1308:                                            processTasks(new ArrayList(
1309:                                                    myInputTaskCallback
1310:                                                            .getSubscription()
1311:                                                            .getCollection()));
1312:                                        } catch (Throwable t) {
1313:                                            //System.err.println("Error: Uncaught exception in "+this+": "+t);
1314:                                            if (logger.isErrorEnabled()) {
1315:                                                logger
1316:                                                        .error("Error: Uncaught exception in "
1317:                                                                + this 
1318:                                                                + ": "
1319:                                                                + t);
1320:                                                t.printStackTrace();
1321:                                            }
1322:                                        } finally {
1323:                                            blackboard.closeTransaction();
1324:                                        }
1325:                                    }
1326:                                }, name);
1327:                        schedulable.start();
1328:                    }
1329:                }
1330:
1331:                /** @return true IFF the alarm has rung (expired) or was canceled. **/
1332:                public boolean hasExpired() {
1333:                    return expired;
1334:                }
1335:
1336:                /** 
1337:                 * Can be called by a client to cancel the alarm.  May or may not remove
1338:                 * the alarm from the queue, but should prevent expire from doing anything.
1339:                 * @return false IF the the alarm has already expired or was already canceled.
1340:                 **/
1341:                public synchronized boolean cancel() {
1342:                    boolean was = expired;
1343:                    expired = true;
1344:                    return was;
1345:                }
1346:
1347:                public String toString() {
1348:                    return "<BufferingAlarm " + clockExpireTime
1349:                            + (expired ? "(Expired) " : " ") + "for "
1350:                            + GLMTransOneToManyExpanderPlugin.this .toString()
1351:                            + ">";
1352:                }
1353:            }
1354:
1355:            public void reviewLevel2() {
1356:                // review the known task list
1357:                replanLevel2(blackboard.query(new UnaryPredicate() {
1358:                    public boolean execute(Object obj) {
1359:                        if (obj instanceof  Task) {
1360:                            Task task = (Task) obj;
1361:                            if (interestingTask(task)) {
1362:                                // if just by looking at the dates it ought to be level 6
1363:                                if (getMode(task) == LEVEL_6_MODE) {
1364:                                    if (task.getPlanElement() != null
1365:                                            && (task.getPlanElement() instanceof  Expansion)) {
1366:                                        Task subtask = (Task) ((Expansion) task
1367:                                                .getPlanElement())
1368:                                                .getWorkflow().getTasks()
1369:                                                .nextElement();
1370:                                        // but it's got low fi children
1371:                                        return (prepHelper.hasPrepNamed(
1372:                                                subtask,
1373:                                                GLMTransConst.LOW_FIDELITY));
1374:                                    } else
1375:                                        return false;
1376:                                } else
1377:                                    return false;
1378:                            } else
1379:                                return false;
1380:                        } else
1381:                            return false;
1382:                    }
1383:                }));
1384:            }
1385:
1386:            /** 
1387:             * Remove the expansions of tasks that were previously expanded
1388:             * into level-2 subtasks.  By removing the expansion and publish
1389:             * changing the task, the task will appear as a "new" task to the 
1390:             * plugin again in the next execute cycle. <p>
1391:             *
1392:             * If the task somehow got it's plan element removed by the time this
1393:             * is called, just skip it.  Somehow a logic provider seems to be able
1394:             * to remove the task's expansion during my transaction. <p>
1395:             * 
1396:             * @param level2Tasks tasks that were previously expanded into level 2
1397:             *        that we want to replan.  
1398:             */
1399:            protected void replanLevel2(Collection level2Tasks) {
1400:                for (Iterator iter = level2Tasks.iterator(); iter.hasNext();) {
1401:                    NewTask level2 = (NewTask) iter.next();
1402:
1403:                    PlanElement pe = level2.getPlanElement();
1404:                    if (pe == null) {
1405:                        if (isInfoEnabled())
1406:                            info("Somehow between calling the predicate and trying\n"
1407:                                    + " to remove task "
1408:                                    + level2.getUID()
1409:                                    + "'s plan element\n"
1410:                                    + " the plan element got removed by another Logic Provider.");
1411:                        continue; // nothing to do
1412:                    }
1413:
1414:                    publishRemove(pe);
1415:                    publishChange(level2);
1416:
1417:                    // replan the task
1418:
1419:                    if (isInfoEnabled())
1420:                        info(getName() + ".reviewLevel2 - replanning task "
1421:                                + level2.getUID() + " as a Level 6 task.");
1422:                }
1423:            }
1424:
1425:            /** 
1426:             * <pre>
1427:             * NOTE : This is called magically by reflection from BindingUtility.setServices 
1428:             * setServices looks for any method in a component that starts with "set" and 
1429:             * tries to find a service X.  
1430:             *
1431:             * More specifically, it's looking for a method signature like:
1432:             *   setXService (XService s)
1433:             *
1434:             * </pre>
1435:             * @see org.cougaar.core.component.BindingUtility#setServices
1436:             */
1437:            public void setDomainService(DomainService ds) {
1438:                theDomainService = ds;
1439:            }
1440:
1441:            public final DomainService getDomainService() {
1442:                return theDomainService;
1443:            }
1444:
1445:            //Domain service (factory service piece of old LDM)
1446:            private DomainService theDomainService = null;
1447:
1448:            /** implemented for BlackboardPlugin interface -- need public access! */
1449:            public BlackboardService getBlackboard() {
1450:                return blackboard;
1451:            }
1452:
1453:            // Utility functions ----------------------------------------------------
1454:
1455:            private void reportError(String err) {
1456:                error(getName() + " : " + err);
1457:            }
1458:
1459:            protected boolean myExpandAggregates;
1460:            protected GLMPrepPhrase glmPrepHelper;
1461:            protected GLMPreference glmPrefHelper;
1462:            protected AssetUtil glmAssetHelper;
1463:            protected PortLocatorImpl portLocator;
1464:            protected Alarm currentAlarm;
1465:            protected Schedulable schedulable;
1466:            protected Object alarmMutex = new Object();
1467:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.