Source Code Cross Referenced for NormalTask.java in  » Project-Management » OpenProj » com » projity » pm » task » 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 » Project Management » OpenProj » com.projity.pm.task 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:        The contents of this file are subject to the Common Public Attribution License 
0003:        Version 1.0 (the "License"); you may not use this file except in compliance with 
0004:        the License. You may obtain a copy of the License at 
0005:        http://www.projity.com/license . The License is based on the Mozilla Public 
0006:        License Version 1.1 but Sections 14 and 15 have been added to cover use of 
0007:        software over a computer network and provide for limited attribution for the 
0008:        Original Developer. In addition, Exhibit A has been modified to be consistent 
0009:        with Exhibit B.
0010:
0011:        Software distributed under the License is distributed on an "AS IS" basis, 
0012:        WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
0013:        specific language governing rights and limitations under the License. The 
0014:        Original Code is OpenProj. The Original Developer is the Initial Developer and 
0015:        is Projity, Inc. All portions of the code written by Projity are Copyright (c) 
0016:        2006, 2007. All Rights Reserved. Contributors Projity, Inc.
0017:
0018:        Alternatively, the contents of this file may be used under the terms of the 
0019:        Projity End-User License Agreeement (the Projity License), in which case the 
0020:        provisions of the Projity License are applicable instead of those above. If you 
0021:        wish to allow use of your version of this file only under the terms of the 
0022:        Projity License and not to allow others to use your version of this file under 
0023:        the CPAL, indicate your decision by deleting the provisions above and replace 
0024:        them with the notice and other provisions required by the Projity  License. If 
0025:        you do not delete the provisions above, a recipient may use your version of this 
0026:        file under either the CPAL or the Projity License.
0027:
0028:        [NOTE: The text of this license may differ slightly from the text of the notices 
0029:        in Exhibits A and B of the license at http://www.projity.com/license. You should 
0030:        use the latest text at http://www.projity.com/license for your modifications.
0031:        You may not remove this license text from the source files.]
0032:
0033:        Attribution Information: Attribution Copyright Notice: Copyright � 2006, 2007 
0034:        Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj, 
0035:        an open source solution from Projity. Attribution URL: http://www.projity.com 
0036:        Graphic Image as provided in the Covered Code as file:  openproj_logo.png with 
0037:        alternatives listed on http://www.projity.com/logo
0038:
0039:        Display of Attribution Information is required in Larger Works which are defined 
0040:        in the CPAL as a work which combines Covered Code or portions thereof with code 
0041:        not governed by the terms of the CPAL. However, in addition to the other notice 
0042:        obligations, all copies of the Covered Code in Executable and Source Code form 
0043:        distributed must, as a form of attribution of the original author, include on 
0044:        each user interface screen the "OpenProj" logo visible to all users.  The 
0045:        OpenProj logo should be located horizontally aligned with the menu bar and left 
0046:        justified on the top left of the screen adjacent to the File menu.  The logo 
0047:        must be at least 100 x 25 pixels.  When users click on the "OpenProj" logo it 
0048:        must direct them back to http://www.projity.com.  
0049:         */
0050:        package com.projity.pm.task;
0051:
0052:        import java.io.IOException;
0053:        import java.io.ObjectInputStream;
0054:        import java.io.ObjectOutputStream;
0055:        import java.util.Collection;
0056:        import java.util.Iterator;
0057:        import java.util.LinkedList;
0058:
0059:        import org.apache.commons.collections.Closure;
0060:
0061:        import com.projity.algorithm.ReverseQuery;
0062:        import com.projity.algorithm.TimeIteratorGenerator;
0063:        import com.projity.algorithm.buffer.CalculatedValues;
0064:        import com.projity.association.AssociationFormatParameters;
0065:        import com.projity.association.AssociationList;
0066:        import com.projity.association.AssociationListFormat;
0067:        import com.projity.configuration.Configuration;
0068:        import com.projity.configuration.Settings;
0069:        import com.projity.datatype.Duration;
0070:        import com.projity.datatype.ImageLink;
0071:        import com.projity.datatype.TimeUnit;
0072:        import com.projity.document.Document;
0073:        import com.projity.field.CustomFieldsImpl;
0074:        import com.projity.field.FieldContext;
0075:        import com.projity.field.FieldParseException;
0076:        import com.projity.functor.IntervalConsumer;
0077:        import com.projity.functor.NumberClosure;
0078:        import com.projity.functor.ObjectVisitor;
0079:        import com.projity.graphic.configuration.HasIndicators;
0080:        import com.projity.graphic.configuration.HasTaskIndicators;
0081:        import com.projity.grouping.core.Node;
0082:        import com.projity.grouping.core.model.NodeModel;
0083:        import com.projity.grouping.core.summaries.DeepChildWalker;
0084:        import com.projity.options.CalculationOption;
0085:        import com.projity.options.CalendarOption;
0086:        import com.projity.options.ScheduleOption;
0087:        import com.projity.pm.assignment.Allocation;
0088:        import com.projity.pm.assignment.Assignment;
0089:        import com.projity.pm.assignment.AssignmentFormat;
0090:        import com.projity.pm.assignment.AssignmentService;
0091:        import com.projity.pm.assignment.HasAssignments;
0092:        import com.projity.pm.assignment.TimeDistributedFields;
0093:        import com.projity.pm.assignment.timesheet.TimesheetHelper;
0094:        import com.projity.pm.calendar.CalendarService;
0095:        import com.projity.pm.calendar.WorkCalendar;
0096:        import com.projity.pm.costing.Accrual;
0097:        import com.projity.pm.costing.EarnedValueCalculator;
0098:        import com.projity.pm.costing.EarnedValueFields;
0099:        import com.projity.pm.costing.EarnedValueValues;
0100:        import com.projity.pm.criticalpath.TaskSchedule;
0101:        import com.projity.pm.key.HasKeyImpl;
0102:        import com.projity.pm.resource.Resource;
0103:        import com.projity.pm.resource.ResourceImpl;
0104:        import com.projity.pm.scheduling.BarClosure;
0105:        import com.projity.pm.scheduling.ConstraintType;
0106:        import com.projity.pm.scheduling.Schedule;
0107:        import com.projity.pm.scheduling.ScheduleEvent;
0108:        import com.projity.pm.scheduling.ScheduleInterval;
0109:        import com.projity.pm.scheduling.ScheduleUtil;
0110:        import com.projity.pm.scheduling.SchedulingFields;
0111:        import com.projity.pm.scheduling.SchedulingRule;
0112:        import com.projity.pm.scheduling.SchedulingType;
0113:        import com.projity.pm.snapshot.BaselineScheduleFields;
0114:        import com.projity.pm.snapshot.DataSnapshot;
0115:        import com.projity.pm.snapshot.SnapshottableImpl;
0116:        import com.projity.strings.Messages;
0117:        import com.projity.util.DateTime;
0118:
0119:        /**
0120:         * @stereotype thing
0121:         */
0122:        public class NormalTask extends Task implements  Allocation,
0123:                TaskSpecificFields, SchedulingFields, HasAssignments,
0124:                EarnedValueValues, EarnedValueFields, TimeDistributedFields,
0125:                BaselineScheduleFields, HasTaskIndicators {
0126:            static final long serialVersionUID = 273898992929L;
0127:
0128:            //	Schedule schedule = null;
0129:
0130:            boolean estimated = true;
0131:            int priority = 500;
0132:
0133:            public NormalTask(Project project) {
0134:                this (project.isLocal(), project);
0135:            }
0136:
0137:            public NormalTask(boolean local, Project project) {
0138:                super (local);
0139:                this .project = project;
0140:                initializeDates();
0141:                addDefaultAssignment();
0142:
0143:            }
0144:
0145:            public NormalTask() {
0146:                super ();
0147:            }
0148:
0149:            /**
0150:             * Used when creating a task to set initial date and duration conditions
0151:             *  
0152:             */
0153:            void initializeDates() {
0154:                setRawConstraintType(project == null ? ConstraintType.ASAP
0155:                        : project.getDefaultConstraintType());
0156:                long duration = CalendarOption.getInstance()
0157:                        .getDefaultDuration(); //MS uses 1 day estimated
0158:                setRawDuration(duration);
0159:                setWorkCalendar(null);
0160:
0161:                // initialize start and end to avoid 0 dates in calculations
0162:                long start = project.getStart();
0163:                currentSchedule.setStart(start);
0164:                currentSchedule.setFinish(start);
0165:
0166:                if (ScheduleOption.getInstance().isNewTasksStartToday())
0167:                    setWindowEarlyStart(CalendarOption.getInstance()
0168:                            .makeValidStart(DateTime.midnightToday(), true));
0169:            }
0170:
0171:            /**
0172:             * This constructor is used to create dummy tasks, such as the UNASSIGNED
0173:             * instance. We do not want to perform standard initialization on it.
0174:             * 
0175:             * @param dummy
0176:             */
0177:            private NormalTask(boolean dummy) {
0178:                super (true);
0179:            }
0180:
0181:            private static NormalTask UNASSIGNED = null;
0182:
0183:            public static NormalTask getUnassignedInstance() {
0184:                if (UNASSIGNED == null) {
0185:                    UNASSIGNED = new NormalTask(true);
0186:                    UNASSIGNED.setName(Messages.getString("Text.Unassigned"));
0187:                }
0188:                return UNASSIGNED;
0189:            }
0190:
0191:            private Assignment newDefaultAssignment() {
0192:                return Assignment.getInstance(this , ResourceImpl
0193:                        .getUnassignedInstance(), 1.0, 0);
0194:            }
0195:
0196:            public boolean isNormal() {
0197:                return !isSummary() && !isMilestone() && !isExternal();
0198:            }
0199:
0200:            public boolean isCritical() {
0201:                if (currentSchedule.isForward())
0202:                    return getEarlyFinish() >= getLateFinish(); //TODO hook into preference
0203:                else
0204:                    // reverse schedule
0205:                    return getLateStart() <= getEarlyStart();
0206:            }
0207:
0208:            public boolean isMilestone() {
0209:                //	return !hasDuration();
0210:                return Duration.millis(getRawDuration()) == 0
0211:                        || isMarkTaskAsMilestone();
0212:            }
0213:
0214:            /****************************************************************************************
0215:             * Schedule
0216:             ****************************************************************************************/
0217:            /**
0218:             * @return
0219:             */
0220:            public long getDuration() {
0221:                long duration;
0222:                if (isWbsParent() || isExternal() || isSubproject()) {
0223:                    duration = getRawDuration();
0224:                } else {
0225:                    AssociationList assignments = getAssignments();
0226:                    if (assignments.size() == 1) {
0227:                        duration = ((Assignment) assignments.getFirst())
0228:                                .getDurationMillis();
0229:                    } else {
0230:                        Iterator i = assignments.iterator();
0231:                        long end = 0;
0232:                        // get the latest ending assignment
0233:                        while (i.hasNext()) {
0234:                            end = Math.max(end, ((Assignment) i.next())
0235:                                    .getEnd());
0236:                        }
0237:                        // duration is calendar time between assignment end and task start
0238:                        duration = getEffectiveWorkCalendar().compare(end,
0239:                                getStart(), false);
0240:                    }
0241:                }
0242:                duration = Duration.setAsEstimated(duration, estimated);
0243:                return duration;
0244:
0245:                //		return calcActiveAssignmentDuration(getEffectiveWorkCalendar());
0246:            }
0247:
0248:            /** Quickly check to see if a task has a duration without actually calculating it
0249:             * 
0250:             * @return true if duration > 0
0251:             */
0252:            public boolean hasDuration() {
0253:                if (isWbsParent()) {
0254:                    return getRawDuration() != 0;
0255:                } else {
0256:                    AssociationList assignments = getAssignments();
0257:                    if (assignments.size() == 1)
0258:                        return ((Assignment) assignments.getFirst())
0259:                                .hasDuration();
0260:                    Iterator i = assignments.iterator();
0261:                    while (i.hasNext()) {
0262:                        if (((Assignment) i.next()).hasDuration())
0263:                            return true;
0264:                    }
0265:                }
0266:                return false;
0267:
0268:            }
0269:
0270:            /**
0271:             * @param duration
0272:             */
0273:            public void setDuration(long duration) {
0274:                setRawDuration(duration); // set the schedule duration, primariy for use when reading a file
0275:                estimated = Duration.isEstimated(duration);
0276:                duration = Duration.millis(duration);
0277:                long actualDurationMillis = Duration
0278:                        .millis(getActualDuration());
0279:                if (duration < actualDurationMillis) // if reducing duration to shorter than the current actual duration
0280:                    setPercentComplete(1);
0281:                if (!isWbsParent()) {
0282:                    long remainingDuration = duration - actualDurationMillis;
0283:                    getSchedulingRule().adjustRemainingDuration(this ,
0284:                            remainingDuration, true);
0285:                }
0286:                updateCachedDuration();
0287:            }
0288:
0289:            /********************************************************************************
0290:             * Calendars
0291:             ***********************************************************************************/
0292:
0293:            private WorkCalendar workCalendar = null;
0294:
0295:            /**
0296:             * @return
0297:             */
0298:            public WorkCalendar getWorkCalendar() {
0299:                return workCalendar;
0300:            }
0301:
0302:            public WorkCalendar getEffectiveWorkCalendar() {
0303:                if (workCalendar == null)
0304:                    return getProject().getEffectiveWorkCalendar();
0305:                return workCalendar;
0306:            }
0307:
0308:            /**
0309:             * @param workCalendar
0310:             */
0311:            public void setWorkCalendar(WorkCalendar workCalendar) {
0312:                this .workCalendar = workCalendar;
0313:            }
0314:
0315:            /**
0316:             * @return
0317:             */
0318:            public DataSnapshot getCurrentSnapshot() {
0319:                return snapshots.getCurrentSnapshot();
0320:            }
0321:
0322:            /**
0323:             * @param i
0324:             * @return
0325:             */
0326:            public DataSnapshot getSnapshot(Object snapshotId) {
0327:                return snapshots.getSnapshot(snapshotId);
0328:            }
0329:
0330:            /**
0331:             * @param i
0332:             */
0333:            public void saveCurrentToSnapshot(Object snapshotId) {
0334:                setSnapshot(snapshotId, cloneSnapshot(getSnapshot(CURRENT)));
0335:                markTaskAsNeedingRecalculation(); // for redraw purpooses, not for recalc.
0336:                setDirty(true);
0337:            }
0338:
0339:            public void restoreSnapshot(Object snapshotId, Object b) {
0340:                TaskBackup backup = (TaskBackup) b;
0341:                if (backup.snapshot == null)
0342:                    return;
0343:                TaskSnapshot snapshot = (TaskSnapshot) ((TaskSnapshot) getSnapshot(CURRENT))
0344:                        .clone();
0345:                //snapshot.setCurrentSchedule(getCurrentSchedule());
0346:                restoreDetail(this , backup, true, snapshot);
0347:                setSnapshot(snapshotId, snapshot);
0348:                markTaskAsNeedingRecalculation(); // for redraw purpooses, not for recalc.
0349:                setDirty(true);
0350:            }
0351:
0352:            /**
0353:             * @param snapshot
0354:             */
0355:            public void setCurrentSnapshot(DataSnapshot snapshot) {
0356:
0357:                snapshots.setCurrentSnapshot(snapshot);
0358:            }
0359:
0360:            /**
0361:             * @param i
0362:             * @param snapshot
0363:             */
0364:            public void setSnapshot(Object snapshotId, DataSnapshot snapshot) {
0365:                snapshots.setSnapshot(snapshotId, snapshot);
0366:            }
0367:
0368:            /**
0369:             * @param i
0370:             */
0371:            public void clearSnapshot(Object snapshotId) {
0372:                snapshots.clearSnapshot(snapshotId);
0373:                markTaskAsNeedingRecalculation(); // for redraw purpooses, not for recalc.
0374:                setDirty(true);
0375:            }
0376:
0377:            public boolean hasRealAssignments() {
0378:                return (null == findAssignment(ResourceImpl
0379:                        .getUnassignedInstance()));
0380:            }
0381:
0382:            /**
0383:             * @return
0384:             */
0385:            public AssociationList getAssignments() {
0386:                return ((TaskSnapshot) getCurrentSnapshot()).getAssignments();
0387:            }
0388:
0389:            public AssociationList getRealAssignments() {
0390:                if (hasRealAssignments())
0391:                    return getAssignments();
0392:                else
0393:                    return new AssociationList(); //empty list
0394:            }
0395:
0396:            public boolean isAssignedToMe() {
0397:                for (Iterator i = getAssignments().iterator(); i.hasNext();) {
0398:                    Assignment a = (Assignment) i.next();
0399:                    if (a.isMine())
0400:                        return true;
0401:                }
0402:                return false;
0403:            }
0404:
0405:            /**
0406:             * Add an assignment to the task.  A task always has at least one assignment, whether or not
0407:             * it has any true assignments.  This is because a default assignment is always present.  This
0408:             * greatly facilitates other calculations.  This method takes care to either create or delete
0409:             * the default assignment.
0410:             * 
0411:             * @param assignment
0412:             */
0413:            public void addDefaultAssignment() {
0414:                addAssignment(newDefaultAssignment());
0415:            }
0416:
0417:            public void addAssignment(Assignment assignment) {
0418:                //project.beginUndoUpdate();
0419:                boolean recalculateDuration = !assignment.isDefault()
0420:                        && assignment.isInitialized() && assignment.isLabor();
0421:                Assignment defaultAssignment = findAssignment(ResourceImpl
0422:                        .getUnassignedInstance());
0423:
0424:                if (!assignment.isDefault()) {
0425:                    // get rid of any default
0426:                    if (defaultAssignment != null) { //Remove any default assignment
0427:                        assignment.usePropertiesOf(defaultAssignment); // the new assignment must take on properties of the default assignment
0428:                        AssignmentService.getInstance().remove(
0429:                                defaultAssignment, null, true);
0430:                    } else {
0431:                        // if the task is started already, then only apply to remaining duration.  This means added delay to new assignment
0432:                        if (getActualStart() != 0L)
0433:                            assignment.setDelay(Duration
0434:                                    .millis(getActualDuration()));
0435:                        assignment.adjustRemainingDuration(Duration
0436:                                .millis(getRemainingDuration()), false);
0437:                    }
0438:                } else {
0439:                    if (defaultAssignment != null) //Remove any default assignment.  This happens importing if the imported task just has no assignments
0440:                        AssignmentService.getInstance().remove(
0441:                                defaultAssignment, null, true);
0442:
0443:                    // use default task duration for the default assignment duraiton
0444:                    assignment.setDuration(getRawDuration());
0445:                }
0446:
0447:                // must calculate these two values before adding assignment!
0448:                double mostLoadedAssignmentUnits = getMostLoadedAssignmentUnits();
0449:                // Get details of current assignments before change
0450:                double assignedRate = getRemainingUnits();
0451:
0452:                // add assignment
0453:                ((TaskSnapshot) getCurrentSnapshot()).addAssignment(assignment);
0454:
0455:                if (!assignment.isInitialized()) // if reading in, then don't recalc duration
0456:                    return;
0457:
0458:                // if effort driven then set duration
0459:                if (recalculateDuration && isEffortDriven()) {
0460:                    if (assignedRate != 0) {// 
0461:                        if (getSchedulingType() == SchedulingType.FIXED_DURATION) // fixed duration effort driven has complicated rule - a new assignment is weighted the same as the most loaded assignment, unless that assignment is over 100%
0462:                            assignment
0463:                                    .adjustRemainingUnits(Math.min(1.0,
0464:                                            mostLoadedAssignmentUnits), 1,
0465:                                            false, false);
0466:                        double newRemainingUnits = assignedRate
0467:                                + assignment.getRemainingLaborUnits();
0468:
0469:                        getSchedulingRule().adjustRemainingUnits(this ,
0470:                                newRemainingUnits, assignedRate, true, true); // conserve total units
0471:                    }
0472:                }
0473:                setDirty(true);
0474:                //project.endUndoUpdate();
0475:
0476:            }
0477:
0478:            /**
0479:             * @param assignment
0480:             */
0481:            public void removeAssignment(Assignment assignment) {
0482:                //project.beginUndoUpdate();
0483:                boolean recalculateDuration = !assignment.isDefault()
0484:                        && assignment.isInitialized(); // && assignment.isLabor();
0485:                // Get details of current assignments before change
0486:
0487:                double assignedRate = getRemainingUnits();
0488:                ((TaskSnapshot) getCurrentSnapshot())
0489:                        .removeAssignment(assignment);
0490:
0491:                if (!assignment.isDefault()) {
0492:
0493:                    if (recalculateDuration && isEffortDriven()) {
0494:                        double newUnits = assignedRate
0495:                                - assignment.getLaborUnits();
0496:                        if (newUnits != 0) {
0497:                            getSchedulingRule().adjustRemainingUnits(this ,
0498:                                    newUnits, assignedRate, true, true); // conserve total units					
0499:                        }
0500:                    }
0501:                    if (getAssignments().isEmpty()) {
0502:                        Assignment newDefault = newDefaultAssignment();
0503:                        newDefault.usePropertiesOf(assignment); // the default assignment must take on properties of the removed assignment
0504:                        AssignmentService.getInstance().connect(newDefault,
0505:                                null);
0506:                    }
0507:                }
0508:                setDirty(true);
0509:                //project.endUndoUpdate();
0510:
0511:            }
0512:
0513:            /*
0514:             * (non-Javadoc)
0515:             * 
0516:             * @see com.projity.pm.snapshot.Snapshottable#cloneSnapshot(com.projity.pm.snapshot.DataSnapshot)
0517:             */
0518:
0519:            public DataSnapshot cloneSnapshot(DataSnapshot snapshot) {
0520:                return (DataSnapshot) ((TaskSnapshot) snapshot).clone();
0521:            }
0522:
0523:            public TaskSnapshot getBaselineSnapshot() {
0524:                return (TaskSnapshot) getSnapshot(CalculationOption
0525:                        .getInstance().getEarnedValueBaselineId());
0526:            }
0527:
0528:            /*
0529:             * (non-Javadoc)
0530:             * 
0531:             * @see com.projity.pm.assignment.HasTimeDistributedData#buildComplexQuery(com.projity.algorithm.ComplexQuery)
0532:             */
0533:            public void buildReverseQuery(ReverseQuery reverseQuery) {
0534:                //Do this ones assignments
0535:                ((TaskSnapshot) getCurrentSnapshot())
0536:                        .buildReverseQuery(reverseQuery);
0537:                Collection children = getWbsChildrenNodes();
0538:                Object current;
0539:                if (children != null) { //  do for all children as well
0540:                    Iterator i = children.iterator();
0541:                    Task child;
0542:                    while (i.hasNext()) {
0543:                        current = ((Node) i.next()).getImpl();
0544:                        if (!(current instanceof  NormalTask))
0545:                            continue;
0546:                        child = (Task) current;
0547:                        child.buildReverseQuery(reverseQuery);
0548:                    }
0549:                }
0550:
0551:            }
0552:
0553:            public long getBaselineStart() {
0554:                TaskSnapshot baseline = getBaselineSnapshot();
0555:                if (baseline == null)
0556:                    return getStart();
0557:
0558:                return baseline.getCurrentSchedule().getStart();
0559:
0560:            }
0561:
0562:            public int getSchedulingType() {
0563:                return ((TaskSnapshot) getCurrentSnapshot())
0564:                        .getSchedulingType();
0565:            }
0566:
0567:            public void setSchedulingType(int schedulingType) {
0568:                ((TaskSnapshot) getCurrentSnapshot())
0569:                        .setSchedulingType(schedulingType);
0570:            }
0571:
0572:            public boolean isEffortDriven() {
0573:                return ((TaskSnapshot) getCurrentSnapshot()).isEffortDriven();
0574:            }
0575:
0576:            public void setEffortDriven(boolean effortDriven) {
0577:                ((TaskSnapshot) getCurrentSnapshot())
0578:                        .setEffortDriven(effortDriven);
0579:
0580:            }
0581:
0582:            public boolean isReadOnlyEffortDriven(FieldContext fieldContext) {
0583:                return ((TaskSnapshot) getCurrentSnapshot())
0584:                        .isReadOnlyEffortDriven(fieldContext);
0585:            }
0586:
0587:            public static Closure forAllAssignments(Closure visitor) {
0588:                return new ObjectVisitor(visitor) {
0589:                    protected Object getObject(Object arg0) {
0590:                        return ((TaskSnapshot) ((Task) arg0)
0591:                                .getCurrentSnapshot()).getHasAssignments();
0592:                    }
0593:                };
0594:            }
0595:
0596:            public double getFixedCost() {
0597:                return ((TaskSnapshot) getCurrentSnapshot()).getFixedCost();
0598:            }
0599:
0600:            public void setFixedCost(double fixedCost) {
0601:                ((TaskSnapshot) getCurrentSnapshot()).setFixedCost(fixedCost);
0602:            }
0603:
0604:            /**
0605:             * @return Returns the fixedCostAccrual.
0606:             */
0607:            public final int getFixedCostAccrual() {
0608:                return ((TaskSnapshot) getCurrentSnapshot())
0609:                        .getFixedCostAccrual();
0610:            }
0611:
0612:            /**
0613:             * @param fixedCostAccrual The fixedCostAccrual to set.
0614:             */
0615:            public final void setFixedCostAccrual(int fixedCostAccrual) {
0616:                ((TaskSnapshot) getCurrentSnapshot())
0617:                        .setFixedCostAccrual(fixedCostAccrual);
0618:            }
0619:
0620:            public int getPriority() {
0621:                return priority;
0622:            }
0623:
0624:            public void setPriority(int priority) {
0625:                this .priority = priority;
0626:            }
0627:
0628:            public Assignment findAssignment(Resource resource) {
0629:                return ((TaskSnapshot) getCurrentSnapshot())
0630:                        .findAssignment(resource);
0631:            }
0632:
0633:            public Assignment findAssignment(Task task) {
0634:                return ((TaskSnapshot) getCurrentSnapshot())
0635:                        .findAssignment(task);
0636:            }
0637:
0638:            public void updateAssignment(Assignment modified) {
0639:                ((TaskSnapshot) getCurrentSnapshot())
0640:                        .updateAssignment(modified);
0641:
0642:            }
0643:
0644:            public void forEachWorkingInterval(Closure visitor,
0645:                    boolean mergeWorking, WorkCalendar workCalendarToUse) {
0646:                ((TaskSnapshot) getCurrentSnapshot()).forEachWorkingInterval(
0647:                        visitor, mergeWorking, workCalendarToUse);
0648:            }
0649:
0650:            /**
0651:             * @return
0652:             */
0653:            public boolean isEstimated() {
0654:                return estimated;
0655:            }
0656:
0657:            /**
0658:             * Set estimated status of flag. First level parents will have their status set by the CP.  Higher levels
0659:             * will need to be set recursively. Note that a parent will only be asked to updated its estimated
0660:             * status if one of its children has had its estimated status change.
0661:             */
0662:            public void setEstimated(boolean estimated) {
0663:                boolean changed = this .estimated != estimated;
0664:                this .estimated = estimated;
0665:                if (changed && isWbsParent()) { // only deal with parents already since CP handles children and sets first parent level
0666:                    NormalTask parent = (NormalTask) this .getWbsParentTask();
0667:                    if (parent != null)
0668:                        parent.updateEstimatedStatus();
0669:                }
0670:
0671:            }
0672:
0673:            private void updateEstimatedStatus() {
0674:                Collection children = getWbsChildrenNodes();
0675:                Iterator i = children.iterator();
0676:                Object current;
0677:                NormalTask child;
0678:                boolean childEstimated = false;
0679:                while (i.hasNext()) {
0680:                    current = ((Node) i.next()).getImpl();
0681:                    if (!(current instanceof  NormalTask))
0682:                        continue;
0683:                    child = (NormalTask) current;
0684:                    childEstimated |= child.isEstimated();
0685:                }
0686:                setEstimated(childEstimated);
0687:            }
0688:
0689:            /**
0690:             * set actual start and competion date for parents
0691:             *  
0692:             */
0693:            protected void assignParentActualDatesFromChildren() {
0694:                NormalTask parent = this ;
0695:                while ((parent = (NormalTask) parent.getWbsParentTask()) != null)
0696:                    parent.assignActualDatesFromChildren();
0697:
0698:            }
0699:
0700:            /**
0701:             * Assigns the actual start and completed date fields of parents based on
0702:             * children values
0703:             *  
0704:             */
0705:            public void assignActualDatesFromChildren() {
0706:                long computedActualStart = Long.MAX_VALUE;
0707:                long stop = 0;
0708:                Collection children = getWbsChildrenNodes();
0709:                Iterator i = children.iterator();
0710:                Task child;
0711:                long currentActualStart;
0712:                long oldActualDuration = Duration.millis(getActualDuration());
0713:                Object current;
0714:                while (i.hasNext()) {
0715:                    current = ((Node) i.next()).getImpl();
0716:                    if (!(current instanceof  NormalTask))
0717:                        continue;
0718:                    child = (NormalTask) current;
0719:                    if (!child.inProgress())
0720:                        continue;
0721:                    if ((currentActualStart = child.getActualStart()) != 0) // if any task has actual start, use the earliest value
0722:                        computedActualStart = Math.min(computedActualStart,
0723:                                currentActualStart);
0724:
0725:                    stop = Math.max(stop, child.getStop());
0726:                }
0727:
0728:                long actualDuration = 0;
0729:                if (computedActualStart != Long.MAX_VALUE && stop != 0)
0730:                    actualDuration = getEffectiveWorkCalendar().compare(stop,
0731:                            getStart(), false);
0732:                if (actualDuration != oldActualDuration) {
0733:                    double percentComplete = ((double) actualDuration)
0734:                            / getDurationMillis();
0735:                    currentSchedule.setPercentComplete(percentComplete);
0736:                    markTaskAsNeedingRecalculation(); // so it redraws
0737:                }
0738:            }
0739:
0740:            /*
0741:             * (non-Javadoc)
0742:             * 
0743:             * @see com.projity.pm.task.TaskSpecificFields#taskCalendar()
0744:             */
0745:            public WorkCalendar getTaskCalendar() {
0746:                return getWorkCalendar();
0747:            }
0748:
0749:            /*
0750:             * (non-Javadoc)
0751:             * 
0752:             * @see com.projity.pm.task.TaskSpecificFields#setTaskCalendar(java.lang.String)
0753:             */
0754:            public void setTaskCalendar(WorkCalendar taskCalendar) {
0755:                if (workCalendar == taskCalendar)
0756:                    return;
0757:                CalendarService.getInstance().reassignCalendar(this ,
0758:                        workCalendar, taskCalendar);
0759:                setWorkCalendar(taskCalendar);
0760:                invalidateAssignmentCalendars(); // assignments intersection calendars need to be recalculated
0761:            }
0762:
0763:            public long getBaselineStart(int numBaseline) {
0764:                TaskSnapshot snapshot = ((TaskSnapshot) getSnapshot(new Integer(
0765:                        numBaseline)));
0766:                if (snapshot == null)
0767:                    return 0;
0768:                return snapshot.getCurrentSchedule().getStart();
0769:            }
0770:
0771:            public long getBaselineFinish(int numBaseline) {
0772:                TaskSnapshot snapshot = ((TaskSnapshot) getSnapshot(new Integer(
0773:                        numBaseline)));
0774:                if (snapshot == null)
0775:                    return 0;
0776:                return snapshot.getCurrentSchedule().getEnd();
0777:            }
0778:
0779:            public long getBaselineDuration(int numBaseline) {
0780:                TaskSnapshot snapshot = ((TaskSnapshot) getSnapshot(new Integer(
0781:                        numBaseline)));
0782:                if (snapshot == null)
0783:                    return 0;
0784:                return snapshot.getCurrentSchedule().getRawDuration();
0785:            }
0786:
0787:            public double getBaselineCost(int numBaseline, long start, long end) {
0788:                TaskSnapshot snapshot = ((TaskSnapshot) getSnapshot(new Integer(
0789:                        numBaseline)));
0790:                if (snapshot == null)
0791:                    return 0;
0792:                return snapshot.cost(start, end);
0793:            }
0794:
0795:            public double getBaselineWork(int numBaseline, long start, long end) {
0796:                TaskSnapshot snapshot = ((TaskSnapshot) getSnapshot(new Integer(
0797:                        numBaseline)));
0798:                if (snapshot == null)
0799:                    return 0;
0800:                return snapshot.work(start, end);
0801:            }
0802:
0803:            //	public long getWork() {
0804:            //		DoubleSum sumFunctor = new DoubleSum() {
0805:            //
0806:            //			protected double getValueForElement(Object object) {
0807:            //				return ((Assignment)object).calcAll(Assignment.WORK);
0808:            //			}};
0809:            //			
0810:            //		CollectionUtils.forAllDo(getAssignments(),sumFunctor);
0811:            //		return (long) sumFunctor.getValue();
0812:            //	}
0813:
0814:            /*
0815:             * (non-Javadoc)
0816:             * 
0817:             * @see com.projity.pm.task.TaskSpecificFields#getResourceInitials()
0818:             */
0819:            public String getResourceInitials() {
0820:                return AssociationListFormat
0821:                        .getInstance(
0822:                                AssignmentFormat
0823:                                        .getInstance(AssociationFormatParameters
0824:                                                .getInstance(
0825:                                                        this ,
0826:                                                        true,
0827:                                                        Configuration
0828:                                                                .getFieldFromId("Field.initials"),
0829:                                                        false, false))).format(
0830:                                getAssignments());
0831:            }
0832:
0833:            /*
0834:             * (non-Javadoc)
0835:             * 
0836:             * @see com.projity.pm.task.TaskSpecificFields#setResourceInitials()
0837:             */
0838:            public void setResourceInitials(String resourceInitials)
0839:                    throws FieldParseException {
0840:                getAssignments()
0841:                        .setAssociations(
0842:                                resourceInitials,
0843:                                AssignmentFormat
0844:                                        .getInstance(AssociationFormatParameters
0845:                                                .getInstance(
0846:                                                        this ,
0847:                                                        true,
0848:                                                        Configuration
0849:                                                                .getFieldFromId("Field.initials"),
0850:                                                        false, false)));
0851:            }
0852:
0853:            /*
0854:             * (non-Javadoc)
0855:             * 
0856:             * @see com.projity.pm.task.TaskSpecificFields#getResourcePhonetics()
0857:             */
0858:            public String getResourcePhonetics() {
0859:                return AssociationListFormat
0860:                        .getInstance(
0861:                                AssignmentFormat
0862:                                        .getInstance(AssociationFormatParameters
0863:                                                .getInstance(
0864:                                                        this ,
0865:                                                        true,
0866:                                                        Configuration
0867:                                                                .getFieldFromId("Field.phonetics"),
0868:                                                        false, true))).format(
0869:                                getAssignments());
0870:
0871:            }
0872:
0873:            /*
0874:             * (non-Javadoc)
0875:             * 
0876:             * @see com.projity.pm.task.TaskSpecificFields#getResourceGroup()
0877:             */
0878:            public String getResourceGroup() {
0879:                return AssociationListFormat.getInstance(
0880:                        AssignmentFormat
0881:                                .getInstance(AssociationFormatParameters
0882:                                        .getInstance(this , true, Configuration
0883:                                                .getFieldFromId("Field.group"),
0884:                                                false, false))).format(
0885:                        getAssignments());
0886:            }
0887:
0888:            /*
0889:             * (non-Javadoc)
0890:             * 
0891:             * @see com.projity.pm.task.TaskSpecificFields#getResourceNames()
0892:             */
0893:            public String getResourceNames() {
0894:                return AssociationListFormat.getInstance(
0895:                        AssignmentFormat
0896:                                .getInstance(AssociationFormatParameters
0897:                                        .getInstance(this , true, Configuration
0898:                                                .getFieldFromId("Field.name"),
0899:                                                true, true))).format(
0900:                        getAssignments());
0901:            }
0902:
0903:            /*
0904:             * (non-Javadoc)
0905:             * 
0906:             * @see com.projity.pm.task.TaskSpecificFields#setResourceNames(java.lang.String)
0907:             */
0908:            public void setResourceNames(String resourceNames)
0909:                    throws FieldParseException {
0910:                getAssignments().setAssociations(
0911:                        resourceNames,
0912:                        AssignmentFormat
0913:                                .getInstance(AssociationFormatParameters
0914:                                        .getInstance(this , true, Configuration
0915:                                                .getFieldFromId("Field.name"),
0916:                                                true, true)));
0917:
0918:            }
0919:
0920:            public double getUnits() {
0921:                if (getAssignments().isEmpty())
0922:                    return 0;
0923:                long duration = getDurationMillis();
0924:                if (duration == 0.0)
0925:                    return 1.0D; // degeneratate case
0926:                if (!isInitialized()) // the case when reading a file, don't boether to
0927:                    // calculate
0928:                    return 1.0;
0929:                long work = calcWork();
0930:                if (work == 0) // degenerate case with no work yet
0931:                    return 1.0;
0932:                return ((double) work) / duration;
0933:            }
0934:
0935:            public double getRemainingUnits() {
0936:                if (getAssignments().isEmpty())
0937:                    return 0;
0938:                long duration = Duration.millis(getRemainingDuration());
0939:                if (duration == 0.0)
0940:                    return 1.0D; // degeneratate case
0941:                if (!isInitialized()) // the case when reading a file, don't boether to
0942:                    // calculate
0943:                    return 1.0;
0944:                long work = getRemainingWork(null);
0945:                //		if (work == 0) // degenerate case with no work yet
0946:                //			return 1.0;
0947:                return ((double) work) / duration;
0948:
0949:            }
0950:
0951:            public void setWork(long work, FieldContext context) {
0952:
0953:                if (FieldContext.hasInterval(context)) {
0954:                    Iterator i = getAssignments().iterator();
0955:                    while (i.hasNext()) {
0956:                        Assignment assignment = (Assignment) i.next();
0957:                        assignment.setWork(work, context);
0958:                    }
0959:                } else {
0960:                    setWork(work);
0961:                }
0962:            }
0963:
0964:            public void setWork(long work) {
0965:                work = Duration.millis(work);
0966:                if (hasLaborAssignment() && work < 60000) {
0967:                    work *= Duration.timeUnitFactor(TimeUnit.HOURS);
0968:                }
0969:                long remainingWork = work - getActualWork(null);
0970:                getSchedulingRule().adjustRemainingWork(this , remainingWork,
0971:                        true);
0972:            }
0973:
0974:            public long calcWork() {
0975:                if (!hasRealAssignments()) // avoid treating dummy assignment
0976:                    return 0;
0977:
0978:                return getWork(null);
0979:            }
0980:
0981:            /**
0982:             * The the most highly loaded assignment's units.  This is used for calculating new assignment's
0983:             * units for fixed-duration effort-driven tasks
0984:             * @return
0985:             */
0986:            public double getMostLoadedAssignmentUnits() {
0987:                double result = 0;
0988:                Iterator i = getAssignments().iterator();
0989:                while (i.hasNext())
0990:                    result = Math.max(result, ((Assignment) i.next())
0991:                            .getLaborUnits());
0992:
0993:                return result;
0994:            }
0995:
0996:            /*
0997:             * (non-Javadoc)
0998:             * 
0999:             * @see com.projity.pm.assignment.Allocation#adjustDuration(long)
1000:             */
1001:            public void adjustRemainingDuration(long newDuration,
1002:                    boolean doChildren) {
1003:                //~~		setRawDuration(newDuration); // keep units
1004:                //hk		long newRemainingDuration = Duration.millis(newDuration) - getActualDuration(); // assignments dont treqt
1005:                long newRemainingDuration = Duration.millis(newDuration); // - getActualDuration(); // assignments dont treqt
1006:                // units
1007:                Iterator i = getAssignments().iterator();
1008:                while (i.hasNext())
1009:                    ((Assignment) i.next())
1010:                            .adjustRemainingDurationIfWorkingAtTaskEnd(newRemainingDuration);
1011:
1012:            }
1013:
1014:            /**
1015:             * Called when an assignment value is modified. We want the task details to
1016:             * be modified without changing the assignment details
1017:             * 
1018:             * @param deltaAdded
1019:             */
1020:            public void adjustUnitsDelta(double deltaAdded) {
1021:                getSchedulingRule().adjustRemainingUnits(this ,
1022:                        getRemainingUnits() + deltaAdded, getRemainingUnits(),
1023:                        false, false);
1024:            }
1025:
1026:            /*
1027:             * (non-Javadoc)
1028:             * 
1029:             * @see com.projity.pm.assignment.Allocation#adjustUnits(double)
1030:             */
1031:            public void adjustRemainingUnits(double newRemainingUnits,
1032:                    double oldRemainingUnits, boolean doChildren,
1033:                    boolean conserveTotalUnits) {
1034:
1035:                if (!doChildren)
1036:                    return;
1037:                double multiplier = 1;
1038:                if (conserveTotalUnits) {
1039:                    multiplier = oldRemainingUnits / newRemainingUnits;
1040:                }
1041:
1042:                double u = newRemainingUnits;
1043:                double remaining = getRemainingUnits();
1044:                double factor = u / remaining;
1045:                Iterator i = getAssignments().iterator();
1046:                while (i.hasNext()) {
1047:                    Assignment assignment = (Assignment) i.next();
1048:                    double r = assignment.getLaborUnits();
1049:                    //			if (!assignment.isLabor())
1050:                    //				continue;
1051:                    if (conserveTotalUnits)
1052:                        getSchedulingRule().adjustRemainingUnits(
1053:                                assignment,
1054:                                assignment.getRemainingLaborUnits()
1055:                                        * multiplier,
1056:                                assignment.getRemainingLaborUnits(), false,
1057:                                false);
1058:                    else {
1059:                        getSchedulingRule().adjustRemainingUnits(assignment,
1060:                                factor * r, r, false, false);
1061:                    }
1062:                }
1063:
1064:            }
1065:
1066:            /*
1067:             * (non-Javadoc)
1068:             * 
1069:             * @see com.projity.pm.assignment.Allocation#adjustWork(double)
1070:             */
1071:            public void adjustRemainingWork(double multiplier,
1072:                    boolean doChildren) {
1073:                //		long newDuration = (long) (getDurationMillis() * multiplier);
1074:                //~~		setRawDuration(newDuration);
1075:                //need to always do children regardless of doChildren flag
1076:                Iterator i = getAssignments().iterator();
1077:                while (i.hasNext()) {
1078:                    Assignment assignment = (Assignment) i.next();
1079:                    if (!assignment.isLabor())
1080:                        continue;
1081:                    getSchedulingRule()
1082:                            .adjustRemainingWork(
1083:                                    assignment,
1084:                                    (long) (assignment.getRemainingWork() * multiplier),
1085:                                    false);
1086:                }
1087:            }
1088:
1089:            /**
1090:             * Gets a (singleton) instance of the scheduling rule to use for the task
1091:             * 
1092:             * @return scheduling rule to use in adjust...() calculations
1093:             */
1094:            public SchedulingRule getSchedulingRule() {
1095:                return SchedulingType
1096:                        .getSchedulingRuleInstance(getSchedulingType());
1097:
1098:            }
1099:
1100:            public boolean isReadOnlyUnits(FieldContext fieldContext) {
1101:                return true;
1102:            }
1103:
1104:            public long getCompletedThrough() {
1105:                long start = getStart();
1106:                if (start == 0)
1107:                    return 0;
1108:                long actualDuration = DateTime.closestDate(getDurationMillis()
1109:                        * getPercentComplete());
1110:                return getEffectiveWorkCalendar().add(start, actualDuration,
1111:                        true);
1112:            }
1113:
1114:            /**
1115:             * Stop is the earliest completion date of the assignments
1116:             * @return
1117:             */
1118:            public long getStop() {
1119:                //		if (isWbsParent( )) {
1120:                //			long start = getStart();
1121:                //			if (start == 0)
1122:                //				return 0;
1123:                //			long actualDuration = DateTime.closestDate(getDurationMillis() * getPercentComplete());
1124:                //			return getEffectiveWorkCalendar().add(start,actualDuration,true);
1125:                //		}
1126:                return getEarliestStop();
1127:                //&&&&&
1128:                //		long stop = 0;
1129:                //		Assignment assignment;
1130:                //		Iterator i = getAssignments().iterator();
1131:                //		while (i.hasNext()) {
1132:                //			assignment = (Assignment)i.next();
1133:                //			stop = Math.max(stop,assignment.getStop());
1134:                //		}
1135:                //		return stop;
1136:            }
1137:
1138:            //Used when an assignment advancement changes
1139:            public void adjustActualStartFromAssignments() {
1140:                Assignment assignment;
1141:                Iterator i = getAssignments().iterator();
1142:                long start = 0L;
1143:                while (i.hasNext()) {
1144:                    assignment = (Assignment) i.next();
1145:                    if (assignment.getPercentComplete() > 0.0D) {
1146:                        start = getStart();
1147:                        break;
1148:                    }
1149:                }
1150:                //		System.out.println("adjusting actual start to " + new java.util.Date(start));
1151:                setActualStart(start);
1152:            }
1153:
1154:            /**
1155:             * @param stop
1156:             */
1157:            public void setStop(long stop) {
1158:                if (stop == getStop())
1159:                    return;
1160:                stop = DateTime.closestDate(stop);
1161:                stop = Math.min(stop, getEnd());
1162:
1163:                Iterator i = getAssignments().iterator();
1164:                Assignment assignment;
1165:                long computedActualStart = Long.MAX_VALUE;
1166:                long assignmentActualStart;
1167:                while (i.hasNext()) {
1168:                    assignment = (Assignment) i.next();
1169:                    assignment.setStop(stop);
1170:                    assignmentActualStart = assignment.getActualStart();
1171:                    if (assignmentActualStart != 0
1172:                            && assignmentActualStart < computedActualStart)
1173:                        computedActualStart = assignmentActualStart;
1174:                }
1175:                if (computedActualStart == Long.MAX_VALUE)
1176:                    computedActualStart = 0;
1177:                setActualStart(computedActualStart);
1178:                assignParentActualDatesFromChildren();
1179:
1180:                // if % complete went down to 0, then the plan changed and need to recalculate all.
1181:                if (computedActualStart == 0) {
1182:                    getDocument().getObjectEventManager().fireUpdateEvent(this ,
1183:                            this , Configuration.getFieldFromId("Field.start"));
1184:                } else {
1185:                    //TODO duplicate event
1186:                    //TODO in the case of progress update this event is useless since critical path runs after.
1187:                    getProject().fireScheduleChanged(this ,
1188:                            ScheduleEvent.ACTUAL, this );
1189:                }
1190:
1191:            }
1192:
1193:            /**
1194:             * @return
1195:             */
1196:            public long getResume() {
1197:                long resume = Long.MAX_VALUE;
1198:                Assignment assignment;
1199:                Iterator i = getAssignments().iterator();
1200:                while (i.hasNext()) {
1201:                    assignment = (Assignment) i.next();
1202:                    resume = Math.min(resume, assignment.getResume());
1203:                }
1204:                return resume;
1205:            }
1206:
1207:            /**
1208:             * @param resume
1209:             */
1210:            public void setResume(long resume) {
1211:                Assignment assignment;
1212:                Iterator i = getAssignments().iterator();
1213:                while (i.hasNext()) {
1214:                    assignment = (Assignment) i.next();
1215:                    assignment.setResume(resume);
1216:                }
1217:            }
1218:
1219:            private void setStopNoExtend(long stop) {
1220:                //TODO figure out
1221:                long start = getStart();
1222:                if (stop < start) {// don't allow completion before start
1223:                    setActualDuration(0);
1224:                    stop = start;
1225:                } else {
1226:                    long duration = getEffectiveWorkCalendar().compare(stop,
1227:                            start, false);
1228:                    duration = Math.min(duration, getDurationMillis()); // don't ever
1229:                    // change finish
1230:                    setActualDuration(duration);
1231:                }
1232:                //		scheduleWindow.setStop(stop);
1233:            }
1234:
1235:            /***************************************************************************
1236:             * TimeDistributedData T********
1237:             **************************************************************************/
1238:            /**
1239:             * For parent tasks, we don't want to count their one day of work
1240:             */
1241:            private boolean isParentWithoutAssignments() {
1242:                return (isWbsParent() && !hasRealAssignments());
1243:            }
1244:
1245:            public double cost(long start, long end) {
1246:                if (isParentWithoutAssignments())
1247:                    return 0.0D;
1248:                return ((TaskSnapshot) getCurrentSnapshot()).cost(start, end);
1249:            }
1250:
1251:            public long work(long start, long end) {
1252:                if (isParentWithoutAssignments())
1253:                    return 0L;
1254:                return ((TaskSnapshot) getCurrentSnapshot()).work(start, end);
1255:            }
1256:
1257:            public double actualCost(long start, long end) {
1258:                if (isParentWithoutAssignments())
1259:                    return 0.0D;
1260:
1261:                return ((TaskSnapshot) getCurrentSnapshot()).actualCost(start,
1262:                        end);
1263:            }
1264:
1265:            public long actualWork(long start, long end) {
1266:                if (isParentWithoutAssignments())
1267:                    return 0L;
1268:                return ((TaskSnapshot) getCurrentSnapshot()).actualWork(start,
1269:                        end);
1270:            }
1271:
1272:            public long remainingWork(long start, long end) {
1273:                if (isParentWithoutAssignments())
1274:                    return 0L;
1275:                return ((TaskSnapshot) getCurrentSnapshot()).remainingWork(
1276:                        start, end);
1277:            }
1278:
1279:            public double baselineCost(long start, long end) {
1280:                if (getBaselineSnapshot() == null)
1281:                    return 0;
1282:
1283:                return getBaselineSnapshot().cost(start, end);
1284:            }
1285:
1286:            public long baselineWork(long start, long end) {
1287:                if (getBaselineSnapshot() == null)
1288:                    return 0;
1289:                return getBaselineSnapshot().work(start, end);
1290:            }
1291:
1292:            /***************************************************************************
1293:             * EarnedValueValues
1294:             **************************************************************************/
1295:
1296:            public double acwp(long start, long end) {
1297:                return ((TaskSnapshot) getCurrentSnapshot()).acwp(start, end);
1298:            }
1299:
1300:            public double bac(long start, long end) {
1301:                return ((TaskSnapshot) getCurrentSnapshot()).bac(start, end);
1302:            }
1303:
1304:            public double bcwp(long start, long end) {
1305:                return ((TaskSnapshot) getCurrentSnapshot()).bcwp(start, end);
1306:            }
1307:
1308:            public double bcws(long start, long end) {
1309:                return ((TaskSnapshot) getCurrentSnapshot()).bcws(start, end);
1310:            }
1311:
1312:            boolean isInRange(long start, long finish) {
1313:                long s = getStart();
1314:                return (finish > s && start < getEnd());
1315:            }
1316:
1317:            private boolean isFieldHidden(FieldContext fieldContext) {
1318:                return fieldContext != null
1319:                        && !isInRange(fieldContext.getStart(), fieldContext
1320:                                .getEnd());
1321:            }
1322:
1323:            private boolean isBaselineFieldHidden(int numBaseline,
1324:                    FieldContext fieldContext) {
1325:                TaskSnapshot baseline = (TaskSnapshot) getSnapshot(new Integer(
1326:                        numBaseline));
1327:                if (baseline == null)
1328:                    return true;
1329:
1330:                if (fieldContext == null) // the baseline exists, but no time range
1331:                    return false;
1332:                return (fieldContext.getStart() >= baseline
1333:                        .getCurrentSchedule().getFinish() || fieldContext
1334:                        .getEnd() <= baseline.getCurrentSchedule().getStart());
1335:            }
1336:
1337:            private boolean isEarnedValueFieldHidden(FieldContext fieldContext) {
1338:                if (isFieldHidden(fieldContext))
1339:                    return true;
1340:                if (fieldContext == null)
1341:                    return false;
1342:                return project.getStatusDate() < fieldContext.getStart();
1343:            }
1344:
1345:            /***************************************************************************
1346:             * Time Distributed Fields
1347:             **************************************************************************/
1348:            public boolean fieldHideCost(FieldContext fieldContext) {
1349:                return isFieldHidden(fieldContext);
1350:            }
1351:
1352:            public boolean fieldHideWork(FieldContext fieldContext) {
1353:                return isFieldHidden(fieldContext);
1354:            }
1355:
1356:            public boolean fieldHideActualCost(FieldContext fieldContext) {
1357:                return isFieldHidden(fieldContext);
1358:            }
1359:
1360:            public boolean fieldHideActualWork(FieldContext fieldContext) {
1361:                return isFieldHidden(fieldContext);
1362:            }
1363:
1364:            public boolean fieldHideBaselineCost(int numBaseline,
1365:                    FieldContext fieldContext) {
1366:                return isBaselineFieldHidden(numBaseline, fieldContext);
1367:            }
1368:
1369:            public boolean fieldHideBaselineWork(int numBaseline,
1370:                    FieldContext fieldContext) {
1371:                return isBaselineFieldHidden(numBaseline, fieldContext);
1372:            }
1373:
1374:            public boolean fieldHideAcwp(FieldContext fieldContext) {
1375:                return isFieldHidden(fieldContext);
1376:            }
1377:
1378:            public boolean fieldHideBac(FieldContext fieldContext) {
1379:                return isFieldHidden(fieldContext);
1380:            }
1381:
1382:            public boolean fieldHideBcwp(FieldContext fieldContext) {
1383:                return isEarnedValueFieldHidden(fieldContext);
1384:            }
1385:
1386:            public boolean fieldHideBcws(FieldContext fieldContext) {
1387:                return isEarnedValueFieldHidden(fieldContext);
1388:            }
1389:
1390:            public boolean fieldHideCv(FieldContext fieldContext) {
1391:                return isFieldHidden(fieldContext);
1392:            }
1393:
1394:            public boolean fieldHideSv(FieldContext fieldContext) {
1395:                return isFieldHidden(fieldContext);
1396:            }
1397:
1398:            public boolean fieldHideEac(FieldContext fieldContext) {
1399:                return isFieldHidden(fieldContext);
1400:            }
1401:
1402:            public boolean fieldHideVac(FieldContext fieldContext) {
1403:                return isFieldHidden(fieldContext);
1404:            }
1405:
1406:            public boolean fieldHideCpi(FieldContext fieldContext) {
1407:                return isFieldHidden(fieldContext);
1408:            }
1409:
1410:            public boolean fieldHideSpi(FieldContext fieldContext) {
1411:                return isFieldHidden(fieldContext);
1412:            }
1413:
1414:            public boolean fieldHideCvPercent(FieldContext fieldContext) {
1415:                return isFieldHidden(fieldContext);
1416:            }
1417:
1418:            public boolean fieldHideSvPercent(FieldContext fieldContext) {
1419:                return isFieldHidden(fieldContext);
1420:            }
1421:
1422:            public boolean fieldHideTcpi(FieldContext fieldContext) {
1423:                return isFieldHidden(fieldContext);
1424:            }
1425:
1426:            public double getCost(FieldContext fieldContext) {
1427:                return getFixedCost(fieldContext)
1428:                        + cost(FieldContext.start(fieldContext), FieldContext
1429:                                .end(fieldContext));
1430:            }
1431:
1432:            public long getWork(FieldContext fieldContext) {
1433:                return work(FieldContext.start(fieldContext), FieldContext
1434:                        .end(fieldContext));
1435:            }
1436:
1437:            public double getActualFixedCost(FieldContext fieldContext) {
1438:                return fixedCost(FieldContext.start(fieldContext), Math.min(
1439:                        getStop(), FieldContext // only up to completion
1440:                                .end(fieldContext)));
1441:            }
1442:
1443:            public double getFixedCost(FieldContext fieldContext) {
1444:                if (!FieldContext.hasInterval(fieldContext))
1445:                    return ((TaskSnapshot) getCurrentSnapshot()).getFixedCost();
1446:
1447:                return fixedCost(FieldContext.start(fieldContext), FieldContext
1448:                        .end(fieldContext));
1449:            }
1450:
1451:            public double actualFixedCost(long start, long end) {
1452:                return fixedCost(start, Math.min(getStop(), end));
1453:            }
1454:
1455:            /** Calculate the fixed cost for the task given its accrual type and percent complete
1456:             */
1457:            public double fixedCost(long start, long end) {
1458:                long taskStart = getStart();
1459:                long taskEnd = getEnd();
1460:                double fixed = 0.0;
1461:                double fixedCost = getFixedCost();
1462:                if (getFixedCostAccrual() == Accrual.START) {
1463:                    if (taskStart >= start && taskStart <= end) // if task starts in this range
1464:                        fixed = fixedCost;
1465:                } else if (getFixedCostAccrual() == Accrual.PRORATED) {
1466:                    // find overlapping actual time
1467:                    start = Math.max(start, taskStart);
1468:                    end = Math.min(end, taskEnd);
1469:                    if (start < end) { // if valid range
1470:                        long overlappingDuration = getEffectiveWorkCalendar()
1471:                                .compare(end, start, false);
1472:                        double fraction = ((double) overlappingDuration)
1473:                                / getDurationMillis();
1474:                        fixed = fixedCost * fraction;
1475:                    }
1476:                } else { // END accrual by default
1477:                    if (taskEnd >= start && taskEnd <= end) // if task ends in this range
1478:                        fixed = fixedCost;
1479:                }
1480:                return fixed;
1481:            }
1482:
1483:            public boolean fieldHideActualFixedCost(FieldContext fieldContext) {
1484:                return false;
1485:            }
1486:
1487:            public double getActualCost(FieldContext fieldContext) {
1488:                return getActualFixedCost(fieldContext)
1489:                        + actualCost(FieldContext.start(fieldContext),
1490:                                FieldContext.end(fieldContext));
1491:            }
1492:
1493:            public long getActualWork(FieldContext fieldContext) {
1494:                return actualWork(FieldContext.start(fieldContext),
1495:                        FieldContext.end(fieldContext));
1496:            }
1497:
1498:            public long getRemainingWork(FieldContext fieldContext) {
1499:                return remainingWork(FieldContext.start(fieldContext),
1500:                        FieldContext.end(fieldContext));
1501:            }
1502:
1503:            public long getRemainingWork() {
1504:                return getRemainingWork(null);
1505:            }
1506:
1507:            public double getRemainingCost(FieldContext fieldContext) {
1508:                return getCost(fieldContext) - getActualCost(fieldContext);
1509:            }
1510:
1511:            //Baseline versions
1512:            public double getBaselineCost(int numBaseline,
1513:                    FieldContext fieldContext) {
1514:                TaskSnapshot snapshot = (TaskSnapshot) getSnapshot(new Integer(
1515:                        numBaseline));
1516:                if (snapshot == null)
1517:                    return 0.0D;
1518:                return ((TaskSnapshot) getSnapshot(new Integer(numBaseline)))
1519:                        .cost(FieldContext.start(fieldContext), FieldContext
1520:                                .end(fieldContext));
1521:            }
1522:
1523:            public long getBaselineWork(int numBaseline,
1524:                    FieldContext fieldContext) {
1525:                TaskSnapshot snapshot = (TaskSnapshot) getSnapshot(new Integer(
1526:                        numBaseline));
1527:                if (snapshot == null)
1528:                    return 0L;
1529:                return ((TaskSnapshot) getSnapshot(new Integer(numBaseline)))
1530:                        .work(FieldContext.start(fieldContext), FieldContext
1531:                                .end(fieldContext));
1532:            }
1533:
1534:            /***************************************************************************
1535:             * Earned Value Fields
1536:             **************************************************************************/
1537:            public double getAcwp(FieldContext fieldContext) {
1538:                return acwp(FieldContext.start(fieldContext), FieldContext
1539:                        .end(fieldContext));
1540:            }
1541:
1542:            public double getBac(FieldContext fieldContext) {
1543:                return bac(FieldContext.start(fieldContext), FieldContext
1544:                        .end(fieldContext));
1545:            }
1546:
1547:            public double getBcwp(FieldContext fieldContext) {
1548:                return bcwp(FieldContext.start(fieldContext), FieldContext
1549:                        .end(fieldContext));
1550:            }
1551:
1552:            public double getBcws(FieldContext fieldContext) {
1553:                return bcws(FieldContext.start(fieldContext), FieldContext
1554:                        .end(fieldContext));
1555:            }
1556:
1557:            public double getCv(FieldContext fieldContext) {
1558:                return EarnedValueCalculator.getInstance().cv(this ,
1559:                        FieldContext.start(fieldContext),
1560:                        FieldContext.end(fieldContext));
1561:            }
1562:
1563:            public double getSv(FieldContext fieldContext) {
1564:                return EarnedValueCalculator.getInstance().sv(this ,
1565:                        FieldContext.start(fieldContext),
1566:                        FieldContext.end(fieldContext));
1567:            }
1568:
1569:            public double getEac(FieldContext fieldContext) {
1570:                return EarnedValueCalculator.getInstance().eac(this ,
1571:                        FieldContext.start(fieldContext),
1572:                        FieldContext.end(fieldContext));
1573:            }
1574:
1575:            public double getVac(FieldContext fieldContext) {
1576:                return EarnedValueCalculator.getInstance().vac(this ,
1577:                        FieldContext.start(fieldContext),
1578:                        FieldContext.end(fieldContext));
1579:            }
1580:
1581:            public double getCpi(FieldContext fieldContext) {
1582:                return EarnedValueCalculator.getInstance().cpi(this ,
1583:                        FieldContext.start(fieldContext),
1584:                        FieldContext.end(fieldContext));
1585:            }
1586:
1587:            public double getSpi(FieldContext fieldContext) {
1588:                return EarnedValueCalculator.getInstance().spi(this ,
1589:                        FieldContext.start(fieldContext),
1590:                        FieldContext.end(fieldContext));
1591:            }
1592:
1593:            public double getCsi(FieldContext fieldContext) {
1594:                return EarnedValueCalculator.getInstance().csi(this ,
1595:                        FieldContext.start(fieldContext),
1596:                        FieldContext.end(fieldContext));
1597:            }
1598:
1599:            public double getCvPercent(FieldContext fieldContext) {
1600:                return EarnedValueCalculator.getInstance().cvPercent(this ,
1601:                        FieldContext.start(fieldContext),
1602:                        FieldContext.end(fieldContext));
1603:            }
1604:
1605:            public double getSvPercent(FieldContext fieldContext) {
1606:                return EarnedValueCalculator.getInstance().svPercent(this ,
1607:                        FieldContext.start(fieldContext),
1608:                        FieldContext.end(fieldContext));
1609:            }
1610:
1611:            public double getTcpi(FieldContext fieldContext) {
1612:                return EarnedValueCalculator.getInstance().tcpi(this ,
1613:                        FieldContext.start(fieldContext),
1614:                        FieldContext.end(fieldContext));
1615:            }
1616:
1617:            /*
1618:             * (non-Javadoc)
1619:             * 
1620:             * @see com.projity.pm.assignment.HasAssignments#calcDataBetween(java.lang.Object,
1621:             *      com.projity.algorithm.TimeIteratorGenerator,
1622:             *      com.projity.algorithm.CalculatedValues)
1623:             */
1624:            public void calcDataBetween(Object type,
1625:                    TimeIteratorGenerator generator, CalculatedValues values) {
1626:                ((TaskSnapshot) getCurrentSnapshot()).calcDataBetween(type,
1627:                        generator, values);
1628:
1629:            }
1630:
1631:            public void setPercentComplete(double percentComplete) {
1632:                if (percentComplete > 1.0) {
1633:                    System.out.println("percent complete more than 100%");
1634:                    percentComplete = 1.0;
1635:                } else if (percentComplete < 0) {
1636:                    System.out.println("percent complete less than 0%");
1637:                    percentComplete = 0.0;
1638:                }
1639:
1640:                long actualDuration = DateTime.closestDate(getDurationMillis()
1641:                        * percentComplete);
1642:                setActualDuration(actualDuration);
1643:                long stop = getEffectiveWorkCalendar().add(getStart(),
1644:                        actualDuration, false);
1645:                DeepChildWalker.recursivelyTreatBranch(getProject()
1646:                        .getTaskOutline(), this , new NumberClosure(stop) {
1647:                    public void execute(Object arg0) {
1648:                        if (arg0 == null) {
1649:                            return;
1650:                        }
1651:                        Object nodeObject = ((Node) arg0).getImpl();
1652:                        if (nodeObject instanceof  NormalTask) { // do not treat assignments 
1653:                            NormalTask task = ((NormalTask) nodeObject);
1654:                            task.setStop(Math.min(longValue(), task.getEnd())); // do within range of task
1655:                        }
1656:                    }
1657:                });
1658:            }
1659:
1660:            /*
1661:             * (non-Javadoc)
1662:             * 
1663:             * @see com.projity.pm.task.TaskSpecificFields#getPercentWorkComplete()
1664:             */
1665:            public double getPercentWorkComplete() {
1666:                //		NodeModel nodeModel = getProject().getTaskOutline();
1667:                //		Node node = nodeModel.search(this);
1668:                //		Number value = (Number)
1669:                // Configuration.getFieldFromId("Field.work").getValue(node,nodeModel,null);
1670:                //		if (value.doubleValue() == 0)
1671:                //			return 0;
1672:                //		Number actualValue = (Number)
1673:                // Configuration.getFieldFromId("Field.actualWork").getValue(node,nodeModel,null);
1674:                //		return actualValue.doubleValue() / value.doubleValue();
1675:                long work = calcSummedWork();
1676:                if (work == 0)
1677:                    return 0;
1678:                else
1679:                    return ((double) calcSummedActualWork()) / work;
1680:            }
1681:
1682:            private long calcSummedWork() {
1683:                NodeModel nodeModel = getProject().getTaskOutline();
1684:                Node node = nodeModel.search(this );
1685:                if (node == null)
1686:                    return 0;
1687:                Number value = (Number) Configuration.getFieldFromId(
1688:                        "Field.work").getValue(node, nodeModel, null);
1689:                return value.longValue();
1690:            }
1691:
1692:            private long calcSummedActualWork() {
1693:                NodeModel nodeModel = getProject().getTaskOutline();
1694:                Node node = nodeModel.search(this );
1695:                Number value = (Number) Configuration.getFieldFromId(
1696:                        "Field.actualWork").getValue(node, nodeModel, null);
1697:                return value.longValue();
1698:            }
1699:
1700:            /*
1701:             * (non-Javadoc)
1702:             * 
1703:             * @see com.projity.pm.task.TaskSpecificFields#setPercentWorkComplete(double)
1704:             */
1705:            public void setPercentWorkComplete(double percentWorkComplete) {
1706:                if (percentWorkComplete < 0)
1707:                    percentWorkComplete = 0;
1708:                if (percentWorkComplete > 1)
1709:                    percentWorkComplete = 1;
1710:                double workValue = percentWorkComplete * calcSummedWork();
1711:                //		System.out.println("work value is " +
1712:                // DurationFormat.format((long)workValue) +" get work null is " +
1713:                // DurationFormat.format(calcSummedWork()));
1714:
1715:                long date = ReverseQuery.getDateAtValue(WORK, this , workValue,
1716:                        true); // allow use of default assignments
1717:                DeepChildWalker.recursivelyTreatBranch(getProject()
1718:                        .getTaskOutline(), this , new NumberClosure(date) {
1719:                    public void execute(Object arg0) {
1720:                        if (arg0 == null)
1721:                            return;
1722:                        Object nodeObject = ((Node) arg0).getImpl();
1723:                        if (nodeObject instanceof  NormalTask) // do not treat assignments
1724:                            ((NormalTask) nodeObject)
1725:                                    .setStopNoExtend(getLongValue());
1726:                    }
1727:                });
1728:
1729:            }
1730:
1731:            //	/*
1732:            //	 * (non-Javadoc)
1733:            //	 * 
1734:            //	 * @see com.projity.pm.criticalpath.ScheduleWindow#getScheduleChildren()
1735:            //	 */
1736:            //	public Collection getScheduleChildren() {
1737:            //		return getWbsChildrenNodes();
1738:            //	}
1739:
1740:            /**
1741:             * Cleans up all links to and form this task and removes all assignments,
1742:             * including baseline ones.
1743:             * 
1744:             * @param eventSource -
1745:             *            if not null, then events will be sent indicating the removal
1746:             *            of links and assignments
1747:             */
1748:            void cleanUp(Object eventSource, boolean deep, boolean undo,
1749:                    boolean cleanDependencies) {
1750:                super .cleanUp(eventSource, deep, undo, cleanDependencies); // gets rid of dependencies
1751:
1752:                // for all snapshots
1753:                if (deep) {
1754:                    TaskSnapshot snapshot;
1755:                    for (int i = 0; i < Settings.numBaselines(); i++) {
1756:                        Integer snapshotId = new Integer(i);
1757:                        snapshot = (TaskSnapshot) getSnapshot(snapshotId);
1758:                        if (snapshot != null) {
1759:                            // send events only for current snapshot
1760:                            Object useEventSource = (getCurrentSnapshot() == snapshot) ? eventSource
1761:                                    : null;
1762:
1763:                            LinkedList toRemove = new LinkedList(); //fix
1764:                            AssignmentService.getInstance().remove(
1765:                                    snapshot.getAssignments(), toRemove);
1766:                            AssignmentService.getInstance().remove(toRemove,
1767:                                    useEventSource, false);
1768:
1769:                            if (snapshot != getCurrentSnapshot())
1770:                                getProject().fireBaselineChanged(eventSource,
1771:                                        this , snapshotId, false);
1772:                        }
1773:
1774:                    }
1775:                }
1776:            }
1777:
1778:            /*
1779:             * (non-Javadoc)
1780:             * 
1781:             * @see com.projity.pm.assignment.HasTimeDistributedData#childrenToRollup()
1782:             */
1783:            public Collection childrenToRollup() {
1784:                return ((TaskSnapshot) getCurrentSnapshot())
1785:                        .getHasAssignments().childrenToRollup();
1786:            }
1787:
1788:            // some functions useful for API
1789:            public double getCost() {
1790:                return getCost(null);
1791:            }
1792:
1793:            public double getBaselineCost() {
1794:                return getBaselineCost(0, null);
1795:            }
1796:
1797:            public double getBaselineCost(int number) {
1798:                return getBaselineCost(number, null);
1799:            }
1800:
1801:            public double getWork() {
1802:                return getWork(null);
1803:            }
1804:
1805:            public double getBaselineWork() {
1806:                return getBaselineWork(0, null);
1807:            }
1808:
1809:            public double getBaselineWork(int number) {
1810:                return getBaselineWork(number, null);
1811:            }
1812:
1813:            /**
1814:             *  Useful for drawing bars
1815:             */
1816:            public long getTotalSlackStart() {
1817:                return (getConstraintType() == ConstraintType.ALAP) ? getEarlyStart()
1818:                        : getEarlyFinish();
1819:
1820:            }
1821:
1822:            /**
1823:             *  Useful for drawing bars
1824:             */
1825:            public long getTotalSlackEnd() {
1826:                return (getConstraintType() == ConstraintType.ALAP) ? getLateStart()
1827:                        : getLateFinish();
1828:            }
1829:
1830:            /**
1831:             * Offset the given date by the duration of the remaining duration.
1832:             */
1833:            public long calcOffsetFrom(long startDate, long dependencyDate,
1834:                    boolean ahead, boolean remainingOnly, boolean useSooner) {
1835:
1836:                //		This is a task based implementation- for parents dont use their assignments
1837:                if (isWbsParent()) {
1838:                    long d = remainingOnly ? Duration
1839:                            .millis(getRemainingDuration())
1840:                            : getDurationMillis();
1841:                    if (!ahead)
1842:                        d = -d;
1843:                    return getEffectiveWorkCalendar().add(startDate, d,
1844:                            useSooner);
1845:                }
1846:                //		
1847:                //		
1848:                //		This is an assignment based implementation
1849:
1850:                Iterator i = getAssignments().iterator();
1851:                long result;
1852:                Assignment assignment;
1853:                if (startDate < 0)
1854:                    result = ahead ? Long.MIN_VALUE : 0;
1855:                else
1856:                    result = ahead ? 0 : Long.MAX_VALUE;
1857:                while (i.hasNext()) {
1858:                    assignment = (Assignment) i.next();
1859:                    long offsetDate = assignment.calcOffsetFrom(startDate,
1860:                            dependencyDate, ahead, remainingOnly, useSooner);
1861:                    result = ahead ? Math.max(result, offsetDate) : Math.min(
1862:                            result, offsetDate);
1863:                }
1864:                return result;
1865:            }
1866:
1867:            /* (non-Javadoc)
1868:             * @see com.projity.pm.assignment.HasAssignments#calcActiveAssignmentDuration(com.projity.pm.calendar.WorkCalendar)
1869:             */
1870:            public long calcActiveAssignmentDuration(
1871:                    WorkCalendar workCalendarToUse) {
1872:                return ((TaskSnapshot) getCurrentSnapshot())
1873:                        .calcActiveAssignmentDuration(workCalendarToUse);
1874:            }
1875:
1876:            /**
1877:             * Move remaining work to date - used when doing a project update for this task
1878:             */
1879:            public void moveRemainingToDate(long date) {
1880:                date = getEffectiveWorkCalendar().adjustInsideCalendar(date,
1881:                        false);
1882:                if (getActualStart() == 0L)
1883:                    setStart(date); // if not started, change start
1884:                else if (inProgress()) {
1885:                    Iterator i = getAssignments().iterator();
1886:                    Assignment assignment;
1887:                    while (i.hasNext()) {
1888:                        assignment = (Assignment) i.next();
1889:                        assignment.moveRemainingToDate(date);
1890:                    }
1891:                } // do nothing for completed tasks
1892:            }
1893:
1894:            /* (non-Javadoc)
1895:             * @see com.projity.pm.scheduling.Schedule#moveInterval(java.lang.Object, long, long, com.projity.pm.scheduling.ScheduleInterval)
1896:             */
1897:            public void moveInterval(Object eventSource, long start, long end,
1898:                    ScheduleInterval oldInterval, boolean isChild) {
1899:                WorkCalendar cal = getEffectiveWorkCalendar();
1900:                start = cal.adjustInsideCalendar(start, false);
1901:                boolean shifting = cal.compare(start, oldInterval.getStart(),
1902:                        false) != 0;
1903:                long assignmentStart = getEarliestAssignmentStart();
1904:                long amountFromStart = cal.compare(oldInterval.getStart(),
1905:                        assignmentStart, false); // possible that they are not the same but there is no working time between them
1906:                if (shifting && amountFromStart == 0L) { // see if first bar shifted -The first bar is drawn from the first assignment and not from the task start.
1907:                    // To figure out the new task start, see how much the shift of this bar is, then apply that difference to the task start
1908:                    long shift = cal.compare(start, assignmentStart, false);
1909:                    long newTaskStart = cal.add(getStart(), shift, false);
1910:                    setStart(newTaskStart);
1911:                } else {
1912:                    long amount = cal.compare(end, oldInterval.getEnd(), false);
1913:                    if (amount == 0L) // skip if nothing moved
1914:                        return;
1915:
1916:                    Iterator i = getAssignments().iterator();
1917:                    Assignment assignment;
1918:                    while (i.hasNext()) {
1919:                        assignment = (Assignment) i.next();
1920:                        assignment.moveInterval(eventSource, start, end,
1921:                                oldInterval, true);
1922:                    }
1923:                }
1924:                setRawDuration(getDurationMillis()); // this fixes all sorts of pbs
1925:
1926:                recalculate(eventSource); // need to recalculate
1927:                assignParentActualDatesFromChildren();
1928:
1929:                //		//Undo
1930:                //		UndoableEditSupport undoableEditSupport=getProject().getUndoController().getEditSupport();
1931:                //		if (undoableEditSupport!=null&&!(eventSource instanceof UndoableEdit)){
1932:                //			undoableEditSupport.postEdit(new ScheduleEdit(this,new ScheduleInterval(start,end),oldInterval,isChild,eventSource));
1933:                //		}
1934:
1935:            }
1936:
1937:            /* (non-Javadoc)
1938:             * @see com.projity.pm.scheduling.Schedule#split(java.lang.Object, long, long)
1939:             */
1940:            public void split(Object eventSource, long from, long to) {
1941:                from = getEffectiveWorkCalendar().adjustInsideCalendar(from,
1942:                        false);
1943:                to = getEffectiveWorkCalendar().adjustInsideCalendar(to, false);
1944:
1945:                if (from == to) { // if from is same as two, split one day
1946:                    to = getEffectiveWorkCalendar().add(from,
1947:                            CalendarOption.getInstance().getMillisPerDay(),
1948:                            false);
1949:                }
1950:
1951:                Iterator i = getAssignments().iterator();
1952:                Assignment assignment;
1953:                while (i.hasNext()) {
1954:                    assignment = (Assignment) i.next();
1955:                    assignment.split(eventSource, from, to);
1956:                }
1957:                recalculate(eventSource); // need to recalculate
1958:                assignParentActualDatesFromChildren();
1959:
1960:            }
1961:
1962:            protected transient static BarClosure barClosureInstance = new BarClosure();
1963:
1964:            public void consumeIntervals(IntervalConsumer consumer) {
1965:                if (isWbsParent() || isSubproject()) { //TODO this shouldn't be needed since default assignment should be ok.  See why
1966:                    consumer.consumeInterval(new ScheduleInterval(getStart(),
1967:                            getEnd()));
1968:                    return;
1969:                }
1970:                barClosureInstance.initialize(consumer, this );
1971:                forEachWorkingInterval(barClosureInstance, true,
1972:                        getEffectiveWorkCalendar());
1973:
1974:                // Below is a hack to prevent hanging on void node promotion
1975:                if (barClosureInstance.getCount() == 0) { // if no bars drawn
1976:                    consumer.consumeInterval(new ScheduleInterval(getStart(),
1977:                            getEnd()));
1978:                }
1979:            }
1980:
1981:            /**
1982:             * Overloads task setEnd but calls it
1983:             */
1984:            public void setEnd(long end) {
1985:                long start = getStart();
1986:                if (start == 0) { // if the end date is entered on a new line creating the task need to set the start correctly
1987:                    start = CalendarOption.getInstance().makeValidStart(
1988:                            DateTime.midnightToday(), true);
1989:                    getCurrentSchedule().setStart(start);
1990:                }
1991:                end = CalendarOption.getInstance().makeValidEnd(end, true);
1992:                if (end < start)
1993:                    end = start;
1994:                long oldEnd = getEnd();
1995:                if (end != oldEnd) {
1996:                    super .setEnd(end);
1997:                    Iterator i = getAssignments().iterator();
1998:                    Assignment assignment;
1999:                    while (i.hasNext()) {
2000:                        assignment = (Assignment) i.next();
2001:                        assignment.setEnd(end);
2002:                    }
2003:                    //			System.out.println("Old End"  + new Date(oldEnd) + " input end " + new Date(end )+ " resulting End " + new Date(getEnd()) + " duration " + DurationFormat.format(getDuration()));
2004:                    setRawDuration(getDurationMillis());
2005:                }
2006:                assignParentActualDatesFromChildren();
2007:            }
2008:
2009:            /**
2010:             * @param actualStart
2011:             */
2012:            public void setActualStart(long actualStart) {
2013:                actualStart = getEffectiveWorkCalendar().adjustInsideCalendar(
2014:                        actualStart, false); //TODO not good if it starts off calendar
2015:
2016:                setActualStartNoEvent(actualStart);
2017:                markTaskAsNeedingRecalculation();
2018:                getProject().fireScheduleChanged(this , ScheduleEvent.ACTUAL,
2019:                        this );
2020:            }
2021:
2022:            public void setActualStartNoEvent(long actualStart) {
2023:                long old = getActualStart();
2024:                if (actualStart == old)
2025:                    return;
2026:                //		if (actualStart != 0) {
2027:                //			if (getPercentComplete() == 0) {
2028:                //				currentSchedule.setPercentComplete(INSTANT_COMPLETION);
2029:                //				setPercentComplete(INSTANT_COMPLETION);
2030:                //			}
2031:                //			currentSchedule.setStart(actualStart);
2032:                //		}
2033:                this .actualStart = actualStart;
2034:                assignParentActualDatesFromChildren();
2035:
2036:            }
2037:
2038:            /* (non-Javadoc)
2039:             * @see com.projity.pm.task.TaskSpecificFields#isIgnoreResourceCalendar()
2040:             */
2041:            public boolean isIgnoreResourceCalendar() {
2042:                return ((TaskSnapshot) getCurrentSnapshot())
2043:                        .isIgnoreResourceCalendar();
2044:            }
2045:
2046:            /* (non-Javadoc)
2047:             * @see com.projity.pm.task.TaskSpecificFields#setIgnoreResourceCalendar(boolean)
2048:             */
2049:            public void setIgnoreResourceCalendar(boolean ignoreResourceCalendar) {
2050:                ((TaskSnapshot) getCurrentSnapshot())
2051:                        .setIgnoreResourceCalendar(ignoreResourceCalendar);
2052:            }
2053:
2054:            public boolean isDefault() {
2055:                return this  == UNASSIGNED;
2056:            }
2057:
2058:            private static short DEFAULT_VERSION = 2;
2059:            private short version = DEFAULT_VERSION;
2060:
2061:            public short getVersion() {
2062:                return version;
2063:            }
2064:
2065:            /* The serialization version must be private. This lets subclasses call this code */
2066:            protected void doWriteObject(ObjectOutputStream s)
2067:                    throws IOException {
2068:                s.defaultWriteObject();
2069:                hasKey.serialize(s);
2070:                customFields.serialize(s);
2071:                if (version < 1)
2072:                    currentSchedule.serialize(s);
2073:                else {
2074:                    int sCount = 0;
2075:                    for (int i = 0; i < Settings.numBaselines(); i++) {
2076:                        TaskSnapshot snapshot = (TaskSnapshot) getSnapshot(new Integer(
2077:                                i));
2078:                        if (snapshot != null)
2079:                            sCount++;
2080:                    }
2081:                    s.writeInt(sCount);
2082:                    for (int i = 0; i < Settings.numBaselines(); i++) {
2083:                        TaskSnapshot snapshot = (TaskSnapshot) getSnapshot(new Integer(
2084:                                i));
2085:                        if (snapshot == null)
2086:                            continue;
2087:                        s.writeInt(i);
2088:                        snapshot.serialize(s);
2089:                    }
2090:                }
2091:            }
2092:
2093:            private void writeObject(ObjectOutputStream s) throws IOException {
2094:                doWriteObject(s);
2095:            }
2096:
2097:            private void readObject(ObjectInputStream s) throws IOException,
2098:                    ClassNotFoundException {
2099:                s.defaultReadObject();
2100:
2101:                hasKey = HasKeyImpl.deserialize(s, this );
2102:                customFields = CustomFieldsImpl.deserialize(s);
2103:                if (version < 1)
2104:                    currentSchedule = TaskSchedule.deserialize(s);
2105:                else {
2106:                    snapshots = new SnapshottableImpl(Settings.numBaselines());
2107:                    int sCount = s.readInt();
2108:                    for (int i = 0; i < sCount; i++) {
2109:                        int snapshotId = s.readInt();
2110:                        TaskSnapshot snapshot = TaskSnapshot.deserialize(s,
2111:                                this );
2112:                        setSnapshot(new Integer(snapshotId), snapshot);
2113:                    }
2114:                }
2115:
2116:                if (version < 1)
2117:                    super .initializeTransientTaskObjects();
2118:                else
2119:                    super .initializeTransientTaskObjectsAfterDeserialization();
2120:                //	    barClosureInstance = new BarClosure();
2121:                //	    This shouldn't be called -hk 4/feb/05 
2122:                //	    initializeDates();
2123:
2124:                version = DEFAULT_VERSION;
2125:            }
2126:
2127:            public Object clone() {
2128:                Task task = (Task) super .clone();
2129:                //		task.barClosureInstance = new BarClosure();
2130:
2131:                return task;
2132:            }
2133:
2134:            public void cloneTo(Task task) {
2135:                if (task instanceof  NormalTask) {
2136:                    NormalTask n = (NormalTask) task;
2137:                    n.estimated = estimated;
2138:                    n.priority = priority;
2139:                    n.version = version;
2140:                    n.workCalendar = workCalendar;
2141:                }
2142:
2143:                super .cloneTo(task);
2144:            }
2145:
2146:            public void serialize(ObjectOutputStream s) throws IOException {
2147:            }
2148:
2149:            public boolean isReadOnlyWork(FieldContext fieldContext) {
2150:                if (!hasLaborAssignment())
2151:                    return true;
2152:                if (fieldContext == null)
2153:                    return false;
2154:                return !hasActiveAssignment(fieldContext.getStart(),
2155:                        fieldContext.getEnd());
2156:            }
2157:
2158:            public void setActualWork(long actualWork, FieldContext context) {
2159:
2160:                if (FieldContext.hasInterval(context)) {
2161:                    Iterator i = getAssignments().iterator();
2162:                    while (i.hasNext()) {
2163:                        Assignment assignment = (Assignment) i.next();
2164:                        assignment.setActualWork(actualWork, context);
2165:                    }
2166:                } else {
2167:                    long workValue = Duration.millis(actualWork);
2168:                    if (workValue == 0L) {
2169:                        setPercentComplete(0);
2170:                    } else {
2171:                        long date = ReverseQuery.getDateAtValue(WORK, this ,
2172:                                workValue, false);
2173:                        setStop(date);
2174:                    }
2175:                }
2176:            }
2177:
2178:            public boolean isReadOnlyActualWork(FieldContext fieldContext) {
2179:                return false;
2180:            }
2181:
2182:            public void setRemainingWork(long remainingWork,
2183:                    FieldContext fieldContext) {
2184:                setActualWork(getWork(fieldContext)
2185:                        - Duration.millis(remainingWork), fieldContext);
2186:            }
2187:
2188:            public boolean isReadOnlyRemainingWork(FieldContext fieldContext) {
2189:                return isReadOnlyWork(fieldContext);
2190:            }
2191:
2192:            /* (non-Javadoc)
2193:             * @see com.projity.pm.assignment.TimeDistributedFields#setFixedCost(double, com.projity.field.FieldContext)
2194:             */
2195:            public void setFixedCost(double fixedCost, FieldContext fieldContext) {
2196:                if (!FieldContext.hasInterval(fieldContext))
2197:                    setFixedCost(fixedCost);
2198:            }
2199:
2200:            /* (non-Javadoc)
2201:             * @see com.projity.pm.assignment.TimeDistributedFields#isReadOnlyFixedCost(com.projity.field.FieldContext)
2202:             */
2203:            public boolean isReadOnlyFixedCost(FieldContext fieldContext) {
2204:                return FieldContext.hasInterval(fieldContext);
2205:            }
2206:
2207:            /* (non-Javadoc)
2208:             * @see com.projity.pm.assignment.HasTimeDistributedData#isLabor()
2209:             */
2210:            public boolean isLabor() {
2211:                return true;
2212:            }
2213:
2214:            /* (non-Javadoc)
2215:             * @see com.projity.pm.assignment.HasAssignments#hasLaborAssignment()
2216:             */
2217:            public boolean hasLaborAssignment() {
2218:                return ((TaskSnapshot) getCurrentSnapshot())
2219:                        .hasLaborAssignment();
2220:            }
2221:
2222:            public void setRawDuration(long duration) {
2223:                currentSchedule.setRawDuration(duration);
2224:            }
2225:
2226:            public void setParentDuration() {
2227:                if (!isWbsParent())
2228:                    return;
2229:                currentSchedule.assignDatesFromChildren();
2230:                long duration = getDurationMillis();
2231:                getSchedulingRule().adjustRemainingDuration(this ,
2232:                        duration - Duration.millis(getActualDuration()), true);
2233:            }
2234:
2235:            /* (non-Javadoc)
2236:             * @see com.projity.pm.assignment.HasAssignments#invalidateAssignmentCalendars()
2237:             */
2238:            public void invalidateAssignmentCalendars() {
2239:                ((TaskSnapshot) getCurrentSnapshot())
2240:                        .invalidateAssignmentCalendars();
2241:            }
2242:
2243:            /* (non-Javadoc)
2244:             * @see com.projity.pm.calendar.HasCalendar#invalidateCalendar()
2245:             */
2246:            public Document invalidateCalendar() {
2247:                invalidateAssignmentCalendars();
2248:                markTaskAsNeedingRecalculation();
2249:                return getProject();
2250:            }
2251:
2252:            public boolean hasActiveAssignment(long start, long end) {
2253:                return ((TaskSnapshot) getCurrentSnapshot())
2254:                        .hasActiveAssignment(start, end);
2255:            }
2256:
2257:            public boolean isInvalidIntersectionCalendar() {
2258:                Iterator i = getAssignments().iterator();
2259:                while (i.hasNext()) {
2260:                    if (((Assignment) i.next()).isInvalidIntersectionCalendar())
2261:                        return true;
2262:                }
2263:                return false;
2264:            }
2265:
2266:            public HasIndicators getIndicators() {
2267:                return this ;
2268:            }
2269:
2270:            public long getEarliestAssignmentStart() {
2271:                return ((TaskSnapshot) getCurrentSnapshot())
2272:                        .getEarliestAssignmentStart();
2273:            }
2274:
2275:            public boolean isParentWithAssignments() {
2276:                return isWbsParent() && hasRealAssignments();
2277:            }
2278:
2279:            public void setComplete(boolean complete) {
2280:                ScheduleUtil.setComplete(this , complete);
2281:            }
2282:
2283:            public boolean applyTimesheet(Collection fieldArray,
2284:                    long timesheetUpdateDate) {
2285:                return TimesheetHelper.applyTimesheet(getAssignments(),
2286:                        fieldArray, timesheetUpdateDate);
2287:            }
2288:
2289:            public long getLastTimesheetUpdate() {
2290:                return TimesheetHelper.getLastTimesheetUpdate(getAssignments());
2291:            }
2292:
2293:            public boolean isPendingTimesheetUpdate() {
2294:                return TimesheetHelper
2295:                        .isPendingTimesheetUpdate(getAssignments());
2296:            }
2297:
2298:            public int getTimesheetStatus() {
2299:                return TimesheetHelper.getTimesheetStatus(getAssignments());
2300:            }
2301:
2302:            public String getTimesheetStatusName() {
2303:                return TimesheetHelper
2304:                        .getTimesheetStatusName(getTimesheetStatus());
2305:            }
2306:
2307:            public final long getEarliestStop() {
2308:                long stop = Long.MAX_VALUE;
2309:                Schedule s;
2310:                Object nodeImpl;
2311:                if (isWbsParent()) {
2312:                    Collection children = getWbsChildrenNodes();
2313:                    Iterator i = children.iterator();
2314:                    while (i.hasNext()) {
2315:                        Object x = i.next();
2316:                        if (!(x instanceof  Node))
2317:                            continue;
2318:                        nodeImpl = ((Node) x).getImpl();
2319:                        if (!(nodeImpl instanceof  Schedule))
2320:                            continue;
2321:                        s = (Schedule) nodeImpl;
2322:                        stop = Math.min(stop, s.getEarliestStop());
2323:                    }
2324:                } else {
2325:                    Iterator i = getAssignments().iterator();
2326:                    while (i.hasNext()) {
2327:                        Assignment ass = (Assignment) i.next();
2328:                        stop = Math.min(stop, ass.getEarliestStop());
2329:                    }
2330:                }
2331:                return stop;
2332:            }
2333:
2334:            public void setCompletedThrough(long completedThrough) {
2335:                completedThrough = DateTime.closestDate(completedThrough);
2336:                completedThrough = Math.min(completedThrough, getEnd());
2337:                if (completedThrough == getCompletedThrough())
2338:                    return;
2339:
2340:                Iterator i = getAssignments().iterator();
2341:                Assignment assignment;
2342:                long computedActualStart = Long.MAX_VALUE;
2343:                long assignmentActualStart;
2344:                while (i.hasNext()) {
2345:                    assignment = (Assignment) i.next();
2346:                    assignment.setCompletedThrough(completedThrough);
2347:                    assignmentActualStart = assignment.getActualStart();
2348:                    if (assignmentActualStart != 0
2349:                            && assignmentActualStart < computedActualStart)
2350:                        computedActualStart = assignmentActualStart;
2351:                }
2352:                if (computedActualStart == Long.MAX_VALUE)
2353:                    computedActualStart = 0;
2354:                setActualStart(computedActualStart);
2355:                assignParentActualDatesFromChildren();
2356:
2357:                // if % complete went down to 0, then the plan changed and need to recalculate all.
2358:                if (computedActualStart == 0) {
2359:                    getDocument().getObjectEventManager().fireUpdateEvent(this ,
2360:                            this , Configuration.getFieldFromId("Field.start"));
2361:                } else {
2362:                    //TODO duplicate event
2363:                    //TODO in the case of progress update this event is useless since critical path runs after.
2364:                    getProject().fireScheduleChanged(this ,
2365:                            ScheduleEvent.ACTUAL, this );
2366:                }
2367:            }
2368:
2369:            public long getFinishOffset() {
2370:                return EarnedValueCalculator.getInstance()
2371:                        .getFinishOffset(this );
2372:            }
2373:
2374:            public long getStartOffset() {
2375:                return EarnedValueCalculator.getInstance().getStartOffset(this );
2376:            }
2377:
2378:            public ImageLink getBudgetStatusIndicator() {
2379:                return EarnedValueCalculator.getInstance()
2380:                        .getBudgetStatusIndicator(getCpi(null));
2381:            }
2382:
2383:            public ImageLink getScheduleStatusIndicator() {
2384:                return EarnedValueCalculator.getInstance()
2385:                        .getBudgetStatusIndicator(getSpi(null));
2386:            }
2387:
2388:            public Object backupDetail() {
2389:                return backupDetail(null);
2390:            }
2391:
2392:            public Object backupDetail(Object snapshotId) {
2393:                TaskSnapshot snapshot = (TaskSnapshot) ((snapshotId == null) ? getCurrentSnapshot()
2394:                        : getSnapshot(snapshotId));
2395:                TaskSnapshotBackup snapshotBackup = TaskSnapshotBackup.backup(
2396:                        snapshot,/*snapshotId!=null*/true);
2397:                TaskBackup backup = new TaskBackup();
2398:                backup.snapshot = snapshotBackup;
2399:                backup.windowEarlyFinish = windowEarlyFinish;
2400:                backup.windowEarlyStart = windowEarlyStart;
2401:                backup.windowLateFinish = windowLateFinish;
2402:                backup.windowLateStart = windowLateStart;
2403:                backup.actualStart = actualStart;
2404:                //TODO Backup other fields? 
2405:                return backup;
2406:            }
2407:
2408:            public void restoreDetail(Object source, Object backup,
2409:                    boolean isChild) {
2410:                restoreDetail(source, backup, isChild,
2411:                        (TaskSnapshot) getCurrentSnapshot());
2412:            }
2413:
2414:            public void restoreDetail(Object source, Object backup,
2415:                    boolean isChild, TaskSnapshot snapshot) {
2416:                TaskBackup b = (TaskBackup) backup;
2417:                windowEarlyFinish = b.windowEarlyFinish;
2418:                windowEarlyStart = b.windowEarlyStart;
2419:                windowLateFinish = b.windowLateFinish;
2420:                windowLateStart = b.windowLateStart;
2421:                actualStart = b.actualStart;
2422:                TaskSnapshotBackup.restore(snapshot, b.snapshot);
2423:                if (!isChild)
2424:                    recalculate(source); //to send update event
2425:            }
2426:
2427:            public void renumber() {
2428:                forSnapshotsAssignments(new Closure() {
2429:                    public void execute(Object arg0) {
2430:                        ((Assignment) arg0).renumber();
2431:                    }
2432:                }, true);
2433:                hasKey.renumber();
2434:            }
2435:
2436:            public boolean isLocal() {
2437:                return hasKey.isLocal();
2438:            }
2439:
2440:            public void setLocal(boolean local) {
2441:                hasKey.setLocal(local);
2442:            }
2443:
2444:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.