0001: /*
0002: The contents of this file are subject to the Common Public Attribution License
0003: Version 1.0 (the "License"); you may not use this file except in compliance with
0004: the License. You may obtain a copy of the License at
0005: http://www.projity.com/license . The License is based on the Mozilla Public
0006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
0007: software over a computer network and provide for limited attribution for the
0008: Original Developer. In addition, Exhibit A has been modified to be consistent
0009: with Exhibit B.
0010:
0011: Software distributed under the License is distributed on an "AS IS" basis,
0012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
0013: specific language governing rights and limitations under the License. The
0014: Original Code is OpenProj. The Original Developer is the Initial Developer and
0015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
0016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
0017:
0018: Alternatively, the contents of this file may be used under the terms of the
0019: Projity End-User License Agreeement (the Projity License), in which case the
0020: provisions of the Projity License are applicable instead of those above. If you
0021: wish to allow use of your version of this file only under the terms of the
0022: Projity License and not to allow others to use your version of this file under
0023: the CPAL, indicate your decision by deleting the provisions above and replace
0024: them with the notice and other provisions required by the Projity License. If
0025: you do not delete the provisions above, a recipient may use your version of this
0026: file under either the CPAL or the Projity License.
0027:
0028: [NOTE: The text of this license may differ slightly from the text of the notices
0029: in Exhibits A and B of the license at http://www.projity.com/license. You should
0030: use the latest text at http://www.projity.com/license for your modifications.
0031: You may not remove this license text from the source files.]
0032:
0033: Attribution Information: Attribution Copyright Notice: Copyright � 2006, 2007
0034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
0035: an open source solution from Projity. Attribution URL: http://www.projity.com
0036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
0037: alternatives listed on http://www.projity.com/logo
0038:
0039: Display of Attribution Information is required in Larger Works which are defined
0040: in the CPAL as a work which combines Covered Code or portions thereof with code
0041: not governed by the terms of the CPAL. However, in addition to the other notice
0042: obligations, all copies of the Covered Code in Executable and Source Code form
0043: distributed must, as a form of attribution of the original author, include on
0044: each user interface screen the "OpenProj" logo visible to all users. The
0045: OpenProj logo should be located horizontally aligned with the menu bar and left
0046: justified on the top left of the screen adjacent to the File menu. The logo
0047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
0048: must direct them back to http://www.projity.com.
0049: */
0050: package com.projity.pm.task;
0051:
0052: import java.io.IOException;
0053: import java.io.ObjectInputStream;
0054: import java.io.ObjectOutputStream;
0055: import java.util.ArrayList;
0056: import java.util.Collection;
0057: import java.util.Date;
0058: import java.util.EventListener;
0059: import java.util.HashMap;
0060: import java.util.Iterator;
0061: import java.util.LinkedList;
0062: import java.util.List;
0063: import java.util.Map;
0064:
0065: import javax.swing.event.EventListenerList;
0066: import javax.swing.undo.UndoableEditSupport;
0067:
0068: import org.apache.commons.collections.Closure;
0069: import org.apache.commons.collections.CollectionUtils;
0070: import org.apache.commons.collections.Predicate;
0071:
0072: import com.projity.algorithm.ReverseQuery;
0073: import com.projity.association.InvalidAssociationException;
0074: import com.projity.configuration.CircularDependencyException;
0075: import com.projity.configuration.Dictionary;
0076: import com.projity.configuration.FieldDictionary;
0077: import com.projity.configuration.Settings;
0078: import com.projity.datatype.Duration;
0079: import com.projity.datatype.Hyperlink;
0080: import com.projity.datatype.ImageLink;
0081: import com.projity.document.Document;
0082: import com.projity.document.ObjectEvent;
0083: import com.projity.document.ObjectEventManager;
0084: import com.projity.field.Field;
0085: import com.projity.field.FieldContext;
0086: import com.projity.field.HasExtraFields;
0087: import com.projity.functor.IntervalConsumer;
0088: import com.projity.graphic.configuration.SpreadSheetCategories;
0089: import com.projity.graphic.configuration.SpreadSheetFieldArray;
0090: import com.projity.grouping.core.Node;
0091: import com.projity.grouping.core.NodeException;
0092: import com.projity.grouping.core.NodeFactory;
0093: import com.projity.grouping.core.NodeList;
0094: import com.projity.grouping.core.NodeVisitor;
0095: import com.projity.grouping.core.OutlineCollection;
0096: import com.projity.grouping.core.OutlineCollectionImpl;
0097: import com.projity.grouping.core.event.HierarchyEvent;
0098: import com.projity.grouping.core.event.HierarchyListener;
0099: import com.projity.grouping.core.hierarchy.NodeHierarchy;
0100: import com.projity.grouping.core.model.AssignmentNodeModel;
0101: import com.projity.grouping.core.model.NodeModel;
0102: import com.projity.grouping.core.model.NodeModelDataFactory;
0103: import com.projity.grouping.core.model.NodeModelFactory;
0104: import com.projity.grouping.core.transform.filtering.NotAssignmentFilter;
0105: import com.projity.options.CalendarOption;
0106: import com.projity.options.TimesheetOption;
0107: import com.projity.pm.assignment.Assignment;
0108: import com.projity.pm.assignment.HasTimeDistributedData;
0109: import com.projity.pm.assignment.TimeDistributedDataConsolidator;
0110: import com.projity.pm.assignment.TimeDistributedFields;
0111: import com.projity.pm.assignment.timesheet.TimesheetHelper;
0112: import com.projity.pm.assignment.timesheet.UpdatesFromTimesheet;
0113: import com.projity.pm.calendar.CalendarService;
0114: import com.projity.pm.calendar.HasBaseCalendar;
0115: import com.projity.pm.calendar.HasCalendar;
0116: import com.projity.pm.calendar.WorkCalendar;
0117: import com.projity.pm.calendar.WorkingCalendar;
0118: import com.projity.pm.costing.EarnedValueCalculator;
0119: import com.projity.pm.costing.EarnedValueFields;
0120: import com.projity.pm.costing.EarnedValueValues;
0121: import com.projity.pm.costing.ExpenseType;
0122: import com.projity.pm.costing.HasExpenseType;
0123: import com.projity.pm.criticalpath.CriticalPath;
0124: import com.projity.pm.criticalpath.HasSentinels;
0125: import com.projity.pm.criticalpath.SchedulingAlgorithm;
0126: import com.projity.pm.dependency.DependencyService;
0127: import com.projity.pm.key.HasKey;
0128: import com.projity.pm.key.HasKeyImpl;
0129: import com.projity.pm.resource.Resource;
0130: import com.projity.pm.resource.ResourcePool;
0131: import com.projity.pm.scheduling.BarClosure;
0132: import com.projity.pm.scheduling.ConstraintType;
0133: import com.projity.pm.scheduling.Schedule;
0134: import com.projity.pm.scheduling.ScheduleEvent;
0135: import com.projity.pm.scheduling.ScheduleEventListener;
0136: import com.projity.pm.scheduling.ScheduleEventManager;
0137: import com.projity.pm.scheduling.ScheduleInterval;
0138: import com.projity.pm.scheduling.ScheduleUtil;
0139: import com.projity.pm.snapshot.BaselineScheduleFields;
0140: import com.projity.pm.snapshot.SnapshottableImpl;
0141: import com.projity.pm.time.MutableHasStartAndEnd;
0142: import com.projity.server.data.DataObject;
0143: import com.projity.session.FileHelper;
0144: import com.projity.strings.Messages;
0145: import com.projity.transaction.MultipleTransactionManager;
0146: import com.projity.undo.ClearSnapshotEdit;
0147: import com.projity.undo.DataFactoryUndoController;
0148: import com.projity.undo.SaveSnapshotEdit;
0149: import com.projity.util.Alert;
0150: import com.projity.util.DateTime;
0151: import com.projity.util.Environment;
0152: import com.projity.workspace.SavableToWorkspace;
0153: import com.projity.workspace.WorkspaceSetting;
0154:
0155: /**
0156: * Project class
0157: */
0158: public class Project implements Document, BelongsToDocument, HasKey,
0159: HasPriority, MutableHasStartAndEnd, ProjectSpecificFields,
0160: HasNotes, HasBaseCalendar, HasCalendar, NodeModelDataFactory,
0161: HierarchyListener, HasTimeDistributedData,
0162: TimeDistributedFields, EarnedValueValues, EarnedValueFields,
0163: DataObject, HasSentinels, BaselineScheduleFields, Schedule,
0164: UpdatesFromTimesheet, HasExtraFields, HasExpenseType,
0165: SavableToWorkspace {
0166: static final long serialVersionUID = 17283790404932L;
0167: private long statusDate = 0;
0168: private String manager = "";
0169: private transient HasKeyImpl hasKey;
0170: private String notes = "";
0171: private transient LinkedList tasks = new LinkedList();
0172: private transient ResourcePool resourcePool = null;
0173: //private transient Schedule schedule = null; //used?
0174: private transient SchedulingAlgorithm schedulingAlgorithm = null;
0175: private transient boolean initialized = false;
0176: private transient ScheduleEventManager scheduleEventManager = new ScheduleEventManager();
0177: private transient MultipleTransactionManager multipleTransactionManager = new MultipleTransactionManager();
0178: private transient ObjectEventManager objectEventManager = new ObjectEventManager();
0179: private transient int taskIdCounter = 0;
0180: private transient boolean isGroupDirty = false;
0181: private transient boolean isDirty = false;
0182: private transient boolean readOnly = false;
0183: private transient SubprojectHandler subprojectHandler;
0184: long start;
0185: long end;
0186: long duration;
0187: boolean forward = true;
0188: int priority = 500;
0189: long currentDate = 0;
0190: private Map extraFields = null;
0191: private double risk = 0.0D;
0192: private double netPresentValue = 0.0D;
0193: private int benefit = 0;
0194: transient int projectStatus = ProjectStatus.PLANNING; // exposed in database
0195: transient int projectType = ProjectType.OTHER; // exposed in database
0196: transient int expenseType = ExpenseType.NONE;// exposed in database
0197: transient String group;// exposed in database
0198: transient String division;// exposed in database
0199:
0200: private transient boolean openedAsSubproject = false;
0201: private transient Hyperlink documentFolderUrl = null;
0202: private transient long earliestStartingTask = 0L; // used for subprojects
0203: private transient long latestFinishingTask = 0L; // used for subprojects
0204: private static Project dummy = null;
0205:
0206: private transient NodeModel taskModel = null;
0207: private transient NodeModel resourceModel = null;
0208: private transient Object taskCache = null;
0209: private transient Object resourceCache = null;
0210:
0211: private transient Date creationDate, lastModificationDate;
0212:
0213: public NodeModel getTaskModel() {
0214: if (taskModel == null)
0215: taskModel = NodeModelFactory.createTaskModel(this );
0216: return taskModel;
0217: }
0218:
0219: public NodeModel getResourceModel() {
0220: if (resourceModel == null)
0221: resourceModel = NodeModelFactory.createResourceModel(this );
0222: return resourceModel;
0223: }
0224:
0225: public Object getResourceCache() {
0226: return resourceCache;
0227: }
0228:
0229: public void setResourceCache(Object resourceCache) {
0230: this .resourceCache = resourceCache;
0231: }
0232:
0233: public Object getTaskCache() {
0234: return taskCache;
0235: }
0236:
0237: public void setTaskCache(Object taskCache) {
0238: this .taskCache = taskCache;
0239: }
0240:
0241: private Project(boolean local) {
0242: super ();
0243: // get the appropriate subproject handler
0244: initSubprojectHandler();
0245: hasKey = new HasKeyImpl(local, this );
0246: setWorkCalendar(CalendarService.getInstance()
0247: .getDefaultInstance());
0248:
0249: start = CalendarOption.getInstance().makeValidStart(
0250: DateTime.midnightToday(), true);
0251: start = getEffectiveWorkCalendar().adjustInsideCalendar(start,
0252: false);
0253: end = start;
0254: }
0255:
0256: private Project(ResourcePool resourcePool,
0257: DataFactoryUndoController undo) {
0258: this (resourcePool.isLocal());
0259: this .resourcePool = resourcePool;
0260: undoController = undo;
0261: }
0262:
0263: public void dispose() {
0264: System.out.println("disposing project " + this );
0265: }
0266:
0267: public static Project getDummy() {
0268: if (dummy == null)
0269: dummy = new Project(true);
0270: return dummy;
0271: }
0272:
0273: public static Project createProject(ResourcePool resourcePool,
0274: DataFactoryUndoController undo) {
0275: Project project = new Project(resourcePool, undo);
0276: project.initializeProject();
0277: project.setUndoController(undo); //undo not properly initialized in new Project(resourcePool,undo)
0278: return project;
0279: }
0280:
0281: public void initializeOutlines() {
0282: int count = Settings.numHierarchies();
0283: for (int i = 0; i < count; i++) {
0284: NodeModel model = taskOutlines.getOutline(i);
0285: if (model == null)
0286: continue;
0287: if (model instanceof AssignmentNodeModel) {
0288: AssignmentNodeModel aModel = (AssignmentNodeModel) model;
0289: aModel.setContainsLeftObjects(true);
0290: aModel.setDocument(this );
0291: }
0292: model.setUndoController(undoController);
0293: }
0294: initializeDefaultOutline();
0295: }
0296:
0297: public void disconnectOutlines() {
0298: int count = Settings.numHierarchies();
0299: for (int i = 0; i < count; i++) {
0300: NodeModel model = taskOutlines.getOutline(i);
0301: if (model instanceof AssignmentNodeModel) {
0302: AssignmentNodeModel aModel = (AssignmentNodeModel) model;
0303: aModel.setDocument(null); //remove ObjectListener
0304: }
0305: }
0306: disconnectDefaultOutline();
0307: }
0308:
0309: public long getStartConstraint() {
0310: long result;
0311: long constraint = getReferringSubprojectTaskDependencyDate();
0312: if (constraint > getStart())
0313: result = getEffectiveWorkCalendar().adjustInsideCalendar(
0314: constraint, false);
0315: else
0316: result = getStart();
0317: return result;
0318: }
0319:
0320: public void initialize(final boolean subproject) {
0321: initialized = true;
0322: if (!subproject)
0323: schedulingAlgorithm.initialize(this );
0324: initializeDefaultOutline();
0325: if (TimesheetOption.getInstance()
0326: .isAutomaticallyIntegrateTimecardData())
0327: applyTimesheet(TimesheetOption.getInstance()
0328: .getTimesheetFieldArray());
0329: setAllTasksAsUnchangedFromPersisted();
0330: }
0331:
0332: /**
0333: * This will set the start and end date of a project to the earliest starting task and the latest finishing
0334: * Its purpose is for use in handling subprojects, when we'd like the subproject's external constraints to determine its start and end, and also
0335: * have it the subproject show up with correct start and end dates when shown upopened in another project
0336: *
0337: */
0338: void setEarliestAndLatestDatesFromSchedule() {
0339: Iterator i = tasks.iterator();
0340: long s = Long.MAX_VALUE;
0341: long e = 0;
0342: while (i.hasNext()) {
0343: Task t = (Task) i.next();
0344: if (t.isExternal() || t.getOwningProject() != this )
0345: continue;
0346: s = Math.min(s, t.getStart());
0347: e = Math.max(e, t.getEnd());
0348: }
0349: if (s != Long.MAX_VALUE)
0350: earliestStartingTask = s;
0351: else
0352: earliestStartingTask = getStart();
0353:
0354: if (e != 0)
0355: latestFinishingTask = e;
0356: else
0357: latestFinishingTask = getEnd();
0358: }
0359:
0360: public void initializeProject() {
0361: setSchedulingAlgorithm(new CriticalPath(this ));
0362: /**TODO fix calendar handling should be created by factory*/
0363:
0364: initializeOutlines();
0365:
0366: }
0367:
0368: public void disconnect() {
0369: disconnectOutlines();
0370: removeObjectListener(getSchedulingAlgorithm());
0371: schedulingAlgorithm = null; // help with gc
0372: }
0373:
0374: private void initializeDefaultOutline() {
0375: taskOutlines.getDefaultOutline().getHierarchy()
0376: .addHierarchyListener(this );
0377: }
0378:
0379: private void disconnectDefaultOutline() {
0380: taskOutlines.getDefaultOutline().getHierarchy()
0381: .removeHierarchyListener(this );
0382: }
0383:
0384: public NormalTask newNormalTaskInstance() {
0385: return newNormalTaskInstance(true);
0386: }
0387:
0388: public void initializeId(Task task) {
0389: long id = ++taskIdCounter;
0390: task.setId(id); //starts at 1TODO check for duplicates -
0391: //task.setUniqueId(id); //TODO use a GUID generator
0392: }
0393:
0394: public NormalTask newNormalTaskInstance(boolean userCreated) {
0395: NormalTask newOne = new NormalTask(this );
0396:
0397: add(newOne);
0398: initializeId(newOne);
0399:
0400: if (userCreated)
0401: objectEventManager.fireCreateEvent(this , newOne);
0402: return newOne;
0403: }
0404:
0405: public void setLocalParent(Task child, Task parent) {
0406: Node childNode = getTaskModel().search(child);
0407: Node parentNode = parent == null ? null : getTaskModel()
0408: .search(parent);
0409: setLocalParent(childNode, parentNode);
0410: }
0411:
0412: public void setLocalParent(Node childNode, Node parentNode) {
0413: Task child = (Task) childNode.getImpl();
0414: Task parent = (Task) (parentNode == null ? null : parentNode
0415: .getImpl());
0416: if (child.getWbsParentTask() == parent)
0417: return;
0418: Node oldParentNode = getTaskModel().search(
0419: child.getWbsParentTask());
0420: if (oldParentNode != null)
0421: oldParentNode.getChildren().remove(childNode);
0422: ArrayList temp = new ArrayList();
0423: temp.add(childNode);
0424: getTaskModel().move(parentNode, temp, -1, NodeModel.NORMAL);
0425: setDefaultRelationship(parentNode, childNode);
0426: }
0427:
0428: public Node createLocalTaskNode(Node parentNode) {
0429: NormalTask task = new NormalTask(this );
0430: Node childNode = NodeFactory.getInstance().createNode(task); // get a node for this task
0431: connectTask(task);
0432: addToDefaultOutline(parentNode, childNode);
0433: getSchedulingAlgorithm().addObject(task);
0434: return childNode;
0435: }
0436:
0437: // public Task cloneTask(Task from) {
0438: // //TODO this does not copy fields correctly
0439: // NormalTask newOne = (NormalTask) from.clone();
0440: // add(newOne);
0441: // initializeId(newOne);
0442: // newOne.setWbsParent(from.getWbsParentTask());
0443: // Node node = NodeFactory.getInstance().createNode(newOne);
0444: // getTaskModel().addBefore(getTaskModel().search(from),node,NodeModel.NORMAL);
0445: // objectEventManager.fireCreateEvent(this,newOne);
0446: // return newOne;
0447: //
0448: // }
0449:
0450: /**
0451: * Used when creating a task on spreadsheet that may not be valid
0452: * @return
0453: */
0454: public NormalTask newStandaloneNormalTaskInstance() {
0455: NormalTask newOne = new NormalTask(this );
0456:
0457: newOne.getCurrentSchedule().setStart(
0458: getWorkCalendar().adjustInsideCalendar(
0459: newOne.getCurrentSchedule().getStart(), false));
0460: initializeId(newOne);
0461: // newOne.initializeDates();
0462: return newOne;
0463: }
0464:
0465: public NormalTask createScriptedTask() {
0466: NormalTask task = newStandaloneNormalTaskInstance();
0467: connectTask(task); // put task in project list
0468: taskOutlines.addToAll(task, null); // update all node models
0469: task.markTaskAsNeedingRecalculation();
0470: updateScheduling(this , task, ObjectEvent.CREATE);
0471: return task;
0472: }
0473:
0474: public void connectTask(Task task) {
0475: add(task);
0476: if (task.getOwningProject() == null)
0477: task.setOwningProject(this );
0478: if (task.getProjectId() == 0) {
0479: task.setProjectId(getUniqueId());
0480: }
0481: Project masterProject = (Project) task.getMasterDocument();
0482: if (masterProject == this ) {
0483: task.setProject(this );
0484: // initially, the task has no predecessors or successors, so signify that it is both a starting point and an ending point
0485: if (task.getSuccessorList().size() == 0)
0486: addEndSentinelDependency(task);
0487: if (task.getPredecessorList().size() == 0)
0488: addStartSentinelDependency(task);
0489: } else {
0490: masterProject.add(task);
0491: task.setProject(masterProject);
0492: }
0493: }
0494:
0495: /**
0496: * @return Returns the statusDate.
0497: */
0498: public long getStatusDate() {
0499: if (statusDate == 0) // if date not set, then use last instant of this day incude all of today
0500: return workCalendar.adjustInsideCalendar(DateTime
0501: .midnightTomorrow() - 1, true);
0502:
0503: return statusDate;
0504: }
0505:
0506: /**
0507: * @param statusDate The statusDate to set.
0508: */
0509: public void setStatusDate(long statusDate) {
0510: statusDate = DateTime.midnightNextDay(statusDate) - 1; // last instant of today
0511: statusDate = workCalendar
0512: .adjustInsideCalendar(statusDate, true);
0513: this .statusDate = statusDate;
0514: }
0515:
0516: public final int getPriority() {
0517: return priority;
0518: }
0519:
0520: public final void setPriority(int priority) {
0521: this .priority = priority;
0522: }
0523:
0524: public void add(Task task) {
0525: tasks.add(task);
0526: }
0527:
0528: /**
0529: * @return Returns the tasks.
0530: */
0531: public LinkedList getTasks() {
0532: return tasks;
0533: }
0534:
0535: // public static Closure forAllTasks(Closure visitor, Predicate filter) {
0536: // return new CollectionVisitor(visitor,filter) {
0537: // protected Collection getCollection(Object arg0) {
0538: // return ((Project)arg0).getTasks();
0539: // }
0540: // };
0541: // }
0542: //
0543: // public int testCount() {
0544: // ReflectionPredicate taskPredicate;
0545: // try {
0546: // taskPredicate = ReflectionPredicate.getInstance(NormalTask.class.getMethod("isVirtual",null));
0547: // Closure t = Project.forAllTasks(NormalTask.forAllAssignments(PrintString.INSTANCE),taskPredicate);
0548: // t.execute(this);
0549: // } catch (SecurityException e) {
0550: // // TODO Auto-generated catch block
0551: // e.printStackTrace();
0552: // } catch (NoSuchMethodException e) {
0553: // // TODO Auto-generated catch block
0554: // e.printStackTrace();
0555: // }
0556: // return 0;
0557: // }
0558:
0559: /**
0560: * @return Returns the resourcePool.
0561: */
0562: public ResourcePool getResourcePool() {
0563: return resourcePool;
0564: }
0565:
0566: public void setResourcePool(ResourcePool resourcePool) {
0567: this .resourcePool = resourcePool;
0568: }
0569:
0570: /* (non-Javadoc)
0571: * @see com.projity.grouping.core.Node#accept(com.projity.grouping.core.NodeVisitor)
0572: */
0573: public void accept(NodeVisitor visitor) {
0574: visitor.execute(this );
0575: }
0576:
0577: /* (non-Javadoc)
0578: * @see com.projity.grouping.core.Node#getType()
0579: */
0580: public Class getType() throws NodeException {
0581: return getClass();
0582: }
0583:
0584: /* (non-Javadoc)
0585: * @see com.projity.grouping.core.Node#isVirtual()
0586: */
0587: public boolean isVirtual() {
0588: return false;
0589: }
0590:
0591: /* (non-Javadoc)
0592: * @see com.projity.grouping.core.Node#setVirtual(boolean)
0593: */
0594: public void setVirtual(boolean virtual) {
0595: }
0596:
0597: private transient OutlineCollection taskOutlines = new OutlineCollectionImpl(
0598: Settings.numHierarchies(), this );
0599:
0600: public NodeModel getTaskOutline() {
0601: return taskOutlines.getOutline();
0602: }
0603:
0604: public NodeModel getTaskOutline(int outlineNumber) {
0605: return taskOutlines.getOutline(outlineNumber);
0606: }
0607:
0608: public void addToDefaultOutline(Node parentNode, Node childNode) {
0609: taskOutlines.addToDefaultOutline(parentNode, childNode);
0610: if (parentNode == null)
0611: return;
0612: setDefaultRelationship(parentNode, childNode);
0613: }
0614:
0615: public void addToDefaultOutline(Node parentNode, Node childNode,
0616: int position, boolean event) {
0617: taskOutlines.addToDefaultOutline(parentNode, childNode,
0618: position, event);
0619: if (parentNode == null || childNode.isVoid())
0620: return;
0621: setDefaultRelationship(parentNode, childNode);
0622: }
0623:
0624: public OutlineCollection getTaskOutlines() {
0625: return taskOutlines;
0626: }
0627:
0628: private void setDefaultRelationship(Node parentNode, Node childNode) {
0629: Task childTask = (Task) childNode.getImpl();
0630: if (parentNode == null) {
0631: childTask.setWbsParent(null);
0632: } else {
0633: Task parentTask = (Task) parentNode.getImpl();
0634: childTask.setWbsParent(parentTask);
0635: if (parentTask != null)
0636: parentTask.setWbsChildrenNodes(taskOutlines
0637: .getDefaultOutline().getHierarchy()
0638: .getChildren(parentNode));
0639: }
0640: }
0641:
0642: public long getStart() {
0643: return start;
0644: }
0645:
0646: public long getEnd() {
0647: return end;
0648: }
0649:
0650: /**
0651: * @return
0652: */
0653: public long getDuration() {
0654: return getEffectiveWorkCalendar().compare(end, start, false);
0655: }
0656:
0657: WorkCalendar workCalendar = null;
0658:
0659: /**
0660: * @return
0661: */
0662: public WorkCalendar getWorkCalendar() {
0663: return workCalendar;
0664: }
0665:
0666: /**
0667: * @param workCalendar
0668: */
0669: public void setWorkCalendar(WorkCalendar workCalendar) {
0670: if (this .workCalendar != null)
0671: ((WorkingCalendar) this .workCalendar)
0672: .removeObjectUsing(this );
0673: this .workCalendar = workCalendar;
0674: ((WorkingCalendar) this .workCalendar).addObjectUsing(this );
0675: }
0676:
0677: /* (non-Javadoc)
0678: * @see com.projity.pm.time.HasCalendar#getEffectiveWorkCalendar()
0679: */
0680: public WorkCalendar getEffectiveWorkCalendar() {
0681: return workCalendar;
0682: }
0683:
0684: /* (non-Javadoc)
0685: * @see com.projity.pm.scheduling.Schedule#getHasCalendar()
0686: */
0687: public HasCalendar getHasCalendar() {
0688: return this ;
0689: }
0690:
0691: /**
0692: * @param end
0693: */
0694: public void setEnd(long end) {
0695: this .end = end;
0696: // setEndConstraint(end);
0697: }
0698:
0699: /**
0700: * @param start
0701: */
0702: public void setStart(long start) {
0703: // System.out.println("setting project " + this + " start " + new Date(start) + " previous " + new Date(this.start));
0704: //if (this.getName().equals("xxx"))
0705: // System.out.println("bah");
0706: this .start = start;
0707: }
0708:
0709: /**
0710: * Quick function to find a task by id. Should probably replaced with hash table
0711: * @param idObject
0712: * @param project
0713: * @return
0714: */
0715: public static Task findTaskById(Object idObject, Collection taskList) {
0716: Iterator i = taskList.iterator();
0717: int id = ((Number) idObject).intValue();
0718: Task task;
0719: while (i.hasNext()) {
0720: task = (Task) i.next();
0721: if (task.getId() == id)
0722: return task;
0723: }
0724: return null;
0725: }
0726:
0727: // public static Task findTaskByUniqueId(Object idObject, Collection taskList) {
0728: // Iterator i = taskList.iterator();
0729: // int id = ((Number)idObject).intValue();
0730: // Task task;
0731: // while (i.hasNext()) {
0732: // task = (Task)i.next();
0733: // if (task.getUniqueId() == id)
0734: // return task;
0735: // }
0736: // return null;
0737: // }
0738:
0739: public Task findByUniqueId(long id) {
0740: Iterator i = getTaskOutlineIterator();
0741: Task task;
0742: while (i.hasNext()) {
0743: task = (Task) i.next();
0744: if (task.getUniqueId() == id)
0745: return task;
0746: }
0747: return null;
0748: }
0749:
0750: // public Task findByUniqueId(long id) {
0751: // return findTaskByUniqueId(new Long(id), getTasks());
0752: // }
0753: /**
0754: * @return Returns the initialized.
0755: */
0756: public boolean isInitialized() {
0757: return initialized;
0758: }
0759:
0760: /**
0761: * @return Returns the manager.
0762: */
0763: public String getManager() {
0764: return manager;
0765: }
0766:
0767: /**
0768: * @param manager The manager to set.
0769: */
0770: public void setManager(String manager) {
0771: this .manager = manager;
0772: }
0773:
0774: /**
0775: * @return Returns the notes.
0776: */
0777: public String getNotes() {
0778: return notes;
0779: }
0780:
0781: /**
0782: * @param notes The notes to set.
0783: */
0784: public void setNotes(String notes) {
0785: this .notes = notes;
0786: }
0787:
0788: /**
0789: * @return
0790: */
0791: public Date getCreated() {
0792: return hasKey.getCreated();
0793: }
0794:
0795: /**
0796: * @return
0797: */
0798: public long getId() {
0799: return hasKey.getId();
0800: }
0801:
0802: /**
0803: * @return
0804: */
0805: public String getName() {
0806: return hasKey.getName();
0807: }
0808:
0809: /**
0810: * @return
0811: */
0812: public long getUniqueId() {
0813: return hasKey.getUniqueId();
0814: }
0815:
0816: // public void setNew(boolean isNew) {
0817: // hasKey.setNew(isNew);
0818: // }
0819: /**
0820: * @param created
0821: */
0822: public void setCreated(Date created) {
0823: hasKey.setCreated(created);
0824: }
0825:
0826: /**
0827: * @param id
0828: */
0829: public void setId(long id) {
0830: hasKey.setId(id);
0831: }
0832:
0833: /**
0834: * @param name
0835: */
0836: public void setName(String name) {
0837: if (name == null || name.length() == 0)
0838: return;
0839: String oldName = getName();
0840: hasKey.setName(name);
0841: if ((oldName == null && name != null)
0842: || (!oldName.equals(name)))
0843: fireNameChanged(this , oldName);
0844: if (getWorkCalendar() == null)
0845: System.out
0846: .println("error work calendar is null on project");
0847: }
0848:
0849: protected transient EventListenerList projectListenerList = new EventListenerList();
0850:
0851: public void addProjectListener(ProjectListener l) {
0852: projectListenerList.add(ProjectListener.class, l);
0853: }
0854:
0855: public void removeProjectListener(ProjectListener l) {
0856: projectListenerList.remove(ProjectListener.class, l);
0857: }
0858:
0859: public ProjectListener[] getProjectListeners() {
0860: return (ProjectListener[]) projectListenerList
0861: .getListeners(ProjectListener.class);
0862: }
0863:
0864: public EventListener[] getProjectListeners(Class listenerType) {
0865: return projectListenerList.getListeners(listenerType);
0866: }
0867:
0868: protected void fireNameChanged(Object source, String oldName) {
0869: Object[] listeners = projectListenerList.getListenerList();
0870: ProjectEvent e = null;
0871: for (int i = 0; i < listeners.length; i += 2) {
0872: if (listeners[i] == ProjectListener.class) {
0873: if (e == null) {
0874: e = new ProjectEvent(source,
0875: ProjectEvent.NAME_CHANGED, this , oldName);
0876: }
0877: ((ProjectListener) listeners[i + 1]).nameChanged(e);
0878:
0879: }
0880: }
0881: }
0882:
0883: protected void fireGroupDirtyChanged(Object source, boolean oldName) {
0884: Object[] listeners = projectListenerList.getListenerList();
0885: ProjectEvent e = null;
0886: for (int i = 0; i < listeners.length; i += 2) {
0887: if (listeners[i] == ProjectListener.class) {
0888: if (e == null) {
0889: e = new ProjectEvent(source,
0890: ProjectEvent.GROUP_DIRTY_CHANGED, this ,
0891: new Boolean(oldName));
0892: }
0893: ((ProjectListener) listeners[i + 1])
0894: .groupDirtyChanged(e);
0895:
0896: }
0897: }
0898: }
0899:
0900: /**
0901: * @param id
0902: */
0903: public void setUniqueId(long id) {
0904: hasKey.setUniqueId(id);
0905: }
0906:
0907: //NodeModelDataFactory
0908: /* (non-Javadoc)
0909: * @see com.projity.grouping.core.DataFactory#createNode(java.lang.Object, java.lang.Object)
0910: */
0911: public Object createUnvalidatedObject(NodeModel nodeModel,
0912: Object parent) {
0913: NormalTask task = newStandaloneNormalTaskInstance();
0914: task.setWbsParent((Task) parent);
0915: return task;
0916: }
0917:
0918: public void addUnvalidatedObject(Object object,
0919: NodeModel nodeModel, Object parent) {
0920: if (!(object instanceof NormalTask))
0921: return;// avoids VoidNodes
0922: NormalTask task = (NormalTask) object;
0923: //task.getCurrentSchedule().setStart(getWorkCalendar().adjustInsideCalendar(task.getCurrentSchedule().getStart(),false));
0924: task.setWbsParent((Task) parent);
0925: task.setInSubproject(task.liesInSubproject());
0926:
0927: }
0928:
0929: public NodeModelDataFactory getFactoryToUseForChildOfParent(
0930: Object parent) {
0931: if (parent == null || !(parent instanceof Task))
0932: return this ;
0933: return ((Task) parent).getEnclosingProject();
0934: }
0935:
0936: /* (non-Javadoc)
0937: * @see com.projity.grouping.core.DataFactory#validateObject(java.lang.Object)
0938: */
0939: public void validateObject(Object newlyCreated,
0940: NodeModel nodeModel, Object eventSource,
0941: Object hierarchyInfo, boolean isNew) {
0942: if (!(newlyCreated instanceof Task))
0943: return;// avoids VoidNodes
0944: Task newTask = (Task) newlyCreated;
0945: newTask.setProject((Project) getSchedulingAlgorithm()
0946: .getMasterDocument());
0947: newTask.setOwningProject(this );
0948:
0949: connectTask(newTask); // put task in project list
0950: taskOutlines.addToAll(newlyCreated, nodeModel); // update all node models except the one passed in
0951: Task parentTask = newTask.getWbsParentTask();
0952: Node parentNode = (parentTask == null) ? null : nodeModel
0953: .search(newTask.getWbsParentTask());
0954: Node childNode = nodeModel.search(newTask);
0955: setDefaultRelationship(parentNode, childNode);
0956: newTask.markTaskAsNeedingRecalculation();
0957: updateScheduling(this , newlyCreated, ObjectEvent.CREATE);
0958: //objectEventManager.fireCreateEvent(eventSource,newlyCreated,hierarchyInfo);
0959:
0960: }
0961:
0962: public void updateScheduling(Object source, Object newlyCreated,
0963: int type) {
0964: ObjectEvent evt = ObjectEvent.getInstance(source, newlyCreated,
0965: type, null);
0966: getSchedulingAlgorithm().objectChanged(evt);
0967: evt.recycle();
0968: }
0969:
0970: public void updateScheduling(Object source, Object newlyCreated,
0971: int type, Field field) {
0972: ObjectEvent evt = ObjectEvent.getInstance(source, newlyCreated,
0973: type, null);
0974: evt.setField(field);
0975: getSchedulingAlgorithm().objectChanged(evt);
0976: evt.recycle();
0977: }
0978:
0979: /* (non-Javadoc)
0980: * @see com.projity.grouping.core.DataFactory#remove(java.lang.Object)
0981: */
0982: public void remove(Object toRemove, NodeModel nodeModel,
0983: boolean deep, boolean undo, boolean cleanDependencies) {
0984: Object eventSource = nodeModel;
0985: if (!(toRemove instanceof Task))
0986: return; // avoid VoidNodes
0987: Task task = (Task) toRemove;
0988: Project owningProject = task.getOwningProject();
0989: if (owningProject != this ) {
0990: owningProject.taskOutlines.removeFromAll(toRemove, null);
0991: owningProject.tasks.remove(task);
0992: }
0993: task.cleanUp(/*null*/eventSource, deep, undo,
0994: cleanDependencies); //lc
0995: tasks.remove(task);
0996: taskOutlines.removeFromAll(task, nodeModel); // update all node models except the one passed in
0997: objectEventManager.fireDeleteEvent(eventSource, task);
0998: }
0999:
1000: /* (non-Javadoc)
1001: * @see com.projity.grouping.core.DataFactory#remove(java.lang.Object)
1002: */
1003: public void removeExternal(Task toRemove) {
1004: // removeStartSentinelDependency(toRemove);
1005: // removeEndSentinelDependency(toRemove);
1006: tasks.remove(toRemove);
1007: taskOutlines.removeFromAll(toRemove, null); // update all node models except the one passed in
1008: objectEventManager.fireDeleteEvent(this , toRemove);
1009: }
1010:
1011: public void saveCurrentToSnapshot(Object snapshotId,
1012: boolean entireProject, List selection, boolean undo) {
1013: if (entireProject)
1014: forTasks(new SnapshottableImpl.SaveCurrentToSnapshotClosure(
1015: snapshotId));
1016: else
1017: CollectionUtils.forAllDo(selection,
1018: new SnapshottableImpl.SaveCurrentToSnapshotClosure(
1019: snapshotId));
1020:
1021: fireBaselineChanged(this , null, (Integer) snapshotId, true);
1022:
1023: if (undo) {
1024: UndoableEditSupport undoableEditSupport = getUndoController()
1025: .getEditSupport();
1026: if (undoableEditSupport != null) {
1027: undoableEditSupport.postEdit(new SaveSnapshotEdit(this ,
1028: snapshotId, entireProject, selection));
1029: }
1030: }
1031:
1032: }
1033:
1034: public void restoreSnapshot(Object snapshotId,
1035: boolean entireProject, List selection,
1036: Collection snapshotDetails) {
1037: Iterator i;
1038: if (entireProject)
1039: i = getTaskOutlineIterator();
1040: else {
1041: if (selection == null)
1042: return;
1043: i = selection.iterator();
1044: }
1045:
1046: Iterator j = snapshotDetails.iterator();
1047: while (i.hasNext()) {
1048: NormalTask t = (NormalTask) i.next();
1049: t.restoreSnapshot(snapshotId, j.next());
1050: }
1051: fireBaselineChanged(this , null, (Integer) snapshotId, true);
1052: }
1053:
1054: public void clearSnapshot(final Object snapshotId,
1055: boolean entireProject, List selection, boolean undo) {
1056: Iterator i;
1057: if (entireProject)
1058: i = getTaskOutlineIterator();
1059: else
1060: i = selection == null ? null : selection.iterator();
1061:
1062: final Collection snapshotDetails;
1063: final boolean[] foundSnapshot = new boolean[1]; //no undo edit of there is no snapshot
1064: if (undo && i != null && i.hasNext()) {
1065: snapshotDetails = new ArrayList();
1066: while (i.hasNext()) {
1067: NormalTask t = (NormalTask) i.next();
1068: TaskBackup taskBackup = (TaskBackup) t
1069: .backupDetail(snapshotId);
1070: if (taskBackup.snapshot != null)
1071: foundSnapshot[0] = true;
1072: snapshotDetails.add(taskBackup);
1073: }
1074: } else
1075: snapshotDetails = null;
1076:
1077: if (entireProject)
1078: forTasks(new SnapshottableImpl.ClearSnapshotClosure(
1079: snapshotId));
1080: else
1081: CollectionUtils.forAllDo(selection,
1082: new SnapshottableImpl.ClearSnapshotClosure(
1083: snapshotId));
1084: // FieldEvent.fire(this, Configuration.getFieldFromId("Field.baseline" + snapshotId + "Cost"), null);
1085: fireBaselineChanged(this , null, (Integer) snapshotId, false);
1086:
1087: if (foundSnapshot[0]) {
1088: UndoableEditSupport undoableEditSupport = getUndoController()
1089: .getEditSupport();
1090: if (undoableEditSupport != null) {
1091: undoableEditSupport.postEdit(new ClearSnapshotEdit(
1092: this , snapshotId, entireProject, selection,
1093: snapshotDetails));
1094: }
1095: }
1096:
1097: }
1098:
1099: /**
1100: * @param context
1101: * @return
1102: */
1103: public String getName(FieldContext context) {
1104: return hasKey.getName(context);
1105: }
1106:
1107: public String toString() {
1108: return getName();
1109: }
1110:
1111: /**
1112: * @param listener
1113: */
1114: public void addScheduleListener(ScheduleEventListener listener) {
1115: scheduleEventManager.addListener(listener);
1116: }
1117:
1118: /**
1119: * @param listener
1120: */
1121: public void removeScheduleListener(ScheduleEventListener listener) {
1122: scheduleEventManager.removeListener(listener);
1123: }
1124:
1125: /**
1126: * @param listener
1127: */
1128: public void addObjectListener(ObjectEvent.Listener listener) {
1129: objectEventManager.addListener(listener);
1130: }
1131:
1132: /**
1133: * @param listener
1134: */
1135: public void removeObjectListener(ObjectEvent.Listener listener) {
1136: objectEventManager.removeListener(listener);
1137: }
1138:
1139: public ObjectEventManager getObjectEventManager() {
1140: return objectEventManager;
1141: }
1142:
1143: public void fireScheduleChanged(Object source, String type) {
1144: scheduleEventManager.fire(source, type);
1145: }
1146:
1147: public void fireScheduleChanged(Object source, String type,
1148: Object object) {
1149: scheduleEventManager.fire(source, type, object);
1150: }
1151:
1152: public void fireBaselineChanged(Object source, Object object,
1153: Integer baselineNumber, boolean save) {
1154: scheduleEventManager.fireBaselineChanged(source, null,
1155: baselineNumber, save);
1156: }
1157:
1158: /* (non-Javadoc)
1159: * @see com.projity.pm.task.BelongsToDocument#getDocument()
1160: */
1161: public Document getDocument() {
1162: return this ;
1163: }
1164:
1165: /* (non-Javadoc)
1166: * @see com.projity.pm.assignment.HasTimeDistributedData#buildReverseQuery(com.projity.algorithm.ReverseQuery)
1167: */
1168: public void buildReverseQuery(ReverseQuery reverseQuery) {
1169: Iterator i = tasks.iterator();
1170: while (i.hasNext()) {
1171: ((Task) i.next()).buildReverseQuery(reverseQuery);
1172: }
1173: }
1174:
1175: /* (non-Javadoc)
1176: * @see com.projity.pm.assignment.HasTimeDistributedData#forEachWorkingInterval(org.apache.commons.collections.Closure, boolean)
1177: */
1178: public void forEachWorkingInterval(Closure visitor,
1179: boolean mergeWorking, WorkCalendar workCalendar) {
1180: Iterator i = tasks.iterator();
1181: while (i.hasNext()) {
1182: ((Task) i.next()).forEachWorkingInterval(visitor,
1183: mergeWorking, workCalendar);
1184: }
1185: }
1186:
1187: /* (non-Javadoc)
1188: * @see com.projity.pm.costing.EarnedValueValues#acwp(long, long)
1189: */
1190: public double acwp(long start, long end) {
1191: return TimeDistributedDataConsolidator.acwp(start, end,
1192: childrenToRollup());
1193: }
1194:
1195: /* (non-Javadoc)
1196: * @see com.projity.pm.costing.EarnedValueValues#bac(long, long)
1197: */
1198: public double bac(long start, long end) {
1199: return TimeDistributedDataConsolidator.bac(start, end,
1200: childrenToRollup());
1201: }
1202:
1203: /* (non-Javadoc)
1204: * @see com.projity.pm.costing.EarnedValueValues#bcwp(long, long)
1205: */
1206: public double bcwp(long start, long end) {
1207: return TimeDistributedDataConsolidator.bcwp(start, end,
1208: childrenToRollup());
1209: }
1210:
1211: /* (non-Javadoc)
1212: * @see com.projity.pm.costing.EarnedValueValues#bcws(long, long)
1213: */
1214: public double bcws(long start, long end) {
1215: return TimeDistributedDataConsolidator.bcws(start, end,
1216: childrenToRollup());
1217: }
1218:
1219: /* (non-Javadoc)
1220: * @see com.projity.pm.assignment.HasTimeDistributedData#cost(long, long)
1221: */
1222: public double baselineCost(long start, long end) {
1223: return TimeDistributedDataConsolidator.baselineCost(start, end,
1224: childrenToRollup());
1225: }
1226:
1227: /* (non-Javadoc)
1228: * @see com.projity.pm.assignment.HasTimeDistributedData#cost(long, long)
1229: */
1230: public long baselineWork(long start, long end) {
1231: return TimeDistributedDataConsolidator.baselineWork(start, end,
1232: childrenToRollup(), true);
1233: }
1234:
1235: /* (non-Javadoc)
1236: * @see com.projity.pm.assignment.HasTimeDistributedData#cost(long, long)
1237: */
1238: public double cost(long start, long end) {
1239: return TimeDistributedDataConsolidator.cost(start, end,
1240: childrenToRollup());
1241: }
1242:
1243: /* (non-Javadoc)
1244: * @see com.projity.pm.assignment.HasTimeDistributedData#actualCost(long, long)
1245: */
1246: public double actualCost(long start, long end) {
1247: return TimeDistributedDataConsolidator.actualCost(start, end,
1248: childrenToRollup());
1249: }
1250:
1251: public double fixedCost(long start, long end) {
1252: return TimeDistributedDataConsolidator.fixedCost(start, end,
1253: childrenToRollup());
1254: }
1255:
1256: public double actualFixedCost(long start, long end) {
1257: return TimeDistributedDataConsolidator.actualFixedCost(start,
1258: end, childrenToRollup());
1259: }
1260:
1261: public boolean fieldHideActualFixedCost(FieldContext fieldContext) {
1262: return false;
1263: }
1264:
1265: /* (non-Javadoc)
1266: * @see com.projity.pm.assignment.HasTimeDistributedData#work(long, long)
1267: */
1268: public long work(long start, long end) {
1269: return TimeDistributedDataConsolidator.work(start, end,
1270: childrenToRollup(), true);
1271: }
1272:
1273: /* (non-Javadoc)
1274: * @see com.projity.pm.assignment.HasTimeDistributedData#actualWork(long, long)
1275: */
1276: public long actualWork(long start, long end) {
1277: return TimeDistributedDataConsolidator.actualWork(start, end,
1278: childrenToRollup(), true);
1279: }
1280:
1281: /* (non-Javadoc)
1282: * @see com.projity.pm.assignment.HasTimeDistributedData#actualWork(long, long)
1283: */
1284: public long remainingWork(long start, long end) {
1285: return TimeDistributedDataConsolidator.remainingWork(start,
1286: end, childrenToRollup(), true);
1287: }
1288:
1289: boolean isInRange(long start, long finish) {
1290: long s = getStart();
1291: return (finish > s && start < getEnd());
1292: }
1293:
1294: private boolean isFieldHidden(FieldContext fieldContext) {
1295: return fieldContext != null
1296: && !isInRange(fieldContext.getStart(), fieldContext
1297: .getEnd());
1298: }
1299:
1300: public boolean fieldHideCost(FieldContext fieldContext) {
1301: return isFieldHidden(fieldContext);
1302: }
1303:
1304: public boolean fieldHideWork(FieldContext fieldContext) {
1305: return isFieldHidden(fieldContext);
1306: }
1307:
1308: public boolean fieldHideActualCost(FieldContext fieldContext) {
1309: return isFieldHidden(fieldContext);
1310: }
1311:
1312: public boolean fieldHideActualWork(FieldContext fieldContext) {
1313: return isFieldHidden(fieldContext);
1314: }
1315:
1316: public boolean fieldHideBaselineCost(int numBaseline,
1317: FieldContext fieldContext) {
1318: return false; //TODO implement
1319: }
1320:
1321: public boolean fieldHideBaselineWork(int numBaseline,
1322: FieldContext fieldContext) {
1323: return false; //TODO implement
1324: }
1325:
1326: public boolean fieldHideAcwp(FieldContext fieldContext) {
1327: return isFieldHidden(fieldContext);
1328: }
1329:
1330: public boolean fieldHideBac(FieldContext fieldContext) {
1331: return isFieldHidden(fieldContext);
1332: }
1333:
1334: public boolean fieldHideBcwp(FieldContext fieldContext) {
1335: return isFieldHidden(fieldContext);
1336: }
1337:
1338: public boolean fieldHideBcws(FieldContext fieldContext) {
1339: return isFieldHidden(fieldContext);
1340: }
1341:
1342: public boolean fieldHideCv(FieldContext fieldContext) {
1343: return isFieldHidden(fieldContext);
1344: }
1345:
1346: public boolean fieldHideSv(FieldContext fieldContext) {
1347: return isFieldHidden(fieldContext);
1348: }
1349:
1350: public boolean fieldHideEac(FieldContext fieldContext) {
1351: return isFieldHidden(fieldContext);
1352: }
1353:
1354: public boolean fieldHideVac(FieldContext fieldContext) {
1355: return isFieldHidden(fieldContext);
1356: }
1357:
1358: public boolean fieldHideCpi(FieldContext fieldContext) {
1359: return isFieldHidden(fieldContext);
1360: }
1361:
1362: public boolean fieldHideSpi(FieldContext fieldContext) {
1363: return isFieldHidden(fieldContext);
1364: }
1365:
1366: public boolean fieldHideCvPercent(FieldContext fieldContext) {
1367: return isFieldHidden(fieldContext);
1368: }
1369:
1370: public boolean fieldHideSvPercent(FieldContext fieldContext) {
1371: return isFieldHidden(fieldContext);
1372: }
1373:
1374: public boolean fieldHideTcpi(FieldContext fieldContext) {
1375: return isFieldHidden(fieldContext);
1376: }
1377:
1378: public double getCost(FieldContext fieldContext) {
1379: return getFixedCost(fieldContext)
1380: + cost(FieldContext.start(fieldContext), FieldContext
1381: .end(fieldContext));
1382: }
1383:
1384: public double getFixedCost(FieldContext fieldContext) {
1385: return fixedCost(FieldContext.start(fieldContext), FieldContext
1386: .end(fieldContext));
1387: }
1388:
1389: public double getActualFixedCost(FieldContext fieldContext) {
1390: return actualFixedCost(FieldContext.start(fieldContext),
1391: FieldContext.end(fieldContext));
1392: }
1393:
1394: public long getWork(FieldContext fieldContext) {
1395: return work(FieldContext.start(fieldContext), FieldContext
1396: .end(fieldContext));
1397: }
1398:
1399: public double getActualCost(FieldContext fieldContext) {
1400: return getActualFixedCost(fieldContext)
1401: + actualCost(FieldContext.start(fieldContext),
1402: FieldContext.end(fieldContext));
1403: }
1404:
1405: public long getActualWork(FieldContext fieldContext) {
1406: return actualWork(FieldContext.start(fieldContext),
1407: FieldContext.end(fieldContext));
1408: }
1409:
1410: public long getRemainingWork(FieldContext fieldContext) {
1411: return remainingWork(FieldContext.start(fieldContext),
1412: FieldContext.end(fieldContext));
1413: }
1414:
1415: public double getRemainingCost(FieldContext fieldContext) {
1416: return getCost(fieldContext) - getActualCost(fieldContext);
1417: }
1418:
1419: public double getBaselineCost(FieldContext fieldContext) {
1420: return baselineCost(FieldContext.start(fieldContext),
1421: FieldContext.end(fieldContext));
1422: }
1423:
1424: public long getBaselineWork(FieldContext fieldContext) {
1425: return baselineWork(FieldContext.start(fieldContext),
1426: FieldContext.end(fieldContext));
1427: }
1428:
1429: public void nodeRemoved(HierarchyEvent e) {
1430:
1431: }
1432:
1433: public double getAcwp(FieldContext fieldContext) {
1434: return acwp(FieldContext.start(fieldContext), FieldContext
1435: .end(fieldContext));
1436: }
1437:
1438: public double getBac(FieldContext fieldContext) {
1439: return bac(FieldContext.start(fieldContext), FieldContext
1440: .end(fieldContext));
1441: }
1442:
1443: public double getBcwp(FieldContext fieldContext) {
1444: return bcwp(FieldContext.start(fieldContext), FieldContext
1445: .end(fieldContext));
1446: }
1447:
1448: public double getBcws(FieldContext fieldContext) {
1449: return bcws(FieldContext.start(fieldContext), FieldContext
1450: .end(fieldContext));
1451: }
1452:
1453: public double getCv(FieldContext fieldContext) {
1454: return EarnedValueCalculator.getInstance().cv(this ,
1455: FieldContext.start(fieldContext),
1456: FieldContext.end(fieldContext));
1457: }
1458:
1459: public double getSv(FieldContext fieldContext) {
1460: return EarnedValueCalculator.getInstance().sv(this ,
1461: FieldContext.start(fieldContext),
1462: FieldContext.end(fieldContext));
1463: }
1464:
1465: public double getEac(FieldContext fieldContext) {
1466: return EarnedValueCalculator.getInstance().eac(this ,
1467: FieldContext.start(fieldContext),
1468: FieldContext.end(fieldContext));
1469: }
1470:
1471: public double getVac(FieldContext fieldContext) {
1472: return EarnedValueCalculator.getInstance().vac(this ,
1473: FieldContext.start(fieldContext),
1474: FieldContext.end(fieldContext));
1475: }
1476:
1477: public double getCpi(FieldContext fieldContext) {
1478: return EarnedValueCalculator.getInstance().cpi(this ,
1479: FieldContext.start(fieldContext),
1480: FieldContext.end(fieldContext));
1481: }
1482:
1483: public double getSpi(FieldContext fieldContext) {
1484: return EarnedValueCalculator.getInstance().spi(this ,
1485: FieldContext.start(fieldContext),
1486: FieldContext.end(fieldContext));
1487: }
1488:
1489: public double getCsi(FieldContext fieldContext) {
1490: return EarnedValueCalculator.getInstance().csi(this ,
1491: FieldContext.start(fieldContext),
1492: FieldContext.end(fieldContext));
1493: }
1494:
1495: public double getCvPercent(FieldContext fieldContext) {
1496: return EarnedValueCalculator.getInstance().cvPercent(this ,
1497: FieldContext.start(fieldContext),
1498: FieldContext.end(fieldContext));
1499: }
1500:
1501: public double getSvPercent(FieldContext fieldContext) {
1502: return EarnedValueCalculator.getInstance().svPercent(this ,
1503: FieldContext.start(fieldContext),
1504: FieldContext.end(fieldContext));
1505: }
1506:
1507: public double getTcpi(FieldContext fieldContext) {
1508: return EarnedValueCalculator.getInstance().tcpi(this ,
1509: FieldContext.start(fieldContext),
1510: FieldContext.end(fieldContext));
1511: }
1512:
1513: /* (non-Javadoc)
1514: * @see com.projity.pm.assignment.HasTimeDistributedData#childrenToRollup()
1515: */
1516: public Collection childrenToRollup() {
1517: return tasks;
1518: }
1519:
1520: public String getSchedulingMethod() {
1521: return schedulingAlgorithm.getName();
1522: }
1523:
1524: //TODO other baselines
1525: public double getBaselineCost(int numBaseline,
1526: FieldContext fieldContext) {
1527: return baselineCost(FieldContext.start(fieldContext),
1528: FieldContext.end(fieldContext));
1529: }
1530:
1531: /* (non-Javadoc)
1532: * @see com.projity.pm.assignment.TimeDistributedFields#getBaselineWork(int, com.projity.field.FieldContext)
1533: */
1534: public long getBaselineWork(int numBaseline,
1535: FieldContext fieldContext) {
1536: return baselineWork(FieldContext.start(fieldContext),
1537: FieldContext.end(fieldContext));
1538: }
1539:
1540: /**
1541: * @param initialized The initialized to set.
1542: */
1543: public void setInitialized(boolean initialized) {
1544: this .initialized = initialized;
1545: }
1546:
1547: public void nodesChanged(HierarchyEvent e) {
1548: // System.out.println("Node changed ...");
1549: // if ("NO_PROJECT_UPDATE".equals(e.getFlag())) return;
1550: Node node, previousParentNode, newParentNode;
1551: Task task, previousParentTask, newParentTask;
1552: int count = e.getNodes().length;
1553: if (count == 0)
1554: return;
1555: for (int i = 0; i < count; i++) {
1556: node = (Node) e.getNodes()[i];
1557: if (!(node.getImpl() instanceof Task))
1558: continue;
1559: task = (Task) node.getImpl();
1560:
1561: //TODO verify that this is ok when pasting for bug 426
1562: // task.setProject((Project) getSchedulingAlgorithm().getMasterDocument());
1563: // task.setOwningProject(this);
1564: //moved to validateObject
1565:
1566: previousParentTask = task.getWbsParentTask();
1567: previousParentNode = taskOutlines.getDefaultOutline()
1568: .search(previousParentTask);
1569:
1570: // refresh the previous parent's children
1571: if (previousParentTask != null) {
1572: previousParentTask
1573: .markAllDependentTasksAsNeedingRecalculation(true); // flag this and dependent tasks as dirty
1574: previousParentTask.setWbsChildrenNodes(taskOutlines
1575: .getDefaultOutline().getHierarchy()
1576: .getChildren(previousParentNode));
1577: }
1578:
1579: // refresh the new parent's children
1580: NodeHierarchy hierarchy = taskOutlines.getDefaultOutline()
1581: .getHierarchy();
1582: newParentNode = hierarchy.getParent(node);
1583: newParentTask = null;
1584: if (newParentNode != hierarchy.getRoot()) {
1585: newParentTask = (Task) newParentNode.getImpl();
1586: newParentTask.setWbsChildrenNodes(taskOutlines
1587: .getDefaultOutline().getHierarchy()
1588: .getChildren(newParentNode));
1589: newParentTask.restrictToValidConstraintType();
1590: // newParentTask.setParentDuration(); //hk
1591: newParentTask
1592: .markAllDependentTasksAsNeedingRecalculation(true); // flag this and dependent tasks as dirty
1593: }
1594:
1595: //refresh this node to point to new parent
1596: task.setWbsParent(newParentTask);
1597:
1598: final Task _newParentTask = newParentTask;
1599: final Object eventSource = e.getSource();
1600:
1601: // recursively remove all dependencies between new parent and any children, grandchildren, etc.
1602: taskOutlines.getDefaultOutline().getHierarchy().visitAll(
1603: newParentNode, new Closure() {
1604: public void execute(Object arg) {
1605: Node node = (Node) arg;
1606: if (!(node.getImpl() instanceof Task))
1607: return;
1608: Task task = (Task) node.getImpl();
1609: DependencyService
1610: .getInstance()
1611: .removeAnyDependencies(task,
1612: _newParentTask, eventSource);
1613: }
1614: });
1615: }
1616: if (!e.isVoid()) { // if the event was not the promotion of a void node
1617: // The critical path needs resetting because its internal list must be rebuilt as it depends on hierarchy
1618: // objectEventManager.fireUpdateEvent(e.getSource(),this);
1619: e.consume();
1620: updateScheduling(e.getSource(), this , ObjectEvent.CREATE); // will cause critical path to reset and to run and send schedule events
1621: }
1622: }
1623:
1624: public void nodesInserted(HierarchyEvent e) {
1625: nodesChanged(e);
1626: }
1627:
1628: public void nodesRemoved(HierarchyEvent e) {
1629: }
1630:
1631: public void structureChanged(HierarchyEvent e) {
1632: }
1633:
1634: public List getRootNodes(List tasks) {
1635: List roots = new LinkedList();
1636: for (Iterator i = tasks.iterator(); i.hasNext();) {
1637: Task task = (Task) i.next();
1638: if (task.getWbsParentTask() == null)
1639: roots
1640: .add(taskOutlines.getDefaultOutline().search(
1641: task));
1642: }
1643: return roots;
1644: }
1645:
1646: public void dump(Collection tasks, String indent) {
1647: if (tasks != null)
1648: for (Iterator i = tasks.iterator(); i.hasNext();) {
1649: Node node = (Node) i.next();
1650: Task task = (Task) node.getImpl();
1651: System.out.println(indent + task.getWbsParentTask()
1652: + "->" + task);
1653: dump(task.getWbsChildrenNodes(), indent + "-");
1654: }
1655: }
1656:
1657: /*
1658: public void clearDuration() {
1659: schedule.clearDuration();
1660: }
1661: public long getDurationActive() {
1662: return schedule.getDurationActive();
1663: }
1664: public long getDurationSpan() {
1665: return schedule.getDurationSpan();
1666: }
1667: public double getPercentComplete() {
1668: return schedule.getPercentComplete();
1669: }
1670: public void setDurationActive(long durationActive) {
1671: schedule.setDurationActive(durationActive);
1672: }
1673: public void setDurationSpan(long durationSpan) {
1674: schedule.setDurationSpan(durationSpan);
1675: }
1676: public void setPercentComplete(double percentComplete) {
1677: schedule.setPercentComplete(percentComplete);
1678: }
1679: public long getDependencyStart() {
1680: return schedule.getDependencyStart();
1681: }
1682: public void setDependencyStart(long dependencyStart) {
1683: schedule.setDependencyStart(dependencyStart);
1684: }
1685: */
1686:
1687: private transient BarClosure barClosureInstance = new BarClosure();
1688:
1689: public void moveInterval(Object eventSource, long start, long end,
1690: ScheduleInterval oldInterval) {
1691: if (start != oldInterval.getStart())
1692: setStart(start); // allow for changing start of subproject. need to add test for actuals
1693: }
1694:
1695: /* (non-Javadoc)
1696: * @see com.projity.pm.scheduling.Schedule#consumeIntervals(com.projity.functor.IntervalConsumer)
1697: */
1698: public void consumeIntervals(IntervalConsumer consumer) {
1699: consumer.consumeInterval(new ScheduleInterval(getStart(),
1700: getEnd()));
1701: }
1702:
1703: public boolean equals(Object obj) {
1704: if (obj instanceof DataObject) {
1705: return getName().equals(((DataObject) obj).getName());
1706: }
1707: return false;
1708: }
1709:
1710: Workspace workspace;
1711:
1712: private void writeObject(ObjectOutputStream s) throws IOException {
1713: workspace = (Workspace) createWorkspace(SavableToWorkspace.PERSIST);
1714: s.defaultWriteObject();
1715: hasKey.serialize(s);
1716: }
1717:
1718: private void readObject(ObjectInputStream s) throws IOException,
1719: ClassNotFoundException {
1720: s.defaultReadObject();
1721: hasKey = HasKeyImpl.deserialize(s, this );
1722: //initUndo();
1723: tasks = new LinkedList();
1724: objectEventManager = new ObjectEventManager();
1725: scheduleEventManager = new ScheduleEventManager();
1726: multipleTransactionManager = new MultipleTransactionManager();
1727: projectListenerList = new EventListenerList();
1728: taskOutlines = new OutlineCollectionImpl(Settings
1729: .numHierarchies(), this );
1730: barClosureInstance = new BarClosure();
1731:
1732: }
1733:
1734: private void initSubprojectHandler() {
1735: try {
1736: subprojectHandler = (SubprojectHandler) Class.forName(
1737: Messages.getMetaString("SubprojectHandler"))
1738: .getConstructor(new Class[] { Project.class })
1739: .newInstance(this );
1740: } catch (Exception e) {
1741: e.printStackTrace();
1742: System.out
1743: .println("SubprojectHandler not valid in meta.properties");
1744: System.exit(-1);
1745: }
1746: }
1747:
1748: public void postDeserialization() {
1749: initSubprojectHandler(); //this is created transiently
1750: setSchedulingAlgorithm(new CriticalPath(this )); // Critical path needs objectEventManager
1751:
1752: int count = Settings.numHierarchies();
1753: for (int i = 0; i < count; i++) {
1754: NodeModel model = taskOutlines.getOutline(i);
1755: if (model == null)
1756: continue;
1757: if (model instanceof AssignmentNodeModel) {
1758: AssignmentNodeModel aModel = (AssignmentNodeModel) model;
1759: aModel.setContainsLeftObjects(true);
1760: aModel.setDocument(this );
1761: }
1762: model.setUndoController(undoController);
1763: }
1764:
1765: //setEnd(getStart());
1766: //setInitialized(true);
1767: //initialize();
1768: initializeDefaultOutline();
1769: setInitialized(true);
1770: setGroupDirty(false);
1771: if (workspace != null)
1772: restoreWorkspace(workspace, SavableToWorkspace.PERSIST);
1773: }
1774:
1775: public void addEndSentinelDependency(Task task) {
1776: if (!task.isInSubproject()) // subprojects have fixed dates, and their children do not depend on master project's sentinels
1777: schedulingAlgorithm.addEndSentinelDependency(task);
1778: }
1779:
1780: public boolean removeEndSentinelDependency(Task task) {
1781: if (!task.isInSubproject()) // subprojects have fixed dates, and their children do not depend on master project's sentinels
1782: return schedulingAlgorithm
1783: .removeEndSentinelDependency(task);
1784: return false;
1785: }
1786:
1787: public void addStartSentinelDependency(Task task) {
1788: if (!task.isInSubproject()) // subprojects have fixed dates, and their children do not depend on master project's sentinels
1789: schedulingAlgorithm.addStartSentinelDependency(task);
1790: }
1791:
1792: public boolean removeStartSentinelDependency(Task task) {
1793: if (!task.isInSubproject()) // subprojects have fixed dates, and their children do not depend on master project's sentinels
1794: return schedulingAlgorithm
1795: .removeStartSentinelDependency(task);
1796: return false;
1797: }
1798:
1799: /**
1800: * @param date
1801: */
1802: public void setEndConstraint(long date) {
1803: schedulingAlgorithm.setEndConstraint(date);
1804: }
1805:
1806: /**
1807: * @param date
1808: */
1809: public void setStartConstraint(long date) {
1810: // System.out.println("setStartConstraint " + new Date(date));
1811: schedulingAlgorithm.setStartConstraint(date);
1812: }
1813:
1814: /**
1815: * @return Returns the forward.
1816: */
1817: public boolean isForward() {
1818: return forward;
1819: }
1820:
1821: /**
1822: * @param forward The forward to set.
1823: */
1824: public void setForward(boolean forward) {
1825: if (forward == this .forward)
1826: return;
1827: this .forward = forward;
1828: Iterator i = tasks.iterator();
1829: // update all of the tasks schedules to reflect their scheduling direction
1830: while (i.hasNext()) {
1831: ((Task) i.next()).setForward(forward);
1832: }
1833: markAllTasksAsNeedingRecalculation(false);
1834: schedulingAlgorithm.setForward(forward);
1835: schedulingAlgorithm.reset();
1836: schedulingAlgorithm.calculate(true);
1837: }
1838:
1839: public void fireUpdateEvent(Object source, Object object) {
1840: if (isInitialized())
1841: objectEventManager.fireUpdateEvent(source, object);
1842: }
1843:
1844: int getCalculationStateCount() {
1845: if (schedulingAlgorithm == null)
1846: return 0;
1847: return schedulingAlgorithm.getCalculationStateCount();
1848: }
1849:
1850: /**
1851: * @return Returns the multipleTransactionManager.
1852: */
1853: public final MultipleTransactionManager getMultipleTransactionManager() {
1854: return multipleTransactionManager;
1855: }
1856:
1857: /* (non-Javadoc)
1858: * @see com.projity.document.Document#fireMultipleTransaction(int, boolean)
1859: */
1860: public int fireMultipleTransaction(int id, boolean begin) {
1861: return multipleTransactionManager.fire(this , id, begin);
1862: }
1863:
1864: /**
1865: * When opening a project or just after saving, need to put all tasks back to their undirty state.
1866: * This means the task is considered as being untouched since the last save.
1867: *
1868: */
1869: public void setAllTasksAsUnchangedFromPersisted() {
1870: Iterator i = tasks.iterator();
1871: NormalTask task;
1872: // update all of the tasks schedules to reflect their scheduling direction
1873: while (i.hasNext()) {
1874: task = (NormalTask) i.next();
1875: task.setDirty(false);
1876: task.setLastSavedStart(task.getStart()); //
1877: task.setLastSavedFinish(task.getEnd());
1878: Iterator j = task.getAssignments().iterator();
1879: while (j.hasNext())
1880: ((Assignment) j.next()).setDirty(false);
1881: }
1882: }
1883:
1884: public void markAllTasksAsNeedingRecalculation(
1885: boolean invalidateSchedules) {
1886: int nextStateCount = getCalculationStateCount() + 1;
1887: Iterator i = tasks.iterator();
1888: Task task;
1889: // update all of the tasks schedules to reflect their scheduling direction
1890: while (i.hasNext()) {
1891: task = (Task) i.next();
1892: task.setCalculationStateCount(nextStateCount);
1893: if (invalidateSchedules)
1894: task.invalidateSchedules();
1895: }
1896: getSchedulingAlgorithm().initEarliestAndLatest();
1897: }
1898:
1899: public void setAllChildrenDirty(boolean dirty) { // used when changing field dirties all tasks
1900: Iterator i = tasks.iterator();
1901: Task task;
1902: while (i.hasNext()) {
1903: task = (Task) i.next();
1904: task.setDirty(dirty);
1905: }
1906: }
1907:
1908: int getDefaultConstraintType() {
1909: if (isForward())
1910: return ConstraintType.ASAP;
1911: else
1912: return ConstraintType.ALAP;
1913: }
1914:
1915: /* (non-Javadoc)
1916: * @see com.projity.document.Document#getDefaultCalendar()
1917: */
1918: public WorkCalendar getDefaultCalendar() {
1919: return getWorkCalendar();
1920: }
1921:
1922: // these fields are not modifiable
1923: public void setWork(long work, FieldContext fieldContext) {
1924: //do nothing
1925: }
1926:
1927: public void setRemainingWork(long work, FieldContext fieldContext) {
1928: //do nothing
1929: }
1930:
1931: public void setActualWork(long work, FieldContext fieldContext) {
1932: //do nothing
1933: }
1934:
1935: public SchedulingAlgorithm getSchedulingAlgorithm() {
1936: return schedulingAlgorithm;
1937: }
1938:
1939: public void setSchedulingAlgorithm(
1940: SchedulingAlgorithm schedulingAlgorithm) {
1941: if (this .schedulingAlgorithm != null) {
1942: removeObjectListener(this .schedulingAlgorithm);
1943: getMultipleTransactionManager().removeListener(
1944: this .schedulingAlgorithm);
1945: }
1946: this .schedulingAlgorithm = schedulingAlgorithm;
1947: addObjectListener(schedulingAlgorithm);
1948: getMultipleTransactionManager()
1949: .addListener(schedulingAlgorithm);
1950: }
1951:
1952: public boolean isReadOnlyWork(FieldContext fieldContext) {
1953: return true;
1954: }
1955:
1956: public boolean isReadOnlyActualWork(FieldContext fieldContext) {
1957: return true;
1958: }
1959:
1960: public boolean isReadOnlyRemainingWork(FieldContext fieldContext) {
1961: return true;
1962: }
1963:
1964: public void setFixedCost(double fixedCost, FieldContext fieldContext) {
1965: }
1966:
1967: public boolean isReadOnlyFixedCost(FieldContext fieldContext) {
1968: return true;
1969: }
1970:
1971: // public boolean isNew() {
1972: // return hasKey.isNew();
1973: // }
1974:
1975: /* (non-Javadoc)
1976: * @see com.projity.pm.assignment.HasTimeDistributedData#isLabor()
1977: */
1978: public boolean isLabor() {
1979: return true;
1980: }
1981:
1982: public final long getStartDate() {
1983: return getStart();
1984: }
1985:
1986: public final void setStartDate(long start) {
1987: start = getEffectiveWorkCalendar().adjustInsideCalendar(start,
1988: false);
1989: setStart(start);
1990: getSchedulingAlgorithm().setStartConstraint(start);
1991: }
1992:
1993: public final boolean isReadOnlyStartDate(FieldContext fieldContext) {
1994: return getSchedulingAlgorithm() == null
1995: || !getSchedulingAlgorithm().isForward();
1996: }
1997:
1998: public final long getFinishDate() {
1999: return getEnd();
2000: }
2001:
2002: /* (non-Javadoc)
2003: * @see com.projity.pm.task.ProjectSpecificFields#setFinishDate(long)
2004: */
2005: public void setFinishDate(long finish) {
2006: finish = getEffectiveWorkCalendar().adjustInsideCalendar(
2007: finish, true);
2008: setEnd(finish);
2009: getSchedulingAlgorithm().setEndConstraint(finish);
2010: }
2011:
2012: public boolean isReadOnlyFinishDate(FieldContext fieldContext) {
2013: return getSchedulingAlgorithm() == null
2014: || getSchedulingAlgorithm().isForward();
2015: }
2016:
2017: public final long getCurrentDate() {
2018: return currentDate;
2019: }
2020:
2021: public final void setCurrentDate(long currentDate) {
2022: this .currentDate = currentDate;
2023: }
2024:
2025: public long getBaselineStart(int numBaseline) {
2026: NormalTask task;
2027: long result = Long.MAX_VALUE;
2028: long val;
2029: for (Iterator i = tasks.iterator(); i.hasNext();) {
2030: task = (NormalTask) i.next();
2031: val = task.getBaselineStart(numBaseline);
2032: if (val != 0 && val < result)
2033: result = val;
2034: }
2035: if (result == Long.MAX_VALUE)
2036: result = 0;
2037: return result;
2038:
2039: }
2040:
2041: public long getBaselineFinish(int numBaseline) {
2042: NormalTask task;
2043: long result = 0;
2044: long val;
2045: for (Iterator i = tasks.iterator(); i.hasNext();) {
2046: task = (NormalTask) i.next();
2047: val = task.getBaselineFinish(numBaseline);
2048: if (val > result)
2049: result = val;
2050: }
2051: return result;
2052: }
2053:
2054: public long getBaselineDuration(int numBaseline) {
2055: // note that I am using the current calendar no matter what.
2056: return getEffectiveWorkCalendar().compare(
2057: getBaselineFinish(numBaseline),
2058: getBaselineStart(numBaseline), false);
2059: }
2060:
2061: public long getActualStart() {
2062: Task task;
2063: long result = Long.MAX_VALUE;
2064: long val;
2065: for (Iterator i = tasks.iterator(); i.hasNext();) {
2066: task = (Task) i.next();
2067: val = task.getActualStart();
2068: if (val != 0 && val < result)
2069: result = val;
2070: }
2071: if (result == Long.MAX_VALUE)
2072: result = 0;
2073: return result;
2074: }
2075:
2076: public void setActualStart(long actualStart) {
2077: }
2078:
2079: public long getActualFinish() {
2080: Task task;
2081: long result = 0;
2082: long val;
2083: for (Iterator i = tasks.iterator(); i.hasNext();) {
2084: task = (Task) i.next();
2085: val = task.getActualFinish();
2086: if (val == 0)
2087: break;
2088: if (val > result)
2089: result = val;
2090: }
2091: return result;
2092: }
2093:
2094: public long getStop() {
2095: Task task;
2096: long result = 0;
2097: long val;
2098: for (Iterator i = tasks.iterator(); i.hasNext();) {
2099: task = (Task) i.next();
2100: val = task.getStop();
2101: if (val == 0)
2102: return 0;
2103: if (val > result)
2104: result = val;
2105: }
2106: return result;
2107: }
2108:
2109: public long getEarliestStop() {
2110: Task task;
2111: long result = Long.MAX_VALUE;
2112: long val;
2113: for (Iterator i = tasks.iterator(); i.hasNext();) {
2114: task = (Task) i.next();
2115: val = task.getEarliestStop();
2116: if (val < result)
2117: result = val;
2118: if (val == 0)
2119: break;
2120: }
2121: if (result == Long.MAX_VALUE)
2122: result = 0;
2123: return result;
2124: }
2125:
2126: public void setActualFinish(long actualFinish) {
2127: }
2128:
2129: public long getActualDuration() {
2130: long stop = getStop();
2131: if (stop == 0)
2132: return 0;
2133: return getEffectiveWorkCalendar().compare(stop, getStartDate(),
2134: false);
2135: }
2136:
2137: public void setActualDuration(long actualDuration) {
2138: }
2139:
2140: public long getRemainingDuration() {
2141: long stop = getStop();
2142: if (stop == 0)
2143: stop = getStartDate();
2144: return getEffectiveWorkCalendar().compare(getFinishDate(),
2145: stop, false);
2146: }
2147:
2148: //TODO to avoid risks of breaking obfuscation, Project will implement all of Schedule for now
2149: public void setRemainingDuration(long remainingDuration) {
2150: }
2151:
2152: public double getPercentComplete() {
2153: Task task;
2154: long actual = 0L;
2155: long total = 0L;
2156: for (Iterator i = tasks.iterator(); i.hasNext();) {
2157: task = (Task) i.next();
2158: actual += Duration.millis(task.getActualDuration());
2159: total += Duration.millis(task.getDuration());
2160: }
2161: if (total == 0L)
2162: return 0D;
2163: else
2164: return ((double) actual) / total;
2165: }
2166:
2167: public void setPercentComplete(double percentComplete) {
2168: }
2169:
2170: public void setDuration(long duration) {
2171: }
2172:
2173: public long getElapsedDuration() {
2174: return Math.round(getEffectiveWorkCalendar().compare(getEnd(),
2175: getStart(), true)
2176: * CalendarOption.getInstance()
2177: .getFractionOfDayThatIsWorking());
2178: }
2179:
2180: public long getDependencyStart() {
2181: return 0;
2182: }
2183:
2184: public void setDependencyStart(long dependencyStart) {
2185: }
2186:
2187: public long getResume() {
2188: return 0;
2189: }
2190:
2191: public void setResume(long resume) {
2192: }
2193:
2194: public void setStop(long stop) {
2195: }
2196:
2197: public void clearDuration() {
2198: }
2199:
2200: public void moveRemainingToDate(long date) {
2201: }
2202:
2203: public void moveInterval(Object eventSource, long start, long end,
2204: ScheduleInterval oldInterval, boolean isChild) {
2205: }
2206:
2207: /* (non-Javadoc)
2208: * @see com.projity.pm.scheduling.Schedule#split(java.lang.Object, long, long)
2209: */
2210: public void split(Object eventSource, long from, long to) {
2211: // TODO Auto-generated method stub
2212:
2213: }
2214:
2215: public final boolean isDirty() {
2216: return isDirty;
2217: }
2218:
2219: public final void setDirty(boolean isDirty) {
2220: this .isDirty = isDirty;
2221: if (isDirty)
2222: setGroupDirty(true);
2223: }
2224:
2225: public final boolean isGroupDirty() {
2226: return isGroupDirty;
2227: }
2228:
2229: public final void setGroupDirty(boolean isGroupDirty) {
2230: boolean old = this .isGroupDirty;
2231: this .isGroupDirty = isGroupDirty;
2232: if (old != isGroupDirty) {
2233: // System.out.println("Project["+hashCode()+"].setGroupDirty("+isGroupDirty+")");
2234: fireGroupDirtyChanged(this , old);
2235: }
2236: }
2237:
2238: //Undo
2239: protected transient DataFactoryUndoController undoController;
2240:
2241: // protected void initUndo(){
2242: // undoController=new DataFactoryUndoController(this);
2243: // }
2244: public DataFactoryUndoController getUndoController() {
2245: return undoController;
2246: }
2247:
2248: public void setUndoController(
2249: DataFactoryUndoController undoController) {
2250: this .undoController = undoController;
2251: if (undoController != null)
2252: undoController.setDataFactory(this );
2253: }
2254:
2255: public static Predicate instanceof Predicate() {
2256: return new Predicate() {
2257: public boolean evaluate(Object arg0) {
2258: return arg0 instanceof Project;
2259: }
2260: };
2261: }
2262:
2263: public void addPastedTask(Task task) {
2264: getSchedulingAlgorithm().addObject(task);
2265: }
2266:
2267: /* (non-Javadoc)
2268: * @see com.projity.pm.calendar.HasCalendar#invalidateCalendar()
2269: */
2270: public Document invalidateCalendar() {
2271: markAllTasksAsNeedingRecalculation(false);
2272: return this ;
2273: }
2274:
2275: public WorkCalendar getBaseCalendar() {
2276: return getWorkCalendar();
2277: }
2278:
2279: public void setBaseCalendar(WorkCalendar baseCalendar)
2280: throws CircularDependencyException {
2281: setWorkCalendar(baseCalendar);
2282: }
2283:
2284: public boolean fieldHideBaseCalendar(FieldContext fieldContext) {
2285: return false;
2286: }
2287:
2288: public boolean isJustModified() {
2289: return true; //Not used
2290: }
2291:
2292: public void setComplete(boolean complete) {
2293: ScheduleUtil.setComplete(this , complete);
2294: }
2295:
2296: public boolean isComplete() {
2297: return getPercentComplete() == 1.0D;
2298: }
2299:
2300: protected boolean master = false;
2301:
2302: public boolean isMaster() {
2303: return master;
2304: }
2305:
2306: public void setMaster(boolean master) {
2307: this .master = master;
2308: }
2309:
2310: public boolean isLocal() {
2311: return hasKey.isLocal();
2312: }
2313:
2314: public void setLocal(boolean local) {
2315: hasKey.setLocal(local);
2316: }
2317:
2318: protected transient boolean temporaryLocal;
2319:
2320: public boolean isTemporaryLocal() {
2321: return temporaryLocal;
2322: }
2323:
2324: public void setTemporaryLocal(boolean temporaryLocal) {
2325: this .temporaryLocal = temporaryLocal;
2326: }
2327:
2328: public boolean isLockable() {
2329: return !(temporaryLocal || isLocal());
2330: }
2331:
2332: public boolean applyTimesheet(Collection fieldArray) {
2333: return applyTimesheet(fieldArray, System.currentTimeMillis());
2334: }
2335:
2336: public boolean applyTimesheet(Collection fieldArray,
2337: long timesheetUpdateDate) {
2338: return TimesheetHelper.applyTimesheet(getTasks(), fieldArray,
2339: timesheetUpdateDate);
2340: }
2341:
2342: public long getLastTimesheetUpdate() {
2343: return TimesheetHelper.getLastTimesheetUpdate(getTasks());
2344: }
2345:
2346: public boolean isPendingTimesheetUpdate() {
2347: return TimesheetHelper.isPendingTimesheetUpdate(getTasks());
2348: }
2349:
2350: public int getTimesheetStatus() {
2351: return TimesheetHelper.getTimesheetStatus(getTasks());
2352: }
2353:
2354: public String getTimesheetStatusName() {
2355: return TimesheetHelper
2356: .getTimesheetStatusName(getTimesheetStatus());
2357: }
2358:
2359: public void rollbackUnvalidated(NodeModel nodeModel, Object object) {
2360: }
2361:
2362: public void initOutline(NodeModel nodeModel) {
2363: }
2364:
2365: public final long getCompletedThrough() {
2366: long start = getStart();
2367: if (start == 0)
2368: return 0;
2369: long actualDuration = DateTime.closestDate(getDuration()
2370: * getPercentComplete());
2371: return getEffectiveWorkCalendar().add(start, actualDuration,
2372: true);
2373: }
2374:
2375: public final void setCompletedThrough(long completedThrough) {
2376: // do nothing
2377: }
2378:
2379: public final boolean isOpenedAsSubproject() {
2380: return openedAsSubproject;
2381: }
2382:
2383: public final void setOpenedAsSubproject(boolean openedAsSubproject) {
2384: this .openedAsSubproject = openedAsSubproject;
2385: }
2386:
2387: private transient ExternalTaskManager externalTaskManager = null;
2388:
2389: private ExternalTaskManager getExternalTaskManager() {
2390: if (externalTaskManager == null)
2391: externalTaskManager = new ExternalTaskManager();
2392: return externalTaskManager;
2393: }
2394:
2395: public void addExternalTask(Task task) {
2396: getExternalTaskManager().add(task);
2397: task.markTaskAsNeedingRecalculation();
2398: }
2399:
2400: public void handleExternalTasks(Project project, boolean opening,
2401: boolean saving) {
2402: getExternalTaskManager().handleExternalTasks(project, opening,
2403: saving);
2404: project.getExternalTaskManager().handleExternalTasks(this ,
2405: opening, saving);
2406:
2407: }
2408:
2409: public boolean needsSaving() {
2410: return (isGroupDirty()/*||getResourcePool().isGroupDirty()*/);
2411: }
2412:
2413: public long getEarliestStartingTask() {
2414: return earliestStartingTask;
2415: }
2416:
2417: public long getEarliestStartingTaskOrStart() {
2418: if (isOpenedAsSubproject())
2419: return earliestStartingTask;
2420: return ((CriticalPath) getSchedulingAlgorithm())
2421: .getEarliestStart();
2422: }
2423:
2424: public long getLatestFinishingTask() {
2425: if (isOpenedAsSubproject())
2426: return latestFinishingTask;
2427: return ((CriticalPath) getSchedulingAlgorithm())
2428: .getLatestFinish();
2429: }
2430:
2431: public final Map getExtraFields() {
2432: if (extraFields == null)
2433: extraFields = new HashMap();
2434: return extraFields;
2435: }
2436:
2437: public final void setExtraFields(Map extraFields) {
2438: this .extraFields = extraFields;
2439: }
2440:
2441: public final Hyperlink getDocumentFolderUrl() {
2442: return documentFolderUrl;
2443: }
2444:
2445: public final void setDocumentFolderUrl(Hyperlink documentFolderUrl) {
2446: this .documentFolderUrl = documentFolderUrl;
2447: }
2448:
2449: public final boolean isReadOnly() {
2450: return readOnly;
2451: }
2452:
2453: public final void setReadOnly(boolean readOnly) {
2454: this .readOnly = readOnly;
2455: }
2456:
2457: public final Collection getReferringSubprojectTasks() {
2458: return subprojectHandler.getReferringSubprojectTasks();
2459: }
2460:
2461: public final void setReferringSubprojectTasks(
2462: Collection referringSubprojectTasks) {
2463: subprojectHandler
2464: .setReferringSubprojectTasks(referringSubprojectTasks);
2465: }
2466:
2467: public final Task getContainingSubprojectTask() {
2468: return subprojectHandler.getContainingSubprojectTask();
2469: }
2470:
2471: public final void setContainingSubprojectTask(Task subprojectTask) {
2472: this .subprojectHandler
2473: .setContainingSubprojectTask(subprojectTask);
2474: }
2475:
2476: public long getFinishOffset() {
2477: return EarnedValueCalculator.getInstance()
2478: .getFinishOffset(this );
2479: }
2480:
2481: public long getStartOffset() {
2482: return EarnedValueCalculator.getInstance().getStartOffset(this );
2483: }
2484:
2485: public double getRisk() {
2486: return risk;
2487: }
2488:
2489: public void setRisk(double risk) {
2490: this .risk = risk;
2491: }
2492:
2493: public int getProjectType() {
2494: return projectType;
2495: }
2496:
2497: public void setProjectType(int projectType) {
2498: this .projectType = projectType;
2499: }
2500:
2501: public int getExpenseType() {
2502: return expenseType;
2503: }
2504:
2505: public void setExpenseType(int budgetType) {
2506: this .expenseType = budgetType;
2507: }
2508:
2509: public int getEffectiveExpenseType() {
2510: return getExpenseType();
2511: }
2512:
2513: public String getDivision() {
2514: return division;
2515: }
2516:
2517: public void setDivision(String division) {
2518: this .division = division;
2519: }
2520:
2521: public String getGroup() {
2522: return group;
2523: }
2524:
2525: public void setGroup(String group) {
2526: this .group = group;
2527: }
2528:
2529: public int getProjectStatus() {
2530: return projectStatus;
2531: }
2532:
2533: public void setProjectStatus(int projectStatus) {
2534: this .projectStatus = projectStatus;
2535: }
2536:
2537: public ImageLink getBudgetStatusIndicator() {
2538: return EarnedValueCalculator.getInstance()
2539: .getBudgetStatusIndicator(getCpi(null));
2540: }
2541:
2542: public ImageLink getScheduleStatusIndicator() {
2543: return EarnedValueCalculator.getInstance()
2544: .getBudgetStatusIndicator(getSpi(null));
2545: }
2546:
2547: public Object backupDetail() {
2548: // TODO Auto-generated method stub
2549: return null;
2550: }
2551:
2552: public void restoreDetail(Object source, Object detail,
2553: boolean isChild) {
2554: // TODO Auto-generated method stub
2555:
2556: }
2557:
2558: public boolean containsAssignments() {
2559: return true;
2560: }
2561:
2562: public void beginUndoUpdate() {
2563: if (undoController != null)
2564: undoController.beginUpdate();
2565: }
2566:
2567: public void endUndoUpdate() {
2568: if (undoController != null)
2569: undoController.endUpdate();
2570: }
2571:
2572: public void renumber() {
2573: long uniqueId = getUniqueId();
2574: for (Iterator i = getTaskOutlineIterator(); i.hasNext();) {
2575: NormalTask task = (NormalTask) i.next(); //ResourceImpl to have the EnterpriseResource link
2576: if (task.getProjectId() != uniqueId) // skip if in another project
2577: continue;
2578: task.renumber();
2579: }
2580: hasKey.renumber();
2581: uniqueId = getUniqueId();
2582: for (Iterator i = getTaskOutlineIterator(); i.hasNext();) {
2583: NormalTask task = (NormalTask) i.next();
2584: task.setProjectId(uniqueId);
2585: }
2586: }
2587:
2588: protected transient int accessControlPolicy;
2589:
2590: public int getAccessControlPolicy() {
2591: return accessControlPolicy;
2592: }
2593:
2594: public void setAccessControlPolicy(int accessControlPolicy) {
2595: this .accessControlPolicy = accessControlPolicy;
2596: }
2597:
2598: public Date getCreationDate() {
2599: return creationDate;
2600: }
2601:
2602: public void setCreationDate(Date creationDate) {
2603: this .creationDate = creationDate;
2604: }
2605:
2606: public Date getLastModificationDate() {
2607: return lastModificationDate;
2608: }
2609:
2610: public void setLastModificationDate(Date lastModificationDate) {
2611: this .lastModificationDate = lastModificationDate;
2612: }
2613:
2614: /**
2615: * Automatically link all siblings at all levels
2616: * A condition can be applied. The condition tests the task and sees whether it can be a successor task ornot
2617: * @param parent - should be null if whole project
2618: */
2619: public void linkAllSiblings(Node parent,
2620: Predicate canBeSuccessorCondition, Object eventSource) {
2621: List<Node> children = getTaskModel().getChildren(parent);
2622:
2623: if (children == null)
2624: return;
2625: try {
2626: DependencyService.getInstance().connect(
2627: NodeList.nodeListToImplList(children,
2628: NotAssignmentFilter.getInstance()),
2629: eventSource, canBeSuccessorCondition);
2630: } catch (InvalidAssociationException e) {
2631: e.printStackTrace();
2632: }
2633: for (Node n : children)
2634: // recursively do children
2635: linkAllSiblings(n, canBeSuccessorCondition, eventSource);
2636:
2637: }
2638:
2639: public List<NormalTask> getRootTasks() {
2640: List<Node> children = getTaskModel().getChildren(null);
2641: return NodeList.nodeListToImplList(children);
2642: }
2643:
2644: public List<Resource> getRootResources() {
2645: List<Node> children = getResourceModel().getChildren(null);
2646: return NodeList.nodeListToImplList(children);
2647: }
2648:
2649: public boolean isCriticalPathJustChanged() {
2650: return ((CriticalPath) getSchedulingAlgorithm())
2651: .isCriticalPathJustChanged();
2652: }
2653:
2654: public int getBenefit() {
2655: return benefit;
2656: }
2657:
2658: public void setBenefit(int benefit) {
2659: this .benefit = benefit;
2660: }
2661:
2662: public double getNetPresentValue() {
2663: return netPresentValue;
2664: }
2665:
2666: public void setNetPresentValue(double netPresentValue) {
2667: this .netPresentValue = netPresentValue;
2668: }
2669:
2670: protected transient String fileName;
2671:
2672: public String getFileName() {
2673: return fileName;
2674: }
2675:
2676: public String getGuessedFileName() {
2677: if (fileName != null)
2678: return fileName;
2679: String name = getName();
2680: if (name == null)
2681: return null;
2682: return getName() + "." + FileHelper.getFileExtension(fileType);
2683: }
2684:
2685: // public String getDefaultExtension(){
2686: // return Environment.getStandAlone()?FileHelper.DEFAULT_FILE_EXTENSION:"xml";
2687: // }
2688: public void setFileName(String fileName) {
2689: this .fileName = fileName;
2690: if (fileName != null) {
2691: setFileType(FileHelper.getFileType(fileName));
2692: }
2693: }
2694:
2695: public String getTitle() {
2696: return getName() + (fileName == null ? "" : (" - " + fileName));
2697: }
2698:
2699: protected transient int fileType = FileHelper.PROJITY_FILE_TYPE;
2700:
2701: public int getFileType() {
2702: return fileType;
2703: }
2704:
2705: public void setFileType(int fileType) {
2706: this .fileType = fileType;
2707: }
2708:
2709: public void setBoundsAfterReadProject() {
2710: getSchedulingAlgorithm().setEarliestAndLatest(getStart(),
2711: getEnd());
2712: fireScheduleChanged(this , ScheduleEvent.SCHEDULE);
2713: }
2714:
2715: public void setAllTasksInSubproject(boolean b, Project masterProject) {
2716: // TODO Auto-generated method stub
2717:
2718: }
2719:
2720: public void setAllNodesInSubproject(boolean b) {
2721: // TODO Auto-generated method stub
2722:
2723: }
2724:
2725: public SubprojectHandler getSubprojectHandler() {
2726: return subprojectHandler;
2727: }
2728:
2729: public long getReferringSubprojectTaskDependencyDate() {
2730: return subprojectHandler
2731: .getReferringSubprojectTaskDependencyDate();
2732: }
2733:
2734: public String getSubprojectOf() {
2735: return subprojectHandler.getSubprojectOf();
2736: }
2737:
2738: public void resetRoles(boolean publicRoles) {
2739: try {
2740: Class
2741: .forName(
2742: Messages
2743: .getMetaString("ProjectRoleManager"))
2744: .getDeclaredMethod(
2745: "resetRoles",
2746: new Class[] { Project.class, Boolean.class })
2747: .invoke(null, new Object[] { this , publicRoles });
2748: } catch (Exception e) {
2749: e.printStackTrace();
2750: System.out
2751: .println("ProjectRoleManager not valid in meta.properties");
2752: System.exit(-1);
2753: }
2754: }
2755:
2756: public class Workspace implements WorkspaceSetting {
2757: private static final long serialVersionUID = 6909144693873463556L;
2758: WorkspaceSetting spreadsheetWorkspace;
2759: HashMap fieldAliasMap;
2760:
2761: }
2762:
2763: public transient SpreadSheetFieldArray fieldArray = null;
2764:
2765: public void restoreWorkspace(WorkspaceSetting w, int context) {
2766: Workspace ws = (Workspace) w;
2767: if (ws.spreadsheetWorkspace != null) {
2768: fieldArray = new SpreadSheetFieldArray();
2769:
2770: fieldArray
2771: .setCategory(SpreadSheetCategories.taskSpreadsheetCategory);
2772: fieldArray.restoreWorkspace(ws.spreadsheetWorkspace,
2773: context);
2774: fieldArray.setName(getName());
2775: Dictionary.add(fieldArray);
2776: }
2777:
2778: if (ws.fieldAliasMap != null)
2779: FieldDictionary.setAliasMap(ws.fieldAliasMap);
2780: // Alert.setGraphicManagerMethod("setCurrentFieldArray",f);
2781: }
2782:
2783: public WorkspaceSetting createWorkspace(int context) {
2784: Workspace ws = new Workspace();
2785: if (Environment.isClientSide()) {
2786: fieldArray = (SpreadSheetFieldArray) Alert
2787: .getGraphicManagerMethod("getCurrentFieldArray");
2788: if (fieldArray != null)
2789: ws.spreadsheetWorkspace = fieldArray
2790: .createWorkspace(context);
2791: }
2792: ws.fieldAliasMap = FieldDictionary.getAliasMap();
2793: return ws;
2794: }
2795:
2796: public SpreadSheetFieldArray getFieldArray() {
2797: return fieldArray;
2798: }
2799:
2800: public void forTasks(Closure c) {
2801: for (Iterator i = getTaskOutlineIterator(); i.hasNext();) {
2802: c.execute(i.next());
2803: }
2804: }
2805:
2806: private class TaskIterator implements Iterator<Task> {
2807: private Iterator iterator;
2808: private Task next = null;
2809:
2810: private Task nextElement() {
2811: Node node = null;
2812: while (iterator.hasNext()
2813: && !((node = (Node) iterator.next()).getImpl() instanceof Task))
2814: ;
2815: if (node != null && node.getImpl() instanceof Task)
2816: next = (Task) node.getImpl();
2817: else
2818: next = null;
2819: return next;
2820: }
2821:
2822: TaskIterator() {
2823: iterator = getTaskOutline().iterator(getTaskOutlineRoot());
2824: nextElement();
2825: }
2826:
2827: public boolean hasNext() {
2828: return next != null;
2829: }
2830:
2831: public Task next() {
2832: Task n = next;
2833: nextElement();
2834: return n;
2835: }
2836:
2837: public void remove() {
2838: throw new UnsupportedOperationException();
2839: }
2840:
2841: }
2842:
2843: public Iterator<Task> getTaskOutlineIterator() {
2844: return new TaskIterator();
2845: }
2846:
2847: public Node getTaskOutlineRoot() {
2848: if (isOpenedAsSubproject()) { // when doing subprojects, we must treat the suproject parent as the root node
2849: if (getTasks().size() > 0) {
2850: NormalTask t = (NormalTask) getTasks().get(0); // get any task in the project
2851: return t.getEnclosingSubprojectNode(); // this will fetch the enclosing subproject task which will be the hierarchy root
2852: }
2853: }
2854: return null;
2855: }
2856:
2857: }
|