001: package com.technoetic.xplanner.actions;
002:
003: import java.text.SimpleDateFormat;
004: import java.util.Date;
005: import java.util.Iterator;
006: import java.util.List;
007: import java.util.Locale;
008: import javax.servlet.ServletException;
009: import javax.servlet.http.HttpServletRequest;
010: import javax.servlet.http.HttpServletResponse;
011: import javax.servlet.http.HttpSession;
012:
013: import net.sf.hibernate.Hibernate;
014: import net.sf.hibernate.HibernateException;
015: import net.sf.hibernate.Session;
016: import org.apache.log4j.Logger;
017: import org.apache.struts.Globals;
018: import org.apache.struts.action.ActionForm;
019: import org.apache.struts.action.ActionForward;
020: import org.apache.struts.action.ActionMapping;
021:
022: import com.technoetic.xplanner.domain.Iteration;
023: import com.technoetic.xplanner.domain.Task;
024: import com.technoetic.xplanner.domain.TimeEntry;
025: import com.technoetic.xplanner.domain.UserStory;
026: import com.technoetic.xplanner.domain.repository.ObjectRepository;
027: import com.technoetic.xplanner.domain.repository.RepositoryException;
028: import com.technoetic.xplanner.format.DecimalFormat;
029: import com.technoetic.xplanner.forms.IterationStatusEditorForm;
030: import com.technoetic.xplanner.forms.TimeEditorForm;
031: import com.technoetic.xplanner.history.HistoricalEvent;
032: import com.technoetic.xplanner.history.HistorySupport;
033: import com.technoetic.xplanner.security.SecurityHelper;
034:
035: public class UpdateTimeAction extends AbstractAction {
036: private static final Logger log = Logger
037: .getLogger("UpdateTimeAction");
038: public static final String UPDATE_TIME_ACTION = "UPDATE_TIME";
039: public static final String UPDATE_ESTIMATE_ACTION = "UPDATE_ESTIMATE";
040: private static final String SAVED_FORM_KEY = "UpdateTimeAction.savedForm";
041:
042: protected ActionForward doExecute(ActionMapping actionMapping,
043: ActionForm actionForm, HttpServletRequest request,
044: HttpServletResponse reply) throws Exception {
045: TimeEditorForm form = loadFormFromSessionIfExistsOrFromRequest(
046: actionForm, request);
047: try {
048: Session session = getSession(request);
049: try {
050: ActionForward forward;
051: if (!form.isSubmitted()) {
052: populateForm(session, form, request);
053: forward = new ActionForward(actionMapping
054: .getInput());
055: } else {
056: if (!isIterationStarted(session, form, request)) {
057: saveFormInSession(request, form);
058: request.setAttribute("from_edit/time", "true");
059: return new ActionForward("/do/start/iteration",
060: false);
061: }
062: forward = doAction(session, form, request,
063: actionMapping);
064: }
065: return forward;
066: // DEBT: Remove exception handling since it is completely handled in super class.
067: } catch (Exception ex) {
068: session.connection().rollback();
069: log.error("error", ex);
070: throw new ServletException(ex);
071: }
072: } catch (ServletException ex) {
073: throw ex;
074: } catch (Exception ex) {
075: log.error("error", ex);
076: throw new ServletException(ex);
077: }
078: }
079:
080: private TimeEditorForm loadFormFromSessionIfExistsOrFromRequest(
081: ActionForm actionForm, HttpServletRequest request) {
082: TimeEditorForm form = (TimeEditorForm) actionForm;
083: TimeEditorForm savedForm = loadFormFromSession(request);
084: if (savedForm != null) {
085: form = savedForm;
086: deleteFormFromSession(request);
087: }
088: return form;
089: }
090:
091: private void saveFormInSession(HttpServletRequest request,
092: TimeEditorForm form) {
093: request.getSession(true).setAttribute(SAVED_FORM_KEY, form);
094: }
095:
096: private void deleteFormFromSession(HttpServletRequest request) {
097: request.getSession(true).removeAttribute(SAVED_FORM_KEY);
098: }
099:
100: private TimeEditorForm loadFormFromSession(
101: HttpServletRequest request) {
102: return (TimeEditorForm) request.getSession(true).getAttribute(
103: SAVED_FORM_KEY);
104: }
105:
106: private ActionForward doAction(Session session,
107: TimeEditorForm form, HttpServletRequest request,
108: ActionMapping actionMapping) throws Exception {
109: if (form.getAction().equals(UPDATE_TIME_ACTION)) {
110: return doUpdateTimeAction(session, form, request,
111: actionMapping);
112: } else if (form.getAction().equals(UPDATE_ESTIMATE_ACTION)) {
113: return doUpdateEstimateAction(session, form, request,
114: actionMapping);
115: } else {
116: throw new ServletException("Unknown action: "
117: + form.getAction());
118: }
119: }
120:
121: private ActionForward doUpdateTimeAction(Session session,
122: TimeEditorForm form, HttpServletRequest request,
123: ActionMapping actionMapping) throws Exception {
124: DecimalFormat decimalParser = new DecimalFormat(request);
125: SimpleDateFormat dateTimeFormat = getDateTimeFormat(request);
126: SimpleDateFormat dateFormat = getDateFormat(request);
127: try {
128: List timeEntries = session
129: .find(
130: "from timeEntry in class com.technoetic.xplanner.domain.TimeEntry "
131: + "where timeEntry.taskId = ? order by timeEntry.reportDate",
132: form.getOid(), Hibernate.STRING);
133:
134: double hoursWorked = 0;
135: boolean rowDeleted = false;
136: for (int i = 0; i < form.getRowcount(); i++) {
137:
138: int id = 0;
139: if (isPresent(form.getEntryId(i))) {
140: id = Integer.parseInt(form.getEntryId(i));
141: }
142:
143: if (form.getDeleted(i) != null
144: && form.getDeleted(i).equals("true")) {
145: TimeEntry entry = getEntry(timeEntries, id);
146: session.delete(entry);
147: rowDeleted = true;
148: continue;
149: }
150:
151: Date startTime = null;
152: if (isPresent(form.getStartTime(i))) {
153: startTime = dateTimeFormat.parse(form
154: .getStartTime(i));
155: }
156:
157: Date endTime = null;
158: if (isPresent(form.getEndTime(i))) {
159: endTime = dateTimeFormat.parse(form.getEndTime(i));
160: }
161:
162: int person1Id = 0;
163: if (isPresent(form.getPerson1Id(i))) {
164: person1Id = Integer.parseInt(form.getPerson1Id(i));
165: }
166:
167: int person2Id = 0;
168: if (isPresent(form.getPerson2Id(i))) {
169: person2Id = Integer.parseInt(form.getPerson2Id(i));
170: }
171:
172: double duration = 0;
173: if (isPresent(form.getDuration(i))) {
174: duration = decimalParser.parse(form.getDuration(i));
175: }
176:
177: Date reportDate = null;
178: if (isPresent(form.getReportDate(i))) {
179: reportDate = dateFormat
180: .parse(form.getReportDate(i));
181: }
182:
183: String description = form.getDescription(i);
184:
185: if (id == 0) {
186: if (startTime != null || duration > 0) {
187: TimeEntry entry = new TimeEntry();
188: entry
189: .setTaskId(Integer.parseInt(form
190: .getOid()));
191: editEntry(entry, startTime, endTime, duration,
192: person1Id, person2Id, reportDate,
193: description);
194: hoursWorked += entry.getEffort();
195: if (timeEntries == null
196: || timeEntries.isEmpty()) {
197: startTask(session, Integer.parseInt(form
198: .getOid()));
199: }
200: session.save(entry);
201: }
202: } else {
203: TimeEntry entry = getEntry(timeEntries, id);
204: editEntry(entry, startTime, endTime, duration,
205: person1Id, person2Id, reportDate,
206: description);
207: hoursWorked += entry.getEffort();
208: }
209: }
210:
211: if (isPresent(form.getRemainingHours())) {
212: Double remainingHours = new Double(form
213: .getRemainingHours());
214: if (remainingHours.doubleValue() >= 0.0) {
215: Task task = (Task) session.load(Task.class,
216: new Integer(form.getOid()));
217: task.setEstimatedHours(hoursWorked
218: + remainingHours.doubleValue());
219: session.save(task);
220: }
221: }
222:
223: if (rowDeleted) {
224: form.reset(actionMapping, request);
225: }
226: return new ActionForward(request.getParameter("returnto"),
227: true);
228: } finally { //DEBT(060107)
229: session.flush();
230: session.connection().commit();
231: }
232: }
233:
234: private void startTask(Session session, int taskId)
235: throws HibernateException {
236: Task task = (Task) session
237: .load(Task.class, new Integer(taskId));
238: task.start();
239: session.save(task);
240: }
241:
242: private void editEntry(TimeEntry entry, Date startTime,
243: Date endTime, double duration, int person1Id,
244: int person2Id, Date reportDate, String description) {
245: entry.setStartTime(startTime);
246: entry.setEndTime(endTime);
247: entry.setDuration(duration);
248: entry.setPerson1Id(person1Id);
249: entry.setPerson2Id(person2Id);
250: entry.setReportDate(reportDate);
251: entry.setDescription(description);
252: }
253:
254: private boolean isIterationStarted(Session session,
255: TimeEditorForm form, HttpServletRequest request)
256: throws RepositoryException, HibernateException {//Autostart iteration
257:
258: Task task = (Task) session.load(Task.class, new Integer(form
259: .getOid()));
260: UserStory story = task.getStory();
261: ObjectRepository repository = getRepository(Iteration.class);
262: Iteration iteration = (Iteration) repository.load(story
263: .getIterationId());
264: if (!iteration.isActive()) {
265: request.setAttribute("edit/iteration", iteration);
266: request.setAttribute(
267: IterationStatusEditorForm.SAVE_TIME_ATTR,
268: Boolean.TRUE);
269: return false;
270: }
271: return true;
272: }
273:
274: private ActionForward doUpdateEstimateAction(Session session,
275: TimeEditorForm form, HttpServletRequest request,
276: ActionMapping actionMapping) throws Exception {
277: try {
278: Task task = (Task) session.load(Task.class, new Integer(
279: form.getOid()));
280: String oldEstimation = DecimalFormat.format(request, task
281: .getEstimatedHours());
282: HistorySupport
283: .saveEvent(session, task,
284: HistoricalEvent.REESTIMATED,
285: "Estimate changed from " + oldEstimation
286: + " to "
287: + request.getParameter("estimate"),
288: SecurityHelper.getRemoteUserId(request),
289: new Date());
290: task.setEstimatedHours(new DecimalFormat(request)
291: .parse(request.getParameter("estimate")));
292: if (request.getSession().getAttribute("edit/iteration") != null) {
293: request.setAttribute("edit/iteration", request
294: .getSession().getAttribute("edit/iteration"));
295: request.getSession().removeAttribute("edit/iteration");
296: return actionMapping.findForward("start/iteration");
297: } else {
298: return new ActionForward(request
299: .getParameter("returnto"), true);
300: }
301: } finally {
302: session.flush();
303: session.connection().commit();
304: }
305: }
306:
307: private boolean isPresent(String value) {
308: return value != null && !value.equals("")
309: && !value.equals("null");
310: }
311:
312: private void populateForm(Session session, TimeEditorForm form,
313: HttpServletRequest request) throws Exception {
314: SimpleDateFormat dateTimeFormat = getDateTimeFormat(request);
315: SimpleDateFormat dateFormat = getDateFormat(request);
316: List entries = session
317: .find(
318: "from timeEntry in class com.technoetic.xplanner.domain.TimeEntry "
319: + "where timeEntry.taskId = ? order by timeEntry.reportDate",
320: form.getOid(), Hibernate.STRING);
321: Task task = null;
322: if (entries.size() == 0) {
323: int taskId = Integer.parseInt(form.getOid());
324: task = (Task) session.load(Task.class, new Integer(taskId));
325: }
326: session.connection().rollback();
327:
328: int i = 0;
329: TimeEntry entry = null;
330: Iterator itr = entries.iterator();
331: while (itr.hasNext()) {
332: entry = (TimeEntry) itr.next();
333: form.setEntryId(i, Integer.toString(entry.getId()));
334: if (entry.getStartTime() != null) {
335: form.setStartTime(i, dateTimeFormat.format(entry
336: .getStartTime()));
337: } else {
338: form.setStartTime(i, "");
339: }
340: if (entry.getEndTime() != null) {
341: form.setEndTime(i, dateTimeFormat.format(entry
342: .getEndTime()));
343: } else {
344: form.setEndTime(i, "");
345: }
346: form.setDuration(i, DecimalFormat.format(request, entry
347: .getDuration()));
348: form
349: .setPerson1Id(i, Integer.toString(entry
350: .getPerson1Id()));
351: form
352: .setPerson2Id(i, Integer.toString(entry
353: .getPerson2Id()));
354: if (entry.getReportDate() != null) {
355: form.setReportDate(i, dateFormat.format(entry
356: .getReportDate()));
357: } else {
358: form.setReportDate(i, "");
359: }
360: form.setDescription(i, entry.getDescription());
361: i++;
362: }
363: if (entry == null || entry.getEndTime() != null
364: || entry.getDuration() > 0) {
365: // start new row
366: form.setEntryId(i, "0");
367: form.setDeleted(i, null);
368: form.setStartTime(i, "");
369: form.setEndTime(i, "");
370: form.setReportDate(i, dateFormat.format(new Date()));
371: if (i == 0) {
372: int personId = task.getAcceptorId();
373: form.setPerson1Id(i, personId == 0 ? null : Integer
374: .toString(personId));
375: form.setPerson2Id(i, null);
376: } else {
377: form.setPerson1Id(i, form.getPerson1Id(i - 1));
378: form.setPerson2Id(i, form.getPerson2Id(i - 1));
379: }
380: i++;
381: }
382: form.setRowcount(i);
383: }
384:
385: private TimeEntry getEntry(List entries, int entryId) {
386: for (int i = 0; i < entries.size(); i++) {
387: if (((TimeEntry) entries.get(i)).getId() == entryId) {
388: return (TimeEntry) entries.get(i);
389: }
390: }
391: return null;
392: }
393:
394: private SimpleDateFormat getDateTimeFormat(
395: HttpServletRequest request) {
396: HttpSession session = request.getSession();
397: Locale locale = (Locale) session
398: .getAttribute(Globals.LOCALE_KEY);
399: if (locale == null) {
400: locale = Locale.getDefault();
401: }
402: return new SimpleDateFormat(getResources(request).getMessage(
403: locale, "format.datetime"));
404: }
405:
406: private SimpleDateFormat getDateFormat(HttpServletRequest request) {
407: HttpSession session = request.getSession();
408: Locale locale = (Locale) session
409: .getAttribute(Globals.LOCALE_KEY);
410: if (locale == null) {
411: locale = Locale.getDefault();
412: }
413: return new SimpleDateFormat(getResources(request).getMessage(
414: locale, "format.date"));
415: }
416:
417: public static boolean isFromUpdateTime(HttpServletRequest request) {
418: return request.getAttribute("from_edit/time") != null;
419: }
420: }
|