/* * OpenClinica is distributed under the * GNU Lesser General Public License (GNU LGPL). * For details see: http://www.openclinica.org/license * copyright 2003-2005 Akaza Research * * Created on Sep 22, 2005 */ package org.akaza.openclinica.control.managestudy; import java.io.IOException; import java.util.ArrayList; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.sql.DataSource; import org.akaza.openclinica.bean.core.DiscrepancyNoteType; import org.akaza.openclinica.bean.core.ResolutionStatus; import org.akaza.openclinica.bean.core.Role; import org.akaza.openclinica.bean.core.Status; import org.akaza.openclinica.bean.managestudy.DiscrepancyNoteBean; import org.akaza.openclinica.bean.managestudy.StudyBean; import org.akaza.openclinica.bean.managestudy.StudyEventBean; import org.akaza.openclinica.bean.managestudy.StudySubjectBean; import org.akaza.openclinica.bean.submit.CRFVersionBean; import org.akaza.openclinica.bean.submit.EventCRFBean; import org.akaza.openclinica.bean.submit.ItemDataBean; import org.akaza.openclinica.bean.submit.ItemFormMetadataBean; import org.akaza.openclinica.control.SpringServletAccess; import org.akaza.openclinica.control.core.SecureController; import org.akaza.openclinica.control.form.FormProcessor; import org.akaza.openclinica.control.submit.CreateDiscrepancyNoteServlet; import org.akaza.openclinica.control.submit.DataEntryServlet; import org.akaza.openclinica.control.submit.EnketoFormServlet; import org.akaza.openclinica.control.submit.EnterDataForStudyEventServlet; import org.akaza.openclinica.control.submit.TableOfContentsServlet; import org.akaza.openclinica.dao.managestudy.DiscrepancyNoteDAO; import org.akaza.openclinica.dao.managestudy.StudyEventDAO; import org.akaza.openclinica.dao.managestudy.StudySubjectDAO; import org.akaza.openclinica.dao.submit.CRFVersionDAO; import org.akaza.openclinica.dao.submit.EventCRFDAO; import org.akaza.openclinica.dao.submit.ItemDataDAO; import org.akaza.openclinica.dao.submit.ItemFormMetadataDAO; import org.akaza.openclinica.service.DiscrepancyNoteUtil; import org.akaza.openclinica.service.crfdata.EnketoUrlService; import org.akaza.openclinica.service.crfdata.xform.PFormCacheSubjectContextEntry; import org.akaza.openclinica.view.Page; import org.akaza.openclinica.web.InconsistentStateException; import org.akaza.openclinica.web.InsufficientPermissionException; import org.akaza.openclinica.web.pform.PFormCache; /** * @author ssachs * * TODO To change the template for this generated type comment go to Window - * Preferences - Java - Code Style - Code Templates */ public class ResolveDiscrepancyServlet extends SecureController { private static final String INPUT_NOTE_ID = "noteId"; private static final String CAN_ADMIN_EDIT = "canAdminEdit"; private static final String EVENT_CRF_ID = "ecId"; private static final String STUDY_SUB_ID = "studySubjectId"; private static final String RESOLVING_NOTE = "resolving_note"; private static final String RETURN_FROM_PROCESS_REQUEST = "returnFromProcess"; public Page getPageForForwarding(DiscrepancyNoteBean note, boolean isCompleted) { String entityType = note.getEntityType().toLowerCase(); request.setAttribute("fromResolvingNotes", "yes"); if ("subject".equalsIgnoreCase(entityType)) { if (ub.isSysAdmin() || ub.isTechAdmin()) { return Page.UPDATE_SUBJECT_SERVLET; } else { return Page.VIEW_STUDY_SUBJECT_SERVLET; } } else if ("studysub".equalsIgnoreCase(entityType)) { if (ub.isSysAdmin() || ub.isTechAdmin()) { return Page.UPDATE_STUDY_SUBJECT_SERVLET; } else { return Page.VIEW_STUDY_SUBJECT_SERVLET; } } else if ("studyevent".equalsIgnoreCase(entityType)) { if (ub.isSysAdmin() || ub.isTechAdmin()) { return Page.UPDATE_STUDY_EVENT_SERVLET; } else { return Page.ENTER_DATA_FOR_STUDY_EVENT_SERVLET; } } else if ("itemdata".equalsIgnoreCase(entityType) || "eventcrf".equalsIgnoreCase(entityType)) { if (currentRole.getRole().equals(Role.MONITOR) || !isCompleted) { return Page.ENKETO_FORM_SERVLET; } else { return Page.ADMIN_EDIT_SERVLET; } } return null; } public boolean prepareRequestForResolution(HttpServletRequest request, DataSource ds, StudyBean currentStudy, DiscrepancyNoteBean note, boolean isCompleted) throws Exception { String entityType = note.getEntityType().toLowerCase(); int id = note.getEntityId(); if ("subject".equalsIgnoreCase(entityType)) { StudySubjectDAO ssdao = new StudySubjectDAO(ds); StudySubjectBean ssb = ssdao.findBySubjectIdAndStudy(id, currentStudy); request.setAttribute("action", "show"); request.setAttribute("id", String.valueOf(note.getEntityId())); request.setAttribute("studySubId", String.valueOf(ssb.getId())); } else if ("studysub".equalsIgnoreCase(entityType)) { request.setAttribute("action", "show"); request.setAttribute("id", String.valueOf(note.getEntityId())); } else if ("eventcrf".equalsIgnoreCase(entityType)) { request.setAttribute("editInterview", "1"); EventCRFDAO ecdao = new EventCRFDAO(ds); EventCRFBean ecb = (EventCRFBean) ecdao.findByPK(id); request.setAttribute(TableOfContentsServlet.INPUT_EVENT_CRF_BEAN, ecb); // If the request is passed along to ViewSectionDataEntryServlet, // that code needs // an event crf id; the (ecb.getId()+"") is necessary because // FormProcessor throws // a ClassCastException without the casting to a String request.setAttribute(ViewSectionDataEntryServlet.EVENT_CRF_ID, ecb.getId() + ""); } else if ("studyevent".equalsIgnoreCase(entityType)) { StudyEventDAO sedao = new StudyEventDAO(ds); StudyEventBean seb = (StudyEventBean) sedao.findByPK(id); request.setAttribute(EnterDataForStudyEventServlet.INPUT_EVENT_ID, String.valueOf(id)); request.setAttribute(UpdateStudyEventServlet.EVENT_ID, String.valueOf(id)); request.setAttribute(UpdateStudyEventServlet.STUDY_SUBJECT_ID, String.valueOf(seb.getStudySubjectId())); } // this is for item data else if ("itemdata".equalsIgnoreCase(entityType)) { ItemDataDAO iddao = new ItemDataDAO(ds); ItemDataBean idb = (ItemDataBean) iddao.findByPK(id); EventCRFDAO ecdao = new EventCRFDAO(ds); EventCRFBean ecb = (EventCRFBean) ecdao.findByPK(idb.getEventCRFId()); CRFVersionDAO cvdao = new CRFVersionDAO(ds); CRFVersionBean crfVersion = (CRFVersionBean) cvdao.findByPK(ecb.getCRFVersionId()); StudyEventDAO sedao = new StudyEventDAO(ds); StudySubjectDAO ssdao = new StudySubjectDAO(sm.getDataSource()); StudySubjectBean ssb = (StudySubjectBean) ssdao.findByPK(ecb.getStudySubjectId()); ItemFormMetadataDAO ifmdao = new ItemFormMetadataDAO(ds); ItemFormMetadataBean ifmb = ifmdao.findByItemIdAndCRFVersionId(idb.getItemId(), ecb.getCRFVersionId()); if (currentRole.getRole().equals(Role.MONITOR) || !isCompleted) { EnketoUrlService enketoUrlService = (EnketoUrlService) SpringServletAccess.getApplicationContext(context).getBean("enketoUrlService"); StudyEventBean seb = (StudyEventBean) sedao.findByPK(ecb.getStudyEventId()); //Cache the subject context for use during xform submission PFormCache cache = PFormCache.getInstance(context); PFormCacheSubjectContextEntry subjectContext = new PFormCacheSubjectContextEntry(); subjectContext.setStudySubjectOid(ssb.getOid()); subjectContext.setStudyEventDefinitionId(seb.getStudyEventDefinitionId()); subjectContext.setOrdinal(seb.getSampleOrdinal()); subjectContext.setCrfVersionOid(crfVersion.getOid()); subjectContext.setUserAccountId(ub.getId()); String contextHash = cache.putSubjectContext(subjectContext); String formUrl = null; if (ecb.getId() > 0) { formUrl = enketoUrlService.getEditUrl(contextHash, subjectContext, currentStudy.getOid()); } else { formUrl = enketoUrlService.getInitialDataEntryUrl(contextHash, subjectContext, currentStudy.getOid()); } request.setAttribute(EnketoFormServlet.FORM_URL, formUrl); } else { request.setAttribute(DataEntryServlet.INPUT_EVENT_CRF_ID, String.valueOf(idb.getEventCRFId())); request.setAttribute(DataEntryServlet.INPUT_SECTION_ID, String.valueOf(ifmb.getSectionId())); } } return true; } /* * (non-Javadoc) * * @see org.akaza.openclinica.control.core.SecureController#processRequest() */ @Override protected void processRequest() throws Exception { FormProcessor fp = new FormProcessor(request); int noteId = fp.getInt(INPUT_NOTE_ID); String module = (String) session.getAttribute("module"); // Integer subjectId = (Integer) session.getAttribute("subjectId"); StudySubjectDAO studySubjectDAO = new StudySubjectDAO(sm.getDataSource()); DiscrepancyNoteDAO dndao = new DiscrepancyNoteDAO(sm.getDataSource()); dndao.setFetchMapping(true); // check that the note exists DiscrepancyNoteBean discrepancyNoteBean = (DiscrepancyNoteBean) dndao.findByPK(noteId); if (!discrepancyNoteBean.isActive()) { throw new InconsistentStateException(Page.MANAGE_STUDY_SERVLET, resexception.getString("you_are_trying_resolve_discrepancy_not_exist")); } // check that the note has not already been closed ArrayList children = dndao.findAllByParent(discrepancyNoteBean); discrepancyNoteBean.setChildren(children); //This logic has been reverted, issue-7459 // if (parentNoteIsClosed(discrepancyNoteBean)) { // throw new InconsistentStateException(Page.VIEW_DISCREPANCY_NOTES_IN_STUDY_SERVLET, respage // .getString("the_discrepancy_choose_has_been_closed_resolved_create_new")); // } // all clear, send the user to the resolved screen String entityType = discrepancyNoteBean.getEntityType().toLowerCase(); discrepancyNoteBean.setResStatus(ResolutionStatus.get(discrepancyNoteBean.getResolutionStatusId())); discrepancyNoteBean.setDisType(DiscrepancyNoteType.get(discrepancyNoteBean.getDiscrepancyNoteTypeId())); // BWP 03/17/2009 3166: if it's not an ItemData type note, redirect // Monitors to View Subject or // View Study Events << if (currentRole.getRole().equals(Role.MONITOR) && !"itemdata".equalsIgnoreCase(entityType) && !"eventcrf".equalsIgnoreCase(entityType)) { redirectMonitor(module, discrepancyNoteBean); return; } // >> // If Study is Frozen or Locked if (currentStudy.getStatus().isFrozen() && !"itemdata".equalsIgnoreCase(entityType) && !"eventcrf".equalsIgnoreCase(entityType)) { redirectMonitor(module, discrepancyNoteBean); return; } boolean toView = false; boolean isCompleted = false; if ("itemdata".equalsIgnoreCase(entityType)) { ItemDataDAO iddao = new ItemDataDAO(sm.getDataSource()); ItemDataBean idb = (ItemDataBean) iddao.findByPK(discrepancyNoteBean.getEntityId()); EventCRFDAO ecdao = new EventCRFDAO(sm.getDataSource()); EventCRFBean ecb = (EventCRFBean) ecdao.findByPK(idb.getEventCRFId()); StudySubjectBean studySubjectBean = (StudySubjectBean) studySubjectDAO.findByPK(ecb.getStudySubjectId()); discrepancyNoteBean.setSubjectId(studySubjectBean.getId()); discrepancyNoteBean.setItemId(idb.getItemId()); if (ecb.getStatus().equals(Status.UNAVAILABLE)) { isCompleted = true; } toView = true;// we want to go to view note page if the note is // for item data } // logger.info("set up pop up url: " + createNoteURL); // System.out.println("set up pop up url: " + createNoteURL); boolean goNext = prepareRequestForResolution(request, sm.getDataSource(), currentStudy, discrepancyNoteBean, isCompleted); Page p = getPageForForwarding(discrepancyNoteBean, isCompleted); // logger.info("found page for forwarding: " + p.getFileName()); if (p == null) { throw new InconsistentStateException(Page.VIEW_DISCREPANCY_NOTES_IN_STUDY_SERVLET, resexception .getString("the_discrepancy_note_triying_resolve_has_invalid_type")); } else { if(p.getFileName().contains("?")) { if(!p.getFileName().contains("fromViewNotes=1")) { p.setFileName(p.getFileName()+"&fromViewNotes=1"); } } else { p.setFileName(p.getFileName()+"?fromViewNotes=1"); } String createNoteURL = CreateDiscrepancyNoteServlet.getAddChildURL(discrepancyNoteBean, ResolutionStatus.CLOSED, true); setPopUpURL(createNoteURL); } if (!goNext) { setPopUpURL(""); addPageMessage(respage.getString("you_may_not_perform_admin_edit_on_CRF_not_completed_by_user")); p = Page.VIEW_DISCREPANCY_NOTES_IN_STUDY_SERVLET; } forwardPage(p); } /** * Determines if a discrepancy note is closed or not. The note is closed if * it has status closed, or any of its children have closed status. * * @param note * The discrepancy note. The children should already be set. * @return <code>true</code> if the note is closed, <code>false</code> * otherwise. */ public static boolean noteIsClosed(DiscrepancyNoteBean note) { if (note.getResolutionStatusId() == ResolutionStatus.CLOSED.getId()) { return true; } ArrayList children = note.getChildren(); for (int i = 0; i < children.size(); i++) { DiscrepancyNoteBean child = (DiscrepancyNoteBean) children.get(i); if (child.getResolutionStatusId() == ResolutionStatus.CLOSED.getId()) { return true; } } return false; } public static boolean parentNoteIsClosed(DiscrepancyNoteBean parentNote) { if (parentNote.getResolutionStatusId() == ResolutionStatus.CLOSED.getId()) { return true; } return false; } /* * (non-Javadoc) * * @see org.akaza.openclinica.control.core.SecureController#mayProceed() */ @Override protected void mayProceed() throws InsufficientPermissionException { String module = (String) session.getAttribute("module"); // Integer subjectId = (Integer) session.getAttribute("subjectId"); /* * BWP: This caused a problem with page refreshing (the subjectId was * lost); so I had to comment it out if(subjectId != null){ * session.removeAttribute("subjectId"); } */ if (module != null) { session.removeAttribute("module"); } // BWP 11/03/2008 3029: redirect monitor user to ViewStudySubject if // they click "add note to thread" link>> // if (currentRole.getRole().equals(Role.MONITOR)) { // addPageMessage(respage.getString("no_have_permission_to_resolve_discrepancy")); // // RequestDispatcher dispatcher = // request.getRequestDispatcher("/ViewStudySubject?id=" + subjectId + // "&module=" + module); // try { // dispatcher.forward(request, response); // } catch (ServletException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // return; // } // tbh 02/2009: now removed, to allow for the Query workflow and allow a // Monitor to Resolve a Query. if (currentRole.getRole().equals(Role.STUDYDIRECTOR) || currentRole.getRole().equals(Role.COORDINATOR) || currentRole.getRole().equals(Role.INVESTIGATOR) || currentRole.getRole().equals(Role.RESEARCHASSISTANT) || currentRole.getRole().equals(Role.RESEARCHASSISTANT2) || currentRole.getRole().equals(Role.MONITOR)) { return; } addPageMessage(respage.getString("no_have_permission_to_resolve_discrepancy") + respage.getString("change_study_contact_sysadmin")); throw new InsufficientPermissionException(Page.MENU_SERVLET, resexception.getString("not_study_director_or_study_coordinator"), "1"); } /** * Redirect the request to another page if the user is a Monitor type and * the discrepancy note is a type other than item data or event crf. * * @param module * A String like "managestudy" or "admin" * @param discrepancyNoteBean */ private void redirectMonitor(String module, DiscrepancyNoteBean discrepancyNoteBean) { if (discrepancyNoteBean != null) { String createNoteURL = ""; // This String will determine whether the type is other than // itemdata. String entityType = discrepancyNoteBean.getEntityType().toLowerCase(); // The id of the subject, study subject, or study event int entityId = discrepancyNoteBean.getEntityId(); RequestDispatcher dispatcher = null; DiscrepancyNoteUtil discNoteUtil = new DiscrepancyNoteUtil(); if (entityType != null && !"".equalsIgnoreCase(entityType) && !"itemdata".equalsIgnoreCase(entityType) && !"eventcrf".equalsIgnoreCase(entityType)) { // redirect to View Study Subject // addPageMessage(resword.getString("monitors_do_not_have_permission_to_resolve_discrepancy_notes")); if ("studySub".equalsIgnoreCase(entityType)) { dispatcher = request.getRequestDispatcher("/ViewStudySubject?id=" + entityId + "&module=" + module); discrepancyNoteBean.setSubjectId(entityId); } else if ("subject".equalsIgnoreCase(entityType)) { int studySubId = discNoteUtil.getStudySubjectIdForDiscNote(discrepancyNoteBean, sm.getDataSource(), currentStudy.getId()); dispatcher = request.getRequestDispatcher("/ViewStudySubject?id=" + studySubId + "&module=" + module); discrepancyNoteBean.setSubjectId(studySubId); } else if ("studyevent".equalsIgnoreCase(entityType)) { dispatcher = request.getRequestDispatcher("/EnterDataForStudyEvent?eventId=" + entityId); } // This code creates the URL for a popup window, which the // processing Servlet will initiate. // 'true' parameter means that ViewDiscrepancyNote is the // handling Servlet. createNoteURL = CreateDiscrepancyNoteServlet.getAddChildURL(discrepancyNoteBean, ResolutionStatus.CLOSED, true); request.setAttribute(POP_UP_URL, createNoteURL); try { if (dispatcher != null) { dispatcher.forward(request, response); } } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } } }