/*
* 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
*/
package org.akaza.openclinica.control.submit;
import org.akaza.openclinica.bean.admin.CRFBean;
import org.akaza.openclinica.bean.core.AuditableEntityBean;
import org.akaza.openclinica.bean.core.DataEntryStage;
import org.akaza.openclinica.bean.core.EntityBean;
import org.akaza.openclinica.bean.core.Role;
import org.akaza.openclinica.bean.core.Status;
import org.akaza.openclinica.bean.core.SubjectEventStatus;
import org.akaza.openclinica.bean.managestudy.EventDefinitionCRFBean;
import org.akaza.openclinica.bean.managestudy.StudyBean;
import org.akaza.openclinica.bean.managestudy.StudyEventBean;
import org.akaza.openclinica.bean.managestudy.StudyEventDefinitionBean;
import org.akaza.openclinica.bean.managestudy.StudySubjectBean;
import org.akaza.openclinica.bean.submit.CRFVersionBean;
import org.akaza.openclinica.bean.submit.DisplayEventCRFBean;
import org.akaza.openclinica.bean.submit.DisplayTableOfContentsBean;
import org.akaza.openclinica.bean.submit.EventCRFBean;
import org.akaza.openclinica.bean.submit.ItemGroupBean;
import org.akaza.openclinica.bean.submit.SectionBean;
import org.akaza.openclinica.control.core.SecureController;
import org.akaza.openclinica.control.form.DiscrepancyValidator;
import org.akaza.openclinica.control.form.FormDiscrepancyNotes;
import org.akaza.openclinica.control.form.FormProcessor;
import org.akaza.openclinica.control.form.Validator;
import org.akaza.openclinica.control.managestudy.ViewStudySubjectServlet;
import org.akaza.openclinica.core.form.StringUtil;
import org.akaza.openclinica.dao.admin.CRFDAO;
import org.akaza.openclinica.dao.managestudy.DiscrepancyNoteDAO;
import org.akaza.openclinica.dao.managestudy.EventDefinitionCRFDAO;
import org.akaza.openclinica.dao.managestudy.StudyDAO;
import org.akaza.openclinica.dao.managestudy.StudyEventDAO;
import org.akaza.openclinica.dao.managestudy.StudyEventDefinitionDAO;
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.ItemGroupDAO;
import org.akaza.openclinica.dao.submit.SectionDAO;
import org.akaza.openclinica.service.crfdata.DynamicsMetadataService;
import org.akaza.openclinica.view.Page;
import org.akaza.openclinica.web.InconsistentStateException;
import org.akaza.openclinica.web.InsufficientPermissionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
/**
* @author ssachs
*/
// TODO: make it possible to input an event crf bean to this servlet rather than
// an int
public class TableOfContentsServlet extends SecureController {
protected final Logger logger = LoggerFactory.getLogger(getClass().getName());
public static final String BEAN_DISPLAY = "toc";
// these inputs are used when you get here from a jsp page
// e.g. TableOfContents?action=ide_c&id=123
public static final String INPUT_ACTION = "action";
public static final String INPUT_ID = "ecid";
// these inputs are used when another servlet sends you here
// such as mark crf complete, initial data entry, etc
public static final String INPUT_EVENT_CRF_BEAN = "eventCRF";
// these are only for use with ACTION_START_INITIAL_DATA_ENTRY
public static final String INPUT_EVENT_DEFINITION_CRF_ID = "eventDefinitionCRFId";
public static final String INPUT_CRF_VERSION_ID = "crfVersionId";
public static final String INPUT_STUDY_EVENT_ID = "studyEventId";
public static final String INPUT_SUBJECT_ID = "subjectId";
public static final String INPUT_EVENT_CRF_ID = "eventCRFId";
// these inputs are displayed on the table of contents and
// are used to edit Event CRF properties
public static final String INPUT_INTERVIEWER = "interviewer";
public static final String INPUT_INTERVIEW_DATE = "interviewDate";
public static final String ACTION_START_INITIAL_DATA_ENTRY = "ide_s";
public static final String ACTION_CONTINUE_INITIAL_DATA_ENTRY = "ide_c";
public static final String ACTION_START_DOUBLE_DATA_ENTRY = "dde_s";
public static final String ACTION_CONTINUE_DOUBLE_DATA_ENTRY = "dde_c";
public static final String ACTION_ADMINISTRATIVE_EDITING = "ae";
public static final String[] ACTIONS =
{ ACTION_START_INITIAL_DATA_ENTRY, ACTION_CONTINUE_INITIAL_DATA_ENTRY, ACTION_START_DOUBLE_DATA_ENTRY, ACTION_CONTINUE_DOUBLE_DATA_ENTRY,
ACTION_ADMINISTRATIVE_EDITING };
private FormProcessor fp;
private EventCRFDAO ecdao;
private EventCRFBean ecb;
private String action;
private void getEventCRFAndAction() {
ecdao = new EventCRFDAO(sm.getDataSource());
ecb = (EventCRFBean) request.getAttribute(INPUT_EVENT_CRF_BEAN);
if (ecb == null) {
int ecid = fp.getInt(INPUT_ID, true);
AuditableEntityBean aeb = ecdao.findByPKAndStudy(ecid, currentStudy);
if (!aeb.isActive()) {
ecb = new EventCRFBean();
} else {
ecb = (EventCRFBean) aeb;
}
action = fp.getString(INPUT_ACTION, true);
} else {
action = getActionForStage(ecb.getStage());
}
}
/**
* Determines if the action requested is a valid action.
*
* @param action
* The action requested.
* @return <code>true</code> if the action is valid, <code>false</code>
* otherwise.
*/
private boolean invalidAction(String action) {
ArrayList validActions = new ArrayList(Arrays.asList(ACTIONS));
return !validActions.contains(action);
}
/**
* Determines if the action requested is consistent with the specified Event
* CRF's data entry stage.
*
* @param action
* The action requested.
* @param ecb
* The Event CRF whose data entry stage is being checked for
* consistency with the action.
* @return <code>true</code> if the action is consistent with the Event
* CRF's stage, <code>false</code> otherwise.
*/
private boolean isConsistentAction(String action, EventCRFBean ecb) {
DataEntryStage stage = ecb.getStage();
boolean isConsistent = true;
if (action.equals(ACTION_START_INITIAL_DATA_ENTRY) && !stage.equals(DataEntryStage.UNCOMPLETED)) {
isConsistent = false;
} else if (action.equals(ACTION_CONTINUE_INITIAL_DATA_ENTRY) && !stage.equals(DataEntryStage.INITIAL_DATA_ENTRY)) {
isConsistent = false;
} else if (action.equals(ACTION_START_DOUBLE_DATA_ENTRY) && !stage.equals(DataEntryStage.INITIAL_DATA_ENTRY_COMPLETE)) {
isConsistent = false;
} else if (action.equals(ACTION_CONTINUE_DOUBLE_DATA_ENTRY) && !stage.equals(DataEntryStage.DOUBLE_DATA_ENTRY)) {
isConsistent = false;
} else if (action.equals(ACTION_ADMINISTRATIVE_EDITING) && !stage.equals(DataEntryStage.DOUBLE_DATA_ENTRY_COMPLETE)) {
isConsistent = false;
}
return isConsistent;
}
/**
* Creates a new Event CRF or update the exsiting one, that is, an event CRF
* can be created but not item data yet, in this case, still consider it is
* not started(called uncompleted before)
*
* @return
* @throws Exception
*/
private EventCRFBean createEventCRF() throws Exception {
EventCRFBean ecb;
ecdao = new EventCRFDAO(sm.getDataSource());
int crfVersionId = fp.getInt(INPUT_CRF_VERSION_ID);
int studyEventId = fp.getInt(INPUT_STUDY_EVENT_ID);
int eventDefinitionCRFId = fp.getInt(INPUT_EVENT_DEFINITION_CRF_ID);
int subjectId = fp.getInt(INPUT_SUBJECT_ID);
int eventCRFId = fp.getInt(INPUT_EVENT_CRF_ID);
logger.info("Creating event CRF within Table of Contents. Study id: " + currentStudy.getId() + "; CRF Version id: " + crfVersionId
+ "; Study Event id: " + studyEventId + "; Event Definition CRF id: " + eventDefinitionCRFId + "; Subject: " + subjectId);
StudySubjectDAO ssdao = new StudySubjectDAO(sm.getDataSource());
StudySubjectBean ssb = ssdao.findBySubjectIdAndStudy(subjectId, currentStudy);
if (!ssb.isActive()) {
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("trying_to_begin_DE1"));
}
StudyEventDefinitionDAO seddao = new StudyEventDefinitionDAO(sm.getDataSource());
StudyEventDefinitionBean sedb = seddao.findByEventDefinitionCRFId(eventDefinitionCRFId);
if (!ssb.isActive() || !sedb.isActive()) {
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("trying_to_begin_DE2"));
}
CRFVersionDAO cvdao = new CRFVersionDAO(sm.getDataSource());
EntityBean eb = cvdao.findByPK(crfVersionId);
if (!eb.isActive()) {
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("trying_to_begin_DE3"));
}
StudyEventDAO sedao = new StudyEventDAO(sm.getDataSource());
StudyEventBean sEvent = (StudyEventBean) sedao.findByPK(studyEventId);
StudyBean studyWithSED = currentStudy;
if (currentStudy.getParentStudyId() > 0) {
studyWithSED = new StudyBean();
studyWithSED.setId(currentStudy.getParentStudyId());
}
AuditableEntityBean aeb = sedao.findByPKAndStudy(studyEventId, studyWithSED);
if (!aeb.isActive()) {
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("trying_to_begin_DE4"));
}
ecb = new EventCRFBean();
if (eventCRFId == 0) {// no event CRF created yet
ecb.setAnnotations("");
ecb.setCreatedDate(new Date());
ecb.setCRFVersionId(crfVersionId);
ecb.setInterviewerName("");
if (sEvent.getDateStarted() != null) {
ecb.setDateInterviewed(sEvent.getDateStarted());// default date
} else {
ecb.setDateInterviewed(null);
}
ecb.setOwnerId(ub.getId());
ecb.setStatus(Status.AVAILABLE);
ecb.setCompletionStatusId(1);
ecb.setStudySubjectId(ssb.getId());
ecb.setStudyEventId(studyEventId);
ecb.setValidateString("");
ecb.setValidatorAnnotations("");
ecb = (EventCRFBean) ecdao.create(ecb);
logger.info("CREATED EVENT CRF");
} else {
// there is an event CRF already, only need to update
ecb = (EventCRFBean) ecdao.findByPK(eventCRFId);
ecb.setCRFVersionId(crfVersionId);
ecb.setUpdatedDate(new Date());
ecb.setUpdater(ub);
ecb = (EventCRFBean) ecdao.update(ecb);
}
if (!ecb.isActive()) {
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("new_event_CRF_not_created_database_error"));
} else {
sEvent.setSubjectEventStatus(SubjectEventStatus.DATA_ENTRY_STARTED);
sEvent.setUpdater(ub);
sEvent.setUpdatedDate(new Date());
sedao.update(sEvent);
}
return ecb;
}
private void validateEventCRFAndAction() throws Exception {
if (invalidAction(action)) {
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("no_action_specified_or_invalid"));
}
if (!isConsistentAction(action, ecb)) {
HashMap verbs = new HashMap();
verbs.put(ACTION_START_INITIAL_DATA_ENTRY, resword.getString("start_initial_data_entry"));
verbs.put(ACTION_CONTINUE_INITIAL_DATA_ENTRY, resword.getString("continue_initial_data_entry"));
verbs.put(ACTION_START_DOUBLE_DATA_ENTRY, resword.getString("start_double_data_entry"));
verbs.put(ACTION_CONTINUE_DOUBLE_DATA_ENTRY, resword.getString("continue_double_data_entry"));
verbs.put(ACTION_ADMINISTRATIVE_EDITING, resword.getString("perform_administrative_editing"));
String verb = (String) verbs.get(action);
if (verb == null) {
verb = "start initial data entry";
}
throw new InconsistentStateException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("you_are_trying_to") + verb + " "
+ resexception.getString("on_event_CRF_inappropiate_action"));
}
if (action.equals(ACTION_START_DOUBLE_DATA_ENTRY)) {
ecb.setValidatorId(ub.getId());
ecb.setDateValidate(new Date());
ecb = (EventCRFBean) ecdao.update(ecb);
}
}
private void updatePresetValues(EventCRFBean ecb) {
fp.addPresetValue(INPUT_INTERVIEWER, ecb.getInterviewerName());
if (ecb.getDateInterviewed() != null) {
// SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
String idateFormatted = local_df.format(ecb.getDateInterviewed());
fp.addPresetValue(INPUT_INTERVIEW_DATE, idateFormatted);
} else {
fp.addPresetValue(INPUT_INTERVIEW_DATE, "");
}
setPresetValues(fp.getPresetValues());
}
/*
* (non-Javadoc)
*
* @see org.akaza.openclinica.control.core.SecureController#processRequest()
*/
@Override
protected void processRequest() throws Exception {
FormDiscrepancyNotes discNotes;
if (action.equals(ACTION_START_INITIAL_DATA_ENTRY)) {
ecb = createEventCRF();
} else {
validateEventCRFAndAction();
}
updatePresetValues(ecb);
Boolean b = (Boolean) request.getAttribute(DataEntryServlet.INPUT_IGNORE_PARAMETERS);
if (fp.isSubmitted() && b == null) {
discNotes = (FormDiscrepancyNotes) session.getAttribute(AddNewSubjectServlet.FORM_DISCREPANCY_NOTES_NAME);
if (discNotes == null) {
discNotes = new FormDiscrepancyNotes();
session.setAttribute(AddNewSubjectServlet.FORM_DISCREPANCY_NOTES_NAME, discNotes);
}
DiscrepancyValidator v = new DiscrepancyValidator(request, discNotes);
v.addValidation(INPUT_INTERVIEWER, Validator.NO_BLANKS);
v.addValidation(INPUT_INTERVIEW_DATE, Validator.IS_A_DATE);
v.alwaysExecuteLastValidation(INPUT_INTERVIEW_DATE);
errors = v.validate();
if (errors.isEmpty()) {
ecb.setInterviewerName(fp.getString(INPUT_INTERVIEWER));
ecb.setDateInterviewed(fp.getDate(INPUT_INTERVIEW_DATE));
if (ecdao == null) {
ecdao = new EventCRFDAO(sm.getDataSource());
}
ecb = (EventCRFBean) ecdao.update(ecb);
// save discrepancy notes into DB
FormDiscrepancyNotes fdn = (FormDiscrepancyNotes) session.getAttribute(AddNewSubjectServlet.FORM_DISCREPANCY_NOTES_NAME);
DiscrepancyNoteDAO dndao = new DiscrepancyNoteDAO(sm.getDataSource());
AddNewSubjectServlet.saveFieldNotes(INPUT_INTERVIEWER, fdn, dndao, ecb.getId(), "EventCRF", currentStudy);
AddNewSubjectServlet.saveFieldNotes(INPUT_INTERVIEW_DATE, fdn, dndao, ecb.getId(), "EventCRF", currentStudy);
if (ecdao.isQuerySuccessful()) {
updatePresetValues(ecb);
if (!fp.getBoolean("editInterview", true)) {
// editing completed
addPageMessage(respage.getString("interviewer_name_date_updated"));
}
} else {
addPageMessage(respage.getString("database_error_interviewer_name_date_not_updated"));
}
} else {
String[] textFields = { INPUT_INTERVIEWER, INPUT_INTERVIEW_DATE };
fp.setCurrentStringValuesAsPreset(textFields);
setInputMessages(errors);
setPresetValues(fp.getPresetValues());
}
} else {
discNotes = new FormDiscrepancyNotes();
session.setAttribute(AddNewSubjectServlet.FORM_DISCREPANCY_NOTES_NAME, discNotes);
}
DisplayTableOfContentsBean displayBean = getDisplayBean(ecb, sm.getDataSource(), currentStudy);
// this is for generating side info panel
StudySubjectDAO ssdao = new StudySubjectDAO(sm.getDataSource());
StudySubjectBean ssb = (StudySubjectBean) ssdao.findByPK(ecb.getStudySubjectId());
ArrayList beans = ViewStudySubjectServlet.getDisplayStudyEventsForStudySubject(ssb, sm.getDataSource(), ub, currentRole);
request.setAttribute("studySubject", ssb);
request.setAttribute("beans", beans);
request.setAttribute("eventCRF", ecb);
request.setAttribute(BEAN_DISPLAY, displayBean);
boolean allowEnterData = true;
if (StringUtil.isBlank(ecb.getInterviewerName())) {
if (discNotes == null || discNotes.getNotes(TableOfContentsServlet.INPUT_INTERVIEWER).isEmpty()) {
allowEnterData = false;
}
}
if (ecb.getDateInterviewed() == null) {
if (discNotes == null || discNotes.getNotes(TableOfContentsServlet.INPUT_INTERVIEW_DATE).isEmpty()) {
allowEnterData = false;
}
}
if (!allowEnterData) {
request.setAttribute("allowEnterData", "no");
// forwardPage(Page.INTERVIEWER);
/*
* BWP 2966 >> the original Page.INTERVIEWER jsp is not a complete
* web page and did not provide a body tag for producing a popup
* window for discrepancy notes. So I changed it to create a
* complete web page.
*/
forwardPage(Page.INTERVIEWER_ENTIRE_PAGE);
} else {
if (fp.getBoolean("editInterview", true)) {
// user wants to edit interview info
request.setAttribute("allowEnterData", "yes");
forwardPage(Page.INTERVIEWER);
} else {
if (fp.isSubmitted() && !errors.isEmpty()) {
// interview form submitted, but has blank field or
// validation error
request.setAttribute("allowEnterData", "no");
forwardPage(Page.INTERVIEWER);
} else {
request.setAttribute("allowEnterData", "yes");
forwardPage(Page.TABLE_OF_CONTENTS);
}
}
}
}
/*
* (non-Javadoc)
*
* @see org.akaza.openclinica.control.core.SecureController#mayProceed()
*/
@Override
protected void mayProceed() throws InsufficientPermissionException {
fp = new FormProcessor(request);
getEventCRFAndAction();
Role r = currentRole.getRole();
boolean isSuper = DisplayEventCRFBean.isSuper(ub, r);
if (!SubmitDataServlet.maySubmitData(ub, currentRole)) {
String exceptionName = resexception.getString("no_permission_to_perform_data_entry");
String noAccessMessage =
respage.getString("you_may_not_perform_data_entry_on_a_CRF") + " " + respage.getString("change_study_contact_study_coordinator");
addPageMessage(noAccessMessage);
throw new InsufficientPermissionException(Page.MENU, exceptionName, "1");
}
// we're creating an event crf
if (action.equals(ACTION_START_INITIAL_DATA_ENTRY)) {
return;
}
// we're editing an existing event crf
else {
if (!ecb.isActive()) {
addPageMessage(respage.getString("event_CRF_not_exist_contact_study_coordinator"));
throw new InsufficientPermissionException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("event_CRF_not_belong_current_study"), "1");
}
if (action.equals(ACTION_CONTINUE_INITIAL_DATA_ENTRY)) {
if (ecb.getOwnerId() == ub.getId() || isSuper) {
return;
} else {
addPageMessage(respage.getString("not_begin_DE_on_CRF_not_resume_DE"));
throw new InsufficientPermissionException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("event_CRF_not_belong_current_user"),
"1");
}
} else if (action.equals(ACTION_START_DOUBLE_DATA_ENTRY)) {
if (ecb.getOwnerId() != ub.getId()) {
return;
} else {
if (!DisplayEventCRFBean.initialDataEntryCompletedMoreThanTwelveHoursAgo(ecb) && !isSuper) {
addPageMessage(respage.getString("began_DE_on_CRF_marked_complete_less_12_not_begin_DE"));
throw new InsufficientPermissionException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("owner_attempting_DDE_12_hours"),
"1");
} else {
return;
}
}
} else if (action.equals(ACTION_CONTINUE_INITIAL_DATA_ENTRY)) {
if (ecb.getValidatorId() == ub.getId() || isSuper) {
return;
} else {
addPageMessage(respage.getString("not_begin_DDE_on_CRF_not_resume_DE"));
throw new InsufficientPermissionException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception.getString("validation_event_CRF_not_begun_user"),
"1");
}
} else if (action.equals(ACTION_ADMINISTRATIVE_EDITING)) {
if (isSuper) {
return;
} else {
addPageMessage(respage.getString("you_may_not_perform_administrative_editing") + " "
+ respage.getString("change_study_contact_study_coordinator"));
throw new InsufficientPermissionException(Page.LIST_STUDY_SUBJECTS_SERVLET, resexception
.getString("no_permission_to_perform_administrative_editing"), "1");
}
} // end else if (action.equals(ACTION_ADMINISTRATIVE_EDITING))
} // end else (for actions other than ACTION_START_INITIAL_DATA_ENTRY
} // end mayProceed
public static int getIntById(HashMap h, Integer key) {
Integer value = (Integer) h.get(key);
if (value == null) {
return 0;
} else {
return value.intValue();
}
}
/**
* Assumes the Event CRF's data entry stage is not Uncompleted.
*
* @param ecb
* An Event CRF which should be displayed in the table of
* contents.
* @return A text link to the Table of Contents servlet for the bean.
*/
public static String getLink(EventCRFBean ecb) {
DataEntryStage stage = ecb.getStage();
String answer = Page.TABLE_OF_CONTENTS_SERVLET.getFileName();
answer = Page.TABLE_OF_CONTENTS_SERVLET.getFileName();
answer += "?action=" + getActionForStage(ecb.getStage());
answer += "&" + INPUT_ID + "=" + ecb.getId();
return answer;
}
public static String getActionForStage(DataEntryStage stage) {
if (stage.equals(DataEntryStage.UNCOMPLETED)) {
}
else if (stage.equals(DataEntryStage.INITIAL_DATA_ENTRY)) {
return ACTION_CONTINUE_INITIAL_DATA_ENTRY;
}
else if (stage.equals(DataEntryStage.INITIAL_DATA_ENTRY_COMPLETE)) {
return ACTION_START_DOUBLE_DATA_ENTRY;
}
else if (stage.equals(DataEntryStage.DOUBLE_DATA_ENTRY)) {
return ACTION_CONTINUE_DOUBLE_DATA_ENTRY;
}
else if (stage.equals(DataEntryStage.DOUBLE_DATA_ENTRY_COMPLETE)) {
return ACTION_ADMINISTRATIVE_EDITING;
}
return "";
}
public static ArrayList getSections(EventCRFBean ecb, DataSource ds) {
SectionDAO sdao = new SectionDAO(ds);
ItemGroupDAO igdao = new ItemGroupDAO(ds);
HashMap numItemsBySectionId = sdao.getNumItemsBySectionId();
HashMap numItemsPlusRepeatBySectionId = sdao.getNumItemsPlusRepeatBySectionId(ecb);
HashMap numItemsCompletedBySectionId = sdao.getNumItemsCompletedBySectionId(ecb);
HashMap numItemsPendingBySectionId = sdao.getNumItemsPendingBySectionId(ecb);
ArrayList sections = sdao.findAllByCRFVersionId(ecb.getCRFVersionId());
for (int i = 0; i < sections.size(); i++) {
SectionBean sb = (SectionBean) sections.get(i);
int sectionId = sb.getId();
Integer key = new Integer(sectionId);
// YW 10-11-2007 << handle number of item completion on tab.
int numItems = getIntById(numItemsBySectionId, key);
List<ItemGroupBean> itemGroups = igdao.findLegitGroupBySectionId(sectionId);
if (!itemGroups.isEmpty()) {
// this section has repeating rows-jxu
int numItemsPlusRepeat = getIntById(numItemsPlusRepeatBySectionId, key);
if (numItemsPlusRepeat > numItems) {
sb.setNumItems(numItemsPlusRepeat);
} else {
sb.setNumItems(numItems);
}
} else {
sb.setNumItems(numItems);
}
// According to logic that I searched from code of this package by
// this time,
// for double data entry and stage.initial_data_entry,
// pending should be the status in query.
int numItemsCompleted = getIntById(numItemsCompletedBySectionId, key);
// the following is removed to fix issue 2091-jxu
// if(numItemsCompleted == 0) {
// numItemsCompleted = getIntById(numItemsPendingBySectionId, key) ;
// }
sb.setNumItemsCompleted(numItemsCompleted);
// YW >>
sb.setNumItemsNeedingValidation(getIntById(numItemsPendingBySectionId, key));
sections.set(i, sb);
}
return sections;
}
public static DisplayTableOfContentsBean getDisplayBean(EventCRFBean ecb, DataSource ds, StudyBean currentStudy) {
DisplayTableOfContentsBean answer = new DisplayTableOfContentsBean();
answer.setEventCRF(ecb);
// get data
StudySubjectDAO ssdao = new StudySubjectDAO(ds);
StudySubjectBean ssb = (StudySubjectBean) ssdao.findByPK(ecb.getStudySubjectId());
answer.setStudySubject(ssb);
StudyEventDAO sedao = new StudyEventDAO(ds);
StudyEventBean seb = (StudyEventBean) sedao.findByPK(ecb.getStudyEventId());
answer.setStudyEvent(seb);
SectionDAO sdao = new SectionDAO(ds);
ArrayList sections = getSections(ecb, ds);
answer.setSections(sections);
// get metadata
StudyEventDefinitionDAO seddao = new StudyEventDefinitionDAO(ds);
StudyEventDefinitionBean sedb = (StudyEventDefinitionBean) seddao.findByPK(seb.getStudyEventDefinitionId());
answer.setStudyEventDefinition(sedb);
CRFVersionDAO cvdao = new CRFVersionDAO(ds);
CRFVersionBean cvb = (CRFVersionBean) cvdao.findByPK(ecb.getCRFVersionId());
answer.setCrfVersion(cvb);
CRFDAO cdao = new CRFDAO(ds);
CRFBean cb = (CRFBean) cdao.findByPK(cvb.getCrfId());
answer.setCrf(cb);
StudyBean studyForStudySubject = new StudyDAO(ds).findByStudySubjectId(ssb.getId());
EventDefinitionCRFDAO edcdao = new EventDefinitionCRFDAO(ds);
EventDefinitionCRFBean edcb = edcdao.findByStudyEventDefinitionIdAndCRFId(studyForStudySubject, sedb.getId(), cb.getId());
answer.setEventDefinitionCRF(edcb);
answer.setAction(getActionForStage(ecb.getStage()));
return answer;
}
/**
* A section contains all hidden dynamics will be removed from data entry tab and jump box.
*
* @param ds
* @param displayTableOfContentsBean
* @param dynamicsMetadataService
* @return
*/
public static DisplayTableOfContentsBean getDisplayBeanWithShownSections(DataSource ds, DisplayTableOfContentsBean displayTableOfContentsBean,
DynamicsMetadataService dynamicsMetadataService) {
if(displayTableOfContentsBean == null) {
return displayTableOfContentsBean;
}
EventCRFBean ecb = displayTableOfContentsBean.getEventCRF();
SectionDAO sectionDAO = new SectionDAO(ds);
ArrayList<SectionBean> sectionBeans = getSections(ecb, ds);
ArrayList<SectionBean> showSections = new ArrayList<SectionBean>();
if(sectionBeans != null && sectionBeans.size()>0) {
for(SectionBean s : sectionBeans) {
if(sectionDAO.containNormalItem(s.getCRFVersionId(), s.getId())) {
showSections.add(s);
} else {
//for section contains dynamics, does it contain showing item_group/item?
if(dynamicsMetadataService.hasShowingDynGroupInSection(s.getId(), s.getCRFVersionId(), ecb.getId())) {
showSections.add(s);
} else {
if(dynamicsMetadataService.hasShowingDynItemInSection(s.getId(), s.getCRFVersionId(), ecb.getId())) {
showSections.add(s);
}
}
}
}
displayTableOfContentsBean.setSections(showSections);
}
return displayTableOfContentsBean;
}
public static LinkedList<Integer> sectionIdsInToc(DisplayTableOfContentsBean toc) {
LinkedList<Integer> ids = new LinkedList<Integer>();
if(toc != null) {
ArrayList<SectionBean> sectionBeans = toc.getSections();
if(sectionBeans!=null && sectionBeans.size()>0) {
for(int i=0; i<sectionBeans.size(); ++i) {
SectionBean s = sectionBeans.get(i);
ids.add(s.getId());
}
}
}
return ids;
}
/**
* Index starts from 0. If not in, return -1.
* @param sb
* @param toc
* @param sectionIdsInToc
* @return
*/
public static int sectionIndexInToc(SectionBean sb, DisplayTableOfContentsBean toc, LinkedList<Integer> sectionIdsInToc) {
ArrayList<SectionBean> sectionBeans = new ArrayList<SectionBean>();
int index = -1;
if(toc!=null) {
sectionBeans = toc.getSections();
}
if(sectionBeans != null && sectionBeans.size()>0) {
for(int i=0; i<sectionIdsInToc.size(); ++i) {
if(sb.getId()==sectionIdsInToc.get(i)) {
index = i;
break;
}
}
}
return index;
}
}