Source Code Cross Referenced for Assignment.java in  » Project-Management » OpenProj » com » projity » pm » assignment » 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.assignment 
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:
0051:        package com.projity.pm.assignment;
0052:
0053:        import java.io.IOException;
0054:        import java.io.ObjectInputStream;
0055:        import java.io.ObjectOutputStream;
0056:        import java.util.Collection;
0057:        import java.util.Comparator;
0058:        import java.util.Date;
0059:
0060:        import org.apache.commons.collections.Closure;
0061:        import org.apache.commons.collections.Predicate;
0062:
0063:        import com.projity.algorithm.CollectionIntervalGenerator;
0064:        import com.projity.algorithm.DoubleValue;
0065:        import com.projity.algorithm.InstantIntervalGenerator;
0066:        import com.projity.algorithm.IntervalGeneratorSet;
0067:        import com.projity.algorithm.Merge;
0068:        import com.projity.algorithm.Query;
0069:        import com.projity.algorithm.RangeIntervalGenerator;
0070:        import com.projity.algorithm.ReverseQuery;
0071:        import com.projity.algorithm.SelectFrom;
0072:        import com.projity.algorithm.TimeIteratorGenerator;
0073:        import com.projity.algorithm.buffer.CalculatedValues;
0074:        import com.projity.association.Association;
0075:        import com.projity.association.InvalidAssociationException;
0076:        import com.projity.configuration.Configuration;
0077:        import com.projity.datatype.CanSupplyRateUnit;
0078:        import com.projity.datatype.Duration;
0079:        import com.projity.datatype.DurationFormat;
0080:        import com.projity.datatype.ImageLink;
0081:        import com.projity.datatype.Rate;
0082:        import com.projity.datatype.RateFormat;
0083:        import com.projity.datatype.TimeUnit;
0084:        import com.projity.document.Document;
0085:        import com.projity.field.Field;
0086:        import com.projity.field.FieldContext;
0087:        import com.projity.functor.IntervalConsumer;
0088:        import com.projity.functor.ObjectVisitor;
0089:        import com.projity.options.AdvancedOption;
0090:        import com.projity.pm.assignment.contour.AbstractContour;
0091:        import com.projity.pm.assignment.contour.AbstractContourBucket;
0092:        import com.projity.pm.assignment.contour.ContourBucketIntervalGenerator;
0093:        import com.projity.pm.assignment.contour.ContourFactory;
0094:        import com.projity.pm.assignment.contour.PersonalContour;
0095:        import com.projity.pm.assignment.functor.AssignmentFieldClosureCollection;
0096:        import com.projity.pm.assignment.functor.AssignmentFieldFunctor;
0097:        import com.projity.pm.assignment.functor.CalculatedValuesFunctor;
0098:        import com.projity.pm.assignment.functor.CostFunctor;
0099:        import com.projity.pm.assignment.functor.DateAtValueFunctor;
0100:        import com.projity.pm.assignment.functor.FixedCostFunctor;
0101:        import com.projity.pm.assignment.functor.PercentAllocFunctor;
0102:        import com.projity.pm.assignment.functor.PersonalContourMaker;
0103:        import com.projity.pm.assignment.functor.PrintValueFunctor;
0104:        import com.projity.pm.assignment.functor.ResourceAvailabilityFunctor;
0105:        import com.projity.pm.assignment.functor.ValueAtInstant;
0106:        import com.projity.pm.assignment.functor.WorkComparator;
0107:        import com.projity.pm.assignment.functor.WorkFunctor;
0108:        import com.projity.pm.assignment.functor.ZeroFunctor;
0109:        import com.projity.pm.assignment.timesheet.AssignmentWorkflowState;
0110:        import com.projity.pm.assignment.timesheet.TimesheetHelper;
0111:        import com.projity.pm.assignment.timesheet.TimesheetStatus;
0112:        import com.projity.pm.assignment.timesheet.UpdatesFromTimesheet;
0113:        import com.projity.pm.calendar.WorkCalendar;
0114:        import com.projity.pm.costing.Accrual;
0115:        import com.projity.pm.costing.EarnedValueCalculator;
0116:        import com.projity.pm.costing.EarnedValueFields;
0117:        import com.projity.pm.costing.EarnedValueValues;
0118:        import com.projity.pm.costing.HasCostRateIndex;
0119:        import com.projity.pm.criticalpath.TaskSchedule;
0120:        import com.projity.pm.key.HasKey;
0121:        import com.projity.pm.key.HasKeyImpl;
0122:        import com.projity.pm.resource.Resource;
0123:        import com.projity.pm.resource.ResourceImpl;
0124:        import com.projity.pm.scheduling.BarClosure;
0125:        import com.projity.pm.scheduling.ConstraintType;
0126:        import com.projity.pm.scheduling.Delayable;
0127:        import com.projity.pm.scheduling.Schedule;
0128:        import com.projity.pm.scheduling.ScheduleInterval;
0129:        import com.projity.pm.scheduling.ScheduleUtil;
0130:        import com.projity.pm.scheduling.SchedulingType;
0131:        import com.projity.pm.snapshot.Snapshottable;
0132:        import com.projity.pm.task.BelongsToDocument;
0133:        import com.projity.pm.task.NormalTask;
0134:        import com.projity.pm.task.Project;
0135:        import com.projity.pm.task.Task;
0136:        import com.projity.pm.time.HasStartAndEnd;
0137:        import com.projity.pm.time.ImmutableInterval;
0138:        import com.projity.pm.time.Interval;
0139:        import com.projity.pm.time.MutableInterval;
0140:        import com.projity.server.data.DataObject;
0141:        import com.projity.strings.Messages;
0142:        import com.projity.util.Alert;
0143:        import com.projity.util.Environment;
0144:
0145:        /**
0146:         * Class representing resource assignments
0147:         * @stereotype thing 
0148:         */
0149:        public final class Assignment implements  Schedule, Association,
0150:                Allocation, Delayable, HasTimeDistributedData,
0151:                TimeDistributedFields, EarnedValueValues, EarnedValueFields,
0152:                AssignmentSpecificFields, HasKey, BelongsToDocument,
0153:                HasRequestDemandType, UpdatesFromTimesheet, CanSupplyRateUnit,
0154:                HasCostRateIndex, Cloneable, DataObject {
0155:            static final long serialVersionUID = 56779404923241L;
0156:            AssignmentDetail detail = null;
0157:            private transient HasKeyImpl hasKey = new HasKeyImpl(true, this ); //local ids only for assignments
0158:
0159:            private static Field unitsFieldInstance = null;
0160:
0161:            private transient Date cachedStart = null;
0162:            private transient Date cachedEnd = null;
0163:            private transient int timesheetStatus = TimesheetStatus.NO_DATA;
0164:            private transient long lastTimesheetUpdate = 0;
0165:            private transient int workflowState = AssignmentWorkflowState.NEW;
0166:            private transient boolean timesheetAssignment = false;
0167:
0168:            public static Field getUnitsField() {
0169:                if (unitsFieldInstance == null)
0170:                    unitsFieldInstance = Configuration
0171:                            .getFieldFromId("Field.assignmentUnits");
0172:                return unitsFieldInstance;
0173:            }
0174:
0175:            private static Field rateFieldInstance = null;
0176:
0177:            public static Field getRateField() {
0178:                if (rateFieldInstance == null)
0179:                    rateFieldInstance = Configuration
0180:                            .getFieldFromId("Field.rate");
0181:                return rateFieldInstance;
0182:            }
0183:
0184:            private static Field requestDemandTypeInstance = null;
0185:
0186:            public static Field getRequestDemandTypeField() {
0187:                if (requestDemandTypeInstance == null)
0188:                    requestDemandTypeInstance = Configuration
0189:                            .getFieldFromId("Field.requestDemandType");
0190:                return requestDemandTypeInstance;
0191:            }
0192:
0193:            public static Assignment getInstance(Task task, Resource resource,
0194:                    double units, int requestDemandType) {
0195:                return new Assignment(task, resource, units, requestDemandType);
0196:            }
0197:
0198:            public static Assignment getInstance(Task task, Resource resource,
0199:                    double units, long delay) {
0200:                return new Assignment(task, resource, units, delay);
0201:            }
0202:
0203:            /**
0204:             * Construct an assignment.  The arguments are those that are presented in the assign resource dialog
0205:             * @param task
0206:             * @param resource
0207:             * @param units
0208:             * @param requestDemandType  -Normally empty
0209:             */
0210:            private Assignment(Task task, Resource resource, double units,
0211:                    int requestDemandType) {
0212:                detail = new AssignmentDetail(task, resource, units,
0213:                        requestDemandType, 0);
0214:            }
0215:
0216:            public Assignment(Assignment from) {
0217:                detail = from.detail;
0218:            }
0219:
0220:            public Assignment(AssignmentDetail detail) {
0221:                this .detail = detail;
0222:            }
0223:
0224:            public boolean isReadOnly() {
0225:                return getTask().isReadOnly();
0226:            }
0227:
0228:            public boolean isExternal() {
0229:                return getTask().isExternal();
0230:            }
0231:
0232:            public static Predicate instanceof Predicate() {
0233:                return new Predicate() {
0234:                    public boolean evaluate(Object arg0) {
0235:                        return arg0 instanceof  Assignment;
0236:                    }
0237:                };
0238:            }
0239:
0240:            /**
0241:             * Copy the properies from another assignment.  This also includes the contour. However, it does NOT
0242:             * include the resource or the units.  This is called in the context of replacing an assignment. 
0243:             * @param from Assignment to copy from
0244:             */
0245:            public void usePropertiesOf(Assignment from) {
0246:                boolean compatibleTypes = isLabor() == from.isLabor();
0247:                double units = getUnits();
0248:                Rate r = getRate();
0249:                Resource resource = getResource();
0250:                detail = (AssignmentDetail) from.detail.clone();
0251:                detail.replaceResourceAndUnits(units, resource);
0252:
0253:                if (!compatibleTypes) // don't want to set units if not compatible
0254:                    detail.setRate(r);
0255:            }
0256:
0257:            public void setStart(long start) {
0258:                detail.setStart(start);
0259:            }
0260:
0261:            public int getRequestDemandType() {
0262:                return detail.getRequestDemandType();
0263:            }
0264:
0265:            public void setRequestDemandType(int requestDemandType) {
0266:                newDetail().setRequestDemandType(requestDemandType);
0267:            }
0268:
0269:            public AbstractContourBucket[] getContour(Object type) {
0270:                return detail.getContour(type);
0271:            }
0272:
0273:            /**
0274:             * Constructor adapted to mpx
0275:             * @param task
0276:             * @param resource
0277:             * @param units
0278:             * @param delay
0279:             */
0280:            private Assignment(Task task, Resource resource, double units,
0281:                    long delay) {
0282:                detail = new AssignmentDetail(task, resource, units,
0283:                        RequestDemandType.NONE, delay);
0284:            }
0285:
0286:            /**
0287:             * Accessor for units (value of work)
0288:             * @return units
0289:             */
0290:            public final double getUnits() {
0291:                return detail.getUnits();
0292:            }
0293:
0294:            public final double getLaborUnits() {
0295:                if (isLabor())
0296:                    return getUnits();
0297:                return 0.0D;
0298:            }
0299:
0300:            public void setOvertimeWork(long overtimeWork) {
0301:                newDetail().setOvertimeWork(overtimeWork);
0302:            }
0303:
0304:            /**
0305:             * For use in sharing with external systems such as salesforce. Uniquely identifies object
0306:             * @return
0307:             */
0308:            public String toExternalId() {
0309:                return getResourceId() + "." + getTaskId();
0310:            }
0311:
0312:            public String toString() {
0313:                return getTask() + "/" + getResource(); //super.toString();
0314:                //		return "[start] " + new java.util.Date(getStart())
0315:                //		      + "\n[end] " +  new java.util.Date(getEnd())
0316:                //			  +"\n[units] " + getUnits()// in hours
0317:                //			  +"\n[work] " + getWork() / (1000*60*60); // in hours
0318:            }
0319:
0320:            /**
0321:             * @return Returns the contour.
0322:             */
0323:            public AbstractContour getWorkContour() {
0324:                return detail.getWorkContour();
0325:            }
0326:
0327:            /**
0328:             * @param contour The contour to set.
0329:             * TODO get rid of this
0330:             */
0331:            public void debugSetWorkContour(AbstractContour contour) {
0332:                newDetail().setWorkContour(contour);
0333:            }
0334:
0335:            /**
0336:             * Accessor for the assignment's delay
0337:             * @return delay
0338:             */
0339:            public long getDelay() {
0340:                return detail.getDelay();
0341:            }
0342:
0343:            public void setDelay(long delay) {
0344:                newDetail().setDelay(delay);
0345:            }
0346:
0347:            public long getLevelingDelay() {
0348:                return detail.getLevelingDelay();
0349:            }
0350:
0351:            public void setLevelingDelay(long levelingDelay) {
0352:                newDetail().setLevelingDelay(levelingDelay);
0353:            }
0354:
0355:            /**
0356:             * @return Returns the duration.
0357:             */
0358:            public long getDurationMillis() {
0359:                return detail.getDuration();
0360:            }
0361:
0362:            private void setDurationMillis(long durationMillis) {
0363:                newDetail().setDuration(durationMillis);
0364:            }
0365:
0366:            public void setDuration(long duration) {
0367:                adjustRemainingDuration(duration - getActualDuration(), false);
0368:            }
0369:
0370:            /**
0371:             * @param duration The duration to set.
0372:             */
0373:            public void adjustRemainingDuration(long newRemainingDuration,
0374:                    boolean doChildren) {
0375:                long old = getRemainingDuration();
0376:                newRemainingDuration = Duration.millis(newRemainingDuration); // don't use time unit
0377:                if (getUnits() == 0) // take care of degenerate case
0378:                    newRemainingDuration = 0;
0379:                newDetail().adjustRemainingDuration(newRemainingDuration);
0380:
0381:                //TODO commented out may 8 2007		
0382:                //		if (getTaskSchedulingType() == SchedulingType.FIXED_WORK && newRemainingDuration != 0) {
0383:                //			double multiplier = ((double)old) / newRemainingDuration;
0384:                //			if (multiplier > 0) {
0385:                //				detail.setWorkContour(detail.getWorkContour().adjustUnits(multiplier, getActualDuration()));
0386:                //				detail.setUnits(getUnits() * multiplier);
0387:                //			}
0388:                //		}
0389:
0390:            }
0391:
0392:            public void adjustRemainingDurationIfWorkingAtTaskEnd(
0393:                    long newRemainingDuration) {
0394:                if (getEnd() >= getTask().getEnd() || !isInitialized())
0395:                    adjustRemainingDuration(newRemainingDuration, false);
0396:            }
0397:
0398:            public void adjustRemainingWork(double multiplier,
0399:                    boolean doChildren) {
0400:                if (getPercentComplete() > 0.0D) // if actuals, then remaining may have different contour
0401:                    makeContourPersonal(); //fix?
0402:                newDetail().adjustRemainingWork(multiplier);
0403:            }
0404:
0405:            /**
0406:             * @param units The units to set.
0407:             */
0408:            public void adjustRemainingUnits(double newRemainingUnits,
0409:                    double oldRemainingUnits, boolean doChildren,
0410:                    boolean conserveTotalUnits) {
0411:                if (!isTemporal()) // for absolute quantities, don't change
0412:                    return;
0413:                oldRemainingUnits = getRemainingUnits();
0414:                NormalTask task = (NormalTask) getTask();
0415:                //	task.adjustUnitsDelta(newRemainingUnits - oldRemainingUnits);
0416:                if (doChildren) {
0417:                    task.getSchedulingRule().adjustRemainingUnits(this ,
0418:                            newRemainingUnits, oldRemainingUnits, false, false);
0419:                } else { // just treat the assignment
0420:                    if (getPercentComplete() > 0.0D) // if actuals, then remaining may have different contour
0421:                        makeContourPersonal();
0422:
0423:                    newDetail().adjustRemainingUnits(newRemainingUnits);
0424:                }
0425:            }
0426:
0427:            public void setWork(long work, FieldContext context) {
0428:                work = Duration.millis(work);
0429:                if (isLabor() && work < 60000) {
0430:                    work *= Duration.timeUnitFactor(TimeUnit.HOURS);
0431:                    System.out
0432:                            .println("modifying invalid work to make it hours");
0433:                }
0434:                long remainingWork = work - getActualWork(null);
0435:                WorkCalendar cal = getEffectiveWorkCalendar();
0436:                if (!FieldContext.hasInterval(context)) {
0437:                    long currentRemainingWork = Duration
0438:                            .millis(getWork(context))
0439:                            - Duration.millis(getActualWork(context));
0440:                    if (currentRemainingWork == 0 && remainingWork == 0)
0441:                        adjustRemainingUnits(0, 0, true, false); //TODO is this ok?
0442:                    else {
0443:                        if (getTaskSchedulingType() == SchedulingType.FIXED_UNITS)
0444:                            adjustRemainingDuration(remainingWork, false);
0445:                        else if (getTaskSchedulingType() == SchedulingType.FIXED_DURATION
0446:                                && currentRemainingWork > 0)
0447:                            adjustRemainingWork(((double) remainingWork)
0448:                                    / currentRemainingWork, true);
0449:                        //					newDetail().setWorkContour(getWorkContour().adjustUnits((((double)remainingWork) / currentRemainingWork), getActualDuration()));
0450:
0451:                        else
0452:                            newDetail().adjustRemainingDuration(remainingWork); // just set duration
0453:
0454:                    }
0455:                } else {
0456:                    long start = cal.adjustInsideCalendar(context.getStart(),
0457:                            false);
0458:                    long end = cal.adjustInsideCalendar(context.getEnd(), true);
0459:                    if (end > start)
0460:                        setWorkInterval(start, end, work);
0461:                    if (getRate().getValue() == 0.0D) {// special case if units was 0
0462:                        double rate = ((double) work)
0463:                                / cal.compare(end, start, false); // use rate for the period as the assignment's rate
0464:                        this .forceUnits(rate);
0465:                    }
0466:                }
0467:            }
0468:
0469:            private boolean addWorkingTimeIfRequired(long work,
0470:                    FieldContext context, boolean actual) {
0471:                WorkCalendar cal = getEffectiveWorkCalendar();
0472:                // adjust start and end inside the calendar
0473:                long start = cal
0474:                        .adjustInsideCalendar(context.getStart(), false);
0475:                long end = cal.adjustInsideCalendar(context.getEnd(), true);
0476:                if (work != 0 && !verifyBounds(start, end))
0477:                    return false;
0478:
0479:                // if adding during non calendar time
0480:                if (end <= start && work != 0) {
0481:                    start = context.getStart();
0482:                    end = context.getEnd();
0483:                    //		example 10 day task -	MTWTFSSMTWTF				
0484:                    //		initial bar:        	=====  =====
0485:                    //		calendar time add    	====== ====   here I make a saturday working, so the task finishes sooner
0486:                    //        shift the saturday   	=====  =====  shifting the saturday puts the task back as it was
0487:                    //		set the interval     	====== =====  now I set the saturday value		
0488:
0489:                    //			System.out.println("before adding" + getWorkContour());
0490:                    addCalendarTime(start, end);
0491:                    cal = getEffectiveWorkCalendar();
0492:                    if (actual && getTask().getActualStart() == 0) {
0493:                        long taskStart = cal.adjustInsideCalendar(start, false);
0494:                        ((NormalTask) getTask())
0495:                                .setActualStartNoEvent(taskStart);
0496:                    }
0497:                    long addedDuration = cal.compare(end, start, false);
0498:                    //			System.out.println("before shift" + getWorkContour());
0499:                    shift(start, end, addedDuration); // shift the remaining contour to the right by the duration of the inserted time
0500:                    //			System.out.println("after shift" + getWorkContour());
0501:
0502:                    getTask().recalculateLater(this ); // task needs to be recalculated
0503:
0504:                    //		SwingUtilities.invokeLater(new Runnable());
0505:
0506:                }
0507:                return true;
0508:            }
0509:
0510:            public void makeFlatIfPossible() {
0511:                if (getWorkContour().isPersonal()) {
0512:                    detail.recalculateDuration(); // set duration from contour
0513:                    detail.setWorkContour(((PersonalContour) getWorkContour())
0514:                            .convertToFlatIfPossible());
0515:                }
0516:
0517:            }
0518:
0519:            public void setActualWork(long actualWork, FieldContext fieldContext) {
0520:                long workValue = Duration.millis(actualWork);
0521:
0522:                if (FieldContext.hasInterval(fieldContext)) {
0523:
0524:                    boolean isComplete = getPercentComplete() == 1.0D;
0525:                    long oldWork = work();
0526:
0527:                    if (!addWorkingTimeIfRequired(actualWork, fieldContext,
0528:                            true))
0529:                        return;
0530:
0531:                    //if the task isn't yet started and setting work, move to start date
0532:                    if (getTask().getActualStart() == 0 && actualWork != 0) {
0533:                        long s = getEffectiveWorkCalendar()
0534:                                .adjustInsideCalendar(fieldContext.getStart(),
0535:                                        false);
0536:                        getTask().setActualStart(s); //TODO handle if setting non calendar time
0537:                    }
0538:
0539:                    long stop = getStop();
0540:
0541:                    setWork(actualWork, fieldContext); //when entering time phased actuals, first thing is adjust the work contour
0542:
0543:                    //			if (!isComplete)
0544:                    //				((NormalTask)getTask()).getSchedulingRule().adjustRemainingWork(this, newRemainingWork, remainingWork, false);
0545:
0546:                    // need to 0 out an time between stop and the intervals start, if any
0547:                    if (fieldContext.getStart() > stop) {
0548:                        FieldContext empty = new FieldContext();
0549:                        empty.setInterval(new ImmutableInterval(
0550:                                stop == 0 ? getStart() : stop, fieldContext
0551:                                        .getStart()));
0552:                        setWork(0L, empty);
0553:                    }
0554:                    if (workValue > 0) {
0555:
0556:                        if (fieldContext.getEnd() > stop) // if will set stop later because new work is after stop
0557:                            setStop(fieldContext.getEnd());
0558:                        else
0559:                            setStop(stop); // use current stop - for case when setting actuals before current stop
0560:                    } else {
0561:                        if (fieldContext.getStart() < stop
0562:                                && fieldContext.getEnd() >= stop) {//if overlapping current stop	
0563:                            setStop(fieldContext.getStart());
0564:                        } else {
0565:                            if (stop != 0)
0566:                                setStop(stop); // make sure stop stays where it is
0567:                        }
0568:                    }
0569:                    //			if (!isComplete)
0570:                    //				((NormalTask)getTask()).getSchedulingRule().adjustRemainingWork(this, newRemainingWork, remainingWork, false);
0571:
0572:                    //	adjust remaining work
0573:                    long remainingWork = oldWork - getActualWork(null);
0574:
0575:                    //				adjustRemainingWork( ((double)remainingWork) / currentRemainingWork, true);
0576:
0577:                    if (!isComplete) {
0578:                        ((NormalTask) getTask())
0579:                                .getSchedulingRule()
0580:                                .adjustRemainingWork(this , remainingWork, false);
0581:                    }
0582:                    getTask().recalculateLater(this ); // task needs to be recalculated
0583:                } else {
0584:                    if (workValue == 0) {
0585:                        setPercentComplete(0);
0586:                        return;
0587:                    }
0588:                    long date = ReverseQuery.getDateAtValue(WORK, this ,
0589:                            workValue, false);
0590:                    setStop(date);
0591:                }
0592:
0593:            }
0594:
0595:            public boolean isInitialized() {
0596:                return getProject().isInitialized();
0597:            }
0598:
0599:            /**
0600:             * Allow setting of working duration. MSProject displays working duration (excludes non-work intervals) except when
0601:             * task type is fixed duration, in which case it shows duration with non-work intervals
0602:             * @param newWorkingDuration
0603:             */
0604:            public void adjustWorkingDuration(long newWorkingDuration) {
0605:                newDetail().adjustWorkingDuration(newWorkingDuration);
0606:            }
0607:
0608:            public WorkCalendar getEffectiveWorkCalendar() {
0609:                return detail.getEffectiveWorkCalendar();
0610:            }
0611:
0612:            /**
0613:             * @return Returns the task.
0614:             */
0615:            public Task getTask() {
0616:                return detail.getTask();
0617:            }
0618:
0619:            public String getTaskName() {
0620:                return getTask().getName();
0621:            }
0622:
0623:            public String getTaskId() {
0624:                return "" + getTask().getId();
0625:            }
0626:
0627:            public String getResourceName() {
0628:                return getResource().getName();
0629:            }
0630:
0631:            public String getResourceId() {
0632:                return "" + getResource().getId();
0633:            }
0634:
0635:            public long getStart() {
0636:                return detail.getStart();
0637:            }
0638:
0639:            public long getFinish() {
0640:                return detail.getFinish();
0641:            }
0642:
0643:            /**
0644:             * Offset a date by its duration or remaining duration
0645:             * @param date
0646:             * @param ahead - true if we want to add duraiton, false otherwise
0647:             * @param remainingOnly - true if use remaining duration, otherwise all duration
0648:             * @param useSooner - Used for end/beginning of day issues
0649:             * @return new date
0650:             */
0651:
0652:            private long computeStart(long startDate, long dependencyDate) {
0653:                long delay = this .calcTotalDelay();
0654:                long s = startDate;
0655:                if (getPercentComplete() == 0) { // if no completion, use task dependency date if needed
0656:                    if (dependencyDate > s)
0657:                        s = dependencyDate;
0658:                }
0659:                if (delay > 0)
0660:                    s = getEffectiveWorkCalendar().add(s, delay, true);
0661:                //TODO check if above should use task calendar or assignment calendar
0662:                return s;
0663:            }
0664:
0665:            public long calcOffsetFrom(long startDate, long dependencyDate,
0666:                    boolean ahead, boolean remainingOnly, boolean useSooner) {
0667:                long start;
0668:                if (ahead)
0669:                    start = computeStart(startDate, dependencyDate);
0670:                else
0671:                    start = startDate;
0672:                if (getPercentComplete() > 0)
0673:                    start = getEffectiveWorkCalendar().add(start,
0674:                            getActualDuration(), useSooner);
0675:
0676:                long duration = remainingOnly ? detail.getRemainingDuration()
0677:                        : detail.getDuration();// + this.detail.getSplitDuration();
0678:                //TODO integrate split - still needed?
0679:
0680:                long amount = (ahead ? duration : -duration);
0681:                return getEffectiveWorkCalendar().add(start, amount, useSooner);
0682:            }
0683:
0684:            boolean isInRange(long start, long finish) {
0685:                long s = getStart();
0686:                return (finish > s && start < getEffectiveWorkCalendar().add(s,
0687:                        detail.getDuration(), true));
0688:            }
0689:
0690:            /**
0691:             * @return Returns the resource.
0692:             */
0693:            public Resource getResource() {
0694:                return detail.getResource();
0695:            }
0696:
0697:            public Closure forResource(Closure visitor) {
0698:                return new ObjectVisitor(visitor) {
0699:                    protected final Object getObject(Object caller) {
0700:                        return ((Assignment) caller).getResource();
0701:                    }
0702:                };
0703:            }
0704:
0705:            public Closure forTask(Closure visitor) {
0706:                return new ObjectVisitor(visitor) {
0707:                    protected final Object getObject(Object caller) {
0708:                        return ((Assignment) caller).getTask();
0709:                    }
0710:                };
0711:            }
0712:
0713:            /**
0714:             * @return
0715:             */
0716:            public long calcWork() {
0717:                if (!isLabor())
0718:                    return 0;
0719:                return detail.calcWork();
0720:            }
0721:
0722:            /**
0723:             * @return
0724:             */
0725:            public long calcTotalDelay() {
0726:                return detail.calcTotalDelay();
0727:            }
0728:
0729:            /**
0730:             * @return Returns the detail.
0731:             */
0732:            public AssignmentDetail getDetail() {
0733:                return detail;
0734:            }
0735:
0736:            /**
0737:             * Gets an instance of a generator that acts on the cost contour
0738:             * @return instance of generator
0739:             */
0740:            public ContourBucketIntervalGenerator contourGeneratorInstance(
0741:                    Object type) {
0742:                return contourGeneratorInstance(type, getStart());
0743:
0744:            }
0745:
0746:            /**
0747:             * Gets an instance of a generator that acts on the cost contour
0748:             * @return instance of generator
0749:             */
0750:            public ContourBucketIntervalGenerator contourGeneratorInstance(
0751:                    Object type, long start) {
0752:                return ContourBucketIntervalGenerator.getInstance(this , type);//getEffectiveWorkCalendar(), detail.getContour(type), detail.getDurationMillis(), getStart());
0753:                //TODO actual cost treatment if entered manually
0754:            }
0755:
0756:            /**
0757:             * Fills in a SelectFrom clause with "select work from contour"
0758:             * @param clause to fill in
0759:             * @return work field functor
0760:             */
0761:            AssignmentFieldFunctor work(SelectFrom clause) {
0762:                ContourBucketIntervalGenerator contour = contourGeneratorInstance(WORK);
0763:                WorkFunctor workF = WorkFunctor
0764:                        .getInstance(this , contour.getWorkCalendar(), contour,
0765:                                detail.calcOvertimeUnits());
0766:                clause.select(workF).from(contour);
0767:                return workF;
0768:            }
0769:
0770:            //	public AssignmentFieldFunctor work(SelectFrom clause, AssignmentFieldFunctor using) {
0771:            //		ContourBucketIntervalGenerator contour = using.getContourBucketIntervalGenerator();
0772:            //		WorkFunctor workF = WorkFunctor.getInstance(this, contour.getWorkCalendar(), contour, detail.calcOvertimeUnits());
0773:            //		clause.select(workF);
0774:            //		return workF;
0775:            //	}
0776:
0777:            private AssignmentFieldFunctor percentAlloc(SelectFrom clause,
0778:                    boolean threshold) {
0779:                ContourBucketIntervalGenerator contour = contourGeneratorInstance(WORK);
0780:                PercentAllocFunctor functor = PercentAllocFunctor.getInstance(
0781:                        this , contour.getWorkCalendar(), contour, threshold);
0782:                clause.select(functor).from(contour);
0783:                return functor;
0784:            }
0785:
0786:            private AssignmentFieldFunctor fixedCost(SelectFrom clause) {
0787:                ContourBucketIntervalGenerator contour = contourGeneratorInstance(COST);
0788:                FixedCostFunctor functor = FixedCostFunctor.getInstance(this );
0789:                clause.select(functor).from(contour);
0790:                return functor;
0791:            }
0792:
0793:            private AssignmentFieldFunctor availability(SelectFrom clause) {
0794:                //TODO this is untested, as histogram is currently broken 8/12/04 hk
0795:                ResourceAvailabilityFunctor functor = ResourceAvailabilityFunctor
0796:                        .getInstance(this );
0797:                CollectionIntervalGenerator availability = CollectionIntervalGenerator
0798:                        .getInstance(((ResourceImpl) detail.getResource())
0799:                                .getAvailabilityTable().getList());
0800:                clause.select(functor).from(availability); //use range?
0801:                return functor;
0802:            }
0803:
0804:            /** This version does not depend on the assignment
0805:             * 
0806:             * @param clause
0807:             * @param resource
0808:             * @return
0809:             */
0810:            private static AssignmentFieldFunctor resourceAvailability(
0811:                    SelectFrom clause, Resource resource) {
0812:                //TODO this is untested, as histogram is currently broken 8/12/04 hk
0813:                ResourceAvailabilityFunctor functor = ResourceAvailabilityFunctor
0814:                        .getInstance(resource);
0815:                CollectionIntervalGenerator availability = CollectionIntervalGenerator
0816:                        .getInstance(resource.getAvailabilityTable().getList());
0817:                clause.select(functor).from(availability); //use range?
0818:                return functor;
0819:            }
0820:
0821:            //	PercentAllocFunctor(Assignment assignment, WorkCalendar workCalendar, ContourBucketIntervalGenerator contourBucketIntervalGenerator) {
0822:            /**
0823:             * Convenience function to fill in the SelectFrom clause and return the cost functor.
0824:             * One particularity of this function is that if the cost has been saved in the cost contour, then the cost contour is used.
0825:             * This is the usual case in baselines.
0826:             * If the cost contour is not personal, then the cost is calculated from costRate and work; however, the resource accrual settings
0827:             * determine how the data is grouped: If accrual is not PRORATED, then the entire cost is calculated, and the result is then put
0828:             * in a special ConstantCost functor which will return the value if and only if the current group by range encloses the value.
0829:             * @param clause: SelectFrom clause to populate
0830:             * @return The functor to use to calculate cost
0831:             */
0832:            private AssignmentFieldFunctor cost(SelectFrom clause, boolean all) {
0833:                if (detail.getCostContour().isPersonal()) { // in the case where a cost contour has already been saved, use it
0834:                    ContourBucketIntervalGenerator costContour = contourGeneratorInstance(COST);
0835:                    WorkFunctor workF = WorkFunctor.getInstance(this ,
0836:                            getEffectiveWorkCalendar(), costContour, detail
0837:                                    .calcOvertimeUnits()); // note that is is a work contour
0838:                    clause.select(workF).from(costContour);
0839:                    return workF;
0840:                } else {
0841:                    boolean prorated = isProratedCost();
0842:                    // if prorated, or if calculating a total, then treat as prorated
0843:                    if (all || prorated) {
0844:                        ContourBucketIntervalGenerator workContour = contourGeneratorInstance(WORK);
0845:                        CollectionIntervalGenerator costRate = CollectionIntervalGenerator
0846:                                .getInstance(detail.getResource()
0847:                                        .getCostRateTable(
0848:                                                detail.getCostRateIndex())
0849:                                        .getList());
0850:                        clause.from(costRate).from(workContour);
0851:                        // Note that the getStart() parameter implies cost per use is applied at start
0852:                        CostFunctor costF = CostFunctor.getInstance(this ,
0853:                                getEffectiveWorkCalendar(), workContour, detail
0854:                                        .calcOvertimeUnits(), costRate,
0855:                                getStart(), prorated);
0856:                        clause.select(costF);
0857:                        return costF;
0858:                    } else { // accrue start or end
0859:                        long triggerDate = (detail.getResource().getAccrueAt() == Accrual.START) ? getStart()
0860:                                : getFinish();// use start or end
0861:                        AssignmentFieldFunctor constantCost = ValueAtInstant
0862:                                .getInstance(triggerDate, calcAll(COST));
0863:                        clause.select(constantCost).from(
0864:                                InstantIntervalGenerator
0865:                                        .getInstance(triggerDate)); // just one instant				
0866:                        return constantCost;
0867:                    }
0868:                }
0869:            }
0870:
0871:            public boolean isProratedCost() {
0872:                return detail.getResource().getAccrueAt() == Accrual.PRORATED;
0873:            }
0874:
0875:            public AssignmentFieldFunctor getDataSelect(Object type,
0876:                    SelectFrom clause, boolean all) {
0877:                if (type == PERCENT_ALLOC) {
0878:                    return percentAlloc(clause, false);
0879:                } else if (type == AVAILABILITY) {
0880:                    return availability(clause);
0881:                } else if (type == COST) {
0882:                    return cost(clause, all);
0883:                } else if (type == OVERALLOCATED) {
0884:                    return work(clause);
0885:                } else if (type == WORK || type == THIS_PROJECT) {
0886:                    return work(clause);
0887:                } else if (type == ACTUAL_WORK) {
0888:                    clause.whereInRange(detail.getStart(), getStop());
0889:                    return work(clause);
0890:                } else if (type == REMAINING_WORK) {
0891:                    clause.whereInRange(getResume(), detail.getFinish());
0892:                    return work(clause);
0893:                } else if (type == ACTUAL_COST) {
0894:                    clause.whereInRange(detail.getStart(), getStop());
0895:                    return cost(clause, all);
0896:                } else if (type == FIXED_COST) {
0897:                    clause.whereInRange(detail.getStart(), getEnd());
0898:                    return fixedCost(clause);
0899:                } else if (type == ACTUAL_FIXED_COST) {
0900:                    clause.whereInRange(detail.getStart(), getStop());
0901:                    return fixedCost(clause);
0902:                } else if (type == REMAINING_COST) {
0903:                    clause.whereInRange(getResume(), detail.getFinish());
0904:                    return cost(clause, all);
0905:                } else if (type == BASELINE_COST) {
0906:                    return baselineData(COST, clause);
0907:                } else if (type == BASELINE_WORK) {
0908:                    return baselineData(WORK, clause);
0909:                } else if (type == ACWP) {
0910:                    clause.whereInRange(detail.effectiveBaselineStart(),
0911:                            getCompletedOrStatusDate());
0912:                    return cost(clause, all);
0913:                } else if (type == BCWP) {
0914:                    clause.whereInRange(detail.getStart(), getStatusDate());
0915:                    AssignmentFieldFunctor costF = cost(clause, all);
0916:                    costF.setMultiplier(efficiency());
0917:                    return costF;
0918:                } else if (type == BCWS) {
0919:                    clause.whereInRange(detail.effectiveBaselineStart(),
0920:                            getStatusDate());
0921:                    return baselineData(COST, clause);
0922:                } else if (type instanceof  Field) { // treat all baselines
0923:                    Field field = (Field) type;
0924:                    if (field.isIndexed()) {
0925:                        Integer index = new Integer(field.getIndex());
0926:                        if (field.isWork())
0927:                            return baselineData(WORK, clause, index);
0928:                        else
0929:                            return baselineData(COST, clause, index);
0930:                    }
0931:                }
0932:
0933:                return null;
0934:            }
0935:
0936:            public void calcDataBetween(Object type, long start, long end) {
0937:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
0938:                        start, end); // automatically also adds a generator to limit range
0939:                AssignmentFieldFunctor dataFunctor = getDataSelect(type,
0940:                        clause, false);
0941:
0942:                RangeIntervalGenerator dailyInRange = RangeIntervalGenerator
0943:                        .getInstance(start, end, 1000 * 60 * 60 * 24);
0944:                PrintValueFunctor print = PrintValueFunctor
0945:                        .getInstance(dataFunctor);
0946:                Query.getInstance().selectFrom(clause).groupBy(dailyInRange)
0947:                        .action(print).execute();
0948:            }
0949:
0950:            /**
0951:             * Calculate the total cost
0952:             * @return
0953:             */
0954:            public double calcAll(Object type) {
0955:                SelectFrom clause = SelectFrom.getInstance();
0956:                AssignmentFieldFunctor dataFunctor = getDataSelect(type,
0957:                        clause, true);
0958:                Query.getInstance().selectFrom(clause).execute();
0959:                return dataFunctor.getValue();
0960:            }
0961:
0962:            //	public void forEach(Object type, Closure actionVisitor) {
0963:            //		SelectFrom clause = SelectFrom.getInstance();
0964:            //		AssignmentFieldFunctor dataFunctor = getDataSelect(type,clause,false);		
0965:            //		Query.getInstance().selectFrom(clause)
0966:            //		.action(actionVisitor)
0967:            //		.execute();
0968:            //	}
0969:
0970:            public void buildReverseQuery(ReverseQuery reverseQuery) {
0971:                SelectFrom clause = SelectFrom.getInstance();
0972:                reverseQuery.addField(getDataSelect(reverseQuery.getType(),
0973:                        clause, false));
0974:                reverseQuery.addGroupBy(IntervalGeneratorSet
0975:                        .extractUnshared(clause.getFromIntervalGenerators()));
0976:                reverseQuery.addSelectFrom(clause);
0977:            }
0978:
0979:            /**
0980:             * calls back on for all "gantt bar" intervals having matching rates.  Matching is determined by a comparator.
0981:             * @param visitor : callback
0982:             * @param mergeWorking : if true, then matching occurs if the periods hava non-zero work, otherwise the work
0983:             * must be an exact match.
0984:             */
0985:            public void forEachWorkingInterval(Closure visitor,
0986:                    boolean mergeWorking, WorkCalendar workCalendar) {
0987:                Comparator comparator = (mergeWorking ? null : WorkComparator
0988:                        .getInstance()); // if a value of null is used , then the bars will be grouped based on time only
0989:                Merge merge = Merge.getInstance(visitor, comparator);
0990:                Query.getInstance().groupBy(contourGeneratorInstance(WORK))
0991:                        .action(merge).execute();
0992:            }
0993:
0994:            private transient static BarClosure barClosureInstance = new BarClosure();
0995:
0996:            public void consumeIntervals(IntervalConsumer consumer) {
0997:                barClosureInstance.initialize(consumer, this );
0998:                boolean inProgress = getPercentComplete() > 0.0D;
0999:                MutableInterval bounds = null;
1000:                if (inProgress) {
1001:                    bounds = new MutableInterval(getStart(), getStop());
1002:                    barClosureInstance.setBounds(bounds);
1003:                }
1004:                forEachWorkingInterval(barClosureInstance, true,
1005:                        getEffectiveWorkCalendar());
1006:                if (inProgress) {
1007:                    //			barClosureInstance.initCount();
1008:                    bounds.setStart(bounds.getEnd()); // shift for second half
1009:                    bounds.setEnd(getEnd());
1010:
1011:                    forEachWorkingInterval(barClosureInstance, true,
1012:                            getEffectiveWorkCalendar());
1013:                }
1014:                barClosureInstance.setBounds(null);
1015:            }
1016:
1017:            public void moveInterval(Object eventSource, long start, long end,
1018:                    ScheduleInterval oldInterval, boolean isChild) {
1019:                long startShiftDuration = getEffectiveWorkCalendar().compare(
1020:                        start, oldInterval.getStart(), false);
1021:                long endShiftDuration = getEffectiveWorkCalendar().compare(end,
1022:                        oldInterval.getEnd(), false);
1023:                boolean shifting = startShiftDuration != 0L
1024:                        && endShiftDuration != 0L;
1025:                long stop = getStop(); // Store old completion
1026:                if (shifting) {
1027:                    shift(oldInterval.getStart(), oldInterval.getEnd(),
1028:                            startShiftDuration);
1029:                } else {
1030:                    if (endShiftDuration != 0)
1031:                        extend(oldInterval.getStart(), oldInterval.getEnd(),
1032:                                endShiftDuration);
1033:                    else
1034:                        extendBefore(oldInterval.getStart(), oldInterval
1035:                                .getEnd(), startShiftDuration);
1036:                }
1037:
1038:                setStop(stop); // put back old completion
1039:                //Need to update schedule if the assignment bar was moved
1040:                if (!isChild) {
1041:                    getTask().updateCachedDuration();
1042:                    getTask().recalculate(eventSource);
1043:                }
1044:
1045:                //		//Undo
1046:                //		UndoableEditSupport undoableEditSupport=getProject().getUndoController().getEditSupport();
1047:                //		if (undoableEditSupport!=null&&!(eventSource instanceof UndoableEdit)){
1048:                //			undoableEditSupport.postEdit(new ScheduleEdit(this,new ScheduleInterval(start,end),oldInterval,isChild,eventSource));
1049:                //		}
1050:
1051:            }
1052:
1053:            /**
1054:             * This function will calculate the exact date/time when the value is achieved
1055:             * @param type
1056:             * @param value
1057:             * @return
1058:             */
1059:            public long getDateAtValue(Object type, double value) {
1060:                SelectFrom clause = SelectFrom.getInstance();
1061:                AssignmentFieldFunctor dataFunctor = (type == COST) ? cost(
1062:                        clause, true) : work(clause);
1063:
1064:                DateAtValueFunctor dateAtValue = DateAtValueFunctor
1065:                        .getInstance(value, AssignmentFieldClosureCollection
1066:                                .getInstance(dataFunctor));
1067:                clause.select(dateAtValue); // override existing select
1068:
1069:                Query.getInstance().selectFrom(clause).execute();
1070:                return dateAtValue.getDate();
1071:            }
1072:
1073:            public long getDateAtWorkFraction(double workFraction) {
1074:                //		System.out.println("all work is " + calcAll(WORK) / (1000*60*60*8));		
1075:                return getDateAtValue(WORK, calcAll(WORK) * workFraction);
1076:            }
1077:
1078:            private AssignmentFieldFunctor baselineData(Object type,
1079:                    SelectFrom baselineSelectFrom) {
1080:                Assignment baselineAssignment = detail.getBaselineAssignment();
1081:                AssignmentFieldFunctor baselineFunctor;
1082:                if (baselineAssignment == null) {
1083:                    baselineFunctor = ZeroFunctor.getInstance();
1084:                    baselineSelectFrom.select(baselineFunctor).from(
1085:                            RangeIntervalGenerator.empty());
1086:                } else {
1087:                    baselineFunctor = baselineAssignment.getDataSelect(type,
1088:                            baselineSelectFrom, false);
1089:                }
1090:                return baselineFunctor;
1091:            }
1092:
1093:            public Assignment getBaselineAssignment(Object baseline,
1094:                    boolean createIfDoesntExist) {
1095:                return detail.getBaselineAssignment(baseline,
1096:                        createIfDoesntExist);
1097:            }
1098:
1099:            private AssignmentFieldFunctor baselineData(Object type,
1100:                    SelectFrom baselineSelectFrom, Object baseline) {
1101:                Assignment baselineAssignment = detail.getBaselineAssignment(
1102:                        baseline, false);
1103:                AssignmentFieldFunctor baselineFunctor;
1104:                if (baselineAssignment == null) {
1105:                    baselineFunctor = ZeroFunctor.getInstance();
1106:                    baselineSelectFrom.select(baselineFunctor).from(
1107:                            RangeIntervalGenerator.empty());
1108:                } else {
1109:                    baselineFunctor = baselineAssignment.getDataSelect(type,
1110:                            baselineSelectFrom, false);
1111:                }
1112:                return baselineFunctor;
1113:            }
1114:
1115:            private long getStatusDate() {
1116:                return getProject().getStatusDate();
1117:            }
1118:
1119:            private long getCompletedOrStatusDate() {
1120:                return Math.min(getStatusDate(), detail.getStop());
1121:            }
1122:
1123:            public double getCost() {
1124:                return calcAll(COST);
1125:            }
1126:
1127:            /**
1128:             * Set the total delay for the assignment.  Priority is given to changing the assignment delay over the
1129:             * leveling delay.
1130:             * @param newDelay
1131:             */
1132:            void setTotalDelay(long newDelay) {
1133:
1134:                /*
1135:                 *   DDDDDDDLLLLLL
1136:                 *   NNNNNNNNNN
1137:                 */
1138:
1139:                //		long delay = getDelay();
1140:                //		long levelingDelay = getLevelingDelay();
1141:                //		long oldTotalDelay = calcTotalDelay();
1142:                //		if (newDelay == oldTotalDelay)
1143:                //			return;
1144:                //		
1145:                //		if (newDelay <= delay) {
1146:                //			delay = newDelay;
1147:                //			levelingDelay = 0;
1148:                //		}
1149:                //		else {
1150:                //			delay = 0;
1151:                //			levelingDelay =
1152:                //		}
1153:                //		if (newDelay < oldTotalDelay) {
1154:                //			delay -= newDelay;
1155:                //			if (delay < 0) {
1156:                //				levelingDelay += delay;
1157:                //				delay = 0;
1158:                //			}
1159:                //		} else {
1160:                //			delay += (newDelay - oldTotalDelay);
1161:                //		}
1162:                //		setDelay(delay);
1163:                //		setLevelingDelay(levelingDelay);
1164:                setDelay(newDelay);
1165:                setLevelingDelay(0);
1166:            }
1167:
1168:            /**
1169:             * This treats just a single interval to merge in
1170:             * @param type - WORK or COST. can also be a time distributed field
1171:             * @param start - start of interval
1172:             * @param end - end of interval
1173:             * @param value - value of interval
1174:             */
1175:            public void setInterval(Object type, long start, long end,
1176:                    double value) {
1177:                //TODO treat cost values - they are currently ignored
1178:                if (type == ACTUAL_WORK || type == WORK
1179:                        || type == REMAINING_WORK) {
1180:                    if (value != 0 && !verifyBounds(start, end))
1181:                        return;
1182:                    if (Environment.isImporting()) {
1183:                        WorkCalendar cal = getEffectiveWorkCalendar();
1184:                        start = cal.adjustInsideCalendar(start, false);
1185:                        end = cal.adjustInsideCalendar(end, true);
1186:                    }
1187:
1188:                    setWorkInterval(start, end, value);
1189:                    if (type == ACTUAL_WORK && end > getStop() && value > 0.0D) // bug fix - actuals were lost
1190:                        setStop(end);
1191:                } else {
1192:                    if (TimeDistributedHelper.isWork(type)) {
1193:                        Object baseline = TimeDistributedHelper
1194:                                .baselineForData(type);
1195:                        //System.out.println("baseline " + baseline + " " + new Date(start) + " " + new Date(end) + " " + value);
1196:
1197:                        Assignment baselineAssignment = getBaselineAssignment(
1198:                                baseline, true); // get or create baseline assignment
1199:
1200:                        // update the task schedule too
1201:                        TaskSchedule schedule = baselineAssignment
1202:                                .getTaskScheduleOfAssignment();
1203:                        long baselineStart = schedule.getStart();
1204:                        long baselineFinish = schedule.getFinish();
1205:                        if (baselineStart == 0 || baselineStart > start)
1206:                            schedule.setStart(start);
1207:                        if (baselineFinish == 0 || baselineFinish < end)
1208:                            schedule.setEnd(end);
1209:
1210:                        baselineAssignment.setWorkInterval(start, end, value);
1211:                    }
1212:                }
1213:            }
1214:
1215:            TaskSchedule getTaskScheduleOfAssignment() {
1216:                return detail.getTaskSchedule();
1217:            }
1218:
1219:            public boolean verifyBounds(long start, long end) {
1220:                if (Environment.isImporting()) // always accept time distributed edits when importing
1221:                    return true;
1222:                if (getProject().getStart() > start) // if setting before project start
1223:                    return Alert
1224:                            .okCancel(Messages
1225:                                    .getString("Message.allowDistrbutedStartBeforeProjectStart"));
1226:                else if (start < getTask().getStart())
1227:                    return Alert
1228:                            .okCancel(Messages
1229:                                    .getString("Message.allowDistrbutedStartBeforeTaskStart"));
1230:                else
1231:                    return true;
1232:
1233:            }
1234:
1235:            /**
1236:             * This treats just a single interval to merge in
1237:             * @param type - WORK or COST
1238:             * @param start - start of interval
1239:             * @param end - end of interval
1240:             * @param value - value of interval (an wmount of work (duration), not units)
1241:             */
1242:            private void setWorkInterval(long start, long end, double value) {
1243:                moveDelayToContour();
1244:                long assignmentStart = getStart(); // the start including any delay
1245:                WorkCalendar cal = getEffectiveWorkCalendar();
1246:
1247:                if (end > getFinish()) { //  add end if necessary
1248:                    if (value == 0) {
1249:                        this .setEnd(start);
1250:                        return; // don't extend if value is 0
1251:                    }
1252:                    makeContourPersonal();
1253:                    long extraDuration = cal.compare(end, getFinish(), false);
1254:                    setDurationMillis(getDurationMillis() + extraDuration);
1255:                    AbstractContour contour = PersonalContour.addEmptyBucket(
1256:                            getWorkContour(), extraDuration, true);
1257:                    newDetail().setWorkContour(contour);
1258:
1259:                    // adjust task end too
1260:                    if (end > getTask().getEnd())
1261:                        getTask().setEnd(end);
1262:                } else if (start < assignmentStart) { // if before assignment start
1263:                //			if (value == 0)
1264:                //				return; // don't extend if value is 0
1265:                    long taskStart = getTask().getStart();
1266:                    if (start < taskStart) {
1267:                        long shiftAmount = cal.compare(taskStart, start, false);
1268:                        setDurationMillis(getDurationMillis() + shiftAmount);
1269:                        if (!getWorkContour().isPersonal())
1270:                            makeContourPersonal();
1271:                        newDetail().setWorkContour(
1272:                                PersonalContour.addEmptyBucket(
1273:                                        getWorkContour(), shiftAmount, false)); // add empty space before
1274:                        getTask().setScheduleConstraintAndUpdate(
1275:                                ConstraintType.SNLT, start); // this can set start before project duration.
1276:                        taskStart = getTask().getStart();
1277:                    }
1278:                    assignmentStart = taskStart;
1279:                }
1280:
1281:                long startDuration = cal.compare(start, assignmentStart, false);
1282:                long endDuration = cal.compare(end, assignmentStart, false);
1283:                if (startDuration == endDuration)
1284:                    return;
1285:
1286:                if (!getWorkContour().isPersonal())
1287:                    makeContourPersonal();
1288:
1289:                value /= (endDuration - startDuration);
1290:                PersonalContour newContour = ((PersonalContour) getWorkContour())
1291:                        .setInterval(startDuration, endDuration, value);
1292:
1293:                extractDelayFromContour(newContour); // move delay back into delay field from contour
1294:                newDetail().setWorkContour(newContour);
1295:                newDetail().recalculateDuration();
1296:                getTask().updateCachedDuration();
1297:            }
1298:
1299:            /**
1300:             * Move remaining work to the date given.  It will either be moved later or sooner.  Also, if at the date, there
1301:             * is a gap in the work, the gap is reduced so that the work begins on the date
1302:             * @param date
1303:             */
1304:            public void moveRemainingToDate(long date) {
1305:                long resume = getResume();
1306:                long end = getEnd();
1307:                long shiftDuration = getEffectiveWorkCalendar().compare(date,
1308:                        resume, false); // get shift time
1309:                shift(resume, end, shiftDuration);
1310:
1311:                long duration = getEffectiveWorkCalendar().compare(date,
1312:                        getStart(), false); // get offset from start
1313:                if (duration > 0)
1314:                    newDetail().removeEmptyBucketAtDuration(duration);
1315:            }
1316:
1317:            public void shift(long start, long end, long shiftDuration) {
1318:                //get bounds.
1319:                WorkCalendar cal = getEffectiveWorkCalendar();
1320:
1321:                if (getTask().inProgress()
1322:                        && cal.compare(getStop(), start, false) > 0) { // if stop greater than start, can't change it
1323:                    //	System.out.println("Not shifting - stop = " + new Date(getStop()) + "start " + new Date(start));
1324:                    return;
1325:                }
1326:                long taskStart = getTask().getStart();
1327:                start = Math.max(start, getStop()); //only shift remaining
1328:                start = Math.max(start, taskStart); // dont shift before task start of course
1329:                long startOffset = cal.compare(start, taskStart, false);
1330:                long endOffset = cal.compare(end, taskStart, false);
1331:
1332:                if (getResume() != 0 && start >= getResume()) {
1333:                    long splitDuration = detail.getSplitDuration();
1334:                    startOffset -= splitDuration;
1335:                    endOffset -= splitDuration;
1336:                }
1337:
1338:                if (startOffset >= endOffset) // this prevents moving a completed interval
1339:                    return;
1340:                boolean firstBar = (cal.compare(getStart(), start, false) == 0);
1341:                MutableInterval range = getRangeThatIntervalCanBeMoved(start,
1342:                        startOffset, endOffset);
1343:                if (firstBar)
1344:                    range.setStart(range.getStart() - calcTotalDelay());
1345:                if (shiftDuration > 0)
1346:                    shiftDuration = Math.min(shiftDuration, range.getEnd()
1347:                            - endOffset); // don't allow to shift more than possible
1348:                else {
1349:                    shiftDuration = Math.max(shiftDuration, range.getStart() /*+ (firstBar ? -calcTotalDelay() : 0)*/
1350:                            - startOffset); // don't allow to shift more than possible
1351:                }
1352:                if (firstBar) {
1353:                    setTotalDelay(calcTotalDelay() + shiftDuration);
1354:                } else {
1355:                    newDetail().shift(startOffset, endOffset, shiftDuration);
1356:                }
1357:            }
1358:
1359:            private MutableInterval getRangeThatIntervalCanBeMoved(long start,
1360:                    long startOffset, long endOffset) {
1361:                MutableInterval range = getRangeThatIntervalCanBeMoved(
1362:                        startOffset, endOffset);
1363:                if (getEffectiveWorkCalendar()
1364:                        .compare(getStart(), start, false) == 0)
1365:                    range.setStart(range.getStart() - calcTotalDelay());
1366:                return range;
1367:
1368:            }
1369:
1370:            public MutableInterval getRangeThatIntervalCanBeMoved(
1371:                    long startOffset, long endOffset) {
1372:                return detail.getRangeThatIntervalCanBeMoved(startOffset,
1373:                        endOffset);
1374:            }
1375:
1376:            public void extend(long start, long end, long extendDuration) {
1377:                if (end < getStop())
1378:                    return;
1379:                WorkCalendar cal = getEffectiveWorkCalendar();
1380:                long startOffset = cal.compare(start, getStart(), false);
1381:                long endOffset = cal.compare(end, getStart(), false);
1382:
1383:                //		if (start >= getResume()) {
1384:                //			long splitDuration = detail.getSplitDuration();
1385:                //			startOffset -= splitDuration;
1386:                //			endOffset -= splitDuration;
1387:                //		}
1388:
1389:                Interval range = getRangeThatIntervalCanBeMoved(start,
1390:                        startOffset, endOffset);
1391:                if (extendDuration > 0)
1392:                    extendDuration = Math.min(extendDuration, range.getEnd()
1393:                            - endOffset); // don't allow to shift more than possible
1394:                else
1395:                    extendDuration = Math.max(extendDuration, startOffset
1396:                            - endOffset);
1397:                newDetail().extend(endOffset, extendDuration);
1398:            }
1399:
1400:            /* (non-Javadoc)
1401:             * @see com.projity.pm.scheduling.Schedule#split(java.lang.Object, long, long)
1402:             */
1403:            public void split(Object eventSource, long from, long to) {
1404:                from = Math.max(from, getResume());
1405:                if (from >= to)
1406:                    return;
1407:                long duration = getEffectiveWorkCalendar().compare(to, from,
1408:                        false); // calculate shift duration
1409:                shift(from, getEnd(), duration); // shift the remaining contour to the right by the duration
1410:            }
1411:
1412:            public void extendBefore(long start, long end, long extendDuration) {
1413:                if (start < getStop())
1414:                    return;
1415:                WorkCalendar cal = getEffectiveWorkCalendar();
1416:
1417:                boolean firstBar = (cal.compare(getStart(), start, false) == 0);
1418:                long startOffset = cal.compare(start, getStart(), false);
1419:                long endOffset = cal.compare(end, getStart(), false);
1420:                Interval range = getRangeThatIntervalCanBeMoved(start,
1421:                        startOffset, startOffset);
1422:
1423:                if (extendDuration > 0)
1424:                    extendDuration = Math.min(extendDuration, endOffset
1425:                            - startOffset);
1426:                else
1427:                    extendDuration = Math.max(extendDuration, range.getStart()
1428:                            - startOffset); // don't allow to shift more than possible			
1429:
1430:                if (firstBar)
1431:                    setTotalDelay(calcTotalDelay() + extendDuration);
1432:                newDetail().extendBefore(startOffset, extendDuration);
1433:
1434:            }
1435:
1436:            public void addCalendarTime(long start, long end) {
1437:                newDetail().addCalendarTime(start, end);
1438:            }
1439:
1440:            /* (non-Javadoc)
1441:             * @see com.projity.pm.assignment.AssignmentSpecificFields#getWorkContourId()
1442:             */
1443:            public int getWorkContourType() {
1444:                return getWorkContour().getType();
1445:            }
1446:
1447:            /* (non-Javadoc)
1448:             * @see com.projity.pm.assignment.AssignmentSpecificFields#setWorkContourId(int)
1449:             */
1450:            public void setWorkContourType(int workContourType) {
1451:                newDetail().setWorkContour(
1452:                        ContourFactory.getInstance(workContourType));
1453:                // TODO need to actually transform contour correctly when changing
1454:
1455:            }
1456:
1457:            public final double getRemainingUnits() {
1458:                if (!isLabor())
1459:                    return 1.0D;
1460:                long duration = getRemainingDuration();
1461:                if (duration == 0.0)
1462:                    return getWorkContour().getLastBucketUnits();
1463:                //			return 1.0D; // degeneratate case
1464:                long work = getRemainingWork();
1465:                if (work == 0) // degenerate case with no work yet
1466:                    return 1.0;
1467:                return ((double) work) / duration;
1468:
1469:            }
1470:
1471:            public final double getRemainingLaborUnits() {
1472:                if (isLabor())
1473:                    return getRemainingUnits();
1474:                return 0.0D;
1475:            }
1476:
1477:            /* (non-Javadoc)
1478:             * @see com.projity.util.Association#getLeft()
1479:             */
1480:            public Object getLeft() {
1481:                return getTask();
1482:            }
1483:
1484:            /* (non-Javadoc)
1485:             * @see com.projity.util.Association#getRight()
1486:             */
1487:            public Object getRight() {
1488:                return getResource();
1489:            }
1490:
1491:            /* (non-Javadoc)
1492:             * @see com.projity.util.Association#testValid()
1493:             */
1494:            public void testValid(boolean allowDuplicate)
1495:                    throws InvalidAssociationException {
1496:            }
1497:
1498:            /* (non-Javadoc)
1499:             * @see com.projity.util.Association#copyPrincipalFieldsFrom(com.projity.util.Association)
1500:             */
1501:            public void copyPrincipalFieldsFrom(Association from) {
1502:                Assignment fromAssignment = (Assignment) from;
1503:                double units = fromAssignment.getUnits();
1504:                if (fromAssignment.isLabor()) {
1505:                    adjustRemainingUnits(fromAssignment.getUnits(), 0, true,
1506:                            false);
1507:                    detail.setUnits(units);
1508:                } else {
1509:                    detail.rate = fromAssignment.detail.getRate();
1510:                    detail.setDuration(getDuration()); // reset duration
1511:                }
1512:
1513:                getTask().updateCachedDuration(); // needed for checking if milestone
1514:
1515:            }
1516:
1517:            public void forceUnits(double units) {
1518:                newDetail().setUnits(units);
1519:            }
1520:
1521:            public void doAddService(Object eventSource) {
1522:                AssignmentService.getInstance().connect(this , eventSource);
1523:            }
1524:
1525:            public void doRemoveService(Object eventSource) {
1526:                AssignmentService.getInstance().remove(this , eventSource, true);
1527:            }
1528:
1529:            /* (non-Javadoc)
1530:             * @see com.projity.association.Association#doUpdateService(java.lang.Object)
1531:             */
1532:            public void doUpdateService(Object eventSource) {
1533:                getUnitsField().fireEvent(this , this , null); // need to update
1534:
1535:            }
1536:
1537:            public boolean isDefault() {
1538:                return getTask() == NormalTask.getUnassignedInstance()
1539:                        || getResource() == ResourceImpl
1540:                                .getUnassignedInstance();
1541:            }
1542:
1543:            public boolean isReadOnlyUnits(FieldContext fieldContext) {
1544:                return false;
1545:            }
1546:
1547:            //Costs and earned value
1548:            public double acwp(long start, long end) {
1549:                if (!isInRange(start, end))
1550:                    return NO_VALUE_DOUBLE;
1551:                Query query = Query.getInstance();
1552:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1553:                        Math.max(start, detail.effectiveBaselineStart()),
1554:                        Math.min(end, getCompletedOrStatusDate()));
1555:                query.selectFrom(clause).action(cost(clause, false)).execute();
1556:                return ((DoubleValue) query.getActionVisitor()).getValue();
1557:            }
1558:
1559:            public double bcws(long start, long end) {
1560:                if (!isInRange(start, end))
1561:                    return NO_VALUE_DOUBLE;
1562:
1563:                if (AdvancedOption.getInstance()
1564:                        .isEarnedValueFieldsCumulative())
1565:                    start = getStart(); // start from the beginning of the task and ignore the range start
1566:
1567:                Query query = Query.getInstance();
1568:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1569:                        Math.max(start, detail.effectiveBaselineStart()),
1570:                        Math.min(end, getStatusDate()));
1571:                query.selectFrom(clause).action(baselineData(COST, clause))
1572:                        .execute();
1573:                return ((DoubleValue) query.getActionVisitor()).getValue();
1574:            }
1575:
1576:            public double efficiency() {
1577:                Assignment baselineAssignment = detail.getBaselineAssignment();
1578:                if (baselineAssignment == null)
1579:                    return 0.0D;
1580:
1581:                long baselineWork = baselineAssignment.work();
1582:                if (baselineWork == 0)
1583:                    return 0.0;
1584:                long work = work();
1585:                if (work == 0.0D)
1586:                    return 1.0D;
1587:                return ((double) baselineWork) / work;
1588:
1589:            }
1590:
1591:            //[(Actual % of completion / Expected % of completion) of an activity for a given period] * Actual cost of activity
1592:            public double bcwp(long start, long end) {
1593:                if (!isInRange(start, end))
1594:                    return NO_VALUE_DOUBLE;
1595:                end = Math.min(end, getStatusDate());
1596:                if (end == 0)
1597:                    return 0.0D;
1598:                if (AdvancedOption.getInstance()
1599:                        .isEarnedValueFieldsCumulative())
1600:                    start = getStart(); // start from the beginning of the task and ignore the range start
1601:                double cost = actualCost(start, end);
1602:                if (cost == 0)
1603:                    return 0;
1604:                return efficiency() * cost;
1605:                //		
1606:                //		Query query = Query.getInstance();
1607:                //		long boundaryStart = detail.getStart(); // always use assignment start and never start
1608:                //		long boundaryEnd = Math.min(getStatusDate(),baselineAssignment.getEffectiveWorkCalendar().add(boundaryStart, (long) (baselineAssignment.getDuration() * getPercentComplete()),false));
1609:                //		SelectFrom clause = SelectFrom.getInstance().whereInRange(boundaryStart,Math.min(end,boundaryEnd));
1610:                //		query.selectFrom(clause)
1611:                //			.action(baselineData(COST,clause))
1612:                //			.execute();
1613:                //		return ((DoubleValue)query.getActionVisitor()).getValue();
1614:            }
1615:
1616:            public double bac(long start, long end) {
1617:                if (!isInRange(start, end))
1618:                    return NO_VALUE_DOUBLE;
1619:                Query query = Query.getInstance();
1620:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1621:                        start, end);
1622:                query.selectFrom(clause).action(baselineData(COST, clause))
1623:                        .execute();
1624:                return ((DoubleValue) query.getActionVisitor()).getValue();
1625:            }
1626:
1627:            public double cost(long start, long end) {
1628:                if (!isInRange(start, end))
1629:                    return NO_VALUE_DOUBLE;
1630:                Query query = Query.getInstance();
1631:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1632:                        start, end);
1633:                query.selectFrom(clause).action(cost(clause, false)).execute();
1634:                return ((DoubleValue) query.getActionVisitor()).getValue();
1635:            }
1636:
1637:            public long work(long start, long end) {
1638:                if (!isInRange(start, end))
1639:                    return NO_VALUE_LONG;
1640:                //		if (!isLabor()) // TODO this right?
1641:                //			return 0;
1642:                Query query = Query.getInstance();
1643:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1644:                        start, end);
1645:                query.selectFrom(clause).action(work(clause)).execute();
1646:                return (long) ((DoubleValue) query.getActionVisitor())
1647:                        .getValue();
1648:
1649:            }
1650:
1651:            public double actualCost(long start, long end) {
1652:                if (!isInRange(start, end))
1653:                    return NO_VALUE_DOUBLE;
1654:
1655:                Query query = Query.getInstance();
1656:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1657:                        Math.max(start, detail.getStart()),
1658:                        Math.min(end, getStop()));
1659:                query.selectFrom(clause).action(cost(clause, false)).execute();
1660:                return ((DoubleValue) query.getActionVisitor()).getValue();
1661:            }
1662:
1663:            public long actualWork(long start, long end) {
1664:                if (!isInRange(start, end))
1665:                    return NO_VALUE_LONG;
1666:                if (!isLabor()) // TODO this right?
1667:                    return 0;
1668:                Query query = Query.getInstance();
1669:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1670:                        Math.max(start, detail.getStart()),
1671:                        Math.min(end, getStop()));
1672:                query.selectFrom(clause).action(work(clause)).execute();
1673:                return (long) ((DoubleValue) query.getActionVisitor())
1674:                        .getValue();
1675:            }
1676:
1677:            public long remainingWork(long start, long end) {
1678:                if (!isInRange(start, end))
1679:                    return NO_VALUE_LONG;
1680:                if (!isLabor()) // TODO this right?
1681:                    return 0;
1682:                Query query = Query.getInstance();
1683:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1684:                        Math.max(start, detail.getStop()),
1685:                        Math.min(end, getEnd()));
1686:                query.selectFrom(clause).action(work(clause)).execute();
1687:                return (long) ((DoubleValue) query.getActionVisitor())
1688:                        .getValue();
1689:            }
1690:
1691:            public double baselineCost(long start, long end) {
1692:                //		if (!isInRange(start,end))
1693:                //			return NO_VALUE_DOUBLE;
1694:
1695:                Query query = Query.getInstance();
1696:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1697:                        start, end);
1698:                query.selectFrom(clause).action(baselineData(COST, clause))
1699:                        .execute();
1700:                return ((DoubleValue) query.getActionVisitor()).getValue();
1701:            }
1702:
1703:            public long baselineWork(long start, long end) {
1704:                //		if (!isInRange(start,end))
1705:                //			return NO_VALUE_LONG;
1706:                if (!isLabor()) // TODO this right?
1707:                    return 0;
1708:                Query query = Query.getInstance();
1709:                SelectFrom clause = SelectFrom.getInstance().whereInRange(
1710:                        start, end);
1711:                query.selectFrom(clause).action(baselineData(WORK, clause))
1712:                        .execute();
1713:                return (long) ((DoubleValue) query.getActionVisitor())
1714:                        .getValue();
1715:            }
1716:
1717:            private boolean isFieldHidden(FieldContext fieldContext) {
1718:                return fieldContext != null
1719:                        && !isInRange(fieldContext.getStart(), fieldContext
1720:                                .getEnd());
1721:            }
1722:
1723:            private boolean isEarnedValueFieldHidden(FieldContext fieldContext) {
1724:                if (isFieldHidden(fieldContext))
1725:                    return true;
1726:                return getStatusDate() < fieldContext.getStart();
1727:            }
1728:
1729:            private boolean isBaselineFieldHidden(int numBaseline,
1730:                    FieldContext fieldContext) {
1731:                Assignment baselineAssignment = getBaselineAssignment(
1732:                        new Integer(numBaseline), false);
1733:                if (baselineAssignment == null)
1734:                    return true;
1735:
1736:                if (fieldContext == null) // the baseline exists, but no time range
1737:                    return false;
1738:                return (fieldContext.getStart() >= baselineAssignment
1739:                        .getFinish() || fieldContext.getEnd() <= baselineAssignment
1740:                        .getStart());
1741:            }
1742:
1743:            /***************************************************************************************
1744:             * Time Distributed Fields
1745:             **************************************************************************************/
1746:
1747:            public boolean fieldHideCost(FieldContext fieldContext) {
1748:                return isFieldHidden(fieldContext);
1749:            }
1750:
1751:            public boolean fieldHideWork(FieldContext fieldContext) {
1752:                return isFieldHidden(fieldContext);
1753:            }
1754:
1755:            public boolean fieldHideActualCost(FieldContext fieldContext) {
1756:                return isFieldHidden(fieldContext);
1757:            }
1758:
1759:            public boolean fieldHideActualWork(FieldContext fieldContext) {
1760:                return fieldHideWork(fieldContext);
1761:            }
1762:
1763:            public boolean fieldHideBaselineCost(int numBaseline,
1764:                    FieldContext fieldContext) {
1765:                return isBaselineFieldHidden(numBaseline, fieldContext);
1766:            }
1767:
1768:            public boolean fieldHideBaselineWork(int numBaseline,
1769:                    FieldContext fieldContext) {
1770:                return isBaselineFieldHidden(numBaseline, fieldContext);
1771:            }
1772:
1773:            public boolean fieldHideAcwp(FieldContext fieldContext) {
1774:                return isFieldHidden(fieldContext);
1775:            }
1776:
1777:            public boolean fieldHideBac(FieldContext fieldContext) {
1778:                return isFieldHidden(fieldContext);
1779:            }
1780:
1781:            public boolean fieldHideBcwp(FieldContext fieldContext) {
1782:                return isEarnedValueFieldHidden(fieldContext);
1783:            }
1784:
1785:            public boolean fieldHideBcws(FieldContext fieldContext) {
1786:                return isEarnedValueFieldHidden(fieldContext);
1787:            }
1788:
1789:            public boolean fieldHideCv(FieldContext fieldContext) {
1790:                return isFieldHidden(fieldContext);
1791:            }
1792:
1793:            public boolean fieldHideSv(FieldContext fieldContext) {
1794:                return isFieldHidden(fieldContext);
1795:            }
1796:
1797:            public boolean fieldHideEac(FieldContext fieldContext) {
1798:                return isFieldHidden(fieldContext);
1799:            }
1800:
1801:            public boolean fieldHideVac(FieldContext fieldContext) {
1802:                return isFieldHidden(fieldContext);
1803:            }
1804:
1805:            public boolean fieldHideCpi(FieldContext fieldContext) {
1806:                return isFieldHidden(fieldContext);
1807:            }
1808:
1809:            public boolean fieldHideSpi(FieldContext fieldContext) {
1810:                return isFieldHidden(fieldContext);
1811:            }
1812:
1813:            public boolean fieldHideCvPercent(FieldContext fieldContext) {
1814:                return isFieldHidden(fieldContext);
1815:            }
1816:
1817:            public boolean fieldHideSvPercent(FieldContext fieldContext) {
1818:                return isFieldHidden(fieldContext);
1819:            }
1820:
1821:            public boolean fieldHideTcpi(FieldContext fieldContext) {
1822:                return isFieldHidden(fieldContext);
1823:            }
1824:
1825:            public double getCost(FieldContext fieldContext) {
1826:                return cost(FieldContext.start(fieldContext), FieldContext
1827:                        .end(fieldContext));
1828:            }
1829:
1830:            public long work() {
1831:                return work(FieldContext.defaultStart, FieldContext.defaultEnd);
1832:            }
1833:
1834:            public long getWork(FieldContext fieldContext) {
1835:                long w = work(FieldContext.start(fieldContext), FieldContext
1836:                        .end(fieldContext));
1837:                if (!isLabor()) {
1838:                    //			System.out.println("work before setting non temporal" + DurationFormat.format(w));
1839:                    w = Duration.setAsNonTemporal(w);
1840:                }
1841:                return w;
1842:            }
1843:
1844:            public double getActualCost(FieldContext fieldContext) {
1845:                return actualCost(FieldContext.start(fieldContext),
1846:                        FieldContext.end(fieldContext));
1847:            }
1848:
1849:            public long getActualWork(FieldContext fieldContext) {
1850:                return actualWork(FieldContext.start(fieldContext),
1851:                        FieldContext.end(fieldContext));
1852:            }
1853:
1854:            public long getRemainingWork(FieldContext fieldContext) {
1855:                return remainingWork(FieldContext.start(fieldContext),
1856:                        FieldContext.end(fieldContext));
1857:            }
1858:
1859:            public long getRemainingWork() {
1860:                return getRemainingWork(null);
1861:            }
1862:
1863:            /* (non-Javadoc)
1864:             * @see com.projity.pm.assignment.TimeDistributedFields#getBaselineCost(int, com.projity.field.FieldContext)
1865:             */
1866:            public double getBaselineCost(int numBaseline,
1867:                    FieldContext fieldContext) {
1868:                return baselineCost(FieldContext.start(fieldContext),
1869:                        FieldContext.end(fieldContext));
1870:            }
1871:
1872:            /* (non-Javadoc)
1873:             * @see com.projity.pm.assignment.TimeDistributedFields#getBaselineWork(int, com.projity.field.FieldContext)
1874:             */
1875:            public long getBaselineWork(int numBaseline,
1876:                    FieldContext fieldContext) {
1877:                return baselineWork(FieldContext.start(fieldContext),
1878:                        FieldContext.end(fieldContext));
1879:            }
1880:
1881:            /***************************************************************************************
1882:             * Earned Value Fields
1883:             **************************************************************************************/
1884:            public double getAcwp(FieldContext fieldContext) {
1885:                return acwp(FieldContext.start(fieldContext), FieldContext
1886:                        .end(fieldContext));
1887:            }
1888:
1889:            public double getBac(FieldContext fieldContext) {
1890:                return bac(FieldContext.start(fieldContext), FieldContext
1891:                        .end(fieldContext));
1892:            }
1893:
1894:            public double getBcwp(FieldContext fieldContext) {
1895:                return bcwp(FieldContext.start(fieldContext), FieldContext
1896:                        .end(fieldContext));
1897:            }
1898:
1899:            public double getBcws(FieldContext fieldContext) {
1900:                return bcws(FieldContext.start(fieldContext), FieldContext
1901:                        .end(fieldContext));
1902:            }
1903:
1904:            public double getCv(FieldContext fieldContext) {
1905:                return EarnedValueCalculator.getInstance().cv(this ,
1906:                        FieldContext.start(fieldContext),
1907:                        FieldContext.end(fieldContext));
1908:            }
1909:
1910:            public double getSv(FieldContext fieldContext) {
1911:                return EarnedValueCalculator.getInstance().sv(this ,
1912:                        FieldContext.start(fieldContext),
1913:                        FieldContext.end(fieldContext));
1914:            }
1915:
1916:            public double getEac(FieldContext fieldContext) {
1917:                return EarnedValueCalculator.getInstance().eac(this ,
1918:                        FieldContext.start(fieldContext),
1919:                        FieldContext.end(fieldContext));
1920:            }
1921:
1922:            public double getVac(FieldContext fieldContext) {
1923:                return EarnedValueCalculator.getInstance().vac(this ,
1924:                        FieldContext.start(fieldContext),
1925:                        FieldContext.end(fieldContext));
1926:            }
1927:
1928:            public double getCpi(FieldContext fieldContext) {
1929:                return EarnedValueCalculator.getInstance().cpi(this ,
1930:                        FieldContext.start(fieldContext),
1931:                        FieldContext.end(fieldContext));
1932:            }
1933:
1934:            public double getSpi(FieldContext fieldContext) {
1935:                return EarnedValueCalculator.getInstance().spi(this ,
1936:                        FieldContext.start(fieldContext),
1937:                        FieldContext.end(fieldContext));
1938:            }
1939:
1940:            public double getCsi(FieldContext fieldContext) {
1941:                return EarnedValueCalculator.getInstance().csi(this ,
1942:                        FieldContext.start(fieldContext),
1943:                        FieldContext.end(fieldContext));
1944:            }
1945:
1946:            public double getCvPercent(FieldContext fieldContext) {
1947:                return EarnedValueCalculator.getInstance().cvPercent(this ,
1948:                        FieldContext.start(fieldContext),
1949:                        FieldContext.end(fieldContext));
1950:            }
1951:
1952:            public double getSvPercent(FieldContext fieldContext) {
1953:                return EarnedValueCalculator.getInstance().svPercent(this ,
1954:                        FieldContext.start(fieldContext),
1955:                        FieldContext.end(fieldContext));
1956:            }
1957:
1958:            public double getTcpi(FieldContext fieldContext) {
1959:                return EarnedValueCalculator.getInstance().tcpi(this ,
1960:                        FieldContext.start(fieldContext),
1961:                        FieldContext.end(fieldContext));
1962:            }
1963:
1964:            /**
1965:             * @return
1966:             */
1967:            public Date getCreated() {
1968:                return hasKey.getCreated();
1969:            }
1970:
1971:            /**
1972:             * @return
1973:             */
1974:            public long getId() {
1975:                return hasKey.getId();
1976:            }
1977:
1978:            /**
1979:             * @return
1980:             */
1981:            public String getName() {
1982:                return "" + getLeft() + " " + getRight();
1983:            }
1984:
1985:            /**
1986:             * @param context
1987:             * @return
1988:             */
1989:            public String getName(FieldContext context) {
1990:                if (context == null)
1991:                    return "???"; //fix
1992:                if (context.isLeftAssociation())
1993:                    return getRight().toString();
1994:                else
1995:                    return getLeft().toString();
1996:            }
1997:
1998:            /**
1999:             * @return
2000:             */
2001:            public long getUniqueId() {
2002:                return hasKey.getUniqueId();
2003:            }
2004:
2005:            //	public void setNew(boolean isNew) {
2006:            //		hasKey.setNew(isNew);
2007:            //	}
2008:            /**
2009:             * @param created
2010:             */
2011:            public void setCreated(Date created) {
2012:                hasKey.setCreated(created);
2013:            }
2014:
2015:            /**
2016:             * @param id
2017:             */
2018:            public void setId(long id) {
2019:                hasKey.setId(id);
2020:            }
2021:
2022:            /**
2023:             * @param name
2024:             */
2025:            public void setName(String name) {
2026:                hasKey.setName(name);
2027:            }
2028:
2029:            /**
2030:             * @param id
2031:             */
2032:            public void setUniqueId(long id) {
2033:                hasKey.setUniqueId(id);
2034:            }
2035:
2036:            public Document getDocument() {
2037:                return getProject();
2038:            }
2039:
2040:            public Document getDocument(boolean leftObject) {
2041:                return (leftObject) ? getTask().getDocument() : getResource()
2042:                        .getDocument();
2043:            }
2044:
2045:            public Query workQuery() {
2046:                Query query = Query.getInstance();
2047:                SelectFrom clause = SelectFrom.getInstance();
2048:                query.selectFrom(clause).action(work(clause));
2049:                return query;
2050:            }
2051:
2052:            public void calcDataBetween(Object type, HasStartAndEnd generator,
2053:                    CalculatedValues values) {
2054:                SelectFrom clause = SelectFrom.getInstance();
2055:                AssignmentFieldFunctor dataFunctor = getDataSelect(type,
2056:                        clause, false);
2057:                calcDataBetween(dataFunctor, clause, generator, values);
2058:            }
2059:
2060:            public static void calcResourceAvailabilityBetween(
2061:                    Resource resource, HasStartAndEnd generator,
2062:                    CalculatedValues values) {
2063:                SelectFrom clause = SelectFrom.getInstance();
2064:                AssignmentFieldFunctor dataFunctor = resourceAvailability(
2065:                        clause, resource);
2066:                calcDataBetween(dataFunctor, clause, generator, values);
2067:            }
2068:
2069:            public static void calcDataBetween(
2070:                    AssignmentFieldFunctor dataFunctor, SelectFrom clause,
2071:                    HasStartAndEnd generator, CalculatedValues values) {
2072:                if (generator != null)
2073:                    clause.whereInRange(generator.getStart(), generator
2074:                            .getEnd()); // automatically also adds a generator to limit range
2075:
2076:                CalculatedValuesFunctor visitor = CalculatedValuesFunctor
2077:                        .getInstance(dataFunctor, values,
2078:                                (TimeIteratorGenerator) generator);
2079:
2080:                Query query = Query.getInstance();
2081:                query.selectFrom(clause);
2082:                if (generator != null
2083:                        && generator instanceof  TimeIteratorGenerator) {
2084:                    query.groupBy((TimeIteratorGenerator) generator).action(
2085:                            visitor);
2086:                } else {
2087:                    clause.select(visitor); // replaces other one
2088:                }
2089:                query.execute();
2090:            }
2091:
2092:            public long getResourceAvailability() {
2093:                return detail.getResourceAvailability();
2094:            }
2095:
2096:            public Collection childrenToRollup() {
2097:                return null;
2098:            }
2099:
2100:            /* (non-Javadoc)
2101:             * @see com.projity.pm.assignment.Allocation#getMostLoadedAssignmentUnits()
2102:             */
2103:            public double getMostLoadedAssignmentUnits() {
2104:                return getUnits();
2105:            }
2106:
2107:            /**
2108:             * @return
2109:             */
2110:
2111:            public void makeContourPersonal() {
2112:                //		if (getWorkContour().isPersonal())
2113:                //			return;
2114:                Object type = WORK;
2115:                ContourBucketIntervalGenerator contourGenerator = contourGeneratorInstance(type); //contour
2116:                PersonalContourMaker contourBuilder = PersonalContourMaker
2117:                        .getInstance(this , contourGenerator);
2118:                Query.getInstance().selectFrom(
2119:                        SelectFrom.getInstance().select(contourBuilder).from(
2120:                                contourGenerator).all()).execute();
2121:
2122:                newDetail().setContour(type, contourBuilder.getList());
2123:                detail.recalculateDuration();
2124:            }
2125:
2126:            /**
2127:             * Clone the detail and set it
2128:             * @return cloned assignment detail
2129:             */
2130:            private AssignmentDetail newDetail() {
2131:                //TODO store off detail for undo
2132:                //System.out.println("before clone " + new Date(detail.getStop())); 	
2133:                detail = (AssignmentDetail) detail.clone();
2134:                if (getTask() != null)
2135:                    getTask().setDirty(true);
2136:                setDirty(true);
2137:                //System.out.println("after clone " + new Date(detail.getStop()));		
2138:                return detail;
2139:            }
2140:
2141:            public long getElapsedDuration() {
2142:                return detail.getElapsedDuration();
2143:            }
2144:
2145:            public long getDuration() {
2146:                return detail.getDuration();
2147:            }
2148:
2149:            public double getPercentComplete() {
2150:                return detail.getPercentComplete();
2151:            }
2152:
2153:            public void setPercentComplete(double percentComplete) {
2154:                newDetail().setPercentComplete(percentComplete);
2155:            }
2156:
2157:            public long getEnd() {
2158:                return detail.getEnd();
2159:            }
2160:
2161:            public void setEnd(long end) {
2162:                detail.setEnd(end);
2163:            }
2164:
2165:            public long getActualStart() {
2166:                return detail.getActualStart();
2167:            }
2168:
2169:            public void setActualStart(long actualStart) {
2170:                newDetail().setActualStart(actualStart);
2171:            }
2172:
2173:            public void setRemainingDuration(long remainingDuration) {
2174:                newDetail().setRemainingDuration(remainingDuration);
2175:            }
2176:
2177:            public long getActualFinish() {
2178:                return detail.getActualFinish();
2179:            }
2180:
2181:            public void setActualFinish(long actualFinish) {
2182:                newDetail().setActualFinish(actualFinish);
2183:            }
2184:
2185:            public long getResume() {
2186:                return detail.getResume();
2187:            }
2188:
2189:            public long getActualDuration() {
2190:                return detail.getActualDuration();
2191:            }
2192:
2193:            public void setActualDuration(long actualDuration) {
2194:                newDetail().setActualDuration(actualDuration);
2195:            }
2196:
2197:            public long getRemainingDuration() {
2198:                return detail.getRemainingDuration();
2199:            }
2200:
2201:            public void setResume(long resume) {
2202:                newDetail().setResume(resume);
2203:            }
2204:
2205:            public long getStop() {
2206:                return detail.getStop();
2207:            }
2208:
2209:            public void setStop(long stop) {
2210:                if (stop < getStart()) // make sure in assignment's range
2211:                    stop = getStart();
2212:                else if (stop > getEnd())
2213:                    stop = getEnd();
2214:                long currentStop = getStop();
2215:                if (currentStop == stop)
2216:                    return;
2217:                if (stop < currentStop) // if uncompleting
2218:                    newDetail().removeFillerAfter(stop);
2219:                if (currentStop > 0 && getDependencyStart() > currentStop
2220:                        && getDependencyStart() < stop) {// if setting stop incorporates split due to dependency
2221:                    makeContourPersonal();
2222:
2223:                }
2224:                newDetail().setStop(stop);
2225:            }
2226:
2227:            public void clearDuration() {
2228:                newDetail().clearDuration();
2229:            }
2230:
2231:            public long getDependencyStart() {
2232:                return detail.getDependencyStart();
2233:            }
2234:
2235:            public void setDependencyStart(long dependencyStart) {
2236:                detail.setDependencyStart(dependencyStart); //TODO is it ok to modify schedule directly?  Should be if it is transient
2237:            }
2238:
2239:            //for gantt bar formula
2240:            //probably to add in a common interface with task
2241:            public boolean isNormal() {
2242:                return false;
2243:            }
2244:
2245:            public boolean isCritical() {
2246:                return false;
2247:            }
2248:
2249:            public boolean isSummary() {
2250:                return false;
2251:            }
2252:
2253:            public boolean isMilestone() {
2254:                return false;
2255:            }
2256:
2257:            public boolean isAssignment() {
2258:                return true;
2259:            }
2260:
2261:            public void setTaskSchedule(TaskSchedule taskSchedule) {
2262:                newDetail().setTaskSchedule(taskSchedule);
2263:            }
2264:
2265:            public boolean inProgress() {
2266:                double percentComplete = getPercentComplete();
2267:                return (percentComplete > 0.0D && percentComplete < 1.0D);
2268:            }
2269:
2270:            public boolean isComplete() {
2271:                return getPercentComplete() == 1.0D;
2272:            }
2273:
2274:            public boolean isUnstarted() {
2275:                return getPercentComplete() == 0.0D;
2276:            }
2277:
2278:            public boolean isMine() {
2279:                return getResource().isMe();
2280:            }
2281:
2282:            private void writeObject(ObjectOutputStream s) throws IOException {
2283:                s.defaultWriteObject();
2284:                hasKey.serialize(s);
2285:            }
2286:
2287:            private void readObject(ObjectInputStream s) throws IOException,
2288:                    ClassNotFoundException {
2289:                s.defaultReadObject();
2290:                hasKey = HasKeyImpl.deserialize(s, this );
2291:                //	    barClosureInstance = new BarClosure();
2292:            }
2293:
2294:            public Object clone() {
2295:                try {
2296:                    Assignment a = (Assignment) super .clone();
2297:                    a.hasKey = new HasKeyImpl(true, a);
2298:                    a.setName(getName());
2299:                    //			barClosureInstance = new BarClosure();
2300:                    a.detail = (AssignmentDetail) detail.clone();
2301:                    return a;
2302:                } catch (CloneNotSupportedException e) {
2303:                    throw new InternalError();
2304:                }
2305:            }
2306:
2307:            public Object cloneWithTask(Task task) {
2308:                Assignment a = (Assignment) clone();
2309:                a.detail.setTask(task);
2310:                return a;
2311:            }
2312:
2313:            public Object cloneWithResource(Resource resource) {
2314:                Assignment a = (Assignment) clone();
2315:                a.detail.setResource(resource);
2316:                return a;
2317:            }
2318:
2319:            public Object cloneWithResourceAndTask(Resource resource, Task task) {
2320:                Assignment a = (Assignment) clone();
2321:                a.detail.setResource(resource);
2322:                a.detail.setTask(task);
2323:                return a;
2324:            }
2325:
2326:            public void convertToBaselineAssignment(boolean useDefaultCalendar) {
2327:                detail.convertToBaselineAssignment(useDefaultCalendar);
2328:            }
2329:
2330:            /**
2331:             * See if assignment duration is empty
2332:             * @return
2333:             */
2334:            public boolean hasDuration() {
2335:                return detail.hasDuration();
2336:            }
2337:
2338:            public void setRemainingWork(long remainingWork,
2339:                    FieldContext fieldContext) {
2340:                setActualWork(getWork(fieldContext)
2341:                        - Duration.millis(remainingWork), fieldContext);
2342:            }
2343:
2344:            public boolean isReadOnlyWork(FieldContext fieldContext) {
2345:
2346:                if (fieldContext == null) {
2347:                    return isMaterial(); //// material resource assignments cannot have their total work modified
2348:                }
2349:                // see if there is some calendar time
2350:                return !isActiveBetween(fieldContext.getStart(), fieldContext
2351:                        .getEnd());
2352:            }
2353:
2354:            public boolean isActiveBetween(long start, long end) {
2355:                return getEffectiveWorkCalendar().compare(end, start, false) > 0;
2356:
2357:            }
2358:
2359:            public boolean isReadOnlyActualWork(FieldContext fieldContext) {
2360:                return false;
2361:            }
2362:
2363:            public boolean isReadOnlyRemainingWork(FieldContext fieldContext) {
2364:                return isReadOnlyWork(fieldContext);
2365:            }
2366:
2367:            public double getFixedCost(FieldContext fieldContext) {
2368:                return 0;
2369:            }
2370:
2371:            public double getActualFixedCost(FieldContext fieldContext) {
2372:                return 0;
2373:            }
2374:
2375:            public boolean fieldHideActualFixedCost(FieldContext fieldContext) {
2376:                return true;
2377:            }
2378:
2379:            public double fixedCost(long start, long end) {
2380:                return ((Task) getTask()).fixedCost(start, end);
2381:            }
2382:
2383:            public double actualFixedCost(long start, long end) {
2384:                return ((Task) getTask()).actualFixedCost(start, end);
2385:            }
2386:
2387:            /* (non-Javadoc)
2388:             * @see com.projity.pm.assignment.TimeDistributedFields#setFixedCost(double, com.projity.field.FieldContext)
2389:             */
2390:            public void setFixedCost(double fixedCost, FieldContext fieldContext) {
2391:            }
2392:
2393:            public boolean isReadOnlyFixedCost(FieldContext fieldContext) {
2394:                return true;
2395:            }
2396:
2397:            public boolean isLabor() {
2398:                return getResource().isLabor();
2399:            }
2400:
2401:            public boolean isTemporal() {
2402:                return detail.isTemporal();
2403:            }
2404:
2405:            /**
2406:             * @param timeUnit
2407:             */
2408:            public void setRateUnit(int timeUnit) {
2409:                detail.setRateUnit(timeUnit);
2410:                getTask().updateCachedDuration(); // needed for checking if milestone - happens when changing units in dialog
2411:            }
2412:
2413:            public final Rate getRate() {
2414:                return detail.getRate();
2415:            }
2416:
2417:            private int getTaskSchedulingType() {
2418:                return ((NormalTask) getTask()).getSchedulingType();
2419:            }
2420:
2421:            public String valuesString() {
2422:                return "Duration=" + DurationFormat.format(getDuration())
2423:                        + " Work=" + DurationFormat.format(getWork(null))
2424:                        + " Units=" + getUnits() + " contour="
2425:                        + getWorkContour().toString(getDuration());
2426:
2427:            }
2428:
2429:            public final void setRate(Rate rate) {
2430:
2431:                if (rate.isNonTemporal() == getRate().isNonTemporal()) { // normal case.  If a material resource is modified from temporal to non (or vice versa), just set the rate
2432:                    double old = getRate().getValue();
2433:                    if (rate.getValue() == old) // if no change
2434:                        return;
2435:                    long oldRemaining = getRemainingDuration();
2436:                    newDetail();
2437:                    double multiplier = rate.getValue() / old;
2438:                    if (getPercentComplete() > 0)
2439:                        makeContourPersonal();
2440:                    detail.adjustRemainingUnits(rate.getValue());
2441:                    if (getTaskSchedulingType() != SchedulingType.FIXED_DURATION)
2442:                        detail
2443:                                .adjustRemainingDuration((long) (oldRemaining / multiplier));
2444:                }
2445:                detail.setRate(rate);
2446:
2447:                getTask().updateCachedDuration(); // needed for checking if milestone
2448:
2449:            }
2450:
2451:            //	public boolean isNew() {
2452:            //		return hasKey.isNew();
2453:            //	}
2454:            public double getRemainingCost(FieldContext fieldContext) {
2455:                return getCost(fieldContext) - getActualCost(fieldContext);
2456:            }
2457:
2458:            public void invalidateAssignmentCalendar() {
2459:                detail.invalidateAssignmentCalendar();
2460:            }
2461:
2462:            public boolean isSubproject() {
2463:                return false;
2464:            }
2465:
2466:            public boolean isJustModified() {
2467:                Task task = getTask();
2468:                if (task == null)
2469:                    return false;
2470:                else
2471:                    return task.isJustModified();
2472:            }
2473:
2474:            public boolean isInvalidIntersectionCalendar() {
2475:                return detail.isInvalidIntersectionCalendar();
2476:            }
2477:
2478:            private void moveDelayToContour() {
2479:                // Remove delay and add at beginning of contour
2480:                long oldDelay = calcTotalDelay();
2481:                if (oldDelay == 0)
2482:                    return;
2483:                makeContourPersonal();
2484:                setTotalDelay(0);
2485:                setDurationMillis(getDurationMillis() + oldDelay);
2486:                AbstractContour contour = PersonalContour.addEmptyBucket(
2487:                        getWorkContour(), oldDelay, false); // add empty space before
2488:                newDetail().setWorkContour(contour);
2489:            }
2490:
2491:            private void extractDelayFromContour(PersonalContour newContour) {
2492:                long delay = newContour.extractDelay(); // the case when adding 0 units at start
2493:                if (delay > 0) {
2494:                    newDetail();
2495:                    detail.setDelay(delay);
2496:                    //			detail.recalculateDuration();
2497:                }
2498:            }
2499:
2500:            public void setComplete(boolean complete) {
2501:                ScheduleUtil.setComplete(this , complete);
2502:            }
2503:
2504:            public String getProjectName() {
2505:                return getOwningProject().getName();
2506:            }
2507:
2508:            public Project getProject() {
2509:                return getTask().getProject();
2510:            }
2511:
2512:            public Project getOwningProject() {
2513:                Project p = getTask().getOwningProject();
2514:                if (p == null)
2515:                    p = getProject();
2516:                return p;
2517:            }
2518:
2519:            public final int getTimesheetStatus() {
2520:                Assignment ts = getTimesheetAssignment();
2521:                if (ts != null)
2522:                    return ts.timesheetStatus;
2523:                return timesheetStatus;
2524:            }
2525:
2526:            public final void setTimesheetStatus(int timesheetStatus) {
2527:                this .timesheetStatus = timesheetStatus;
2528:            }
2529:
2530:            public final long getLastTimesheetUpdate() {
2531:                return lastTimesheetUpdate;
2532:            }
2533:
2534:            public final void setLastTimesheetUpdate(long lastTimesheetUpdate) {
2535:                this .lastTimesheetUpdate = lastTimesheetUpdate;
2536:                ;
2537:            }
2538:
2539:            public boolean isPendingTimesheetUpdate() {
2540:                return (getTimesheetStatus() == TimesheetStatus.VALIDATED);
2541:            }
2542:
2543:            public String getTimesheetStatusName() {
2544:                return TimesheetHelper
2545:                        .getTimesheetStatusName(getTimesheetStatus());
2546:            }
2547:
2548:            public final boolean isTimesheetAssignment() {
2549:                return timesheetAssignment;
2550:            }
2551:
2552:            public final void setTimesheetAssignment(boolean timesheetAssignment) {
2553:                this .timesheetAssignment = timesheetAssignment;
2554:            }
2555:
2556:            public Assignment getTimesheetAssignment() {
2557:                if (isTimesheetAssignment())
2558:                    return this ;
2559:                return detail.getBaselineAssignment(Snapshottable.TIMESHEET,
2560:                        false);
2561:            }
2562:
2563:            public long getTimesheetStart() {
2564:                return getCachedStart().getTime();
2565:            }
2566:
2567:            public long getTimesheetFinish() {
2568:                return getCachedEnd().getTime();
2569:            }
2570:
2571:            public boolean isTimesheetEditable() {
2572:                return getTimesheetStatus() != TimesheetStatus.INTEGRATED;
2573:            }
2574:
2575:            public boolean isTimesheetEntered() {
2576:                return getTimesheetStatus() != TimesheetStatus.ENTERED;
2577:            }
2578:
2579:            public boolean isTimesheetValidated() {
2580:                return getTimesheetStatus() != TimesheetStatus.VALIDATED;
2581:            }
2582:
2583:            public boolean isTimesheetRejected() {
2584:                return getTimesheetStatus() != TimesheetStatus.REJECTED;
2585:            }
2586:
2587:            public boolean copyFieldsFromTimesheet(Collection fieldArray) {
2588:                Assignment ts = getTimesheetAssignment();
2589:                if (ts == null)
2590:                    return false;
2591:                if (ts.getTimesheetStatus() != TimesheetStatus.VALIDATED) // only incorporate validated data
2592:                    return false;
2593:                Field.copyData(fieldArray, this , ts);
2594:                return true;
2595:            }
2596:
2597:            public boolean applyTimesheet(Collection fieldArray,
2598:                    long timesheetUpdateDate) {
2599:                boolean updated = copyFieldsFromTimesheet(fieldArray);
2600:                if (updated) {
2601:                    setTimesheetStatus(TimesheetStatus.INTEGRATED);
2602:                    this .lastTimesheetUpdate = timesheetUpdateDate;
2603:                    Assignment ts = getTimesheetAssignment();
2604:                    ts.setTimesheetStatus(TimesheetStatus.INTEGRATED);
2605:                    ts.lastTimesheetUpdate = timesheetUpdateDate;
2606:
2607:                }
2608:                return updated;
2609:            }
2610:
2611:            public String getTimesheetStatusStyle() { // used for display style in web
2612:                return TimesheetHelper
2613:                        .getTimesheetStatusStyle(getTimesheetStatus());
2614:            }
2615:
2616:            private transient boolean dirty = true;
2617:
2618:            public boolean isDirty() {
2619:                return dirty;
2620:            }
2621:
2622:            public void setDirty(boolean dirty) {
2623:                this .dirty = dirty;
2624:            }
2625:
2626:            public final Date getCachedEnd() {
2627:                return cachedEnd;
2628:            }
2629:
2630:            public final void setCachedEnd(Date savedEnd) {
2631:                this .cachedEnd = savedEnd;
2632:            }
2633:
2634:            public final Date getCachedStart() {
2635:                return cachedStart;
2636:            }
2637:
2638:            public final void setCachedStart(Date savedStart) {
2639:                this .cachedStart = savedStart;
2640:            }
2641:
2642:            public final int getWorkflowState() {
2643:                return workflowState;
2644:            }
2645:
2646:            public final void setWorkflowState(int workflowState) {
2647:                this .workflowState = workflowState;
2648:            }
2649:
2650:            public void setTaskAndResource(Task task, Resource resource) {
2651:                detail.setTask(task);
2652:                detail.setResource(resource);
2653:            }
2654:
2655:            public long getDeadline() { // needed for indicators
2656:                return 0;
2657:            }
2658:
2659:            public final long getEarliestStop() {
2660:                return detail.getEarliestStop();
2661:            }
2662:
2663:            public final long getCompletedThrough() {
2664:                return detail.getCompletedThrough();
2665:            }
2666:
2667:            public void setCompletedThrough(long completedThrough) {
2668:                setStop(completedThrough);
2669:            }
2670:
2671:            public void replace(Object newOne, boolean leftObject) {
2672:                if (leftObject)
2673:                    newDetail().setTask((Task) newOne);
2674:                else
2675:                    newDetail().setResource((Resource) newOne);
2676:            }
2677:
2678:            public long getFinishOffset() {
2679:                return EarnedValueCalculator.getInstance()
2680:                        .getFinishOffset(this );
2681:            }
2682:
2683:            public long getStartOffset() {
2684:                return EarnedValueCalculator.getInstance().getStartOffset(this );
2685:            }
2686:
2687:            public String getTimeUnitLabel() {
2688:                return getResource().getTimeUnitLabel();
2689:            }
2690:
2691:            public boolean isMaterial() {
2692:                return getResource().isMaterial();
2693:            }
2694:
2695:            public RateFormat getRateFormat() {
2696:                return getResource().getRateFormat();
2697:            }
2698:
2699:            public ImageLink getBudgetStatusIndicator() {
2700:                return EarnedValueCalculator.getInstance()
2701:                        .getBudgetStatusIndicator(getCpi(null));
2702:            }
2703:
2704:            public ImageLink getScheduleStatusIndicator() {
2705:                return EarnedValueCalculator.getInstance()
2706:                        .getBudgetStatusIndicator(getSpi(null));
2707:            }
2708:
2709:            public Object backupDetail() {
2710:                return detail.backupDetail();
2711:            }
2712:
2713:            //use when updating only this assignment
2714:            public void restoreDetail(Object source, Object detail,
2715:                    boolean isChild) {
2716:                restoreDetail(detail);
2717:                getTask().recalculate(source);
2718:                getTask().updateCachedDuration();
2719:            }
2720:
2721:            public void restoreDetail(Object detail) {
2722:                this .detail = (AssignmentDetail) detail;
2723:            }
2724:
2725:            public String getDelegatedToName() {
2726:                return getTask().getDelegatedToName();
2727:            }
2728:
2729:            public boolean isLocal() {
2730:                return true;
2731:            }
2732:
2733:            public void setLocal(boolean local) {
2734:            }
2735:
2736:            public void renumber() {
2737:                hasKey.renumber();
2738:            }
2739:
2740:            public int getCostRateIndex() {
2741:                return detail.getCostRateIndex();
2742:            }
2743:
2744:            public void setCostRateIndex(int val) {
2745:                newDetail().setCostRateIndex(val);
2746:            }
2747:
2748:            public String getUniqueIdString() {
2749:                return getTask().getUniqueId() + "."
2750:                        + getResource().getUniqueId();
2751:            }
2752:
2753:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.