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.resource;
0051:
0052: import java.io.IOException;
0053: import java.io.ObjectInputStream;
0054: import java.io.ObjectOutputStream;
0055: import java.util.Collection;
0056: import java.util.Date;
0057: import java.util.Iterator;
0058: import java.util.List;
0059: import java.util.Set;
0060:
0061: import org.apache.commons.collections.Closure;
0062:
0063: import com.projity.algorithm.ReverseQuery;
0064: import com.projity.algorithm.TimeIteratorGenerator;
0065: import com.projity.algorithm.buffer.CalculatedValues;
0066: import com.projity.algorithm.buffer.GroupedCalculatedValues;
0067: import com.projity.association.AssociationList;
0068: import com.projity.company.ApplicationUser;
0069: import com.projity.configuration.CircularDependencyException;
0070: import com.projity.datatype.ImageLink;
0071: import com.projity.datatype.Rate;
0072: import com.projity.datatype.RateFormat;
0073: import com.projity.datatype.TimeUnit;
0074: import com.projity.document.Document;
0075: import com.projity.field.CustomFields;
0076: import com.projity.field.CustomFieldsImpl;
0077: import com.projity.field.FieldContext;
0078: import com.projity.interval.InvalidValueObjectForIntervalException;
0079: import com.projity.pm.assignment.Assignment;
0080: import com.projity.pm.assignment.HasAssignments;
0081: import com.projity.pm.assignment.HasAssignmentsImpl;
0082: import com.projity.pm.assignment.timesheet.TimesheetHelper;
0083: import com.projity.pm.availability.AvailabilityTable;
0084: import com.projity.pm.calendar.CalendarService;
0085: import com.projity.pm.calendar.WorkCalendar;
0086: import com.projity.pm.calendar.WorkingCalendar;
0087: import com.projity.pm.costing.Accrual;
0088: import com.projity.pm.costing.CostRateTable;
0089: import com.projity.pm.costing.CostRateTables;
0090: import com.projity.pm.costing.EarnedValueCalculator;
0091: import com.projity.pm.key.HasKeyImpl;
0092: import com.projity.pm.task.Task;
0093: import com.projity.strings.Messages;
0094: import com.projity.util.Environment;
0095:
0096: /**
0097: * A global resource that belongs to the enterprise resource pool
0098: */
0099: public class EnterpriseResource implements Resource {
0100: static final long serialVersionUID = 273977742329L;
0101: private static Resource UNASSIGNED = null;
0102: public static final int UNASSIGNED_ID = -65535; // correponds to MSDI
0103:
0104: public long getEarliestAssignmentStart() {
0105: return hasAssignments.getEarliestAssignmentStart();
0106: }
0107:
0108: public boolean hasActiveAssignment(long start, long end) {
0109: return hasAssignments.hasActiveAssignment(start, end);
0110: }
0111:
0112: public EnterpriseResource(ResourcePool resourcePool) {
0113: this (resourcePool == null || resourcePool.isLocal(),
0114: resourcePool);
0115: }
0116:
0117: public EnterpriseResource(boolean local, ResourcePool resourcePool) {
0118: hasKey = new HasKeyImpl(local, this );
0119: this .resourcePool = resourcePool;
0120: if (resourcePool != null) {
0121: workCalendar = WorkingCalendar
0122: .getInstanceBasedOn(resourcePool
0123: .getDefaultCalendar());
0124: workCalendar.setName("");
0125: }
0126: }
0127:
0128: /**
0129: * @return
0130: */
0131: public static Resource getUnassignedInstance() {
0132: if (UNASSIGNED == null) {
0133: UNASSIGNED = new EnterpriseResource(null); //local
0134: UNASSIGNED.setName(Messages.getString("Text.Unassigned"));
0135: UNASSIGNED.setUniqueId(UNASSIGNED_ID);
0136: }
0137: return UNASSIGNED;
0138: }
0139:
0140: public boolean isDefault() {
0141: return getUniqueId() == UNASSIGNED_ID;
0142: }
0143:
0144: transient HasAssignments hasAssignments = new HasAssignmentsImpl();
0145: private transient HasKeyImpl hasKey;
0146: /* (non-Javadoc)
0147: * @see com.projity.pm.resource.Resource#getResourceType()
0148: */
0149: protected transient ResourcePool resourcePool;
0150:
0151: protected String notes = "";
0152: protected String group = "";
0153: protected String initials = "";
0154: protected String phonetics = "";
0155: protected String rbsCode = "";
0156: protected String emailAddress = "";
0157: protected String materialLabel = "";
0158: protected String userAccount = "";
0159: protected int resourceType = ResourceType.WORK;
0160: protected transient CostRateTables costRateTables = new CostRateTables();
0161: protected double maximumUnits = 1.0D;
0162: protected boolean generic = false;
0163: protected boolean inactive = false;
0164: protected transient CustomFieldsImpl customFields = new CustomFieldsImpl();
0165: protected long externalId = -1;
0166:
0167: public long getExternalId() {
0168: return externalId;
0169: }
0170:
0171: public void setExternalId(long externalId) {
0172: this .externalId = externalId;
0173: }
0174:
0175: public int getResourceType() {
0176: return resourceType;
0177: }
0178:
0179: public String toString() {
0180: return getName();
0181: }
0182:
0183: public void setResourceType(int resourceType) {
0184: if (resourceType == this .resourceType)
0185: return;
0186: boolean oldIsLabor = isLabor();
0187: this .resourceType = resourceType;
0188:
0189: // if resource type changes to/from labor, then initialize rates
0190: if (oldIsLabor != isLabor()) {
0191: setStandardRate(new Rate());
0192: setOvertimeRate(new Rate());
0193:
0194: if (!isLabor()) { // Non labor resources have no time unit
0195: getStandardRate().setTimeUnit(TimeUnit.NON_TEMPORAL);
0196: getOvertimeRate().setTimeUnit(TimeUnit.NON_TEMPORAL);
0197: }
0198: }
0199: }
0200:
0201: /* (non-Javadoc)
0202: * @see com.projity.pm.costing.Rate#getCostPerUse()
0203: */
0204: public double getCostPerUse() {
0205: return costRateTables.getCostPerUse();
0206: }
0207:
0208: /* (non-Javadoc)
0209: * @see com.projity.pm.costing.Rate#getOvertimeRate()
0210: */
0211: public Rate getOvertimeRate() {
0212: return costRateTables.getOvertimeRate();
0213: }
0214:
0215: /* (non-Javadoc)
0216: * @see com.projity.pm.costing.Rate#getStandardRate()
0217: */
0218: public Rate getStandardRate() {
0219: return costRateTables.getStandardRate();
0220: }
0221:
0222: /* (non-Javadoc)
0223: * @see com.projity.pm.costing.Cost#setCostPerUse(double)
0224: */
0225: public void setCostPerUse(double costPerUse) {
0226: costRateTables.setCostPerUse(costPerUse);
0227: }
0228:
0229: /* (non-Javadoc)
0230: * @see com.projity.pm.costing.Cost#setOvertimeRate(double)
0231: */
0232: public void setOvertimeRate(Rate overtimeRate) {
0233: if (!isLabor())
0234: overtimeRate.makeUnitless();
0235: costRateTables.setOvertimeRate(overtimeRate);
0236: }
0237:
0238: /* (non-Javadoc)
0239: * @see com.projity.pm.costing.Cost#setStandardRate(double)
0240: */
0241: public void setStandardRate(Rate standardRate) {
0242: if (!isLabor())
0243: standardRate.makeUnitless();
0244: costRateTables.setStandardRate(standardRate);
0245: }
0246:
0247: /* (non-Javadoc)
0248: * @see com.projity.pm.costing.Cost#getEffectiveDate()
0249: */
0250: public long getEffectiveDate() {
0251: return costRateTables.getEffectiveDate();
0252: }
0253:
0254: /* (non-Javadoc)
0255: * @see com.projity.pm.costing.Cost#setEffectiveDate(long)
0256: */
0257: public void setEffectiveDate(long effectiveDate)
0258: throws InvalidValueObjectForIntervalException {
0259: costRateTables.setEffectiveDate(effectiveDate);
0260: }
0261:
0262: /* (non-Javadoc)
0263: * @see com.projity.pm.costing.Cost#isReadOnlyEffectiveDate()
0264: */
0265: public boolean isReadOnlyEffectiveDate(FieldContext fieldContext) {
0266: return costRateTables.isReadOnlyEffectiveDate(fieldContext);
0267: }
0268:
0269: /**
0270: * @return Returns the costRateTable.
0271: */
0272: public CostRateTable getCostRateTable(int costRateIndex) {
0273: return costRateTables.getCostRateTable(costRateIndex);
0274: }
0275:
0276: protected int accrueAt = Accrual.PRORATED;
0277:
0278: /* (non-Javadoc)
0279: * @see com.projity.pm.resource.Resource#getAccrueAt()
0280: */
0281: public int getAccrueAt() {
0282: return accrueAt;
0283: }
0284:
0285: /**
0286: * @param accrueAt The accrueAt to set.
0287: */
0288: public void setAccrueAt(int accrueAt) {
0289: this .accrueAt = accrueAt;
0290: }
0291:
0292: /**
0293: * @param assignment
0294: */
0295: public void addAssignment(Assignment assignment) {
0296: hasAssignments.addAssignment(assignment);
0297: }
0298:
0299: /*public void addDefaultAssignment() {
0300: hasAssignments.addAssignment(newDefaultAssignment());
0301: }
0302: private Assignment newDefaultAssignment() {
0303: return Assignment.getInstance(NormalTask
0304: .getUnassignedInstance(),this, 1.0, 0);
0305: }*/
0306:
0307: /**
0308: * @param reverseQuery
0309: */
0310: public void buildReverseQuery(ReverseQuery reverseQuery) {
0311: hasAssignments.buildReverseQuery(reverseQuery);
0312: }
0313:
0314: /**
0315: * @param resource
0316: * @return
0317: */
0318: public Assignment findAssignment(Resource resource) {
0319: return hasAssignments.findAssignment(resource);
0320: }
0321:
0322: /**
0323: * @param task
0324: * @return
0325: */
0326: public Assignment findAssignment(Task task) {
0327: return hasAssignments.findAssignment(task);
0328: }
0329:
0330: /**
0331: * @return Returns the maxUnits.
0332: */
0333: public double getMaximumUnits() {
0334: return maximumUnits;
0335: }
0336:
0337: /**
0338: * @param maxUnits The maxUnits to set.
0339: */
0340: public void setMaximumUnits(double maxUnits) {
0341: this .maximumUnits = maxUnits;
0342: }
0343:
0344: /**
0345: * @return
0346: */
0347: public AssociationList getAssignments() {
0348: return hasAssignments.getAssignments();
0349: }
0350:
0351: /**
0352: * This is unused
0353: * @return
0354: */
0355: public int getSchedulingType() {
0356: return hasAssignments.getSchedulingType();
0357: }
0358:
0359: /* (non-Javadoc)
0360: * @see java.lang.Object#hashCode()
0361: */
0362: public int hashCode() {
0363: return hasAssignments.hashCode();
0364: }
0365:
0366: /**
0367: * This is unused - a resource is not effort driven
0368: * @return
0369: */
0370: public boolean isEffortDriven() {
0371: return false;
0372: }
0373:
0374: /**
0375: * @param assignment
0376: */
0377: public void removeAssignment(Assignment assignment) {
0378: hasAssignments.removeAssignment(assignment);
0379: }
0380:
0381: /**
0382: * @param effortDriven
0383: */
0384: public void setEffortDriven(boolean effortDriven) {
0385: hasAssignments.setEffortDriven(effortDriven);
0386: }
0387:
0388: /**
0389: * @param schedulingType
0390: */
0391: public void setSchedulingType(int schedulingType) {
0392: hasAssignments.setSchedulingType(schedulingType);
0393: }
0394:
0395: /**
0396: * @param modified
0397: */
0398: public void updateAssignment(Assignment modified) {
0399: hasAssignments.updateAssignment(modified);
0400: }
0401:
0402: /**
0403: * @param visitor
0404: * @return
0405: */
0406: public static Closure forAllAssignments(Closure visitor) {
0407: return HasAssignmentsImpl.forAllAssignments(visitor);
0408: }
0409:
0410: /**
0411: * @return Returns the notes.
0412: */
0413: public String getNotes() {
0414: return notes;
0415: }
0416:
0417: /**
0418: * @param notes The notes to set.
0419: */
0420: public void setNotes(String notes) {
0421: this .notes = notes;
0422: }
0423:
0424: /**
0425: * @param visitor
0426: * @param mergeWorking
0427: */
0428: public void forEachWorkingInterval(Closure visitor,
0429: boolean mergeWorking, WorkCalendar workCalendar) {
0430: hasAssignments.forEachWorkingInterval(visitor, mergeWorking,
0431: workCalendar);
0432: }
0433:
0434: protected WorkCalendar workCalendar = null;
0435:
0436: public void setWorkCalendar(WorkCalendar workCalendar) {
0437: this .workCalendar = workCalendar;
0438: }
0439:
0440: /* (non-Javadoc)
0441: * @see com.projity.pm.time.HasCalendar#getWorkCalendar()
0442: */
0443: public WorkCalendar getWorkCalendar() {
0444: return workCalendar;
0445: }
0446:
0447: /* (non-Javadoc)
0448: * @see com.projity.pm.time.HasCalendar#getEffectiveWorkCalendar()
0449: */
0450: public WorkCalendar getEffectiveWorkCalendar() {
0451: return workCalendar; // can be null
0452: }
0453:
0454: /**
0455: * @return
0456: */
0457: public boolean isReadOnlyEffortDriven(FieldContext fieldContext) {
0458: return hasAssignments.isReadOnlyEffortDriven(fieldContext);
0459: }
0460:
0461: /**
0462: * @return Returns the group.
0463: */
0464: public String getGroup() {
0465: return group;
0466: }
0467:
0468: /**
0469: * @param group The group to set.
0470: */
0471: public void setGroup(String group) {
0472: this .group = group;
0473: }
0474:
0475: /**
0476: * @return Returns the initials.
0477: */
0478: public String getInitials() {
0479: return initials;
0480: }
0481:
0482: /**
0483: * @param initials The initials to set.
0484: */
0485: public void setInitials(String initials) {
0486: this .initials = initials;
0487: if (getName() == null) // for the case where the resource is created by entering initials, set name too
0488: setName(initials);
0489: }
0490:
0491: /**
0492: * @return Returns the phonetics.
0493: */
0494: public String getPhonetics() {
0495: return phonetics;
0496: }
0497:
0498: /**
0499: * @param phonetics The phonetics to set.
0500: */
0501: public void setPhonetics(String phonetics) {
0502: this .phonetics = phonetics;
0503: }
0504:
0505: /* (non-Javadoc)
0506: * @see com.projity.pm.resource.ResourceSpecificFields#getRemainingOvertimeCost()
0507: */
0508: public double getRemainingOvertimeCost() {
0509: // TODO implement this
0510: return -1;
0511: }
0512:
0513: /**
0514: * @return
0515: */
0516: public Date getCreated() {
0517: return hasKey.getCreated();
0518: }
0519:
0520: /**
0521: * @return
0522: */
0523: public long getId() {
0524: return hasKey.getId();
0525: }
0526:
0527: /**
0528: * @return
0529: */
0530: public String getName() {
0531: return hasKey.getName();
0532: }
0533:
0534: /**
0535: * @return
0536: */
0537: public long getUniqueId() {
0538: return hasKey.getUniqueId();
0539: }
0540:
0541: // public void setNew(boolean isNew) {
0542: // hasKey.setNew(isNew);
0543: // }
0544: /**
0545: * @param created
0546: */
0547: public void setCreated(Date created) {
0548: hasKey.setCreated(created);
0549: }
0550:
0551: /**
0552: * @param id
0553: */
0554: public void setId(long id) {
0555: hasKey.setId(id);
0556: }
0557:
0558: /**
0559: * @param name
0560: */
0561: public void setName(String name) {
0562: hasKey.setName(name);
0563: // set initials too to first character of name if initials is empty
0564: if (getInitials() == null || getInitials().length() == 0) {
0565: if (name != null && name.length() > 0)
0566: setInitials(name.substring(0, 1));
0567: }
0568: if (workCalendar != null)
0569: workCalendar.setName(name);
0570:
0571: }
0572:
0573: /**
0574: * @param id
0575: */
0576: public void setUniqueId(long id) {
0577: hasKey.setUniqueId(id);
0578: }
0579:
0580: /**
0581: * @param start
0582: * @param end
0583: * @return
0584: */
0585: public double actualCost(long start, long end) {
0586: return hasAssignments.actualCost(start, end);
0587: }
0588:
0589: /**
0590: * @param start
0591: * @param end
0592: * @return
0593: */
0594: public long actualWork(long start, long end) {
0595: return hasAssignments.actualWork(start, end);
0596: }
0597:
0598: /**
0599: * @param start
0600: * @param end
0601: * @return
0602: */
0603: public long remainingWork(long start, long end) {
0604: return hasAssignments.remainingWork(start, end);
0605: }
0606:
0607: /**
0608: * @param start
0609: * @param end
0610: * @return
0611: */
0612: public double acwp(long start, long end) {
0613: return hasAssignments.acwp(start, end);
0614: }
0615:
0616: /**
0617: * @param start
0618: * @param end
0619: * @return
0620: */
0621: public double bac(long start, long end) {
0622: return hasAssignments.bac(start, end);
0623: }
0624:
0625: /**
0626: * @param start
0627: * @param end
0628: * @return
0629: */
0630: public double bcwp(long start, long end) {
0631: return hasAssignments.bcwp(start, end);
0632: }
0633:
0634: /**
0635: * @param start
0636: * @param end
0637: * @return
0638: */
0639: public double bcws(long start, long end) {
0640: return hasAssignments.bcws(start, end);
0641: }
0642:
0643: /**
0644: * @param start
0645: * @param end
0646: * @return
0647: */
0648: public double cost(long start, long end) {
0649: return hasAssignments.cost(start, end);
0650: }
0651:
0652: /**
0653: * @param start
0654: * @param end
0655: * @return
0656: */
0657: public long work(long start, long end) {
0658: return hasAssignments.work(start, end);
0659: }
0660:
0661: /**
0662: * @param context
0663: * @return
0664: */
0665: public String getName(FieldContext context) {
0666: return hasKey.getName(context);
0667: }
0668:
0669: /**
0670: * @param type
0671: * @param generator
0672: * @param values
0673: */
0674: public void calcDataBetween(Object type,
0675: TimeIteratorGenerator generator, CalculatedValues values) {
0676: hasAssignments.calcDataBetween(type, generator, values);
0677: }
0678:
0679: /**
0680: * @return Returns the rbsCode.
0681: */
0682: public String getRbsCode() {
0683: return rbsCode;
0684: }
0685:
0686: /**
0687: * @param rbsCode The rbsCode to set.
0688: */
0689: public void setRbsCode(String rbsCode) {
0690: this .rbsCode = rbsCode;
0691: }
0692:
0693: /**
0694: * @return Returns the resourcePool.
0695: */
0696: public ResourcePool getResourcePool() {
0697: return resourcePool;
0698: }
0699:
0700: public void setResourcePool(ResourcePool resourcePool) {
0701: this .resourcePool = resourcePool;
0702: }
0703:
0704: /* (non-Javadoc)
0705: * @see com.projity.pm.task.BelongsToDocument#getDocument()
0706: */
0707: public Document getDocument() {
0708: return resourcePool;
0709: }
0710:
0711: /**
0712: * @return
0713: */
0714: public Collection childrenToRollup() {
0715: return hasAssignments.childrenToRollup();
0716: }
0717:
0718: /* (non-Javadoc)
0719: * @see com.projity.pm.assignment.HasTimeDistributedData#actualWork(long, long)
0720: */
0721: public double getCost(FieldContext fieldContext) {
0722: return cost(FieldContext.start(fieldContext), FieldContext
0723: .end(fieldContext));
0724: }
0725:
0726: public long getWork(FieldContext fieldContext) {
0727: return work(FieldContext.start(fieldContext), FieldContext
0728: .end(fieldContext));
0729: }
0730:
0731: public double getActualCost(FieldContext fieldContext) {
0732: return actualCost(FieldContext.start(fieldContext),
0733: FieldContext.end(fieldContext));
0734: }
0735:
0736: public long getActualWork(FieldContext fieldContext) {
0737: return actualWork(FieldContext.start(fieldContext),
0738: FieldContext.end(fieldContext));
0739: }
0740:
0741: public long getRemainingWork(FieldContext fieldContext) {
0742: return remainingWork(FieldContext.start(fieldContext),
0743: FieldContext.end(fieldContext));
0744: }
0745:
0746: public double getRemainingCost(FieldContext fieldContext) {
0747: return getCost(fieldContext) - getActualCost(fieldContext);
0748: }
0749:
0750: public double getAcwp(FieldContext fieldContext) {
0751: return acwp(FieldContext.start(fieldContext), FieldContext
0752: .end(fieldContext));
0753: }
0754:
0755: public double getBac(FieldContext fieldContext) {
0756: return bac(FieldContext.start(fieldContext), FieldContext
0757: .end(fieldContext));
0758: }
0759:
0760: public double getBcwp(FieldContext fieldContext) {
0761: return bcwp(FieldContext.start(fieldContext), FieldContext
0762: .end(fieldContext));
0763: }
0764:
0765: public double getBcws(FieldContext fieldContext) {
0766: return bcws(FieldContext.start(fieldContext), FieldContext
0767: .end(fieldContext));
0768: }
0769:
0770: public double getCv(FieldContext fieldContext) {
0771: return EarnedValueCalculator.getInstance().cv(this ,
0772: FieldContext.start(fieldContext),
0773: FieldContext.end(fieldContext));
0774: }
0775:
0776: public double getSv(FieldContext fieldContext) {
0777: return EarnedValueCalculator.getInstance().sv(this ,
0778: FieldContext.start(fieldContext),
0779: FieldContext.end(fieldContext));
0780: }
0781:
0782: public double getEac(FieldContext fieldContext) {
0783: return EarnedValueCalculator.getInstance().eac(this ,
0784: FieldContext.start(fieldContext),
0785: FieldContext.end(fieldContext));
0786: }
0787:
0788: public double getVac(FieldContext fieldContext) {
0789: return EarnedValueCalculator.getInstance().vac(this ,
0790: FieldContext.start(fieldContext),
0791: FieldContext.end(fieldContext));
0792: }
0793:
0794: public double getCpi(FieldContext fieldContext) {
0795: return EarnedValueCalculator.getInstance().cpi(this ,
0796: FieldContext.start(fieldContext),
0797: FieldContext.end(fieldContext));
0798: }
0799:
0800: public double getSpi(FieldContext fieldContext) {
0801: return EarnedValueCalculator.getInstance().spi(this ,
0802: FieldContext.start(fieldContext),
0803: FieldContext.end(fieldContext));
0804: }
0805:
0806: public double getCsi(FieldContext fieldContext) {
0807: return EarnedValueCalculator.getInstance().csi(this ,
0808: FieldContext.start(fieldContext),
0809: FieldContext.end(fieldContext));
0810: }
0811:
0812: public double getCvPercent(FieldContext fieldContext) {
0813: return EarnedValueCalculator.getInstance().cvPercent(this ,
0814: FieldContext.start(fieldContext),
0815: FieldContext.end(fieldContext));
0816: }
0817:
0818: public double getSvPercent(FieldContext fieldContext) {
0819: return EarnedValueCalculator.getInstance().svPercent(this ,
0820: FieldContext.start(fieldContext),
0821: FieldContext.end(fieldContext));
0822: }
0823:
0824: public double getTcpi(FieldContext fieldContext) {
0825: return EarnedValueCalculator.getInstance().tcpi(this ,
0826: FieldContext.start(fieldContext),
0827: FieldContext.end(fieldContext));
0828: }
0829:
0830: /**
0831: * @param start
0832: * @param end
0833: * @return
0834: */
0835: public double baselineCost(long start, long end) {
0836: return hasAssignments.baselineCost(start, end);
0837: }
0838:
0839: /**
0840: * @param start
0841: * @param end
0842: * @return
0843: */
0844: public long baselineWork(long start, long end) {
0845: return hasAssignments.baselineWork(start, end);
0846: }
0847:
0848: public double getBaselineCost(int numBaseline,
0849: FieldContext fieldContext) {
0850: return baselineCost(FieldContext.start(fieldContext),
0851: FieldContext.end(fieldContext));
0852: }
0853:
0854: /* (non-Javadoc)
0855: * @see com.projity.pm.assignment.TimeDistributedFields#getBaselineWork(int, com.projity.field.FieldContext)
0856: */
0857: public long getBaselineWork(int numBaseline,
0858: FieldContext fieldContext) {
0859: return baselineWork(FieldContext.start(fieldContext),
0860: FieldContext.end(fieldContext));
0861: }
0862:
0863: private boolean isFieldHidden(FieldContext fieldContext) {
0864: return false;
0865: }
0866:
0867: public boolean fieldHideCost(FieldContext fieldContext) {
0868: return isFieldHidden(fieldContext);
0869: }
0870:
0871: public boolean fieldHideWork(FieldContext fieldContext) {
0872: return isFieldHidden(fieldContext);
0873: }
0874:
0875: public boolean fieldHideActualCost(FieldContext fieldContext) {
0876: return isFieldHidden(fieldContext);
0877: }
0878:
0879: public boolean fieldHideActualWork(FieldContext fieldContext) {
0880: return isFieldHidden(fieldContext);
0881: }
0882:
0883: public boolean fieldHideBaselineCost(int numBaseline,
0884: FieldContext fieldContext) {
0885: return false; //TODO implement
0886: }
0887:
0888: public boolean fieldHideBaselineWork(int numBaseline,
0889: FieldContext fieldContext) {
0890: return false; //TODO implement
0891: }
0892:
0893: public boolean fieldHideAcwp(FieldContext fieldContext) {
0894: return isFieldHidden(fieldContext);
0895: }
0896:
0897: public boolean fieldHideBac(FieldContext fieldContext) {
0898: return isFieldHidden(fieldContext);
0899: }
0900:
0901: public boolean fieldHideBcwp(FieldContext fieldContext) {
0902: return isFieldHidden(fieldContext);
0903: }
0904:
0905: public boolean fieldHideBcws(FieldContext fieldContext) {
0906: return isFieldHidden(fieldContext);
0907: }
0908:
0909: public boolean fieldHideCv(FieldContext fieldContext) {
0910: return isFieldHidden(fieldContext);
0911: }
0912:
0913: public boolean fieldHideSv(FieldContext fieldContext) {
0914: return isFieldHidden(fieldContext);
0915: }
0916:
0917: public boolean fieldHideEac(FieldContext fieldContext) {
0918: return isFieldHidden(fieldContext);
0919: }
0920:
0921: public boolean fieldHideVac(FieldContext fieldContext) {
0922: return isFieldHidden(fieldContext);
0923: }
0924:
0925: public boolean fieldHideCpi(FieldContext fieldContext) {
0926: return isFieldHidden(fieldContext);
0927: }
0928:
0929: public boolean fieldHideSpi(FieldContext fieldContext) {
0930: return isFieldHidden(fieldContext);
0931: }
0932:
0933: public boolean fieldHideCvPercent(FieldContext fieldContext) {
0934: return isFieldHidden(fieldContext);
0935: }
0936:
0937: public boolean fieldHideSvPercent(FieldContext fieldContext) {
0938: return isFieldHidden(fieldContext);
0939: }
0940:
0941: public boolean fieldHideTcpi(FieldContext fieldContext) {
0942: return isFieldHidden(fieldContext);
0943: }
0944:
0945: /**
0946: * @param workCalendar
0947: * @return
0948: */
0949: public long calcActiveAssignmentDuration(WorkCalendar workCalendar) {
0950: return hasAssignments
0951: .calcActiveAssignmentDuration(workCalendar);
0952: }
0953:
0954: public boolean isAssignment() { //for filters
0955: return false;
0956: }
0957:
0958: /**
0959: * @return Returns the emailAddress.
0960: */
0961: public String getEmailAddress() {
0962: return emailAddress;
0963: }
0964:
0965: /**
0966: * @param emailAddress The emailAddress to set.
0967: */
0968: public void setEmailAddress(String emailAddress) {
0969: this .emailAddress = emailAddress;
0970: }
0971:
0972: /**
0973: * @return Returns the materialLabel.
0974: */
0975: public String getMaterialLabel() {
0976: return materialLabel;
0977: }
0978:
0979: /**
0980: * @param materialLabel The materialLabel to set.
0981: */
0982: public void setMaterialLabel(String materialLabel) {
0983: this .materialLabel = materialLabel;
0984: }
0985:
0986: public boolean isLabor() {
0987: return resourceType == ResourceType.WORK; // work resources are time based
0988:
0989: }
0990:
0991: public boolean isReadOnlyMaterialLabel(FieldContext fieldContext) {
0992: return isLabor();
0993: }
0994:
0995: public String getUserAccount() {
0996: return userAccount;
0997: }
0998:
0999: public final void setUserAccount(String userAccount) {
1000: this .userAccount = userAccount;
1001: }
1002:
1003: /**
1004: * @return Returns the active.
1005: */
1006: public boolean isInactive() {
1007: return inactive;
1008: }
1009:
1010: /**
1011: * @param inactive The active to set.
1012: */
1013: public void setInactive(boolean inactive) {
1014: this .inactive = inactive;
1015: }
1016:
1017: /**
1018: * @return Returns the generic.
1019: */
1020: public boolean isGeneric() {
1021: return generic;
1022: }
1023:
1024: /**
1025: * @param generic The generic to set.
1026: */
1027: public void setGeneric(boolean generic) {
1028: this .generic = generic;
1029: }
1030:
1031: private static short DEFAULT_VERSION = 2;
1032: private short version = DEFAULT_VERSION;
1033:
1034: public short getVersion() {
1035: return version;
1036: }
1037:
1038: private void writeObject(ObjectOutputStream s) throws IOException {
1039: s.defaultWriteObject();
1040: hasKey.serialize(s);
1041: costRateTables.serialize(s);
1042: customFields.serialize(s);
1043: s.writeInt(hasAssignments.getSchedulingType());
1044: s.writeBoolean(hasAssignments.isEffortDriven());
1045: availabilityTable.serialize(s);
1046: }
1047:
1048: private void readObject(ObjectInputStream s) throws IOException,
1049: ClassNotFoundException {
1050: s.defaultReadObject();
1051: hasKey = HasKeyImpl.deserialize(s, this );
1052: costRateTables = CostRateTables.deserialize(s);
1053: try {
1054: customFields = CustomFieldsImpl.deserialize(s);
1055: } catch (java.io.OptionalDataException e) {
1056: // to ensure compatibilty with old files
1057: customFields = new CustomFieldsImpl();
1058: }
1059: hasAssignments = new HasAssignmentsImpl();
1060: if (version >= 2) {
1061: hasAssignments.setSchedulingType(s.readInt());
1062: hasAssignments.setEffortDriven(s.readBoolean());
1063: availabilityTable = AvailabilityTable.deserialize(s);
1064: } else
1065: availabilityTable = new AvailabilityTable(null);
1066: version = DEFAULT_VERSION;
1067: }
1068:
1069: public Object clone() {
1070: try {
1071: EnterpriseResource resource = (EnterpriseResource) super
1072: .clone();
1073: resource.hasKey = new HasKeyImpl(isLocal(), resource);
1074: resource.setName(new String(getName()));
1075: if (notes != null)
1076: resource.notes = new String(notes);
1077: if (group != null)
1078: resource.group = new String(group);
1079: if (group != null)
1080: resource.initials = new String(initials);
1081: if (phonetics != null)
1082: resource.phonetics = new String(phonetics);
1083: if (rbsCode != null)
1084: resource.rbsCode = new String(rbsCode);
1085: if (emailAddress != null)
1086: resource.emailAddress = new String(emailAddress);
1087: if (materialLabel != null)
1088: resource.materialLabel = new String(materialLabel);
1089: if (userAccount != null)
1090: resource.userAccount = new String(userAccount);
1091:
1092: resource.costRateTables = (CostRateTables) costRateTables
1093: .clone();
1094: resource.hasAssignments = (HasAssignments) ((HasAssignmentsImpl) hasAssignments)
1095: .cloneWithResource(resource);
1096: resource.customFields = (CustomFieldsImpl) customFields
1097: .clone();
1098:
1099: resource.availabilityTable = (AvailabilityTable) availabilityTable
1100: .clone();
1101: resource.availabilityTable.initAfterCloning();
1102:
1103: return resource;
1104: } catch (CloneNotSupportedException e) {
1105: throw new InternalError();
1106: }
1107: }
1108:
1109: public void cleanClone() {
1110: resourcePool = null;
1111: }
1112:
1113: /* (non-Javadoc)
1114: * @see com.projity.pm.resource.ResourceSpecificFields#getBaseCalendar()
1115: */
1116: public WorkCalendar getBaseCalendar() {
1117: if (getWorkCalendar() == null)
1118: return null;
1119: return (WorkingCalendar) ((WorkingCalendar) getWorkCalendar())
1120: .getBaseCalendar();
1121: }
1122:
1123: /* (non-Javadoc)
1124: * @see com.projity.pm.resource.ResourceSpecificFields#setBaseCalendar(com.projity.pm.calendar.WorkingCalendar)
1125: */
1126: public void setBaseCalendar(WorkCalendar baseCalendar)
1127: throws CircularDependencyException {
1128: WorkCalendar old = getWorkCalendar();
1129: if (old == null)
1130: return;
1131:
1132: CalendarService.getInstance().reassignCalendar(this , old,
1133: baseCalendar);
1134:
1135: ((WorkingCalendar) getWorkCalendar())
1136: .changeBaseCalendar(baseCalendar);
1137: invalidateAssignmentCalendars(); // assignments intersection calendars need to be recalculated
1138:
1139: }
1140:
1141: // these fields are not modifiable
1142: public void setWork(long work, FieldContext fieldContext) {
1143: //do nothing
1144: }
1145:
1146: public void setRemainingWork(long work, FieldContext fieldContext) {
1147: //do nothing
1148: }
1149:
1150: public void setActualWork(long work, FieldContext fieldContext) {
1151: //do nothing
1152: }
1153:
1154: public boolean isReadOnlyWork(FieldContext fieldContext) {
1155: return true;
1156: }
1157:
1158: public boolean isReadOnlyActualWork(FieldContext fieldContext) {
1159: return true;
1160: }
1161:
1162: public boolean isReadOnlyRemainingWork(FieldContext fieldContext) {
1163: return true;
1164: }
1165:
1166: public double getActualFixedCost(FieldContext fieldContext) {
1167: return 0;
1168: }
1169:
1170: public boolean fieldHideActualFixedCost(FieldContext fieldContext) {
1171: return true;
1172: }
1173:
1174: /* (non-Javadoc)
1175: * @see com.projity.pm.assignment.HasTimeDistributedData#actualFixedCost(long, long)
1176: */
1177: public double fixedCost(long start, long end) {
1178: return 0;
1179: }
1180:
1181: public double actualFixedCost(long start, long end) {
1182: return 0;
1183: }
1184:
1185: public double getFixedCost(FieldContext fieldContext) {
1186: return 0;
1187: }
1188:
1189: public void setFixedCost(double fixedCost, FieldContext fieldContext) {
1190: }
1191:
1192: /* (non-Javadoc)
1193: * @see com.projity.pm.assignment.TimeDistributedFields#isReadOnlyFixedCost(com.projity.field.FieldContext)
1194: */
1195: public boolean isReadOnlyFixedCost(FieldContext fieldContext) {
1196: return true;
1197: }
1198:
1199: /* (non-Javadoc)
1200: * @see com.projity.datatype.CanSupplyRateUnit#getTimeUnit()
1201: */
1202: public String getTimeUnitLabel() {
1203: if (getResourceType() == ResourceType.WORK)
1204: return null;
1205: return getMaterialLabel();
1206: }
1207:
1208: public boolean fieldHideOvertimeRate(FieldContext fieldContext) {
1209: return !isLabor();
1210: }
1211:
1212: public boolean fieldHideBaseCalendar(FieldContext fieldContext) {
1213: return !isLabor();
1214: }
1215:
1216: // public boolean isNew() {
1217: // return hasKey.isNew();
1218: // }
1219: public boolean hasLaborAssignment() {
1220: return isLabor() && !getAssignments().isEmpty();
1221: }
1222:
1223: public void invalidateAssignmentCalendars() {
1224: hasAssignments.invalidateAssignmentCalendars();
1225: }
1226:
1227: /* (non-Javadoc)
1228: * @see com.projity.pm.calendar.HasCalendar#invalidateCalendar()
1229: */
1230: public Document invalidateCalendar() {
1231: invalidateAssignmentCalendars();
1232: return getResourcePool();
1233: }
1234:
1235: public boolean isWork() {
1236: return getResourceType() == ResourceType.WORK;
1237: }
1238:
1239: public boolean isMaterial() {
1240: return getResourceType() == ResourceType.MATERIAL;
1241: }
1242:
1243: public boolean isMe() {
1244: if (userAccount == null)
1245: return false;
1246: return userAccount.equals(Environment.getLogin());
1247: }
1248:
1249: public boolean isParent() {
1250: // currently the model contains ResourceImpls and not enterprise resources
1251: return false;
1252: }
1253:
1254: public long getParentId(int outlineNumber) {
1255: // currently the model contains ResourceImpls and not enterprise resources
1256: return 0;
1257: }
1258:
1259: public double getCustomCost(int i) {
1260: return customFields.getCustomCost(i);
1261: }
1262:
1263: public long getCustomDate(int i) {
1264: return customFields.getCustomDate(i);
1265: }
1266:
1267: public long getCustomDuration(int i) {
1268: return customFields.getCustomDuration(i);
1269: }
1270:
1271: public long getCustomFinish(int i) {
1272: return customFields.getCustomFinish(i);
1273: }
1274:
1275: public boolean getCustomFlag(int i) {
1276: return customFields.getCustomFlag(i);
1277: }
1278:
1279: public double getCustomNumber(int i) {
1280: return customFields.getCustomNumber(i);
1281: }
1282:
1283: public long getCustomStart(int i) {
1284: return customFields.getCustomStart(i);
1285: }
1286:
1287: public String getCustomText(int i) {
1288: return customFields.getCustomText(i);
1289: }
1290:
1291: public void setCustomCost(int i, double cost) {
1292: customFields.setCustomCost(i, cost);
1293: }
1294:
1295: public void setCustomDate(int i, long date) {
1296: customFields.setCustomDate(i, date);
1297: }
1298:
1299: public void setCustomDuration(int i, long duration) {
1300: customFields.setCustomDuration(i, duration);
1301: }
1302:
1303: public void setCustomFinish(int i, long finish) {
1304: customFields.setCustomFinish(i, finish);
1305: }
1306:
1307: public void setCustomFlag(int i, boolean flag) {
1308: customFields.setCustomFlag(i, flag);
1309: }
1310:
1311: public void setCustomNumber(int i, double number) {
1312: customFields.setCustomNumber(i, number);
1313: }
1314:
1315: public void setCustomStart(int i, long start) {
1316: customFields.setCustomStart(i, start);
1317: }
1318:
1319: public void setCustomText(int i, String text) {
1320: customFields.setCustomText(i, text);
1321: }
1322:
1323: public CustomFields getCustomFields() {
1324: return customFields;
1325: }
1326:
1327: public boolean applyTimesheet(Collection fieldArray,
1328: long timesheetUpdateDate) {
1329: return TimesheetHelper.applyTimesheet(getAssignments(),
1330: fieldArray, timesheetUpdateDate);
1331: }
1332:
1333: public long getLastTimesheetUpdate() {
1334: return TimesheetHelper.getLastTimesheetUpdate(getAssignments());
1335: }
1336:
1337: public boolean isPendingTimesheetUpdate() {
1338: return TimesheetHelper
1339: .isPendingTimesheetUpdate(getAssignments());
1340: }
1341:
1342: public int getTimesheetStatus() {
1343: return TimesheetHelper.getTimesheetStatus(getAssignments());
1344: }
1345:
1346: public String getTimesheetStatusName() {
1347: return TimesheetHelper
1348: .getTimesheetStatusName(getTimesheetStatus());
1349: }
1350:
1351: private transient boolean dirty;
1352:
1353: public boolean isDirty() {
1354: return dirty;
1355: }
1356:
1357: public void setDirty(boolean dirty) {
1358: this .dirty = dirty;
1359: }
1360:
1361: public boolean isReadOnly() {
1362: return !master && !isLocal() && !Environment.getStandAlone();
1363: }
1364:
1365: protected transient boolean master;
1366:
1367: public boolean isLocal() {
1368: return hasKey.isLocal();
1369: }
1370:
1371: public void setLocal(boolean local) {
1372: hasKey.setLocal(local);
1373: }
1374:
1375: public boolean isMaster() {
1376: return master;
1377: }
1378:
1379: public void setMaster(boolean master) {
1380: this .master = master;
1381: }
1382:
1383: protected transient GroupedCalculatedValues globalWorkVector;
1384:
1385: public GroupedCalculatedValues getGlobalWorkVector() {
1386: return globalWorkVector;
1387: }
1388:
1389: public void setGlobalWorkVector(
1390: GroupedCalculatedValues globalWorkVector) {
1391: this .globalWorkVector = globalWorkVector;
1392: }
1393:
1394: public long getFinishOffset() {
1395: // TODO Auto-generated method stub
1396: return 0;
1397: }
1398:
1399: public long getStartOffset() {
1400: // TODO Auto-generated method stub
1401: return 0;
1402: }
1403:
1404: public RateFormat getRateFormat() {
1405: return RateFormat.getInstance(getTimeUnitLabel(), false,
1406: isLabor(), isLabor());
1407: }
1408:
1409: public String getResourceName() {
1410: return getName();
1411: }
1412:
1413: public ImageLink getBudgetStatusIndicator() {
1414: return EarnedValueCalculator.getInstance()
1415: .getBudgetStatusIndicator(getCpi(null));
1416: }
1417:
1418: public ImageLink getScheduleStatusIndicator() {
1419: return EarnedValueCalculator.getInstance()
1420: .getBudgetStatusIndicator(getSpi(null));
1421: }
1422:
1423: public boolean isUser() {
1424: return userAccount != null && userAccount.length() > 0;
1425: }
1426:
1427: public void renumber() {
1428: hasKey.renumber();
1429: }
1430:
1431: public boolean isAssignedToSomeProject() {
1432: if (hasAssignments.getAssignments().size() > 0)
1433: return true;
1434: if (globalWorkVector == null || globalWorkVector.size() == 0) // note that this doesn't mean there isn't baseline info assigned
1435: return false;
1436: return true;
1437: }
1438:
1439: private transient Set<Integer> authorizedRoles;
1440:
1441: public Set<Integer> getAuthorizedRoles() {
1442: return authorizedRoles;
1443: }
1444:
1445: public void setAuthorizedRoles(Set<Integer> authorizedRoles) {
1446: this .authorizedRoles = authorizedRoles;
1447: }
1448:
1449: public void filterRoles(List keys, List values) {
1450: if (authorizedRoles == null)
1451: return;
1452: Iterator k = keys.iterator();
1453: Iterator<Integer> v = ((List<Integer>) values).iterator();
1454: Object inactiveKey = null;
1455: while (v.hasNext()) {
1456: Object key = k.next();
1457: int r = v.next();
1458: if (r == ApplicationUser.INACTIVE)
1459: inactiveKey = key;
1460: if ((r == ApplicationUser.INACTIVE && getAssignments()
1461: .size() > 0)
1462: || !authorizedRoles.contains(r))
1463: k.remove();
1464: }
1465: if (keys.size() == 0)
1466: keys.add(inactiveKey); //occurs when an user becomes "inactive"
1467: }
1468:
1469: private transient int defaultRole;
1470:
1471: public int getDefaultRole() {
1472: return defaultRole;
1473: }
1474:
1475: public void setDefaultRole(int defaultRole) {
1476: this .defaultRole = defaultRole;
1477: }
1478:
1479: private transient int license;
1480: private transient int licenseOptions;
1481:
1482: public int getLicense() {
1483: return license;
1484: }
1485:
1486: public void setLicense(int license) {
1487: this .license = license;
1488: }
1489:
1490: public int getLicenseOptions() {
1491: return licenseOptions;
1492: }
1493:
1494: public void setLicenseOptions(int licenseOptions) {
1495: this .licenseOptions = licenseOptions;
1496: }
1497:
1498: public boolean isInactiveLicense() {
1499: return license == ApplicationUser.INACTIVE;
1500: }
1501:
1502: public boolean isExternal() {
1503: return (licenseOptions & ApplicationUser.EXTERNAL) == ApplicationUser.EXTERNAL;
1504: }
1505:
1506: public boolean isAdministrator() {
1507: return (licenseOptions & ApplicationUser.ADMINISTRATOR) == ApplicationUser.ADMINISTRATOR;
1508: }
1509:
1510: private transient AvailabilityTable availabilityTable = new AvailabilityTable(
1511: null);
1512:
1513: public AvailabilityTable getAvailabilityTable() {
1514: //TODO implement this somehow. need to figure out relationship to ResourceImpl version
1515: // Do projects have their own availability tables or not?
1516: // TODO Auto-generated method stub
1517: return availabilityTable;
1518: }
1519:
1520: protected transient Object serverMeta;
1521:
1522: public Object getServerMeta() {
1523: return serverMeta;
1524: }
1525:
1526: public void setServerMeta(Object serverMeta) {
1527: this.serverMeta = serverMeta;
1528: }
1529:
1530: }
|