001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright © 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.pm.assignment.contour;
051:
052: import java.util.ArrayList;
053: import java.util.LinkedList;
054:
055: import com.projity.datatype.DurationFormat;
056: import com.projity.pm.time.MutableInterval;
057:
058: /**
059: * Abstract base class for work and cost contours
060: * @stereotype strategy
061: */
062: public abstract class AbstractContour implements Cloneable {
063: protected AbstractContourBucket[] contourBuckets = null;
064: protected double maxUnits = 0;
065:
066: public abstract int getType();
067:
068: public abstract boolean isPersonal();
069:
070: public abstract long calcTotalWork(long assignmentDuration);
071:
072: public AbstractContour adjustDuration(long newDuration,
073: long actualDuration) {
074: return this ;
075: } // only personal contours will treat this
076:
077: public AbstractContour adjustUnits(double multiplier,
078: long startingFrom) {
079: return this ;
080: } // only personal contours will treat this
081:
082: public AbstractContour contourAdjustWork(double multiplier,
083: long actualDuration) {
084: return this ;
085: }// only personal contours will treat this
086:
087: public AbstractContourBucket[] getContourBuckets() {
088: return contourBuckets;
089: }
090:
091: public abstract String getName();
092:
093: public int numBuckets() {
094: if (contourBuckets == null)
095: return 0;
096: return contourBuckets.length;
097: }
098:
099: private long calcSumBucketDuration(long assignmentDuration,
100: boolean excludeNonWorkBuckets) {
101: long duration = 0;
102: for (int i = 0; i < contourBuckets.length; i++) {
103: if (contourBuckets[i] == null)
104: System.out.println(toString(assignmentDuration));
105: if (!excludeNonWorkBuckets
106: || contourBuckets[i].getUnits() != 0.0) // do not add in durations for time off if excluding nonwork buckets
107: duration += contourBuckets[i]
108: .getBucketDuration(assignmentDuration);
109: }
110: return duration;
111: }
112:
113: public long calcTotalBucketDuration(long assignmentDuration) {
114: return calcSumBucketDuration(assignmentDuration, false);
115: }
116:
117: public long calcWorkingBucketDuration(long assignmentDuration) {
118: return calcSumBucketDuration(assignmentDuration, true);
119: }
120:
121: protected double calcMaxUnits() {
122: double units = 0.0;
123: for (int i = 0; i < contourBuckets.length; i++) {
124: if (contourBuckets[i] != null) // in case called from constructor and array is unitialized
125: units = Math.max(units, contourBuckets[i].getUnits());
126: }
127: return units;
128: }
129:
130: /**
131: * Returns an array list containing elements of bucket array
132: * @return
133: */
134: public ArrayList toArrayList() {
135: if (contourBuckets == null)
136: return null;
137:
138: ArrayList list = new ArrayList(contourBuckets.length);
139: for (int i = 0; i < contourBuckets.length; i++) {
140: list.add(contourBuckets[i]);
141: }
142: return list;
143: }
144:
145: /**
146: * @return Returns the maxUnits.
147: */
148: public double getMaxUnits() {
149: return maxUnits;
150: }
151:
152: public AbstractContour(AbstractContourBucket contourBuckets[]) {
153: this .contourBuckets = contourBuckets;
154: maxUnits = calcMaxUnits();
155: }
156:
157: /**
158: * Returns a linked list of buckets that fall between two duration points. Used when copying planned to actuals.
159: * @param start
160: * @param end
161: * @param assignmentDuration
162: * @return
163: */
164: public LinkedList bucketsBetweenDurations(long start, long end,
165: long assignmentDuration) {
166: LinkedList list = new LinkedList();
167: AbstractContourBucket bucket = null;
168: long currentEnd = 0;
169: long currentStart = 0;
170: AbstractContourBucket newBucket;
171: for (int i = 0; i < contourBuckets.length; i++) {
172: bucket = contourBuckets[i];
173: currentStart = currentEnd;
174: currentEnd += bucket.getBucketDuration(assignmentDuration);
175: if (currentEnd <= start) // if not at start yet, keep going
176: continue;
177: if (currentStart >= end) // if past end, stop
178: break;
179: // Add a new bucket that falls both within this bucket and the between range
180: long newBucketDuration = Math.min(end, currentEnd)
181: - Math.max(start, currentStart);
182: list.add(PersonalContourBucket.getInstance(
183: newBucketDuration, bucket.getUnits()));
184: }
185: return list;
186: }
187:
188: public String toString(long assignmentDuration) {
189: StringBuffer result = new StringBuffer();
190: if (contourBuckets == null)
191: return null;
192: for (int i = 0; i < contourBuckets.length; i++) {
193: result.append("bucket[" + i + "]");
194: if (contourBuckets[i] == null)
195: result.append(" NULL!");
196: else
197: result.append(" duration="
198: + DurationFormat.format(contourBuckets[i]
199: .getBucketDuration(assignmentDuration))
200: + " units " + contourBuckets[i].getUnits()
201: + "\n");
202: }
203: return result.toString();
204: }
205:
206: public String toString() {
207: return toString(0);
208: }
209:
210: /**
211: * @param end
212: * @param extendDuration
213: * @return
214: */
215: public abstract AbstractContour extend(long end, long extendDuration);
216:
217: /**
218: * @param startOffset
219: * @param extendDuration
220: * @return
221: */
222: public abstract AbstractContour extendBefore(long startOffset,
223: long extendDuration);
224:
225: public abstract MutableInterval getRangeThatIntervalCanBeMoved(
226: long start, long end);
227:
228: public AbstractContour removeFillerAfter(long atDuration) {
229: return this ;
230: }
231:
232: /**
233: * Remove any starting empty bucket from the contour and return the duration of that bucket
234: * @return
235: */
236: public long extractDelay() {
237: return 0;
238: }
239:
240: public Object clone() {
241: try {
242: AbstractContour c = (AbstractContour) super .clone();
243: if (contourBuckets != null) {
244: c.contourBuckets = new AbstractContourBucket[contourBuckets.length];
245: for (int i = 0; i < contourBuckets.length; i++) {
246: c.contourBuckets[i] = (AbstractContourBucket) contourBuckets[i]
247: .clone();
248: }
249: }
250: return c;
251: } catch (CloneNotSupportedException e) {
252: throw new InternalError();
253: }
254: }
255:
256: public double getLastBucketUnits() {
257: return contourBuckets[contourBuckets.length - 1].getUnits();
258: }
259:
260: }
|