/* * file: Task.java * author: Scott Melville * Jon Iles * copyright: (c) Packwood Software 2002-2003 * date: 15/08/2002 */ /* * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package net.sf.mpxj; import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.UUID; import net.sf.mpxj.common.BooleanHelper; import net.sf.mpxj.common.DateHelper; import net.sf.mpxj.common.NumberHelper; import net.sf.mpxj.common.TaskFieldLists; import net.sf.mpxj.listener.FieldListener; /** * This class represents a task record from an project file. */ public final class Task extends ProjectEntity implements Comparable<Task>, ProjectEntityWithID, FieldContainer, ChildTaskContainer { /** * Default constructor. * * @param file Parent file to which this record belongs. * @param parent Parent task */ Task(ProjectFile file, Task parent) { super(file); setType(TaskType.FIXED_UNITS); setConstraintType(ConstraintType.AS_SOON_AS_POSSIBLE); setTaskMode(TaskMode.AUTO_SCHEDULED); setActive(true); m_parent = parent; ProjectConfig config = file.getProjectConfig(); if (config.getAutoTaskUniqueID() == true) { setUniqueID(Integer.valueOf(config.getNextTaskUniqueID())); } if (config.getAutoTaskID() == true) { setID(Integer.valueOf(config.getNextTaskID())); } if (config.getAutoWBS() == true) { generateWBS(parent); } if (config.getAutoOutlineNumber() == true) { generateOutlineNumber(parent); } if (config.getAutoOutlineLevel() == true) { if (parent == null) { setOutlineLevel(Integer.valueOf(1)); } else { setOutlineLevel(Integer.valueOf(NumberHelper.getInt(parent.getOutlineLevel()) + 1)); } } } /** * This method is used to automatically generate a value * for the WBS field of this task. * * @param parent Parent Task */ public void generateWBS(Task parent) { String wbs; if (parent == null) { if (NumberHelper.getInt(getUniqueID()) == 0) { wbs = "0"; } else { wbs = Integer.toString(getParentFile().getChildTasks().size() + 1); } } else { wbs = parent.getWBS(); // // Apparently I added the next lines to support MPX files generated by Artemis, back in 2005 // Unfortunately I have no test data which exercises this code, and it now breaks // otherwise valid WBS values read (in this case) from XER files. So it's commented out // until someone complains about their 2005-era Artemis MPX files not working! // // int index = wbs.lastIndexOf(".0"); // if (index != -1) // { // wbs = wbs.substring(0, index); // } int childTaskCount = parent.getChildTasks().size() + 1; if (wbs.equals("0")) { wbs = Integer.toString(childTaskCount); } else { wbs += ("." + childTaskCount); } } setWBS(wbs); } /** * This method is used to automatically generate a value * for the Outline Number field of this task. * * @param parent Parent Task */ public void generateOutlineNumber(Task parent) { String outline; if (parent == null) { if (NumberHelper.getInt(getUniqueID()) == 0) { outline = "0"; } else { outline = Integer.toString(getParentFile().getChildTasks().size() + 1); } } else { outline = parent.getOutlineNumber(); int index = outline.lastIndexOf(".0"); if (index != -1) { outline = outline.substring(0, index); } int childTaskCount = parent.getChildTasks().size() + 1; if (outline.equals("0")) { outline = Integer.toString(childTaskCount); } else { outline += ("." + childTaskCount); } } setOutlineNumber(outline); } /** * This method is used to add notes to the current task. * * @param notes notes to be added */ public void setNotes(String notes) { set(TaskField.NOTES, notes); } /** * This method allows nested tasks to be added, with the WBS being * completed automatically. * * @return new task */ public Task addTask() { ProjectFile parent = getParentFile(); Task task = new Task(parent, this); m_children.add(task); parent.getAllTasks().add(task); setSummary(true); return (task); } /** * This method is used to associate a child task with the current * task instance. It has package access, and has been designed to * allow the hierarchical outline structure of tasks in an MPX * file to be constructed as the file is read in. * * @param child Child task. * @param childOutlineLevel Outline level of the child task. */ public void addChildTask(Task child, int childOutlineLevel) { int outlineLevel = NumberHelper.getInt(getOutlineLevel()); if ((outlineLevel + 1) == childOutlineLevel) { m_children.add(child); setSummary(true); } else { if (m_children.isEmpty() == false) { (m_children.get(m_children.size() - 1)).addChildTask(child, childOutlineLevel); } } } /** * This method is used to associate a child task with the current * task instance. It has been designed to * allow the hierarchical outline structure of tasks in an MPX * file to be updated once all of the task data has been read. * * @param child child task */ public void addChildTask(Task child) { child.m_parent = this; m_children.add(child); setSummary(true); if (getParentFile().getProjectConfig().getAutoOutlineLevel() == true) { child.setOutlineLevel(Integer.valueOf(NumberHelper.getInt(getOutlineLevel()) + 1)); } } /** * Inserts a child task prior to a given sibling task. * * @param child new child task * @param previousSibling sibling task */ public void addChildTaskBefore(Task child, Task previousSibling) { int index = m_children.indexOf(previousSibling); if (index == -1) { m_children.add(child); } else { m_children.add(index, child); } child.m_parent = this; setSummary(true); if (getParentFile().getProjectConfig().getAutoOutlineLevel() == true) { child.setOutlineLevel(Integer.valueOf(NumberHelper.getInt(getOutlineLevel()) + 1)); } } /** * Removes a child task. * * @param child child task instance */ public void removeChildTask(Task child) { if (m_children.remove(child)) { child.m_parent = null; } setSummary(!m_children.isEmpty()); } /** * This method allows the list of child tasks to be cleared in preparation * for the hierarchical task structure to be built. */ public void clearChildTasks() { m_children.clear(); setSummary(false); } /** * This method allows recurring task details to be added to the * current task. * * @return RecurringTask object */ public RecurringTask addRecurringTask() { if (m_recurringTask == null) { m_recurringTask = new RecurringTask(); } return (m_recurringTask); } /** * This method retrieves the recurring task record. If the current * task is not a recurring task, then this method will return null. * * @return Recurring task record. */ public RecurringTask getRecurringTask() { return (m_recurringTask); } /** * This method allows a resource assignment to be added to the * current task. * * @param resource the resource to assign * @return ResourceAssignment object */ public ResourceAssignment addResourceAssignment(Resource resource) { ResourceAssignment assignment = getExistingResourceAssignment(resource); if (assignment == null) { assignment = new ResourceAssignment(getParentFile(), this); m_assignments.add(assignment); getParentFile().getAllResourceAssignments().add(assignment); assignment.setTaskUniqueID(getUniqueID()); assignment.setWork(getDuration()); assignment.setUnits(ResourceAssignment.DEFAULT_UNITS); if (resource != null) { assignment.setResourceUniqueID(resource.getUniqueID()); resource.addResourceAssignment(assignment); } } return (assignment); } /** * Add a resource assignment which has been populated elsewhere. * * @param assignment resource assignment */ public void addResourceAssignment(ResourceAssignment assignment) { if (getExistingResourceAssignment(assignment.getResource()) == null) { m_assignments.add(assignment); getParentFile().getAllResourceAssignments().add(assignment); Resource resource = assignment.getResource(); if (resource != null) { resource.addResourceAssignment(assignment); } } } /** * Retrieves an existing resource assignment if one is present, * to prevent duplicate resource assignments being added. * * @param resource resource to test for * @return existing resource assignment */ private ResourceAssignment getExistingResourceAssignment(Resource resource) { ResourceAssignment assignment = null; Integer resourceUniqueID = null; if (resource != null) { Iterator<ResourceAssignment> iter = m_assignments.iterator(); resourceUniqueID = resource.getUniqueID(); while (iter.hasNext() == true) { assignment = iter.next(); Integer uniqueID = assignment.getResourceUniqueID(); if (uniqueID != null && uniqueID.equals(resourceUniqueID) == true) { break; } assignment = null; } } return assignment; } /** * This method allows the list of resource assignments for this * task to be retrieved. * * @return list of resource assignments */ public List<ResourceAssignment> getResourceAssignments() { return (m_assignments); } /** * Internal method used as part of the process of removing a * resource assignment. * * @param assignment resource assignment to be removed */ void removeResourceAssignment(ResourceAssignment assignment) { m_assignments.remove(assignment); } /** * This method allows a predecessor relationship to be added to this * task instance. * * @param targetTask the predecessor task * @param type relation type * @param lag relation lag * @return relationship */ @SuppressWarnings("unchecked") public Relation addPredecessor(Task targetTask, RelationType type, Duration lag) { // // Ensure that we have a valid lag duration // if (lag == null) { lag = Duration.getInstance(0, TimeUnit.DAYS); } // // Retrieve the list of predecessors // List<Relation> predecessorList = (List<Relation>) getCachedValue(TaskField.PREDECESSORS); if (predecessorList == null) { predecessorList = new LinkedList<Relation>(); set(TaskField.PREDECESSORS, predecessorList); } // // Ensure that there is only one predecessor relationship between // these two tasks. // Relation predecessorRelation = null; Iterator<Relation> iter = predecessorList.iterator(); while (iter.hasNext() == true) { predecessorRelation = iter.next(); if (predecessorRelation.getTargetTask() == targetTask) { if (predecessorRelation.getType() != type || predecessorRelation.getLag().compareTo(lag) != 0) { predecessorRelation = null; } break; } predecessorRelation = null; } // // If necessary, create a new predecessor relationship // if (predecessorRelation == null) { predecessorRelation = new Relation(this, targetTask, type, lag); predecessorList.add(predecessorRelation); } // // Retrieve the list of successors // List<Relation> successorList = (List<Relation>) targetTask.getCachedValue(TaskField.SUCCESSORS); if (successorList == null) { successorList = new LinkedList<Relation>(); targetTask.set(TaskField.SUCCESSORS, successorList); } // // Ensure that there is only one successor relationship between // these two tasks. // Relation successorRelation = null; iter = successorList.iterator(); while (iter.hasNext() == true) { successorRelation = iter.next(); if (successorRelation.getTargetTask() == this) { if (successorRelation.getType() != type || successorRelation.getLag().compareTo(lag) != 0) { successorRelation = null; } break; } successorRelation = null; } // // If necessary, create a new successor relationship // if (successorRelation == null) { successorRelation = new Relation(targetTask, this, type, lag); successorList.add(successorRelation); } return (predecessorRelation); } /** * The % Complete field contains the current status of a task, expressed * as the percentage of the * task's duration that has been completed. You can enter percent complete, * or you can have * Microsoft Project calculate it for you based on actual duration. * * @param val value to be set */ public void setPercentageComplete(Number val) { set(TaskField.PERCENT_COMPLETE, val); } /** * The % Work Complete field contains the current status of a task, * expressed as the * percentage of the task's work that has been completed. You can enter * percent work * complete, or you can have Microsoft Project calculate it for you * based on actual * work on the task. * * @param val value to be set */ public void setPercentageWorkComplete(Number val) { set(TaskField.PERCENT_WORK_COMPLETE, val); } /** * The Actual Cost field shows costs incurred for work already performed * by all resources * on a task, along with any other recorded costs associated with the task. * You can enter * all the actual costs or have Microsoft Project calculate them for you. * * @param val value to be set */ public void setActualCost(Number val) { set(TaskField.ACTUAL_COST, val); } /** * The Actual Duration field shows the span of actual working time for a * task so far, * based on the scheduled duration and current remaining work or * completion percentage. * * @param val value to be set */ public void setActualDuration(Duration val) { set(TaskField.ACTUAL_DURATION, val); } /** * The Actual Finish field shows the date and time that a task actually * finished. * Microsoft Project sets the Actual Finish field to the scheduled finish * date if * the completion percentage is 100. This field contains "NA" until you * enter actual * information or set the completion percentage to 100. * * @param val value to be set */ public void setActualFinish(Date val) { set(TaskField.ACTUAL_FINISH, val); } /** * The Actual Start field shows the date and time that a task actually began. * When a task is first created, the Actual Start field contains "NA." Once you * enter the first actual work or a completion percentage for a task, Microsoft * Project sets the actual start date to the scheduled start date. * @param val value to be set */ public void setActualStart(Date val) { set(TaskField.ACTUAL_START, val); } /** * The Actual Work field shows the amount of work that has already been * done by the * resources assigned to a task. * @param val value to be set */ public void setActualWork(Duration val) { set(TaskField.ACTUAL_WORK, val); } /** * The Baseline Cost field shows the total planned cost for a task. * Baseline cost is also referred to as budget at completion (BAC). * * @param val the amount to be set */ public void setBaselineCost(Number val) { set(TaskField.BASELINE_COST, val); } /** * The Baseline Duration field shows the original span of time planned to * complete a task. * * @param val duration */ public void setBaselineDuration(Duration val) { set(TaskField.BASELINE_DURATION, val); } /** * The Baseline Finish field shows the planned completion date for a * task at the time * you saved a baseline. Information in this field becomes available * when you set a * baseline for a task. * * @param val Date to be set */ public void setBaselineFinish(Date val) { set(TaskField.BASELINE_FINISH, val); } /** * The Baseline Start field shows the planned beginning date for a task at * the time * you saved a baseline. Information in this field becomes available when you * set a baseline. * * @param val Date to be set */ public void setBaselineStart(Date val) { set(TaskField.BASELINE_START, val); } /** * The Baseline Work field shows the originally planned amount of work to * be performed * by all resources assigned to a task. This field shows the planned * person-hours * scheduled for a task. Information in the Baseline Work field * becomes available * when you set a baseline for the project. * * @param val the duration to be set. */ public void setBaselineWork(Duration val) { set(TaskField.BASELINE_WORK, val); } /** * The BCWP (budgeted cost of work performed) field contains the * cumulative value * of the assignment's timephased percent complete multiplied by * the assignments * timephased baseline cost. BCWP is calculated up to the status * date or todays * date. This information is also known as earned value. * * @param val the amount to be set */ public void setBCWP(Number val) { set(TaskField.BCWP, val); } /** * The BCWS (budgeted cost of work scheduled) field contains the cumulative * timephased baseline costs up to the status date or today's date. * * @param val the amount to set */ public void setBCWS(Number val) { set(TaskField.BCWS, val); } /** * The Confirmed field indicates whether all resources assigned to a task have * accepted or rejected the task assignment in response to a TeamAssign message * regarding their assignments. * * @param val boolean value */ public void setConfirmed(boolean val) { set(TaskField.CONFIRMED, val); } /** * The Constraint Date field shows the specific date associated with certain * constraint types, * such as Must Start On, Must Finish On, Start No Earlier Than, * Start No Later Than, * Finish No Earlier Than, and Finish No Later Than. * SEE class constants * * @param val Date to be set */ public void setConstraintDate(Date val) { set(TaskField.CONSTRAINT_DATE, val); } /** * Private method for dealing with string parameters from File. * * @param type string constraint type */ public void setConstraintType(ConstraintType type) { set(TaskField.CONSTRAINT_TYPE, type); } /** * The Contact field contains the name of an individual * responsible for a task. * * @param val value to be set */ public void setContact(String val) { set(TaskField.CONTACT, val); } /** * The Cost field shows the total scheduled, or projected, cost for a task, * based on costs already incurred for work performed by all resources assigned * to the task, in addition to the costs planned for the remaining work for the * assignment. This can also be referred to as estimate at completion (EAC). * * @param val amount */ public void setCost(Number val) { set(TaskField.COST, val); } /** * Set a cost value. * * @param index cost index (1-10) * @param value cost value */ public void setCost(int index, Number value) { set(selectField(TaskFieldLists.CUSTOM_COST, index), value); } /** * Retrieve a cost value. * * @param index cost index (1-10) * @return cost value */ public Number getCost(int index) { return (Number) getCachedValue(selectField(TaskFieldLists.CUSTOM_COST, index)); } /** * The Cost Variance field shows the difference between the * baseline cost and total cost for a task. The total cost is the * current estimate of costs based on actual costs and remaining costs. * * @param val amount */ public void setCostVariance(Number val) { set(TaskField.COST_VARIANCE, val); } /** * The Created field contains the date and time when a task was * added to the project. * * @param val date */ public void setCreateDate(Date val) { set(TaskField.CREATED, val); } /** * The Critical field indicates whether a task has any room in the * schedule to slip, * or if a task is on the critical path. The Critical field contains * Yes if the task * is critical and No if the task is not critical. * * @param val whether task is critical or not */ public void setCritical(boolean val) { set(TaskField.CRITICAL, val); } /** * The CV (earned value cost variance) field shows the difference * between how much it should have cost to achieve the current level of * completion on the task, and how much it has actually cost to achieve the * current level of completion up to the status date or today's date. * * @param val value to set */ public void setCV(Number val) { set(TaskField.CV, val); } /** * Set amount of delay as elapsed real time. * * @param val elapsed time */ public void setLevelingDelay(Duration val) { set(TaskField.LEVELING_DELAY, val); } /** * The Duration field is the total span of active working time for a task. * This is generally the amount of time from the start to the finish of a task. * The default for new tasks is 1 day (1d). * * @param val duration */ public void setDuration(Duration val) { set(TaskField.DURATION, val); } /** * Set the duration text used for a manually scheduled task. * * @param val text */ public void setDurationText(String val) { set(TaskField.DURATION_TEXT, val); } /** * Set the manual duration attribute. * * @param dur manual duration */ public void setManualDuration(Duration dur) { set(TaskField.MANUAL_DURATION, dur); } /** * Read the manual duration attribute. * * @return manual duration */ public Duration getManualDuration() { return (Duration) getCachedValue(TaskField.MANUAL_DURATION); } /** * The Duration Variance field contains the difference between the * baseline duration of a task and the forecast or actual duration * of the task. * * @param duration duration value */ public void setDurationVariance(Duration duration) { set(TaskField.DURATION_VARIANCE, duration); } /** * The Early Finish field contains the earliest date that a task * could possibly finish, based on early finish dates of predecessor * and successor tasks, other constraints, and any leveling delay. * * @param date Date value */ public void setEarlyFinish(Date date) { set(TaskField.EARLY_FINISH, date); } /** * The Early Start field contains the earliest date that a task could * possibly begin, based on the early start dates of predecessor and * successor tasks, and other constraints. * * @param date Date value */ public void setEarlyStart(Date date) { set(TaskField.EARLY_START, date); } /** * The Finish field shows the date and time that a task is scheduled to be * completed. MS project allows a finish date to be entered, and will * calculate the duration, or a duration can be supplied and MS Project * will calculate the finish date. * * @param date Date value */ public void setFinish(Date date) { set(TaskField.FINISH, date); } /** * Set the finish text used for a manually scheduled task. * * @param val text */ public void setFinishText(String val) { set(TaskField.FINISH_TEXT, val); } /** * The Finish Variance field contains the amount of time that represents the * difference between a task's baseline finish date and its forecast * or actual finish date. * * @param duration duration value */ public void setFinishVariance(Duration duration) { set(TaskField.FINISH_VARIANCE, duration); } /** * The Fixed Cost field shows any task expense that is not associated * with a resource cost. * * @param val amount */ public void setFixedCost(Number val) { set(TaskField.FIXED_COST, val); } /** * The Free Slack field contains the amount of time that a task can be * delayed without delaying any successor tasks. If the task has no * successors, free slack is the amount of time that a task can be delayed * without delaying the entire project's finish date. * * @param duration duration value */ public void setFreeSlack(Duration duration) { set(TaskField.FREE_SLACK, duration); } /** * The Hide Bar flag indicates whether the Gantt bars and Calendar bars * for a task are hidden when this project's data is displayed in MS Project. * * @param flag boolean value */ public void setHideBar(boolean flag) { set(TaskField.HIDE_BAR, flag); } /** * The ID field contains the identifier number that Microsoft Project * automatically assigns to each task as you add it to the project. * The ID indicates the position of a task with respect to the other tasks. * * @param val ID */ @Override public void setID(Integer val) { ProjectFile parent = getParentFile(); Integer previous = getID(); if (previous != null) { parent.getAllTasks().unmapID(previous); } parent.getAllTasks().mapID(val, this); set(TaskField.ID, val); } /** * The Late Finish field contains the latest date that a task can finish * without delaying the finish of the project. This date is based on the * task's late start date, as well as the late start and late finish dates * of predecessor and successor tasks, and other constraints. * * @param date date value */ public void setLateFinish(Date date) { set(TaskField.LATE_FINISH, date); } /** * The Late Start field contains the latest date that a task can start * without delaying the finish of the project. This date is based on the * task's start date, as well as the late start and late finish dates of * predecessor and successor tasks, and other constraints. * * @param date date value */ public void setLateStart(Date date) { set(TaskField.LATE_START, date); } /** * The Linked Fields field indicates whether there are OLE links to the task, * either from elsewhere in the active project, another Microsoft Project * file, or from another program. * * @param flag boolean value */ public void setLinkedFields(boolean flag) { set(TaskField.LINKED_FIELDS, flag); } /** * This is a user defined field used to mark a task for some form of * additional action. * * @param flag boolean value */ public void setMarked(boolean flag) { set(TaskField.MARKED, flag); } /** * The Milestone field indicates whether a task is a milestone. * * @param flag boolean value */ public void setMilestone(boolean flag) { set(TaskField.MILESTONE, flag); } /** * The Name field contains the name of a task. * * @param name task name */ public void setName(String name) { set(TaskField.NAME, name); } /** * The Objects field contains the number of objects attached to a task. * * @param val - integer value */ public void setObjects(Integer val) { set(TaskField.OBJECTS, val); } /** * The Outline Level field contains the number that indicates the level of * the task in the project outline hierarchy. * * @param val - int */ public void setOutlineLevel(Integer val) { set(TaskField.OUTLINE_LEVEL, val); } /** * The Outline Number field contains the number of the task in the structure * of an outline. This number indicates the task's position within the * hierarchical structure of the project outline. The outline number is * similar to a WBS (work breakdown structure) number, except that the * outline number is automatically entered by Microsoft Project. * * @param val - text */ public void setOutlineNumber(String val) { set(TaskField.OUTLINE_NUMBER, val); } /** * The Priority field provides choices for the level of importance * assigned to a task, which in turn indicates how readily a task can be * delayed or split during resource leveling. * The default priority is Medium. Those tasks with a priority * of Do Not Level are never delayed or split when Microsoft Project levels * tasks that have overallocated resources assigned. * * @param priority the priority value */ public void setPriority(Priority priority) { set(TaskField.PRIORITY, priority); } /** * The Project field shows the name of the project from which a * task originated. * This can be the name of the active project file. If there are * other projects * inserted into the active project file, the name of the * inserted project appears * in this field for the task. * * @param val - text */ public void setProject(String val) { set(TaskField.PROJECT, val); } /** * The Remaining Cost field shows the remaining scheduled expense of a task that * will be incurred in completing the remaining scheduled work by all resources * assigned to the task. * * @param val - currency amount */ public void setRemainingCost(Number val) { set(TaskField.REMAINING_COST, val); } /** * The Remaining Duration field shows the amount of time required to complete * the unfinished portion of a task. * * @param val - duration. */ public void setRemainingDuration(Duration val) { set(TaskField.REMAINING_DURATION, val); } /** * The Remaining Work field shows the amount of time, or person-hours, * still required by all assigned resources to complete a task. * @param val - duration */ public void setRemainingWork(Duration val) { set(TaskField.REMAINING_WORK, val); } /** * The Resource Group field contains the list of resource groups to which the * resources assigned to a task belong. * * @param val - String list */ public void setResourceGroup(String val) { set(TaskField.RESOURCE_GROUP, val); } /** * The Resource Initials field lists the abbreviations for the names of * resources assigned to a task. These initials can serve as substitutes * for the names. * * Note that MS Project 98 does no normally populate this field when * it generates an MPX file, and will therefore not expect to see values * in this field when it reads an MPX file. Supplying values for this * field will cause MS Project 98, 2000, and 2002 to create new resources * and ignore any other resource assignments that have been defined * in the MPX file. * * @param val String containing a comma separated list of initials */ public void setResourceInitials(String val) { set(TaskField.RESOURCE_INITIALS, val); } /** * The Resource Names field lists the names of all resources * assigned to a task. * * Note that MS Project 98 does not normally populate this field when * it generates an MPX file, and will therefore not expect to see values * in this field when it reads an MPX file. Supplying values for this * field when writing an MPX file will cause MS Project 98, 2000, and 2002 * to create new resources and ignore any other resource assignments * that have been defined in the MPX file. * * @param val String containing a comma separated list of names */ public void setResourceNames(String val) { set(TaskField.RESOURCE_NAMES, val); } /** * The Resume field shows the date that the remaining portion of a task is * scheduled to resume after you enter a new value for the % Complete field. * The Resume field is also recalculated when the remaining portion of a task * is moved to a new date. * * @param val - Date */ public void setResume(Date val) { set(TaskField.RESUME, val); } /** * For subtasks, the Rollup field indicates whether information on the subtask * Gantt bars will be rolled up to the summary task bar. For summary tasks, the * Rollup field indicates whether the summary task bar displays rolled up bars. * You must have the Rollup field for summary tasks set to Yes for any subtasks * to roll up to them. * * @param val - boolean */ public void setRollup(boolean val) { set(TaskField.ROLLUP, val); } /** * The Start field shows the date and time that a task is scheduled to begin. * You can enter the start date you want, to indicate the date when the task * should begin. Or, you can have Microsoft Project calculate the start date. * @param val - Date */ public void setStart(Date val) { set(TaskField.START, val); } /** * Set the start text used for a manually scheduled task. * * @param val text */ public void setStartText(String val) { set(TaskField.START_TEXT, val); } /** * The Start Variance field contains the amount of time that represents the * difference between a task's baseline start date and its currently * scheduled start date. * * @param val - duration */ public void setStartVariance(Duration val) { set(TaskField.START_VARIANCE, val); } /** * The Stop field shows the date that represents the end of the actual * portion of a task. Typically, Microsoft Project calculates the stop date. * However, you can edit this date as well. * * @param val - Date */ public void setStop(Date val) { set(TaskField.STOP, val); } /** * The Subproject File field contains the name of a project inserted into * the active project file. The Subproject File field contains the inserted * project's path and file name. * * @param val - String */ public void setSubprojectName(String val) { set(TaskField.SUBPROJECT_FILE, val); } /** * The Summary field indicates whether a task is a summary task. * * @param val - boolean */ public void setSummary(boolean val) { set(TaskField.SUMMARY, val); } /** * The SV (earned value schedule variance) field shows the difference * in cost terms between the current progress and the baseline plan * of the task up to the status date or today's date. You can use SV * to check costs to determine whether tasks are on schedule. * @param val - currency amount */ public void setSV(Number val) { set(TaskField.SV, val); } /** * The Total Slack field contains the amount of time a task can be delayed * without delaying the project's finish date. * * @param val - duration */ public void setTotalSlack(Duration val) { set(TaskField.TOTAL_SLACK, val); } /** * The Unique ID field contains the number that Microsoft Project * automatically designates whenever a new task is created. * This number indicates the sequence in which the task was created, * regardless of placement in the schedule. * * @param val unique ID */ @Override public void setUniqueID(Integer val) { set(TaskField.UNIQUE_ID, val); } /** * The Update Needed field indicates whether a TeamUpdate message should * be sent to the assigned resources because of changes to the start date, * finish date, or resource reassignments of the task. * * @param val - boolean */ public void setUpdateNeeded(boolean val) { set(TaskField.UPDATE_NEEDED, val); } /** * The work breakdown structure code. The WBS field contains an alphanumeric * code you can use to represent the task's position within the hierarchical * structure of the project. This field is similar to the outline number, * except that you can edit it. * * @param val - String */ public void setWBS(String val) { set(TaskField.WBS, val); } /** * The Work field shows the total amount of work scheduled to be performed * on a task by all assigned resources. This field shows the total work, * or person-hours, for a task. * * @param val - duration */ public void setWork(Duration val) { set(TaskField.WORK, val); } /** * The Work Variance field contains the difference between a task's baseline * work and the currently scheduled work. * * @param val - duration */ public void setWorkVariance(Duration val) { set(TaskField.WORK_VARIANCE, val); } /** * The % Complete field contains the current status of a task, * expressed as the percentage of the task's duration that has been completed. * You can enter percent complete, or you can have Microsoft Project calculate * it for you based on actual duration. * @return percentage as float */ public Number getPercentageComplete() { return ((Number) getCachedValue(TaskField.PERCENT_COMPLETE)); } /** * The % Work Complete field contains the current status of a task, * expressed as the percentage of the task's work that has been completed. * You can enter percent work complete, or you can have Microsoft Project * calculate it for you based on actual work on the task. * * @return percentage as float */ public Number getPercentageWorkComplete() { return ((Number) getCachedValue(TaskField.PERCENT_WORK_COMPLETE)); } /** * The Actual Cost field shows costs incurred for work already performed * by all resources on a task, along with any other recorded costs associated * with the task. You can enter all the actual costs or have Microsoft Project * calculate them for you. * * @return currency amount as float */ public Number getActualCost() { return ((Number) getCachedValue(TaskField.ACTUAL_COST)); } /** * The Actual Duration field shows the span of actual working time for a * task so far, based on the scheduled duration and current remaining work * or completion percentage. * * @return duration string */ public Duration getActualDuration() { return ((Duration) getCachedValue(TaskField.ACTUAL_DURATION)); } /** * The Actual Finish field shows the date and time that a task actually * finished. Microsoft Project sets the Actual Finish field to the scheduled * finish date if the completion percentage is 100. This field contains "NA" * until you enter actual information or set the completion percentage to 100. * If "NA" is entered as value, arbitrary year zero Date is used. Date(0); * * @return Date */ public Date getActualFinish() { return ((Date) getCachedValue(TaskField.ACTUAL_FINISH)); } /** * The Actual Start field shows the date and time that a task actually began. * When a task is first created, the Actual Start field contains "NA." Once * you enter the first actual work or a completion percentage for a task, * Microsoft Project sets the actual start date to the scheduled start date. * If "NA" is entered as value, arbitrary year zero Date is used. Date(0); * * @return Date */ public Date getActualStart() { return ((Date) getCachedValue(TaskField.ACTUAL_START)); } /** * The Actual Work field shows the amount of work that has already been done * by the resources assigned to a task. * * @return duration string */ public Duration getActualWork() { return ((Duration) getCachedValue(TaskField.ACTUAL_WORK)); } /** * The Baseline Cost field shows the total planned cost for a task. * Baseline cost is also referred to as budget at completion (BAC). * @return currency amount as float */ public Number getBaselineCost() { return ((Number) getCachedValue(TaskField.BASELINE_COST)); } /** * The Baseline Duration field shows the original span of time planned * to complete a task. * * @return - duration string */ public Duration getBaselineDuration() { Object result = getCachedValue(TaskField.BASELINE_DURATION); if (result == null) { result = getCachedValue(TaskField.BASELINE_ESTIMATED_DURATION); } if (!(result instanceof Duration)) { result = null; } return (Duration) result; } /** * Retrieves the text value for the baseline duration. * * @return baseline duration text */ public String getBaselineDurationText() { Object result = getCachedValue(TaskField.BASELINE_DURATION); if (result == null) { result = getCachedValue(TaskField.BASELINE_ESTIMATED_DURATION); } if (!(result instanceof String)) { result = null; } return (String) result; } /** * Sets the baseline duration text value. * * @param value baseline duration text */ public void setBaselineDurationText(String value) { set(TaskField.BASELINE_DURATION, value); } /** * The Baseline Finish field shows the planned completion date for a task * at the time you saved a baseline. Information in this field becomes * available when you set a baseline for a task. * * @return Date */ public Date getBaselineFinish() { Object result = getCachedValue(TaskField.BASELINE_FINISH); if (result == null) { result = getCachedValue(TaskField.BASELINE_ESTIMATED_FINISH); } if (!(result instanceof Date)) { result = null; } return (Date) result; } /** * Retrieves the baseline finish text value. * * @return baseline finish text */ public String getBaselineFinishText() { Object result = getCachedValue(TaskField.BASELINE_FINISH); if (result == null) { result = getCachedValue(TaskField.BASELINE_ESTIMATED_FINISH); } if (!(result instanceof String)) { result = null; } return (String) result; } /** * Sets the baseline finish text value. * * @param value baseline finish text */ public void setBaselineFinishText(String value) { set(TaskField.BASELINE_FINISH, value); } /** * The Baseline Start field shows the planned beginning date for a task at * the time you saved a baseline. Information in this field becomes available * when you set a baseline. * * @return Date */ public Date getBaselineStart() { Object result = getCachedValue(TaskField.BASELINE_START); if (result == null) { result = getCachedValue(TaskField.BASELINE_ESTIMATED_START); } if (!(result instanceof Date)) { result = null; } return (Date) result; } /** * Retrieves the baseline start text value. * * @return baseline start value */ public String getBaselineStartText() { Object result = getCachedValue(TaskField.BASELINE_START); if (result == null) { result = getCachedValue(TaskField.BASELINE_ESTIMATED_START); } if (!(result instanceof String)) { result = null; } return (String) result; } /** * Sets the baseline start text value. * * @param value baseline start text */ public void setBaselineStartText(String value) { set(TaskField.BASELINE_START, value); } /** * The Baseline Work field shows the originally planned amount of work to be * performed by all resources assigned to a task. This field shows the planned * person-hours scheduled for a task. Information in the Baseline Work field * becomes available when you set a baseline for the project. * * @return Duration */ public Duration getBaselineWork() { return ((Duration) getCachedValue(TaskField.BASELINE_WORK)); } /** * The BCWP (budgeted cost of work performed) field contains * the cumulative value of the assignment's timephased percent complete * multiplied by the assignment's timephased baseline cost. * BCWP is calculated up to the status date or today's date. * This information is also known as earned value. * * @return currency amount as float */ public Number getBCWP() { return ((Number) getCachedValue(TaskField.BCWP)); } /** * The BCWS (budgeted cost of work scheduled) field contains the cumulative * timephased baseline costs up to the status date or today's date. * * @return currency amount as float */ public Number getBCWS() { return ((Number) getCachedValue(TaskField.BCWS)); } /** * The Confirmed field indicates whether all resources assigned to a task * have accepted or rejected the task assignment in response to a TeamAssign * message regarding their assignments. * * @return boolean */ public boolean getConfirmed() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.CONFIRMED))); } /** * The Constraint Date field shows the specific date associated with certain * constraint types, such as Must Start On, Must Finish On, * Start No Earlier Than, * Start No Later Than, Finish No Earlier Than, and Finish No Later Than. * * @return Date */ public Date getConstraintDate() { return ((Date) getCachedValue(TaskField.CONSTRAINT_DATE)); } /** * The Constraint Type field provides choices for the type of constraint you * can apply for scheduling a task. * * @return constraint type */ public ConstraintType getConstraintType() { return ((ConstraintType) getCachedValue(TaskField.CONSTRAINT_TYPE)); } /** * The Contact field contains the name of an individual * responsible for a task. * * @return String */ public String getContact() { return ((String) getCachedValue(TaskField.CONTACT)); } /** * The Cost field shows the total scheduled, or projected, cost for a task, * based on costs already incurred for work performed by all resources assigned * to the task, in addition to the costs planned for the remaining work for the * assignment. This can also be referred to as estimate at completion (EAC). * * @return cost amount */ public Number getCost() { return ((Number) getCachedValue(TaskField.COST)); } /** * The Cost Variance field shows the difference between the baseline cost * and total cost for a task. The total cost is the current estimate of costs * based on actual costs and remaining costs. * * @return amount */ public Number getCostVariance() { Number variance = (Number) getCachedValue(TaskField.COST_VARIANCE); if (variance == null) { Number cost = getCost(); Number baselineCost = getBaselineCost(); if (cost != null && baselineCost != null) { variance = NumberHelper.getDouble(cost.doubleValue() - baselineCost.doubleValue()); set(TaskField.COST_VARIANCE, variance); } } return (variance); } /** * The Created field contains the date and time when a task was added * to the project. * * @return Date */ public Date getCreateDate() { return ((Date) getCachedValue(TaskField.CREATED)); } /** * The Critical field indicates whether a task has any room in the schedule * to slip, or if a task is on the critical path. The Critical field contains * Yes if the task is critical and No if the task is not critical. * * @return boolean */ public boolean getCritical() { Boolean critical = (Boolean) getCachedValue(TaskField.CRITICAL); if (critical == null) { Duration totalSlack = getTotalSlack(); critical = Boolean.valueOf(totalSlack.getDuration() <= 0 && NumberHelper.getInt(getPercentageComplete()) != 100 && ((getTaskMode() == TaskMode.AUTO_SCHEDULED) || (getDurationText() == null && getStartText() == null && getFinishText() == null))); set(TaskField.CRITICAL, critical); } return (BooleanHelper.getBoolean(critical)); } /** * The CV (earned value cost variance) field shows the difference between * how much it should have cost to achieve the current level of completion * on the task, and how much it has actually cost to achieve the current * level of completion up to the status date or today's date. * How Calculated CV is the difference between BCWP * (budgeted cost of work performed) and ACWP * (actual cost of work performed). Microsoft Project calculates * the CV as follows: CV = BCWP - ACWP * * @return sum of earned value cost variance */ public Number getCV() { Number variance = (Number) getCachedValue(TaskField.CV); if (variance == null) { variance = Double.valueOf(NumberHelper.getDouble(getBCWP()) - NumberHelper.getDouble(getACWP())); set(TaskField.CV, variance); } return (variance); } /** * Delay , in MPX files as eg '0ed'. Use duration * * @return Duration */ public Duration getLevelingDelay() { return ((Duration) getCachedValue(TaskField.LEVELING_DELAY)); } /** * The Duration field is the total span of active working time for a task. * This is generally the amount of time from the start to the finish of a task. * The default for new tasks is 1 day (1d). * * @return Duration */ public Duration getDuration() { return (Duration) getCachedValue(TaskField.DURATION); } /** * Retrieves the duration text of a manually scheduled task. * * @return duration text */ public String getDurationText() { return (String) getCachedValue(TaskField.DURATION_TEXT); } /** * Set a duration value. * * @param index duration index (1-10) * @param value duration value */ public void setDuration(int index, Duration value) { set(selectField(TaskFieldLists.CUSTOM_DURATION, index), value); } /** * Retrieve a duration value. * * @param index duration index (1-10) * @return duration value */ public Duration getDuration(int index) { return (Duration) getCachedValue(selectField(TaskFieldLists.CUSTOM_DURATION, index)); } /** * The Duration Variance field contains the difference between the * baseline duration of a task and the total duration (current estimate) * of a task. * * @return Duration */ public Duration getDurationVariance() { Duration variance = (Duration) getCachedValue(TaskField.DURATION_VARIANCE); if (variance == null) { Duration duration = getDuration(); Duration baselineDuration = getBaselineDuration(); if (duration != null && baselineDuration != null) { variance = Duration.getInstance(duration.getDuration() - baselineDuration.convertUnits(duration.getUnits(), getParentFile().getProjectProperties()).getDuration(), duration.getUnits()); set(TaskField.DURATION_VARIANCE, variance); } } return (variance); } /** * The Early Finish field contains the earliest date that a task could * possibly finish, based on early finish dates of predecessor and * successor tasks, other constraints, and any leveling delay. * * @return Date */ public Date getEarlyFinish() { return ((Date) getCachedValue(TaskField.EARLY_FINISH)); } /** * The Early Start field contains the earliest date that a task could * possibly begin, based on the early start dates of predecessor and * successor tasks, and other constraints. * * @return Date */ public Date getEarlyStart() { return ((Date) getCachedValue(TaskField.EARLY_START)); } /** * The Finish field shows the date and time that a task is scheduled to * be completed. You can enter the finish date you want, to indicate the * date when the task should be completed. Or, you can have Microsoft * Project calculate the finish date. * * @return Date */ public Date getFinish() { return (Date) getCachedValue(TaskField.FINISH); } /** * Retrieves the finish text of a manually scheduled task. * * @return finish text */ public String getFinishText() { return (String) getCachedValue(TaskField.FINISH_TEXT); } /** * Set a finish value. * * @param index finish index (1-10) * @param value finish value */ public void setFinish(int index, Date value) { set(selectField(TaskFieldLists.CUSTOM_FINISH, index), value); } /** * Retrieve a finish value. * * @param index finish index (1-10) * @return finish value */ public Date getFinish(int index) { return (Date) getCachedValue(selectField(TaskFieldLists.CUSTOM_FINISH, index)); } /** * Calculate the finish variance. * * @return finish variance */ public Duration getFinishVariance() { Duration variance = (Duration) getCachedValue(TaskField.FINISH_VARIANCE); if (variance == null) { TimeUnit format = getParentFile().getProjectProperties().getDefaultDurationUnits(); variance = DateHelper.getVariance(this, getBaselineFinish(), getFinish(), format); set(TaskField.FINISH_VARIANCE, variance); } return (variance); } /** * The Fixed Cost field shows any task expense that is not associated * with a resource cost. * * @return currency amount */ public Number getFixedCost() { return ((Number) getCachedValue(TaskField.FIXED_COST)); } /** * Set a flag value. * * @param index flag index (1-20) * @param value flag value */ public void setFlag(int index, boolean value) { set(selectField(TaskFieldLists.CUSTOM_FLAG, index), value); } /** * Retrieve a flag value. * * @param index flag index (1-20) * @return flag value */ public boolean getFlag(int index) { return BooleanHelper.getBoolean((Boolean) getCachedValue(selectField(TaskFieldLists.CUSTOM_FLAG, index))); } /** * The Free Slack field contains the amount of time that a task can be * delayed without delaying any successor tasks. If the task has no * successors, free slack is the amount of time that a task can be * delayed without delaying the entire project's finish date. * * @return Duration */ public Duration getFreeSlack() { return ((Duration) getCachedValue(TaskField.FREE_SLACK)); } /** * The Hide Bar field indicates whether the Gantt bars and Calendar bars * for a task are hidden. Click Yes in the Hide Bar field to hide the * bar for the task. Click No in the Hide Bar field to show the bar * for the task. * * @return boolean */ public boolean getHideBar() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.HIDE_BAR))); } /** * The ID field contains the identifier number that Microsoft Project * automatically assigns to each task as you add it to the project. * The ID indicates the position of a task with respect to the other tasks. * * @return the task ID */ @Override public Integer getID() { return ((Integer) getCachedValue(TaskField.ID)); } /** * The Late Finish field contains the latest date that a task can finish * without delaying the finish of the project. This date is based on the * task's late start date, as well as the late start and late finish * dates of predecessor and successor * tasks, and other constraints. * * @return Date */ public Date getLateFinish() { return ((Date) getCachedValue(TaskField.LATE_FINISH)); } /** * The Late Start field contains the latest date that a task can start * without delaying the finish of the project. This date is based on * the task's start date, as well as the late start and late finish * dates of predecessor and successor tasks, and other constraints. * * @return Date */ public Date getLateStart() { return ((Date) getCachedValue(TaskField.LATE_START)); } /** * The Linked Fields field indicates whether there are OLE links to the task, * either from elsewhere in the active project, another Microsoft Project file, * or from another program. * * @return boolean */ public boolean getLinkedFields() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.LINKED_FIELDS))); } /** * The Marked field indicates whether a task is marked for further action or * identification of some kind. To mark a task, click Yes in the Marked field. * If you don't want a task marked, click No. * * @return true for marked */ public boolean getMarked() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.MARKED))); } /** * The Milestone field indicates whether a task is a milestone. * * @return boolean */ public boolean getMilestone() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.MILESTONE))); } /** * Retrieves the task name. * * @return task name */ public String getName() { return ((String) getCachedValue(TaskField.NAME)); } /** * The Notes field contains notes that you can enter about a task. * You can use task notes to help maintain a history for a task. * * @return notes */ public String getNotes() { String notes = (String) getCachedValue(TaskField.NOTES); return (notes == null ? "" : notes); } /** * Set a number value. * * @param index number index (1-20) * @param value number value */ public void setNumber(int index, Number value) { set(selectField(TaskFieldLists.CUSTOM_NUMBER, index), value); } /** * Retrieve a number value. * * @param index number index (1-20) * @return number value */ public Number getNumber(int index) { return (Number) getCachedValue(selectField(TaskFieldLists.CUSTOM_NUMBER, index)); } /** * The Objects field contains the number of objects attached to a task. * Microsoft Project counts the number of objects linked or embedded to a task. * However, objects in the Notes box in the Resource Form are not included * in this count. * * @return int */ public Integer getObjects() { return ((Integer) getCachedValue(TaskField.OBJECTS)); } /** * The Outline Level field contains the number that indicates the level * of the task in the project outline hierarchy. * * @return int */ public Integer getOutlineLevel() { return ((Integer) getCachedValue(TaskField.OUTLINE_LEVEL)); } /** * The Outline Number field contains the number of the task in the structure * of an outline. This number indicates the task's position within the * hierarchical structure of the project outline. The outline number is * similar to a WBS (work breakdown structure) number, * except that the outline number is automatically entered by * Microsoft Project. * * @return String */ public String getOutlineNumber() { return ((String) getCachedValue(TaskField.OUTLINE_NUMBER)); } /** * Retrieves the list of predecessors for this task. * * @return list of predecessor Relation instances */ @SuppressWarnings("unchecked") public List<Relation> getPredecessors() { return ((List<Relation>) getCachedValue(TaskField.PREDECESSORS)); } /** * Retrieves the list of succesors for this task. * * @return list of successor Relation instances */ @SuppressWarnings("unchecked") public List<Relation> getSuccessors() { return ((List<Relation>) getCachedValue(TaskField.SUCCESSORS)); } /** * The Priority field provides choices for the level of importance * assigned to a task, which in turn indicates how readily a task can be * delayed or split during resource leveling. * The default priority is Medium. Those tasks with a priority * of Do Not Level are never delayed or split when Microsoft Project levels * tasks that have overallocated resources assigned. * * @return priority class instance */ public Priority getPriority() { return ((Priority) getCachedValue(TaskField.PRIORITY)); } /** * The Project field shows the name of the project from which a task * originated. * This can be the name of the active project file. If there are other * projects inserted * into the active project file, the name of the inserted project appears * in this field * for the task. * * @return name of originating project */ public String getProject() { return ((String) getCachedValue(TaskField.PROJECT)); } /** * The Remaining Cost field shows the remaining scheduled expense of a * task that will be incurred in completing the remaining scheduled work * by all resources assigned to the task. * * @return remaining cost */ public Number getRemainingCost() { return ((Number) getCachedValue(TaskField.REMAINING_COST)); } /** * The Remaining Duration field shows the amount of time required * to complete the unfinished portion of a task. * * @return Duration */ public Duration getRemainingDuration() { return ((Duration) getCachedValue(TaskField.REMAINING_DURATION)); } /** * The Remaining Work field shows the amount of time, or person-hours, * still required by all assigned resources to complete a task. * * @return the amount of time still required to complete a task */ public Duration getRemainingWork() { return ((Duration) getCachedValue(TaskField.REMAINING_WORK)); } /** * The Resource Group field contains the list of resource groups to which * the resources assigned to a task belong. * * @return single string list of groups */ public String getResourceGroup() { return ((String) getCachedValue(TaskField.RESOURCE_GROUP)); } /** * The Resource Initials field lists the abbreviations for the names of * resources assigned to a task. These initials can serve as substitutes * for the names. * * Note that MS Project 98 does not export values for this field when * writing an MPX file, and the field is not currently populated by MPXJ * when reading an MPP file. * * @return String containing a comma separated list of initials */ public String getResourceInitials() { return ((String) getCachedValue(TaskField.RESOURCE_INITIALS)); } /** * The Resource Names field lists the names of all resources assigned * to a task. * * Note that MS Project 98 does not export values for this field when * writing an MPX file, and the field is not currently populated by MPXJ * when reading an MPP file. * * @return String containing a comma separated list of names */ public String getResourceNames() { return ((String) getCachedValue(TaskField.RESOURCE_NAMES)); } /** * The Resume field shows the date that the remaining portion of a task * is scheduled to resume after you enter a new value for the % Complete * field. The Resume field is also recalculated when the remaining portion * of a task is moved to a new date. * * @return Date */ public Date getResume() { return ((Date) getCachedValue(TaskField.RESUME)); } /** * For subtasks, the Rollup field indicates whether information on the * subtask Gantt bars * will be rolled up to the summary task bar. For summary tasks, the * Rollup field indicates * whether the summary task bar displays rolled up bars. You must * have the Rollup field for * summary tasks set to Yes for any subtasks to roll up to them. * * @return boolean */ public boolean getRollup() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.ROLLUP))); } /** * The Start field shows the date and time that a task is scheduled to begin. * You can enter the start date you want, to indicate the date when the task * should begin. Or, you can have Microsoft Project calculate the start date. * * @return Date */ public Date getStart() { return (Date) getCachedValue(TaskField.START); } /** * Retrieve the start text for a manually scheduled task. * * @return start text */ public String getStartText() { return (String) getCachedValue(TaskField.START_TEXT); } /** * Set a start value. * * @param index start index (1-10) * @param value start value */ public void setStart(int index, Date value) { set(selectField(TaskFieldLists.CUSTOM_START, index), value); } /** * Retrieve a start value. * * @param index start index (1-10) * @return start value */ public Date getStart(int index) { return (Date) getCachedValue(selectField(TaskFieldLists.CUSTOM_START, index)); } /** * Calculate the start variance. * * @return start variance */ public Duration getStartVariance() { Duration variance = (Duration) getCachedValue(TaskField.START_VARIANCE); if (variance == null) { TimeUnit format = getParentFile().getProjectProperties().getDefaultDurationUnits(); variance = DateHelper.getVariance(this, getBaselineStart(), getStart(), format); set(TaskField.START_VARIANCE, variance); } return (variance); } /** * The Stop field shows the date that represents the end of the actual * portion of a task. Typically, Microsoft Project calculates the stop date. * However, you can edit this date as well. * * @return Date */ public Date getStop() { return ((Date) getCachedValue(TaskField.STOP)); } /** * Contains the file name and path of the sub project represented by * the current task. * * @return sub project file path */ public String getSubprojectName() { return ((String) getCachedValue(TaskField.SUBPROJECT_FILE)); } /** * The Summary field indicates whether a task is a summary task. * * @return boolean, true-is summary task */ public boolean getSummary() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.SUMMARY))); } /** * The SV (earned value schedule variance) field shows the difference in * cost terms between the current progress and the baseline plan of the * task up to the status date or today's date. You can use SV to * check costs to determine whether tasks are on schedule. * * @return -earned value schedule variance */ public Number getSV() { Number variance = (Number) getCachedValue(TaskField.SV); if (variance == null) { Number bcwp = getBCWP(); Number bcws = getBCWS(); if (bcwp != null && bcws != null) { variance = NumberHelper.getDouble(bcwp.doubleValue() - bcws.doubleValue()); set(TaskField.SV, variance); } } return (variance); } /** * Set a text value. * * @param index text index (1-30) * @param value text value */ public void setText(int index, String value) { set(selectField(TaskFieldLists.CUSTOM_TEXT, index), value); } /** * Retrieve a text value. * * @param index text index (1-30) * @return text value */ public String getText(int index) { return (String) getCachedValue(selectField(TaskFieldLists.CUSTOM_TEXT, index)); } /** * Set an outline code value. * * @param index outline code index (1-10) * @param value outline code value */ public void setOutlineCode(int index, String value) { set(selectField(TaskFieldLists.CUSTOM_OUTLINE_CODE, index), value); } /** * Retrieve an outline code value. * * @param index outline code index (1-10) * @return outline code value */ public String getOutlineCode(int index) { return (String) getCachedValue(selectField(TaskFieldLists.CUSTOM_OUTLINE_CODE, index)); } /** * The Total Slack field contains the amount of time a task can be * delayed without delaying the project's finish date. * * @return string representing duration */ public Duration getTotalSlack() { Duration totalSlack = (Duration) getCachedValue(TaskField.TOTAL_SLACK); if (totalSlack == null) { Duration duration = getDuration(); if (duration == null) { duration = Duration.getInstance(0, TimeUnit.DAYS); } TimeUnit units = duration.getUnits(); Duration startSlack = getStartSlack(); if (startSlack == null) { startSlack = Duration.getInstance(0, units); } else { if (startSlack.getUnits() != units) { startSlack = startSlack.convertUnits(units, getParentFile().getProjectProperties()); } } Duration finishSlack = getFinishSlack(); if (finishSlack == null) { finishSlack = Duration.getInstance(0, units); } else { if (finishSlack.getUnits() != units) { finishSlack = finishSlack.convertUnits(units, getParentFile().getProjectProperties()); } } double startSlackDuration = startSlack.getDuration(); double finishSlackDuration = finishSlack.getDuration(); if (startSlackDuration == 0 || finishSlackDuration == 0) { if (startSlackDuration != 0) { totalSlack = startSlack; } else { totalSlack = finishSlack; } } else { if (startSlackDuration < finishSlackDuration) { totalSlack = startSlack; } else { totalSlack = finishSlack; } } set(TaskField.TOTAL_SLACK, totalSlack); } return (totalSlack); } /** * The Unique ID field contains the number that Microsoft Project * automatically designates whenever a new task is created. This number * indicates the sequence in which the task was * created, regardless of placement in the schedule. * * @return String */ @Override public Integer getUniqueID() { return ((Integer) getCachedValue(TaskField.UNIQUE_ID)); } /** * The Update Needed field indicates whether a TeamUpdate message * should be sent to the assigned resources because of changes to the * start date, finish date, or resource reassignments of the task. * * @return true if needed. */ public boolean getUpdateNeeded() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.UPDATE_NEEDED))); } /** * The work breakdown structure code. The WBS field contains an * alphanumeric code you can use to represent the task's position within * the hierarchical structure of the project. This field is similar to * the outline number, except that you can edit it. * * @return string */ public String getWBS() { return ((String) getCachedValue(TaskField.WBS)); } /** * The Work field shows the total amount of work scheduled to be performed * on a task by all assigned resources. This field shows the total work, * or person-hours, for a task. * * @return Duration representing duration . */ public Duration getWork() { return ((Duration) getCachedValue(TaskField.WORK)); } /** * The Work Variance field contains the difference between a task's * baseline work and the currently scheduled work. * * @return Duration representing duration. */ public Duration getWorkVariance() { Duration variance = (Duration) getCachedValue(TaskField.WORK_VARIANCE); if (variance == null) { Duration work = getWork(); Duration baselineWork = getBaselineWork(); if (work != null && baselineWork != null) { variance = Duration.getInstance(work.getDuration() - baselineWork.convertUnits(work.getUnits(), getParentFile().getProjectProperties()).getDuration(), work.getUnits()); set(TaskField.WORK_VARIANCE, variance); } } return (variance); } /** * This method retrieves a reference to the parent of this task, as * defined by the outline level. If this task is at the top level, * this method will return null. * * @return parent task */ public Task getParentTask() { return (m_parent); } /** * This method retrieves a list of child tasks relative to the * current task, as defined by the outine level. If there * are no child tasks, this method will return an empty list. * * @return child tasks */ @Override public List<Task> getChildTasks() { return (m_children); } /** * This method implements the only method in the Comparable interface. * This allows Tasks to be compared and sorted based on their ID value. * Note that if the MPX/MPP file has been generated by MSP, the ID value * will always be in the correct sequence. The Unique ID value will not * necessarily be in the correct sequence as task insertions and deletions * will change the order. * * @param o object to compare this instance with * @return result of comparison */ @Override public int compareTo(Task o) { int id1 = NumberHelper.getInt(getID()); int id2 = NumberHelper.getInt(o.getID()); return ((id1 < id2) ? (-1) : ((id1 == id2) ? 0 : 1)); } /** * This method retrieves a flag indicating whether the duration of the * task has only been estimated. * * @return boolean */ public boolean getEstimated() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.ESTIMATED))); } /** * This method retrieves a flag indicating whether the duration of the * task has only been estimated. * @param estimated Boolean flag */ public void setEstimated(boolean estimated) { set(TaskField.ESTIMATED, estimated); } /** * This method retrieves the deadline for this task. * * @return Task deadline */ public Date getDeadline() { return ((Date) getCachedValue(TaskField.DEADLINE)); } /** * This method sets the deadline for this task. * * @param deadline deadline date */ public void setDeadline(Date deadline) { set(TaskField.DEADLINE, deadline); } /** * This method retrieves the task type. * * @return int representing the task type */ public TaskType getType() { return ((TaskType) getCachedValue(TaskField.TYPE)); } /** * This method sets the task type. * * @param type task type */ public void setType(TaskType type) { set(TaskField.TYPE, type); } /** * Retrieves the flag indicating if this is a null task. * * @return boolean flag */ public boolean getNull() { return (m_null); } /** * Sets the flag indicating if this is a null task. * * @param isNull boolean flag */ public void setNull(boolean isNull) { m_null = isNull; } /** * Retrieve the WBS level. * * @return WBS level */ public String getWBSLevel() { return (m_wbsLevel); } /** * Set the WBS level. * * @param wbsLevel WBS level */ public void setWBSLevel(String wbsLevel) { m_wbsLevel = wbsLevel; } /** * Retrieve the resume valid flag. * * @return resume valie flag */ public boolean getResumeValid() { return (m_resumeValid); } /** * Set the resume valid flag. * * @param resumeValid resume valid flag */ public void setResumeValid(boolean resumeValid) { m_resumeValid = resumeValid; } /** * Retrieve the recurring flag. * * @return recurring flag */ public boolean getRecurring() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.RECURRING))); } /** * Set the recurring flag. * * @param recurring recurring flag */ public void setRecurring(boolean recurring) { set(TaskField.RECURRING, recurring); } /** * Retrieve the over allocated flag. * * @return over allocated flag */ public boolean getOverAllocated() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.OVERALLOCATED))); } /** * Set the over allocated flag. * * @param overAllocated over allocated flag */ public void setOverAllocated(boolean overAllocated) { set(TaskField.OVERALLOCATED, overAllocated); } /** * Where a task in an MPP file represents a task from a subproject, * this value will be non-zero. The value itself is the unique ID * value shown in the parent project. To retrieve the value of the * task unique ID in the child project, remove the top two bytes: * * taskID = (subprojectUniqueID & 0xFFFF) * * @return sub project unique task ID */ public Integer getSubprojectTaskUniqueID() { return (Integer) getCachedValue(TaskField.SUBPROJECT_UNIQUE_TASK_ID); } /** * Sets the sub project unique task ID. * * @param subprojectUniqueTaskID subproject unique task ID */ public void setSubprojectTaskUniqueID(Integer subprojectUniqueTaskID) { set(TaskField.SUBPROJECT_UNIQUE_TASK_ID, subprojectUniqueTaskID); } /** * Where a task in an MPP file represents a task from a subproject, * this value will be non-zero. The value itself is the ID * value shown in the parent project. * * @return sub project task ID */ public Integer getSubprojectTaskID() { return (Integer) getCachedValue(TaskField.SUBPROJECT_TASK_ID); } /** * Sets the sub project task ID. * * @param subprojectTaskID subproject task ID */ public void setSubprojectTaskID(Integer subprojectTaskID) { set(TaskField.SUBPROJECT_TASK_ID, subprojectTaskID); } /** * Sets the offset added to unique task IDs from sub projects * to generate the task ID shown in the master project. * * @param offset unique ID offset */ public void setSubprojectTasksUniqueIDOffset(Integer offset) { set(TaskField.SUBPROJECT_TASKS_UNIQUEID_OFFSET, offset); } /** * Retrieves the offset added to unique task IDs from sub projects * to generate the task ID shown in the master project. * * @return unique ID offset */ public Integer getSubprojectTasksUniqueIDOffset() { return (Integer) getCachedValue(TaskField.SUBPROJECT_TASKS_UNIQUEID_OFFSET); } /** * Retrieve the subproject read only flag. * * @return subproject read only flag */ public boolean getSubprojectReadOnly() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.SUBPROJECT_READ_ONLY))); } /** * Set the subproject read only flag. * * @param subprojectReadOnly subproject read only flag */ public void setSubprojectReadOnly(boolean subprojectReadOnly) { set(TaskField.SUBPROJECT_READ_ONLY, subprojectReadOnly); } /** * Retrieves the external task flag. * * @return external task flag */ public boolean getExternalTask() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.EXTERNAL_TASK))); } /** * Sets the external task flag. * * @param externalTask external task flag */ public void setExternalTask(boolean externalTask) { set(TaskField.EXTERNAL_TASK, externalTask); } /** * Retrieves the external task project file name. * * @return external task project file name */ public String getExternalTaskProject() { return (m_externalTaskProject); } /** * Sets the external task project file name. * * @param externalTaskProject external task project file name */ public void setExternalTaskProject(String externalTaskProject) { m_externalTaskProject = externalTaskProject; } /** * Retrieve the ACWP value. * * @return ACWP value */ public Number getACWP() { return ((Number) getCachedValue(TaskField.ACWP)); } /** * Set the ACWP value. * * @param acwp ACWP value */ public void setACWP(Number acwp) { set(TaskField.ACWP, acwp); } /** * Retrieve the leveling delay format. * * @return leveling delay format */ public TimeUnit getLevelingDelayFormat() { return (m_levelingDelayFormat); } /** * Set the leveling delay format. * * @param levelingDelayFormat leveling delay format */ public void setLevelingDelayFormat(TimeUnit levelingDelayFormat) { m_levelingDelayFormat = levelingDelayFormat; } /** * Retrieves the ignore resource celandar flag. * * @return ignore resource celandar flag */ public boolean getIgnoreResourceCalendar() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.IGNORE_RESOURCE_CALENDAR))); } /** * Sets the ignore resource celandar flag. * * @param ignoreResourceCalendar ignore resource celandar flag */ public void setIgnoreResourceCalendar(boolean ignoreResourceCalendar) { set(TaskField.IGNORE_RESOURCE_CALENDAR, ignoreResourceCalendar); } /** * Retrieves the physical percent complete value. * * @return physical percent complete value */ public Number getPhysicalPercentComplete() { return (Number) getCachedValue(TaskField.PHYSICAL_PERCENT_COMPLETE); } /** * Sets the physical percent complete value. * * @param physicalPercentComplete physical percent complete value */ public void setPhysicalPercentComplete(Number physicalPercentComplete) { set(TaskField.PHYSICAL_PERCENT_COMPLETE, physicalPercentComplete); } /** * Retrieves the earned value method. * * @return earned value method */ public EarnedValueMethod getEarnedValueMethod() { return (m_earnedValueMethod); } /** * Sets the earned value method. * * @param earnedValueMethod earned value method */ public void setEarnedValueMethod(EarnedValueMethod earnedValueMethod) { m_earnedValueMethod = earnedValueMethod; } /** * Retrieves the actual work protected value. * * @return actual work protected value */ public Duration getActualWorkProtected() { return (m_actualWorkProtected); } /** * Sets the actual work protected value. * * @param actualWorkProtected actual work protected value */ public void setActualWorkProtected(Duration actualWorkProtected) { m_actualWorkProtected = actualWorkProtected; } /** * Retrieves the actual overtime work protected value. * * @return actual overtime work protected value */ public Duration getActualOvertimeWorkProtected() { return (m_actualOvertimeWorkProtected); } /** * Sets the actual overtime work protected value. * * @param actualOvertimeWorkProtected actual overtime work protected value */ public void setActualOvertimeWorkProtected(Duration actualOvertimeWorkProtected) { m_actualOvertimeWorkProtected = actualOvertimeWorkProtected; } /** * Retrieve the amount of regular work. * * @return amount of regular work */ public Duration getRegularWork() { return ((Duration) getCachedValue(TaskField.REGULAR_WORK)); } /** * Set the amount of regular work. * * @param regularWork amount of regular work */ public void setRegularWork(Duration regularWork) { set(TaskField.REGULAR_WORK, regularWork); } /** * Sets the effort driven flag. * * @param flag value */ public void setEffortDriven(boolean flag) { set(TaskField.EFFORT_DRIVEN, flag); } /** * Retrieves the effort driven flag. * * @return Flag value */ public boolean getEffortDriven() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.EFFORT_DRIVEN))); } /** * Set a date value. * * @param index date index (1-10) * @param value date value */ public void setDate(int index, Date value) { set(selectField(TaskFieldLists.CUSTOM_DATE, index), value); } /** * Retrieve a date value. * * @param index date index (1-10) * @return date value */ public Date getDate(int index) { return (Date) getCachedValue(selectField(TaskFieldLists.CUSTOM_DATE, index)); } /** * Retrieves the overtime cost. * * @return Cost value */ public Number getOvertimeCost() { return ((Number) getCachedValue(TaskField.OVERTIME_COST)); } /** * Sets the overtime cost value. * * @param number Cost value */ public void setOvertimeCost(Number number) { set(TaskField.OVERTIME_COST, number); } /** * Retrieves the actual overtime cost for this task. * * @return actual overtime cost */ public Number getActualOvertimeCost() { return ((Number) getCachedValue(TaskField.ACTUAL_OVERTIME_COST)); } /** * Sets the actual overtime cost for this task. * * @param cost actual overtime cost */ public void setActualOvertimeCost(Number cost) { set(TaskField.ACTUAL_OVERTIME_COST, cost); } /** * Retrieves the actual overtime work value. * * @return actual overtime work value */ public Duration getActualOvertimeWork() { return ((Duration) getCachedValue(TaskField.ACTUAL_OVERTIME_WORK)); } /** * Sets the actual overtime work value. * * @param work actual overtime work value */ public void setActualOvertimeWork(Duration work) { set(TaskField.ACTUAL_OVERTIME_WORK, work); } /** * Retrieves the fixed cost accrual flag value. * * @return fixed cost accrual flag */ public AccrueType getFixedCostAccrual() { return ((AccrueType) getCachedValue(TaskField.FIXED_COST_ACCRUAL)); } /** * Sets the fixed cost accrual flag value. * * @param type fixed cost accrual type */ public void setFixedCostAccrual(AccrueType type) { set(TaskField.FIXED_COST_ACCRUAL, type); } /** * Retrieves the task hyperlink attribute. * * @return hyperlink attribute */ public String getHyperlink() { return ((String) getCachedValue(TaskField.HYPERLINK)); } /** * Retrieves the task hyperlink address attribute. * * @return hyperlink address attribute */ public String getHyperlinkAddress() { return ((String) getCachedValue(TaskField.HYPERLINK_ADDRESS)); } /** * Retrieves the task hyperlink sub-address attribute. * * @return hyperlink sub address attribute */ public String getHyperlinkSubAddress() { return ((String) getCachedValue(TaskField.HYPERLINK_SUBADDRESS)); } /** * Sets the task hyperlink attribute. * * @param text hyperlink attribute */ public void setHyperlink(String text) { set(TaskField.HYPERLINK, text); } /** * Sets the task hyperlink address attribute. * * @param text hyperlink address attribute */ public void setHyperlinkAddress(String text) { set(TaskField.HYPERLINK_ADDRESS, text); } /** * Sets the task hyperlink sub address attribute. * * @param text hyperlink sub address attribute */ public void setHyperlinkSubAddress(String text) { set(TaskField.HYPERLINK_SUBADDRESS, text); } /** * Retrieves the level assignments flag. * * @return level assignments flag */ public boolean getLevelAssignments() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.LEVEL_ASSIGNMENTS))); } /** * Sets the level assignments flag. * * @param flag level assignments flag */ public void setLevelAssignments(boolean flag) { set(TaskField.LEVEL_ASSIGNMENTS, flag); } /** * Retrieves the leveling can split flag. * * @return leveling can split flag */ public boolean getLevelingCanSplit() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.LEVELING_CAN_SPLIT))); } /** * Sets the leveling can split flag. * * @param flag leveling can split flag */ public void setLevelingCanSplit(boolean flag) { set(TaskField.LEVELING_CAN_SPLIT, flag); } /** * Retrieves the overtime work attribute. * * @return overtime work value */ public Duration getOvertimeWork() { return ((Duration) getCachedValue(TaskField.OVERTIME_WORK)); } /** * Sets the overtime work attribute. * * @param work overtime work value */ public void setOvertimeWork(Duration work) { set(TaskField.OVERTIME_WORK, work); } /** * Retrieves the preleveled start attribute. * * @return preleveled start */ public Date getPreleveledStart() { return ((Date) getCachedValue(TaskField.PRELEVELED_START)); } /** * Retrieves the preleveled finish attribute. * * @return preleveled finish */ public Date getPreleveledFinish() { return ((Date) getCachedValue(TaskField.PRELEVELED_FINISH)); } /** * Sets the preleveled start attribute. * * @param date preleveled start attribute */ public void setPreleveledStart(Date date) { set(TaskField.PRELEVELED_START, date); } /** * Sets the preleveled finish attribute. * * @param date preleveled finish attribute */ public void setPreleveledFinish(Date date) { set(TaskField.PRELEVELED_FINISH, date); } /** * Retrieves the remaining overtime work attribute. * * @return remaining overtime work */ public Duration getRemainingOvertimeWork() { return ((Duration) getCachedValue(TaskField.REMAINING_OVERTIME_WORK)); } /** * Sets the remaining overtime work attribute. * * @param work remaining overtime work */ public void setRemainingOvertimeWork(Duration work) { set(TaskField.REMAINING_OVERTIME_WORK, work); } /** * Retrieves the remaining overtime cost. * * @return remaining overtime cost value */ public Number getRemainingOvertimeCost() { return ((Number) getCachedValue(TaskField.REMAINING_OVERTIME_COST)); } /** * Sets the remaining overtime cost value. * * @param cost overtime cost value */ public void setRemainingOvertimeCost(Number cost) { set(TaskField.REMAINING_OVERTIME_COST, cost); } /** * Retrieves the base calendar instance associated with this task. * Note that this attribute appears in MPP9 and MSPDI files. * * @return ProjectCalendar instance */ public ProjectCalendar getCalendar() { return ((ProjectCalendar) getCachedValue(TaskField.CALENDAR)); } /** * Sets the name of the base calendar associated with this task. * Note that this attribute appears in MPP9 and MSPDI files. * * @param calendar calendar instance */ public void setCalendar(ProjectCalendar calendar) { set(TaskField.CALENDAR, calendar); } /** * Retrieve a flag indicating if the task is shown as expanded * in MS Project. If this flag is set to true, any sub tasks * for this current task will be visible. If this is false, * any sub tasks will be hidden. * * @return boolean flag */ public boolean getExpanded() { return (m_expanded); } /** * Set a flag indicating if the task is shown as expanded * in MS Project. If this flag is set to true, any sub tasks * for this current task will be visible. If this is false, * any sub tasks will be hidden. * * @param expanded boolean flag */ public void setExpanded(boolean expanded) { m_expanded = expanded; } /** * Set the start slack. * * @param duration start slack */ public void setStartSlack(Duration duration) { set(TaskField.START_SLACK, duration); } /** * Set the finish slack. * * @param duration finish slack */ public void setFinishSlack(Duration duration) { set(TaskField.FINISH_SLACK, duration); } /** * Retrieve the start slack. * * @return start slack */ public Duration getStartSlack() { Duration startSlack = (Duration) getCachedValue(TaskField.START_SLACK); if (startSlack == null) { Duration duration = getDuration(); if (duration != null) { startSlack = DateHelper.getVariance(this, getLateStart(), getEarlyStart(), duration.getUnits()); set(TaskField.START_SLACK, startSlack); } } return (startSlack); } /** * Retrieve the finish slack. * * @return finish slack */ public Duration getFinishSlack() { Duration finishSlack = (Duration) getCachedValue(TaskField.FINISH_SLACK); if (finishSlack == null) { Duration duration = getDuration(); if (duration != null) { finishSlack = DateHelper.getVariance(this, getLateFinish(), getEarlyFinish(), duration.getUnits()); set(TaskField.FINISH_SLACK, finishSlack); } } return (finishSlack); } /** * Retrieve the value of a field using its alias. * * @param alias field alias * @return field value */ public Object getFieldByAlias(String alias) { return getCachedValue(getParentFile().getCustomFields().getFieldByAlias(FieldTypeClass.TASK, alias)); } /** * Set the value of a field using its alias. * * @param alias field alias * @param value field value */ public void setFieldByAlias(String alias, Object value) { set(getParentFile().getCustomFields().getFieldByAlias(FieldTypeClass.TASK, alias), value); } /** * This method retrieves a list of task splits. Each split is represented * by a DateRange instance. The list will always follow the pattern * task range, split range, task range and so on. * * Note that this method will return null if the task is not split. * * @return list of split times */ public List<DateRange> getSplits() { return (m_splits); } /** * Internal method used to set the list of splits. * * @param splits list of split times */ public void setSplits(List<DateRange> splits) { m_splits = splits; } /** * Task splits contain the time up to which the splits are completed. * * @return Duration of completed time for the splits. */ public Date getSplitCompleteDuration() { return m_splitsComplete; } /** * Set the time up to which the splits are completed. * * @param splitsComplete Duration of completed time for the splits. */ public void setSplitCompleteDuration(Date splitsComplete) { m_splitsComplete = splitsComplete; } /** * Removes this task from the project. */ public void remove() { getParentFile().removeTask(this); } /** * Retrieve the sub project represented by this task. * * @return sub project */ public SubProject getSubProject() { return (m_subProject); } /** * Set the sub project represented by this task. * * @param subProject sub project */ public void setSubProject(SubProject subProject) { m_subProject = subProject; } /** * Retrieve an enterprise field value. * * @param index field index * @return field value */ public Number getEnterpriseCost(int index) { return ((Number) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_COST, index))); } /** * Set an enterprise field value. * * @param index field index * @param value field value */ public void setEnterpriseCost(int index, Number value) { set(selectField(TaskFieldLists.ENTERPRISE_COST, index), value); } /** * Retrieve an enterprise field value. * * @param index field index * @return field value */ public Date getEnterpriseDate(int index) { return ((Date) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_DATE, index))); } /** * Set an enterprise field value. * * @param index field index * @param value field value */ public void setEnterpriseDate(int index, Date value) { set(selectField(TaskFieldLists.ENTERPRISE_DATE, index), value); } /** * Retrieve an enterprise field value. * * @param index field index * @return field value */ public Duration getEnterpriseDuration(int index) { return ((Duration) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_DURATION, index))); } /** * Set an enterprise field value. * * @param index field index * @param value field value */ public void setEnterpriseDuration(int index, Duration value) { set(selectField(TaskFieldLists.ENTERPRISE_DURATION, index), value); } /** * Retrieve an enterprise field value. * * @param index field index * @return field value */ public boolean getEnterpriseFlag(int index) { return (BooleanHelper.getBoolean((Boolean) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_FLAG, index)))); } /** * Set an enterprise field value. * * @param index field index * @param value field value */ public void setEnterpriseFlag(int index, boolean value) { set(selectField(TaskFieldLists.ENTERPRISE_FLAG, index), value); } /** * Retrieve an enterprise field value. * * @param index field index * @return field value */ public Number getEnterpriseNumber(int index) { return ((Number) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_NUMBER, index))); } /** * Set an enterprise field value. * * @param index field index * @param value field value */ public void setEnterpriseNumber(int index, Number value) { set(selectField(TaskFieldLists.ENTERPRISE_NUMBER, index), value); } /** * Retrieve an enterprise field value. * * @param index field index * @return field value */ public String getEnterpriseText(int index) { return ((String) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_TEXT, index))); } /** * Set an enterprise field value. * * @param index field index * @param value field value */ public void setEnterpriseText(int index, String value) { set(selectField(TaskFieldLists.ENTERPRISE_TEXT, index), value); } /** * Retrieve an enterprise custom field value. * * @param index field index * @return field value */ public String getEnterpriseCustomField(int index) { return ((String) getCachedValue(selectField(TaskFieldLists.ENTERPRISE_CUSTOM_FIELD, index))); } /** * Set an enterprise custom field value. * * @param index field index * @param value field value */ public void setEnterpriseCustomField(int index, String value) { set(selectField(TaskFieldLists.ENTERPRISE_CUSTOM_FIELD, index), value); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineCost(int baselineNumber, Number value) { set(selectField(TaskFieldLists.BASELINE_COSTS, baselineNumber), value); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineDuration(int baselineNumber, Duration value) { set(selectField(TaskFieldLists.BASELINE_DURATIONS, baselineNumber), value); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineFinish(int baselineNumber, Date value) { set(selectField(TaskFieldLists.BASELINE_FINISHES, baselineNumber), value); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineStart(int baselineNumber, Date value) { set(selectField(TaskFieldLists.BASELINE_STARTS, baselineNumber), value); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineWork(int baselineNumber, Duration value) { set(selectField(TaskFieldLists.BASELINE_WORKS, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Number getBaselineCost(int baselineNumber) { return ((Number) getCachedValue(selectField(TaskFieldLists.BASELINE_COSTS, baselineNumber))); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Duration getBaselineDuration(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_DURATIONS, baselineNumber)); if (result == null) { result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_DURATIONS, baselineNumber)); } if (!(result instanceof Duration)) { result = null; } return (Duration) result; } /** * Retrieves the baseline duration text value. * * @param baselineNumber baseline number * @return baseline duration text value */ public String getBaselineDurationText(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_DURATIONS, baselineNumber)); if (result == null) { result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_DURATIONS, baselineNumber)); } if (!(result instanceof String)) { result = null; } return (String) result; } /** * Sets the baseline duration text value. * * @param baselineNumber baseline number * @param value baseline duration text value */ public void setBaselineDurationText(int baselineNumber, String value) { set(selectField(TaskFieldLists.BASELINE_DURATIONS, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Date getBaselineFinish(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_FINISHES, baselineNumber)); if (result == null) { result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_FINISHES, baselineNumber)); } if (!(result instanceof Date)) { result = null; } return (Date) result; } /** * Retrieves the baseline finish text value. * * @param baselineNumber baseline number * @return baseline finish text value */ public String getBaselineFinishText(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_FINISHES, baselineNumber)); if (result == null) { result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_FINISHES, baselineNumber)); } if (!(result instanceof String)) { result = null; } return (String) result; } /** * Sets the baseline finish text value. * * @param baselineNumber baseline number * @param value baseline finish text value */ public void setBaselineFinishText(int baselineNumber, String value) { set(selectField(TaskFieldLists.BASELINE_FINISHES, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Date getBaselineStart(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_STARTS, baselineNumber)); if (result == null) { result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_STARTS, baselineNumber)); } if (!(result instanceof Date)) { result = null; } return (Date) result; } /** * Retrieves the baseline start text value. * * @param baselineNumber baseline number * @return baseline start text value */ public String getBaselineStartText(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_STARTS, baselineNumber)); if (result == null) { result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_STARTS, baselineNumber)); } if (!(result instanceof String)) { result = null; } return (String) result; } /** * Sets the baseline start text value. * * @param baselineNumber baseline number * @param value baseline start text value */ public void setBaselineStartText(int baselineNumber, String value) { set(selectField(TaskFieldLists.BASELINE_STARTS, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Duration getBaselineWork(int baselineNumber) { return ((Duration) getCachedValue(selectField(TaskFieldLists.BASELINE_WORKS, baselineNumber))); } /** * Retrieve the "complete through" date. * * @return complete through date */ public Date getCompleteThrough() { Date value = (Date) getCachedValue(TaskField.COMPLETE_THROUGH); if (value == null) { int percentComplete = NumberHelper.getInt(getPercentageComplete()); switch (percentComplete) { case 0: { break; } case 100: { value = getActualFinish(); break; } default: { Date actualStart = getActualStart(); Duration duration = getDuration(); if (actualStart != null && duration != null) { double durationValue = (duration.getDuration() * percentComplete) / 100d; duration = Duration.getInstance(durationValue, duration.getUnits()); ProjectCalendar calendar = getCalendar(); if (calendar == null) { calendar = getParentFile().getDefaultCalendar(); } value = calendar.getDate(actualStart, duration, true); } break; } } set(TaskField.COMPLETE_THROUGH, value); } return value; } /** * Retrieve the summary progress date. * * @return summary progress date */ public Date getSummaryProgress() { Date value = (Date) getCachedValue(TaskField.SUMMARY_PROGRESS); return value; } /** * Set the summary progress date. * * @param value summary progress date */ public void setSummaryProgress(Date value) { set(TaskField.SUMMARY_PROGRESS, value); } /** * Retrieve the task GUID. * * @return task GUID */ public UUID getGUID() { return (UUID) getCachedValue(TaskField.GUID); } /** * Set the task GUID. * * @param value task GUID */ public void setGUID(UUID value) { set(TaskField.GUID, value); } /** * Retrieves the task mode. * * @return task mode */ public TaskMode getTaskMode() { return BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.TASK_MODE)) ? TaskMode.MANUALLY_SCHEDULED : TaskMode.AUTO_SCHEDULED; } /** * Sets the task mode. * * @param mode task mode */ public void setTaskMode(TaskMode mode) { set(TaskField.TASK_MODE, mode == TaskMode.MANUALLY_SCHEDULED); } /** * Retrieves the active flag. * * @return active flag value */ public boolean getActive() { return (BooleanHelper.getBoolean((Boolean) getCachedValue(TaskField.ACTIVE))); } /** * Sets the active flag. * * @param active active flag value */ public void setActive(boolean active) { set(TaskField.ACTIVE, active); } /** * Retrieve the baseline estimated duration. * * @return baseline estimated duration */ public Duration getBaselineEstimatedDuration() { return (Duration) getCachedValue(TaskField.BASELINE_ESTIMATED_DURATION); } /** * Set the baseline estimated duration. * * @param duration baseline estimated duration */ public void setBaselineEstimatedDuration(Duration duration) { set(TaskField.BASELINE_ESTIMATED_DURATION, duration); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineEstimatedDuration(int baselineNumber, Duration value) { set(selectField(TaskFieldLists.BASELINE_ESTIMATED_DURATIONS, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Duration getBaselineEstimatedDuration(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_DURATIONS, baselineNumber)); if (!(result instanceof Duration)) { result = null; } return (Duration) result; } /** * Retrieve the baseline estimated start. * * @return baseline estimated start */ public Date getBaselineEstimatedStart() { return (Date) getCachedValue(TaskField.BASELINE_ESTIMATED_START); } /** * Set the baseline estimated start. * * @param date baseline estimated start */ public void setBaselineEstimatedStart(Date date) { set(TaskField.BASELINE_ESTIMATED_START, date); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Date getBaselineEstimatedStart(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_STARTS, baselineNumber)); if (!(result instanceof Date)) { result = null; } return (Date) result; } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineEstimatedStart(int baselineNumber, Date value) { set(selectField(TaskFieldLists.BASELINE_ESTIMATED_STARTS, baselineNumber), value); } /** * Retrieve the baseline estimated finish. * * @return baseline estimated finish */ public Date getBaselineEstimatedFinish() { return (Date) getCachedValue(TaskField.BASELINE_ESTIMATED_FINISH); } /** * Set the baseline estimated finish. * * @param date baseline estimated finish */ public void setBaselineEstimatedFinish(Date date) { set(TaskField.BASELINE_ESTIMATED_FINISH, date); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Date getBaselineEstimatedFinish(int baselineNumber) { Object result = getCachedValue(selectField(TaskFieldLists.BASELINE_ESTIMATED_FINISHES, baselineNumber)); if (!(result instanceof Date)) { result = null; } return (Date) result; } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineEstimatedFinish(int baselineNumber, Date value) { set(selectField(TaskFieldLists.BASELINE_ESTIMATED_FINISHES, baselineNumber), value); } /** * The Fixed Cost field shows any task expense that is not associated * with a resource cost. * * @param val amount */ public void setBaselineFixedCost(Number val) { set(TaskField.BASELINE_FIXED_COST, val); } /** * The Fixed Cost field shows any task expense that is not associated * with a resource cost. * * @return currency amount */ public Number getBaselineFixedCost() { return ((Number) getCachedValue(TaskField.BASELINE_FIXED_COST)); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineFixedCost(int baselineNumber, Number value) { set(selectField(TaskFieldLists.BASELINE_FIXED_COSTS, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public Number getBaselineFixedCost(int baselineNumber) { return ((Number) getCachedValue(selectField(TaskFieldLists.BASELINE_FIXED_COSTS, baselineNumber))); } /** * Retrieves the baseline fixed cost accrual. * * @return fixed cost accrual flag */ public AccrueType getBaselineFixedCostAccrual() { return ((AccrueType) getCachedValue(TaskField.BASELINE_FIXED_COST_ACCRUAL)); } /** * Sets the baseline fixed cost accrual. * * @param type fixed cost accrual type */ public void setBaselineFixedCostAccrual(AccrueType type) { set(TaskField.BASELINE_FIXED_COST_ACCRUAL, type); } /** * Set a baseline value. * * @param baselineNumber baseline index (1-10) * @param value baseline value */ public void setBaselineFixedCostAccrual(int baselineNumber, AccrueType value) { set(selectField(TaskFieldLists.BASELINE_FIXED_COST_ACCRUALS, baselineNumber), value); } /** * Retrieve a baseline value. * * @param baselineNumber baseline index (1-10) * @return baseline value */ public AccrueType getBaselineFixedCostAccrual(int baselineNumber) { return ((AccrueType) getCachedValue(selectField(TaskFieldLists.BASELINE_FIXED_COST_ACCRUALS, baselineNumber))); } /** * This method allows a predecessor relationship to be removed from this * task instance. It will only delete relationships that exactly match the * given targetTask, type and lag time. * * @param targetTask the predecessor task * @param type relation type * @param lag relation lag * @return returns true if the relation is found and removed */ public boolean removePredecessor(Task targetTask, RelationType type, Duration lag) { boolean matchFound = false; // // Retrieve the list of predecessors // List<Relation> predecessorList = getPredecessors(); if (predecessorList != null && !predecessorList.isEmpty()) { // // Ensure that we have a valid lag duration // if (lag == null) { lag = Duration.getInstance(0, TimeUnit.DAYS); } // // Ensure that there is a predecessor relationship between // these two tasks, and remove it. // matchFound = removeRelation(predecessorList, targetTask, type, lag); // // If we have removed a predecessor, then we must remove the // corresponding successor entry from the target task list // if (matchFound) { // // Retrieve the list of successors // List<Relation> successorList = targetTask.getSuccessors(); if (successorList != null && !successorList.isEmpty()) { // // Ensure that there is a successor relationship between // these two tasks, and remove it. // removeRelation(successorList, this, type, lag); } } } return matchFound; } /** * Internal method used to locate an remove an item from a list Relations. * * @param relationList list of Relation instances * @param targetTask target relationship task * @param type target relationship type * @param lag target relationship lag * @return true if a relationship was removed */ private boolean removeRelation(List<Relation> relationList, Task targetTask, RelationType type, Duration lag) { boolean matchFound = false; for (Relation relation : relationList) { if (relation.getTargetTask() == targetTask) { if (relation.getType() == type && relation.getLag().compareTo(lag) == 0) { matchFound = relationList.remove(relation); break; } } } return matchFound; } /** * Maps a field index to a TaskField instance. * * @param fields array of fields used as the basis for the mapping. * @param index required field index * @return TaskField instance */ private TaskField selectField(TaskField[] fields, int index) { if (index < 1 || index > fields.length) { throw new IllegalArgumentException(index + " is not a valid field index"); } return (fields[index - 1]); } /** * {@inheritDoc} */ @Override public Object getCachedValue(FieldType field) { return (field == null ? null : m_array[field.getValue()]); } /** * {@inheritDoc} */ @Override public Object getCurrentValue(FieldType field) { Object result = null; if (field != null) { switch ((TaskField) field) { case START_VARIANCE: { result = getStartVariance(); break; } case COST_VARIANCE: { result = getCostVariance(); break; } case DURATION_VARIANCE: { result = getDurationVariance(); break; } case WORK_VARIANCE: { result = getWorkVariance(); break; } case CV: { result = getCV(); break; } case SV: { result = getSV(); break; } case TOTAL_SLACK: { result = getTotalSlack(); break; } case CRITICAL: { result = Boolean.valueOf(getCritical()); break; } case COMPLETE_THROUGH: { result = getCompleteThrough(); break; } default: { result = m_array[field.getValue()]; break; } } } return (result); } /** * {@inheritDoc} */ @Override public void set(FieldType field, Object value) { if (field != null) { int index = field.getValue(); if (m_eventsEnabled) { fireFieldChangeEvent((TaskField) field, m_array[index], value); } m_array[index] = value; } } /** * Handle the change in a field value. Reset any cached calculated * values affected by this change, pass on the event to any external * listeners. * * @param field field changed * @param oldValue old field value * @param newValue new field value */ private void fireFieldChangeEvent(TaskField field, Object oldValue, Object newValue) { // // Internal event handling // switch (field) { case UNIQUE_ID: { ProjectFile parent = getParentFile(); if (oldValue != null) { parent.getAllTasks().unmapUniqueID((Integer) oldValue); } parent.getAllTasks().mapUniqueID((Integer) newValue, this); break; } case START: case BASELINE_START: { m_array[TaskField.START_VARIANCE.getValue()] = null; break; } case FINISH: case BASELINE_FINISH: { m_array[TaskField.FINISH_VARIANCE.getValue()] = null; break; } case COST: case BASELINE_COST: { m_array[TaskField.COST_VARIANCE.getValue()] = null; break; } case DURATION: { m_array[TaskField.DURATION_VARIANCE.getValue()] = null; m_array[TaskField.COMPLETE_THROUGH.getValue()] = null; break; } case BASELINE_DURATION: { m_array[TaskField.DURATION_VARIANCE.getValue()] = null; break; } case WORK: case BASELINE_WORK: { m_array[TaskField.WORK_VARIANCE.getValue()] = null; break; } case BCWP: case ACWP: { m_array[TaskField.CV.getValue()] = null; m_array[TaskField.SV.getValue()] = null; break; } case BCWS: { m_array[TaskField.SV.getValue()] = null; break; } case START_SLACK: case FINISH_SLACK: { m_array[TaskField.TOTAL_SLACK.getValue()] = null; m_array[TaskField.CRITICAL.getValue()] = null; break; } case EARLY_FINISH: case LATE_FINISH: { m_array[TaskField.FINISH_SLACK.getValue()] = null; m_array[TaskField.TOTAL_SLACK.getValue()] = null; m_array[TaskField.CRITICAL.getValue()] = null; break; } case EARLY_START: case LATE_START: { m_array[TaskField.START_SLACK.getValue()] = null; m_array[TaskField.TOTAL_SLACK.getValue()] = null; m_array[TaskField.CRITICAL.getValue()] = null; break; } case ACTUAL_START: case PERCENT_COMPLETE: { m_array[TaskField.COMPLETE_THROUGH.getValue()] = null; break; } default: { break; } } // // External event handling // if (m_listeners != null) { for (FieldListener listener : m_listeners) { listener.fieldChange(this, field, oldValue, newValue); } } } /** * {@inheritDoc} */ @Override public void addFieldListener(FieldListener listener) { if (m_listeners == null) { m_listeners = new LinkedList<FieldListener>(); } m_listeners.add(listener); } /** * {@inheritDoc} */ @Override public void removeFieldListener(FieldListener listener) { if (m_listeners != null) { m_listeners.remove(listener); } } /** * This method inserts a name value pair into internal storage. * * @param field task field * @param value attribute value */ private void set(FieldType field, boolean value) { set(field, (value ? Boolean.TRUE : Boolean.FALSE)); } /** * {@inheritDoc} */ @Override public String toString() { return ("[Task id=" + getID() + " uniqueID=" + getUniqueID() + " name=" + getName() + (getExternalTask() ? " [EXTERNAL uid=" + getSubprojectTaskUniqueID() + " id=" + getSubprojectTaskID() + "]" : "]") + (getSubProject() == null ? "" : (" project=" + getSubProject()))); } /** * Utility method used to determine if the supplied task * is a predecessor of the current task. * * @param task potential predecessor task * @return Boolean flag */ public boolean isPredecessor(Task task) { return isRelated(task, getPredecessors()); } /** * Utility method used to determine if the supplied task * is a successor of the current task. * * @param task potential successor task * @return Boolean flag */ public boolean isSucessor(Task task) { return isRelated(task, getSuccessors()); } /** * Internal method used to test for the existence of a relationship * with a task. * * @param task target task * @param list list of relationships * @return boolean flag */ private boolean isRelated(Task task, List<Relation> list) { boolean result = false; if (list != null) { for (Relation relation : list) { if (relation.getTargetTask().getUniqueID().intValue() == task.getUniqueID().intValue()) { result = true; break; } } } return result; } /** * Disable events firing when fields are updated. */ public void disableEvents() { m_eventsEnabled = false; } /** * Enable events firing when fields are updated. This is the default state. */ public void enableEvents() { m_eventsEnabled = true; } /** * Array of field values. */ private Object[] m_array = new Object[TaskField.MAX_VALUE]; /** * This is a reference to the parent task, as specified by the * outline level. */ private Task m_parent; /** * This list holds references to all tasks that are children of the * current task as specified by the outline level. */ private List<Task> m_children = new LinkedList<Task>(); /** * List of resource assignments for this task. */ private List<ResourceAssignment> m_assignments = new LinkedList<ResourceAssignment>(); /** * Recurring task details associated with this task. */ private RecurringTask m_recurringTask; private boolean m_eventsEnabled = true; private boolean m_null; private String m_wbsLevel; private boolean m_resumeValid; private String m_externalTaskProject; private TimeUnit m_levelingDelayFormat; private EarnedValueMethod m_earnedValueMethod; private Duration m_actualWorkProtected; private Duration m_actualOvertimeWorkProtected; private boolean m_expanded = true; private List<DateRange> m_splits; private Date m_splitsComplete; private SubProject m_subProject; private List<FieldListener> m_listeners; }