1:
45:
46: package ;
47:
48: import ;
49: import ;
50: import ;
51:
52: import ;
53: import ;
54:
55:
63: public class TimePeriodValues extends Series implements Serializable {
64:
65:
66: static final long serialVersionUID = -2210593619794989709L;
67:
68:
69: protected static final String DEFAULT_DOMAIN_DESCRIPTION = "Time";
70:
71:
72: protected static final String DEFAULT_RANGE_DESCRIPTION = "Value";
73:
74:
75: private String domain;
76:
77:
78: private String range;
79:
80:
81: private List data;
82:
83:
84: private int minStartIndex = -1;
85:
86:
87: private int maxStartIndex = -1;
88:
89:
90: private int minMiddleIndex = -1;
91:
92:
93: private int maxMiddleIndex = -1;
94:
95:
96: private int minEndIndex = -1;
97:
98:
99: private int maxEndIndex = -1;
100:
101:
106: public TimePeriodValues(String name) {
107: this(name, DEFAULT_DOMAIN_DESCRIPTION, DEFAULT_RANGE_DESCRIPTION);
108: }
109:
110:
121: public TimePeriodValues(String name, String domain, String range) {
122: super(name);
123: this.domain = domain;
124: this.range = range;
125: this.data = new ArrayList();
126: }
127:
128:
133: public String getDomainDescription() {
134: return this.domain;
135: }
136:
137:
142: public void setDomainDescription(String description) {
143: String old = this.domain;
144: this.domain = description;
145: firePropertyChange("Domain", old, description);
146: }
147:
148:
153: public String getRangeDescription() {
154: return this.range;
155: }
156:
157:
162: public void setRangeDescription(String description) {
163: String old = this.range;
164: this.range = description;
165: firePropertyChange("Range", old, description);
166: }
167:
168:
173: public int getItemCount() {
174: return this.data.size();
175: }
176:
177:
184: public TimePeriodValue getDataItem(int index) {
185: return (TimePeriodValue) this.data.get(index);
186: }
187:
188:
195: public TimePeriod getTimePeriod(int index) {
196: return getDataItem(index).getPeriod();
197: }
198:
199:
206: public Number getValue(int index) {
207: return getDataItem(index).getValue();
208: }
209:
210:
215: public void add(TimePeriodValue item) {
216:
217:
218: if (item == null) {
219: throw new IllegalArgumentException("Null item not allowed.");
220: }
221:
222:
223: this.data.add(item);
224: updateBounds(item.getPeriod(), this.data.size() - 1);
225:
226: }
227:
228:
234: private void updateBounds(TimePeriod period, int index) {
235:
236: long start = period.getStart().getTime();
237: long end = period.getEnd().getTime();
238: long middle = start + ((end - start) / 2);
239:
240: if (this.minStartIndex >= 0) {
241: long minStart = getDataItem(this.minStartIndex).getPeriod()
242: .getStart().getTime();
243: if (start < minStart) {
244: this.minStartIndex = index;
245: }
246: }
247: else {
248: this.minStartIndex = index;
249: }
250:
251: if (this.maxStartIndex >= 0) {
252: long maxStart = getDataItem(this.maxStartIndex).getPeriod()
253: .getStart().getTime();
254: if (start > maxStart) {
255: this.maxStartIndex = index;
256: }
257: }
258: else {
259: this.maxStartIndex = index;
260: }
261:
262: if (this.minMiddleIndex >= 0) {
263: long s = getDataItem(this.minMiddleIndex).getPeriod().getStart()
264: .getTime();
265: long e = getDataItem(this.minMiddleIndex).getPeriod().getEnd()
266: .getTime();
267: long minMiddle = s + (e - s) / 2;
268: if (middle < minMiddle) {
269: this.minMiddleIndex = index;
270: }
271: }
272: else {
273: this.minMiddleIndex = index;
274: }
275:
276: if (this.maxMiddleIndex >= 0) {
277: long s = getDataItem(this.minMiddleIndex).getPeriod().getStart()
278: .getTime();
279: long e = getDataItem(this.minMiddleIndex).getPeriod().getEnd()
280: .getTime();
281: long maxMiddle = s + (e - s) / 2;
282: if (middle > maxMiddle) {
283: this.maxMiddleIndex = index;
284: }
285: }
286: else {
287: this.maxMiddleIndex = index;
288: }
289:
290: if (this.minEndIndex >= 0) {
291: long minEnd = getDataItem(this.minEndIndex).getPeriod().getEnd()
292: .getTime();
293: if (end < minEnd) {
294: this.minEndIndex = index;
295: }
296: }
297: else {
298: this.minEndIndex = index;
299: }
300:
301: if (this.maxEndIndex >= 0) {
302: long maxEnd = getDataItem(this.maxEndIndex).getPeriod().getEnd()
303: .getTime();
304: if (end > maxEnd) {
305: this.maxEndIndex = index;
306: }
307: }
308: else {
309: this.maxEndIndex = index;
310: }
311:
312: }
313:
314:
317: private void recalculateBounds() {
318: this.minStartIndex = -1;
319: this.minMiddleIndex = -1;
320: this.minEndIndex = -1;
321: this.maxStartIndex = -1;
322: this.maxMiddleIndex = -1;
323: this.maxEndIndex = -1;
324: for (int i = 0; i < this.data.size(); i++) {
325: TimePeriodValue tpv = (TimePeriodValue) this.data.get(i);
326: updateBounds(tpv.getPeriod(), i);
327: }
328: }
329:
330:
336: public void add(TimePeriod period, double value) {
337: TimePeriodValue item = new TimePeriodValue(period, value);
338: add(item);
339: }
340:
341:
347: public void add(TimePeriod period, Number value) {
348: TimePeriodValue item = new TimePeriodValue(period, value);
349: add(item);
350: }
351:
352:
358: public void update(int index, Number value) {
359: TimePeriodValue item = getDataItem(index);
360: item.setValue(value);
361: fireSeriesChanged();
362: }
363:
364:
370: public void delete(int start, int end) {
371: for (int i = 0; i <= (end - start); i++) {
372: this.data.remove(start);
373: }
374: recalculateBounds();
375: fireSeriesChanged();
376: }
377:
378:
385: public boolean equals(Object obj) {
386:
387: if (obj == this) {
388: return true;
389: }
390:
391: if (!(obj instanceof TimePeriodValues)) {
392: return false;
393: }
394:
395: if (!super.equals(obj)) {
396: return false;
397: }
398:
399: TimePeriodValues that = (TimePeriodValues) obj;
400: if (!getDomainDescription().equals(that.getDomainDescription())) {
401: return false;
402: }
403: if (!getRangeDescription().equals(that.getRangeDescription())) {
404: return false;
405: }
406:
407: int count = getItemCount();
408: if (count != that.getItemCount()) {
409: return false;
410: }
411: for (int i = 0; i < count; i++) {
412: if (!getDataItem(i).equals(that.getDataItem(i))) {
413: return false;
414: }
415: }
416: return true;
417:
418: }
419:
420:
425: public int hashCode() {
426: int result;
427: result = (this.domain != null ? this.domain.hashCode() : 0);
428: result = 29 * result + (this.range != null ? this.range.hashCode() : 0);
429: result = 29 * result + this.data.hashCode();
430: result = 29 * result + this.minStartIndex;
431: result = 29 * result + this.maxStartIndex;
432: result = 29 * result + this.minMiddleIndex;
433: result = 29 * result + this.maxMiddleIndex;
434: result = 29 * result + this.minEndIndex;
435: result = 29 * result + this.maxEndIndex;
436: return result;
437: }
438:
439:
454: public Object clone() throws CloneNotSupportedException {
455: Object clone = createCopy(0, getItemCount() - 1);
456: return clone;
457: }
458:
459:
470: public TimePeriodValues createCopy(int start, int end)
471: throws CloneNotSupportedException {
472:
473: TimePeriodValues copy = (TimePeriodValues) super.clone();
474:
475: copy.data = new ArrayList();
476: if (this.data.size() > 0) {
477: for (int index = start; index <= end; index++) {
478: TimePeriodValue item = (TimePeriodValue) this.data.get(index);
479: TimePeriodValue clone = (TimePeriodValue) item.clone();
480: try {
481: copy.add(clone);
482: }
483: catch (SeriesException e) {
484: System.err.println("Failed to add cloned item.");
485: }
486: }
487: }
488: return copy;
489:
490: }
491:
492:
497: public int getMinStartIndex() {
498: return this.minStartIndex;
499: }
500:
501:
506: public int getMaxStartIndex() {
507: return this.maxStartIndex;
508: }
509:
510:
516: public int getMinMiddleIndex() {
517: return this.minMiddleIndex;
518: }
519:
520:
526: public int getMaxMiddleIndex() {
527: return this.maxMiddleIndex;
528: }
529:
530:
535: public int getMinEndIndex() {
536: return this.minEndIndex;
537: }
538:
539:
544: public int getMaxEndIndex() {
545: return this.maxEndIndex;
546: }
547:
548: }