Source Code Cross Referenced for TaskVelocityData.java in  » Project-Management » XPlanner-0.7b7 » com » technoetic » xplanner » charts » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Project Management » XPlanner 0.7b7 » com.technoetic.xplanner.charts 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.technoetic.xplanner.charts;
002:
003:        import org.jfree.chart.tooltips.CategoryToolTipGenerator;
004:        import org.jfree.data.CategoryDataset;
005:        import org.jfree.data.DefaultCategoryDataset;
006:        import com.technoetic.xplanner.db.IterationStatisticsQuery;
007:        import com.technoetic.xplanner.domain.Task;
008:        import com.technoetic.xplanner.domain.TimeEntry;
009:        import de.laures.cewolf.CategoryItemLinkGenerator;
010:        import de.laures.cewolf.DatasetProduceException;
011:        import de.laures.cewolf.DatasetProducer;
012:        import org.apache.log4j.Category;
013:
014:        import java.io.Serializable;
015:        import java.text.SimpleDateFormat;
016:        import java.util.Calendar;
017:        import java.util.Collection;
018:        import java.util.Date;
019:        import java.util.GregorianCalendar;
020:        import java.util.HashMap;
021:        import java.util.Iterator;
022:        import java.util.Map;
023:
024:        public class TaskVelocityData implements  DatasetProducer,
025:                CategoryItemLinkGenerator, CategoryToolTipGenerator,
026:                Serializable {
027:            private static final Category log = Category
028:                    .getInstance("TaskVelocityData");
029:
030:            private static final int COMPLETED_SERIES = 0;
031:            private static final int REQUIRED_SERIES = 1;
032:
033:            private String[] seriesNames = new String[REQUIRED_SERIES + 1];
034:            private String[] seriesPrefix = new String[REQUIRED_SERIES + 1];
035:            private SimpleDateFormat majorFormatter = null;
036:
037:            private Integer[][] values = null;
038:            private DefaultCategoryDataset dataSet = null;
039:
040:            private static final SimpleDateFormat keyFormatter = new SimpleDateFormat(
041:                    "yyyy.MM.dd");
042:
043:            // Utility methods ======================================================
044:
045:            /**
046:             * Indicates if the specified day of the week is a working day. Saturday and Sunday are assumed to not be
047:             * working days and are not shown on the velocity graph.
048:             *
049:             * @param dayOfWeek the specified day (from the <code>Calendar</code> interface) to check the status of.
050:             *
051:             * @return <code>true</code> if the specified day is a work day, otherwise <code>false</code>.
052:             */
053:            private static boolean isWorkingDay(int dayOfWeek) {
054:                if ((dayOfWeek == Calendar.SATURDAY)
055:                        || (dayOfWeek == Calendar.SUNDAY)) {
056:                    return false;
057:                } else {
058:                    return true;
059:                }
060:            }
061:
062:            /**
063:             * Indicates if the specified day of the week is a the first day of the working week.
064:             *
065:             * @param dayOfWeek the specified day (from the <code>Calendar</code> interface) to check the status of.
066:             *
067:             * @return <code>true</code> if the specified day is the first day of the week, otherwise <code>false</code>.
068:             */
069:            private static boolean isFirstDayOfWeek(int dayOfWeek) {
070:                if (dayOfWeek == Calendar.MONDAY) {
071:                    return true;
072:                } else {
073:                    return false;
074:                }
075:            }
076:
077:            /**
078:             * Returns the number of working days between the sepcifed dates.
079:             *
080:             * @param startTime the start of the date range.
081:             * @param endTime the end of the date range.
082:             *
083:             * @return the number of working days between the specified dates.
084:             */
085:            private static int getNumberOfWorkingDays(Date startTime,
086:                    Date endTime) {
087:                Calendar start = new GregorianCalendar();
088:                start.setTime(startTime);
089:                Calendar end = new GregorianCalendar();
090:                end.setTime(endTime);
091:
092:                Calendar current = start;
093:                int numWorkingDays = 0;
094:
095:                while (current.before(end)) {
096:                    if (isWorkingDay(current.get(Calendar.DAY_OF_WEEK))) {
097:                        numWorkingDays++;
098:                    }
099:
100:                    current.add(Calendar.DATE, 1);
101:                }
102:
103:                return numWorkingDays;
104:            }
105:
106:            /**
107:             * Generates a <code>HashMap</code> key from the supplied date.
108:             *
109:             * @param date the date for which a key is to be generated.
110:             *
111:             * @return the key associated with the specified date.
112:             */
113:            private static String buildKeyFromDate(Date date) {
114:                return keyFormatter.format(date);
115:            }
116:
117:            /**
118:             * Increments the value stored in the map at the specified date.
119:             *
120:             * @param dateValues the map which contains the set of existing dates and their associated values.
121:             * @param dateToChange the date for which the amount is to be increment.
122:             * @param incrementAmount the amount to increment by.
123:             */
124:            private void incrementValueOnDate(HashMap dateValues,
125:                    Date dateToChange, double incrementAmount) {
126:                String dateKey = buildKeyFromDate(dateToChange);
127:                Double currentAmount = (Double) dateValues.get(dateKey);
128:
129:                if (currentAmount == null) {
130:                    currentAmount = new Double(incrementAmount);
131:                } else {
132:                    currentAmount = new Double(currentAmount.doubleValue()
133:                            + incrementAmount);
134:                }
135:
136:                dateValues.put(dateKey, currentAmount);
137:            }
138:
139:            /**
140:             * Returns then data at which the specified task was completed. The completed time is assumed to be the last
141:             * time entry specified for the task rounded to the end of the day.
142:             *
143:             * @param task the task to be examined.
144:             *
145:             * @return The date at which the task was completed.
146:             */
147:            private Date getCompletedDate(Task task) {
148:                Date completedTime = null;
149:
150:                Collection timeEntries = task.getTimeEntries();
151:                if (timeEntries != null) {
152:                    Iterator iter = timeEntries.iterator();
153:
154:                    while (iter.hasNext()) {
155:                        TimeEntry entry = (TimeEntry) iter.next();
156:                        Date endTime = entry.getEndTime();
157:
158:                        // This is a fix for duration-only entries
159:                        // It may not be quite right.
160:                        if (endTime == null && entry.getDuration() > 0) {
161:                            endTime = entry.getLastUpdateTime();
162:                        }
163:
164:                        if (endTime != null) {
165:                            if ((completedTime == null)
166:                                    || (endTime.after(completedTime))) {
167:                                completedTime = endTime;
168:                            }
169:                        }
170:                    }
171:                }
172:
173:                if (completedTime == null) {
174:                    log.error("Asked for completion time of task ["
175:                            + task.getId()
176:                            + "] which wasn't marked as completed");
177:                    return null;
178:                } else {
179:                    return completedTime;
180:                }
181:            }
182:
183:            /**
184:             * Returns a two dimensional array, for the category and series information, sized to the duration of the
185:             * iteration. It is assumed that the data will only contain entries for working days.
186:             *
187:             * @param startTime the date at which the iteration started.
188:             * @param endTime the date at which the iteration ended.
189:             *
190:             * @return A two dimensional array where the first dimension contains the hour values and the second
191:             * dimension contains the series.
192:             */
193:            private Integer[][] initializeDataArray(Date startTime, Date endTime) {
194:                return new Integer[seriesNames.length][getNumberOfWorkingDays(
195:                        startTime, endTime)];
196:            }
197:
198:            /**
199:             * Addes the supplied data values to the specified series of the chart. The series are culuminative.
200:             * The data supplied to create the series indicates the increment at each date in the series. Note,
201:             * since the source date is doubles, but the series data can only contains whole numbers, some small
202:             * rounding errors may occur.
203:             *
204:             * @param lineData two dimensional array to be populated with the series point information.
205:             * @param seriesNum the index of the series in the line data to which the data should be added.
206:             * @param startDate the date at which the first entry in the chart starts at.
207:             * @param dataValues expected to contain a set of <code>Double</code> values keys by <code>Dates</code>.
208:             * For example it may specify the effort (hours) complete on individual dates.
209:             */
210:            private void addSeriesData(Integer[][] lineData, int seriesNum,
211:                    Date startDate, HashMap dataValues) {
212:                if (dataValues.size() == 0) {
213:                    return;
214:                }
215:
216:                // Step through the points of the series and accumulate their values one day at a time
217:                //
218:                Calendar now = new GregorianCalendar();
219:                Calendar currentDate = new GregorianCalendar();
220:                currentDate.setTime(startDate);
221:                double cumulativeValue = 0.0;
222:                int dayIndex = 0;
223:
224:                while (dayIndex < lineData[seriesNum].length) {
225:                    Double value = (Double) dataValues
226:                            .get(buildKeyFromDate(currentDate.getTime()));
227:
228:                    if (value != null) {
229:                        cumulativeValue += value.doubleValue();
230:                    }
231:
232:                    if (isWorkingDay(currentDate.get(Calendar.DAY_OF_WEEK))) {
233:                        if (currentDate.getTimeInMillis() < now
234:                                .getTimeInMillis()) {
235:                            int pointValue = (int) Math.round(cumulativeValue);
236:                            lineData[seriesNum][dayIndex] = new Integer(
237:                                    pointValue);
238:                        } else {
239:                            lineData[seriesNum][dayIndex] = null;
240:                        }
241:                        dayIndex++;
242:                    }
243:
244:                    currentDate.add(Calendar.DATE, 1);
245:                }
246:            }
247:
248:            /**
249:             * Returns the list of dates that make up the x-axis of the velocity graph. THe first day of each week
250:             * is represented by the date all other days are represented by their index within the velocity.
251:             *
252:             * @param startDate the date at which the first entry in the chart starts at.
253:             * @param lineData two dimensional array to be populated with the series point information.
254:             *
255:             * @return The names to be displayed for date entries on the x-axis.
256:             */
257:            private String[] createCategoryNames(Date startDate,
258:                    Integer[][] lineData) {
259:                int numDays = lineData[0].length;
260:                String[] categories = new String[numDays];
261:
262:                Calendar currentDate = new GregorianCalendar();
263:                currentDate.setTime(startDate);
264:                int dayIndex = 0;
265:
266:                while (dayIndex < numDays) {
267:                    int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK);
268:
269:                    if (isWorkingDay(dayOfWeek)) {
270:                        if (isFirstDayOfWeek(dayOfWeek)) {
271:                            categories[dayIndex] = majorFormatter
272:                                    .format(currentDate.getTime());
273:                        } else {
274:                            //categories[dayIndex] = Long.toString(dayIndex);
275:                            categories[dayIndex] = Long.toString(currentDate
276:                                    .get(Calendar.DAY_OF_MONTH));
277:                        }
278:                        dayIndex++;
279:                    }
280:
281:                    currentDate.add(Calendar.DATE, 1);
282:                }
283:
284:                return categories;
285:            }
286:
287:            // Public methods =======================================================
288:
289:            public void setStatistics(IterationStatisticsQuery statistics) {
290:                // Before generating the graph data ensure all the required objects are set
291:                //
292:                seriesNames[COMPLETED_SERIES] = statistics
293:                        .getResourceString("iteration.statistics.velocity.series_completed");
294:                seriesNames[REQUIRED_SERIES] = statistics
295:                        .getResourceString("iteration.statistics.velocity.series_required");
296:
297:                seriesPrefix[COMPLETED_SERIES] = statistics
298:                        .getResourceString("iteration.statistics.velocity.prefix_completed");
299:                seriesPrefix[REQUIRED_SERIES] = statistics
300:                        .getResourceString("iteration.statistics.velocity.prefix_required");
301:
302:                majorFormatter = new SimpleDateFormat(statistics
303:                        .getResourceString("format.date"));
304:
305:                Date velocityStart = statistics.getIteration().getStartDate();
306:                Date velocityEnd = statistics.getIteration().getEndDate();
307:
308:                // Build a list of all the dates at which tasks were added to the system. Any
309:                // dates past the start or end of the iteration are added to the first and last
310:                // day of the iteration.
311:                //
312:                Collection tasks = statistics.getIterationTasks();
313:                HashMap effortAdded = new HashMap(tasks.size());
314:
315:                Iterator iter = tasks.iterator();
316:                while (iter.hasNext()) {
317:                    Task task = (Task) iter.next();
318:                    Date createdDate = task.getCreatedDate();
319:
320:                    if ((createdDate == null) || (createdDate.getTime() == 0)
321:                            || (createdDate.before(velocityStart))) {
322:                        createdDate = velocityStart;
323:                    } else if (createdDate.after(velocityEnd)) {
324:                        createdDate = velocityEnd;
325:                    }
326:
327:                    incrementValueOnDate(effortAdded, createdDate, task
328:                            .getEstimatedOriginalHours());
329:                }
330:
331:                // Build a list of all the dates at which tasks are completed.
332:                //
333:                HashMap effortCompleted = new HashMap(tasks.size());
334:
335:                iter = tasks.iterator();
336:                while (iter.hasNext()) {
337:                    Task task = (Task) iter.next();
338:
339:                    if (task.isCompleted()) {
340:                        Date completedDate = getCompletedDate(task);
341:
342:                        // If a task was completed but it didn't have any time entries then assume that
343:                        // it finished when it was created.
344:                        //
345:                        if (completedDate == null) {
346:                            completedDate = task.getCreatedDate();
347:
348:                            if ((completedDate == null)
349:                                    || (completedDate.getTime() == 0)) {
350:                                completedDate = velocityStart;
351:                            }
352:                        }
353:
354:                        incrementValueOnDate(effortCompleted, completedDate,
355:                                task.getEstimatedOriginalHours());
356:                    }
357:                }
358:
359:                // Now that we know the range of the iteration we can go through each day calculating the
360:                // hour completed and required on that single day.
361:                //
362:                values = initializeDataArray(velocityStart, velocityEnd);
363:                addSeriesData(values, REQUIRED_SERIES, velocityStart,
364:                        effortAdded);
365:                addSeriesData(values, COMPLETED_SERIES, velocityStart,
366:                        effortCompleted);
367:                String[] categoryNames = createCategoryNames(velocityStart,
368:                        values);
369:
370:                dataSet = new DefaultCategoryDataset();
371:
372:                for (int seriesNum = 0; seriesNum < values.length; seriesNum++) {
373:                    for (int categoryNum = 0; categoryNum < values[seriesNum].length; categoryNum++) {
374:                        dataSet.addValue(values[seriesNum][categoryNum],
375:                                seriesNames[seriesNum],
376:                                categoryNames[categoryNum]);
377:                    }
378:                }
379:            }
380:
381:            // DatasetProducer methods ===============================================
382:
383:            public Object produceDataset(Map params)
384:                    throws DatasetProduceException {
385:                return dataSet;
386:            }
387:
388:            public boolean hasExpired(Map params, Date since) {
389:                return true;
390:            }
391:
392:            public String getProducerId() {
393:                return TaskVelocityData.class.getName();
394:            }
395:
396:            // CategoryItemLinkGenerator methods ====================================
397:
398:            public String generateLink(Object data, int series, Object category) {
399:                return seriesNames[series];
400:            }
401:
402:            // CategoryToolTipGenerator methods =====================================
403:
404:            public String generateToolTip(CategoryDataset categoryDataset,
405:                    int series, int category) {
406:                return seriesPrefix[series] + values[series][category];
407:            }
408:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.