001: package com.technoetic.xplanner.export;
002:
003: import com.technoetic.xplanner.domain.Iteration;
004: import com.technoetic.xplanner.domain.Person;
005: import com.technoetic.xplanner.domain.Task;
006: import com.technoetic.xplanner.domain.UserStory;
007: import dori.jasper.engine.JRDataSource;
008: import dori.jasper.engine.JRException;
009: import dori.jasper.engine.JRField;
010: import dori.jasper.engine.JasperManager;
011: import dori.jasper.engine.JasperReport;
012: import net.sf.hibernate.Hibernate;
013: import net.sf.hibernate.HibernateException;
014: import net.sf.hibernate.Session;
015:
016: import javax.servlet.http.HttpServletResponse;
017: import java.io.InputStream;
018: import java.util.Date;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Map;
023:
024: public class PdfReportExporter implements Exporter {
025: public void initializeHeaders(HttpServletResponse response) {
026: response.setHeader("Content-type", "application/pdf");
027: response.setHeader("Content-disposition",
028: "inline; filename=report.pdf");
029: }
030:
031: public byte[] export(Session session, Object object)
032: throws ExportException {
033: InputStream reportStream = null;
034: JRDataSource ds = null;
035: Map parameters = new HashMap();
036:
037: if (object instanceof Iteration) {
038: Iteration iteration = (Iteration) object;
039:
040: try {
041: ds = new IterationDataSource(iteration, session);
042: } catch (HibernateException he) {
043: throw new ExportException(he);
044: }
045:
046: reportStream = PdfReportExporter.class
047: .getClassLoader()
048: .getResourceAsStream(
049: "com/technoetic/xplanner/export/reports/JRIteration.jasper");
050: parameters.put("IterationName", iteration.getName());
051: parameters.put("IterationStartDate", iteration
052: .getStartDate());
053: parameters.put("IterationEndDate", iteration.getEndDate());
054: } else if (object instanceof UserStory) {
055: UserStory story = (UserStory) object;
056:
057: try {
058: ds = new UserStoryDataSource(story, session);
059: } catch (HibernateException he) {
060: throw new ExportException(he);
061: }
062:
063: reportStream = PdfReportExporter.class
064: .getClassLoader()
065: .getResourceAsStream(
066: "com/technoetic/xplanner/export/reports/JRStory.jasper");
067: parameters.put("StoryName", story.getName());
068: Person cust = story.getCustomer();
069: parameters.put("StoryCustomerName", (cust != null) ? cust
070: .getName() : null);
071: parameters.put("StoryEstimatedHours", new java.lang.Double(
072: story.getEstimatedHours()));
073: parameters.put("StoryDescription", story.getDescription());
074: } else if (object instanceof Task) {
075: Task task = (Task) object;
076:
077: try {
078: ds = new TaskDataSource(task, session);
079: } catch (HibernateException he) {
080: throw new ExportException(he);
081: }
082:
083: reportStream = PdfReportExporter.class
084: .getClassLoader()
085: .getResourceAsStream(
086: "com/technoetic/xplanner/export/reports/JRTask.jasper");
087: parameters.put("TaskName", task.getName());
088: parameters.put("TaskDescription", task.getDescription());
089: double actual = task.getActualHours();
090: parameters.put("TaskPercentage", new java.lang.Integer(
091: (int) ((actual * 100) / (actual + task
092: .getRemainingHours()))));
093: parameters.put("TaskDisposition", task.getDisposition()
094: .getName());
095: parameters.put("TaskType", task.getType());
096: parameters.put("TaskAcceptor", getPersonName(session,
097: new Integer(task.getAcceptorId())));
098: parameters.put("TaskEstimate", new java.lang.Double(task
099: .getEstimatedHours()));
100: parameters.put("TaskCompleted", new java.lang.Boolean(task
101: .isCompleted()));
102: } else if (object instanceof Person) {
103: Person person = (Person) object;
104:
105: try {
106: ds = new PersonDataSource(person, session);
107: } catch (HibernateException he) {
108: throw new ExportException(he);
109: }
110:
111: reportStream = PdfReportExporter.class
112: .getClassLoader()
113: .getResourceAsStream(
114: "com/technoetic/xplanner/export/reports/JRPerson.jasper");
115: parameters.put("PersonName", person.getName());
116: }
117:
118: if (ds == null) {
119: throw new ExportException(
120: "Could not instantiate data source");
121: }
122:
123: if (reportStream == null) {
124: throw new ExportException("Could not open compiled report");
125: }
126:
127: try {
128: JasperReport report = JasperManager
129: .loadReport(reportStream);
130: return JasperManager.runReportToPdf(report, parameters, ds);
131: } catch (JRException jre) {
132: throw new ExportException(jre);
133: }
134: }
135:
136: public static String getPersonName(Session session, Integer id) {
137: if (id == null || id.intValue() == 0) {
138: return null;
139: }
140:
141: Person person = null;
142: try {
143: person = (Person) session.load(Person.class, id);
144: } catch (HibernateException he) {
145: return null;
146: }
147:
148: if (person == null) {
149: return null;
150: }
151:
152: return person.getName();
153: }
154:
155: private class UserStoryDataSource implements JRDataSource {
156: private Iterator iterator = null;
157: private Task task = null;
158: private String acceptor = null;
159: private Session session = null;
160:
161: public UserStoryDataSource(UserStory story, Session session)
162: throws HibernateException {
163: super ();
164:
165: List data = session.find("select task"
166: + " from com.technoetic.xplanner.domain.Task task"
167: + " where task.story = ?" + " order by task.name",
168: new java.lang.Integer(story.getId()),
169: Hibernate.INTEGER);
170:
171: this .session = session;
172: if (data != null) {
173: iterator = data.iterator();
174: }
175: }
176:
177: public boolean next() throws JRException {
178: if (iterator == null || !iterator.hasNext()) {
179: return false;
180: }
181:
182: task = (Task) iterator.next();
183: acceptor = getPersonName(session, new Integer(task
184: .getAcceptorId()));
185: return true;
186: }
187:
188: public Object getFieldValue(JRField field) throws JRException {
189: String fieldName = field.getName();
190:
191: if ("TaskName".equals(fieldName)) {
192: return task.getName();
193: }
194:
195: if ("TaskPercentage".equals(fieldName)) {
196: double actual = task.getActualHours();
197: return new java.lang.Integer(
198: (int) ((actual * 100) / (actual + task
199: .getRemainingHours())));
200: }
201:
202: if ("TaskDisposition".equals(fieldName)) {
203: return task.getDisposition().getName();
204: }
205:
206: if ("TaskType".equals(fieldName)) {
207: return task.getType();
208: }
209:
210: if ("TaskAcceptor".equals(fieldName)) {
211: return acceptor;
212: }
213:
214: if ("TaskEstimate".equals(fieldName)) {
215: return new java.lang.Double(task.getEstimatedHours());
216: }
217:
218: if ("TaskCompleted".equals(fieldName)) {
219: return new java.lang.Boolean(task.isCompleted());
220: }
221:
222: throw new JRException("Unexpected field name '" + fieldName
223: + "'");
224: }
225: }
226:
227: private class TaskDataSource implements JRDataSource {
228: private Iterator iterator = null;
229: private java.util.Date start = null;
230: private Double duration = null;
231: private String pair1 = null;
232: private String pair2 = null;
233: private Session session = null;
234:
235: public TaskDataSource(Task task, Session session)
236: throws HibernateException {
237: super ();
238:
239: // I don't get this... what is the relationship between
240: // last_update, start_time, end_time and report_date, and why
241: // do we have a duration that can be non-zero when the
242: // end_time is NULL?
243: //
244: // How can I do a left join on the personXIds to get a null when they haven't been assigned?
245: List data = session
246: .find(
247: "select te.startTime, te.endTime, te.duration, te.person1Id, te.person2Id"
248: + " from com.technoetic.xplanner.domain.TimeEntry te"
249: + " where te.taskId = ?"
250: + " order by te.startTime",
251: new java.lang.Integer(task.getId()),
252: Hibernate.INTEGER);
253: this .session = session;
254: if (data != null) {
255: iterator = data.iterator();
256: }
257: }
258:
259: public boolean next() throws JRException {
260: if (iterator == null || !iterator.hasNext()) {
261: return false;
262: }
263:
264: Object[] result = (Object[]) iterator.next();
265:
266: start = (java.util.Date) result[0];
267: duration = (result[1] == null) ? null : (Double) result[2];
268:
269: pair1 = getPersonName(session, (Integer) result[3]);
270: pair2 = getPersonName(session, (Integer) result[4]);
271:
272: return true;
273: }
274:
275: public Object getFieldValue(JRField field) throws JRException {
276: String fieldName = field.getName();
277:
278: if ("TimeEntryStart".equals(fieldName)) {
279: if (start != null) {
280: return start.toString();
281: } else {
282: return "";
283: }
284: }
285:
286: if ("TimeEntryDuration".equals(fieldName)) {
287: return duration;
288: }
289:
290: if ("TimeEntryPair1".equals(fieldName)) {
291: return pair1;
292: }
293:
294: if ("TimeEntryPair2".equals(fieldName)) {
295: return pair2;
296: }
297:
298: throw new JRException("Unexpected field name '" + fieldName
299: + "'");
300: }
301: }
302:
303: private class PersonDataSource implements JRDataSource {
304: private Iterator iterator = null;
305: private Task task = null;
306: private Session session = null;
307: private int userId = 0;
308: private boolean currentlyActive = false;
309: private String iterationName = null;
310: private Date iterationStart = null;
311: private Date iterationEnd = null;
312: private String storyName = null;
313: private Double storyEstimate = null;
314:
315: public PersonDataSource(Person person, Session session)
316: throws HibernateException {
317: super ();
318:
319: // return user tasks for current iteration
320: List data = session
321: .find(
322: "select task, iteration.name, iteration.startDate, iteration.endDate, story"
323: + " from com.technoetic.xplanner.domain.Task task,"
324: + " story in class com.technoetic.xplanner.domain.UserStory,"
325: + " iteration in class com.technoetic.xplanner.domain.Iteration"
326: + " where task.story = story.id and story.iterationId = iteration.id"
327: + " and ? between iteration.startDate and iteration.endDate"
328: + " order by iteration.name, story.name, task.name",
329: new java.util.Date(), Hibernate.DATE);
330:
331: this .userId = person.getId();
332: this .session = session;
333: if (data != null) {
334: iterator = data.iterator();
335: }
336: }
337:
338: public boolean next() throws JRException {
339: if (iterator == null || !iterator.hasNext()) {
340: return false;
341: }
342:
343: Object[] result = (Object[]) iterator.next();
344:
345: task = (Task) result[0];
346:
347: currentlyActive = task.isCurrentlyActive(userId);
348:
349: // user is not involved with this task
350: if (task.getAcceptorId() != userId && !currentlyActive) {
351: return next();
352: }
353:
354: iterationName = (String) result[1];
355: iterationStart = (Date) result[2];
356: iterationEnd = (Date) result[3];
357: UserStory story = (UserStory) result[4];
358: storyName = story.getName();
359: storyEstimate = new Double(story.getEstimatedHours());
360:
361: return true;
362: }
363:
364: public Object getFieldValue(JRField field) throws JRException {
365: String fieldName = field.getName();
366:
367: if ("IterationName".equals(fieldName)) {
368: return iterationName;
369: }
370:
371: if ("IterationStartDate".equals(fieldName)) {
372: return iterationStart;
373: }
374:
375: if ("IterationEndDate".equals(fieldName)) {
376: return iterationEnd;
377: }
378:
379: if ("StoryName".equals(fieldName)) {
380: return storyName;
381: }
382:
383: if ("StoryEstimatedHours".equals(fieldName)) {
384: return storyEstimate;
385: }
386:
387: if ("TaskName".equals(fieldName)) {
388: return task.getName();
389: }
390:
391: if ("TaskPercentage".equals(fieldName)) {
392: double actual = task.getActualHours();
393: return new java.lang.Integer(
394: (int) ((actual * 100) / (actual + task
395: .getRemainingHours())));
396: }
397:
398: if ("TaskDisposition".equals(fieldName)) {
399: return task.getDisposition().getName();
400: }
401:
402: if ("TaskType".equals(fieldName)) {
403: return task.getType();
404: }
405:
406: if ("TaskCompleted".equals(fieldName)) {
407: return new java.lang.Boolean(task.isCompleted());
408: }
409:
410: if ("TaskEstimate".equals(fieldName)) {
411: return new java.lang.Double(task.getEstimatedHours());
412: }
413:
414: if ("TaskActive".equals(fieldName)) {
415: return new java.lang.Boolean(currentlyActive);
416: }
417:
418: throw new JRException("Unexpected field name '" + fieldName
419: + "'");
420: }
421: }
422: }
|