source: trunk/src/org/expeditee/items/widgets/charts/TimeSeries.java@ 1102

Last change on this file since 1102 was 1102, checked in by davidb, 6 years ago

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File size: 6.8 KB
Line 
1/**
2 * TimeSeries.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.items.widgets.charts;
20
21import java.text.DateFormat;
22import java.text.ParseException;
23import java.text.SimpleDateFormat;
24import java.util.Calendar;
25import java.util.Collection;
26import java.util.Date;
27
28import org.expeditee.Util;
29import org.expeditee.core.Colour;
30import org.expeditee.gio.swing.SwingConversions;
31import org.expeditee.gui.AttributeValuePair;
32import org.expeditee.gui.Frame;
33import org.expeditee.gui.MessageBay;
34import org.expeditee.items.Text;
35import org.expeditee.stats.Formatter;
36import org.jfree.chart.ChartFactory;
37import org.jfree.chart.JFreeChart;
38import org.jfree.data.time.Day;
39import org.jfree.data.time.Hour;
40import org.jfree.data.time.Millisecond;
41import org.jfree.data.time.Minute;
42import org.jfree.data.time.Month;
43import org.jfree.data.time.Quarter;
44import org.jfree.data.time.RegularTimePeriod;
45import org.jfree.data.time.Second;
46import org.jfree.data.time.TimeSeriesCollection;
47import org.jfree.data.time.Week;
48import org.jfree.data.time.Year;
49import org.jfree.data.xy.XYDataset;
50
51public class TimeSeries extends AbstractValueAxis {
52
53 public TimeSeries(Text source, String[] args) {
54 super(source, args);
55 }
56
57 private TimeSeriesCollection _data;
58
59 private Class<? extends RegularTimePeriod> _periodType;
60
61 private Date _startDate;
62
63 protected XYDataset getChartData() {
64 if (_data == null)
65 _data = new TimeSeriesCollection();
66 return _data;
67 }
68
69 @Override
70 public void refreshData(Frame dataFrame) {
71 String period = dataFrame.getAnnotationValue("period");
72 if (period == null) {
73 period = "day";
74 } else {
75 period = period.toLowerCase();
76 }
77 if (period.startsWith("quarter")) {
78 _periodType = Quarter.class;
79 } else if (period.startsWith("year")) {
80 _periodType = Year.class;
81 } else if (period.startsWith("month")) {
82 _periodType = Month.class;
83 } else if (period.startsWith("week")) {
84 _periodType = Week.class;
85 } else if (period.startsWith("hour")) {
86 _periodType = Hour.class;
87 } else if (period.startsWith("min")) {
88 _periodType = Minute.class;
89 } else if (period.startsWith("sec")) {
90 _periodType = Second.class;
91 } else if (period.startsWith("milli")) {
92 _periodType = Millisecond.class;
93 } else if (period.startsWith("day")) {
94 _periodType = Day.class;
95 } else {
96 MessageBay.errorMessage("Invalid time series period type: "
97 + period);
98 _periodType = Day.class;
99 }
100
101 try {
102 String startDateString = dataFrame.getAnnotationValue("start");
103 if (startDateString != null) {
104 _startDate = Util.parseDate(startDateString);
105 }
106 } catch (Exception e) {
107 // Use the current date
108 }
109 if (_startDate == null) {
110 _startDate = new Date();
111 }
112 super.refreshData(dataFrame);
113 }
114
115 /**
116 * @param dataFrame
117 */
118 @Override
119 protected void clearData() {
120 _data.removeAllSeries();
121 }
122
123 @Override
124 protected JFreeChart createNewChart() {
125 return ChartFactory.createTimeSeriesChart(DEFAULT_TITLE, DEFAULT_XAXIS,
126 DEFAULT_YAXIS, getChartData(), true, // legend?
127 true, // tooltips?
128 false // URLs?
129 );
130 }
131
132 @Override
133 protected boolean addCategoryData(String categoryName,
134 Collection<Text> items, boolean swap) {
135 org.jfree.data.time.TimeSeries newSeries = new org.jfree.data.time.TimeSeries(
136 categoryName, _periodType);
137
138 boolean foundData = false;
139 Colour newColor = null;
140 for (Text i : items) {
141 if (!i.isLineEnd()) {
142 Text t = (Text) i;
143 AttributeValuePair avp = new AttributeValuePair(t.getText());
144 if (avp != null) {
145 Double attribute = null;
146 try {
147 attribute = avp.getDoubleAttribute();
148 } catch (NumberFormatException e) {
149 }
150 Double value = null;
151 try {
152 // If the data is not valid move to the next item
153 value = avp.getDoubleValue();
154 } catch (NumberFormatException e) {
155 continue;
156 }
157
158 try {
159 RegularTimePeriod rtp = null;
160 if (attribute == null) {
161 Date date = Util.parseDate(avp.getAttribute());
162 rtp = _periodType.getConstructor(
163 new Class[] { Date.class }).newInstance(
164 new Object[] { date });
165 } else {
166 if (_periodType.equals(Year.class)) {
167 int year = (int) Math.floor(attribute);
168 Calendar c = Calendar.getInstance();
169 c.setTime(_startDate);
170 rtp = new Year(year + c.get(Calendar.YEAR));
171 } else if (_periodType.equals(Quarter.class)) {
172 int quarter = (int) Math.floor(attribute);
173 rtp = new Quarter(quarter, new Year(_startDate));
174 } else if (_periodType.equals(Month.class)) {
175 int month = (int) Math.floor(attribute);
176 rtp = new Month(month, new Year(_startDate));
177 } else if (_periodType.equals(Week.class)) {
178 int week = (int) Math.floor(attribute);
179 rtp = new Week(week, new Year(_startDate));
180 } else if (_periodType.equals(Day.class)) {
181 int day = (int) Math.floor(attribute);
182 Calendar c = Calendar.getInstance();
183 c.setTime(_startDate);
184 rtp = new Day(day
185 + c.get(Calendar.DAY_OF_MONTH), 1 + c
186 .get(Calendar.MONTH), c
187 .get(Calendar.YEAR));
188 } else if (_periodType.equals(Hour.class)) {
189 int hour = (int) Math.floor(attribute);
190 rtp = new Hour(hour, new Day(_startDate));
191 } else if (_periodType.equals(Minute.class)) {
192 int minute = (int) Math.floor(attribute);
193 rtp = new Minute(minute, new Hour(_startDate));
194 } else if (_periodType.equals(Second.class)) {
195 int second = (int) Math.floor(attribute);
196 rtp = new Second(second, new Minute(_startDate));
197 } else if (_periodType.equals(Millisecond.class)) {
198 int milli = (int) Math.floor(attribute);
199 rtp = new Millisecond(milli, new Second(
200 _startDate));
201 }
202 }
203 newSeries.add(rtp, value);
204 foundData = true;
205 if (newColor == null)
206 newColor = i.getColor();
207 } catch (Exception e) {
208 // Ignore the data point if it cant be parsed
209 e.printStackTrace();
210 }
211 }
212 }
213 }
214 if (foundData) {
215 _data.addSeries(newSeries);
216 _paints.put(categoryName, SwingConversions.toSwingColor(newColor));
217 }
218 return foundData;
219 }
220}
Note: See TracBrowser for help on using the repository browser.