package org.akaza.openclinica.web.table.sdv; import org.akaza.openclinica.bean.admin.CRFBean; import org.akaza.openclinica.bean.core.Status; 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.StudyGroupBean; import org.akaza.openclinica.bean.managestudy.StudySubjectBean; import org.akaza.openclinica.bean.submit.EventCRFBean; import org.akaza.openclinica.control.AbstractTableFactory; import org.akaza.openclinica.control.DefaultActionsEditor; import org.akaza.openclinica.controller.helper.table.SDVToolbarSubject; import org.akaza.openclinica.controller.helper.table.SubjectAggregateContainer; import org.akaza.openclinica.dao.StudySubjectSDVFilter; import org.akaza.openclinica.dao.StudySubjectSDVSort; import org.akaza.openclinica.dao.admin.CRFDAO; 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.StudyGroupDAO; import org.akaza.openclinica.dao.managestudy.StudySubjectDAO; import org.akaza.openclinica.dao.submit.EventCRFDAO; import org.akaza.openclinica.domain.SourceDataVerification; import org.akaza.openclinica.i18n.util.ResourceBundleProvider; import org.jmesa.core.filter.MatcherKey; import org.jmesa.facade.TableFacade; import org.jmesa.limit.Filter; import org.jmesa.limit.FilterSet; import org.jmesa.limit.Limit; import org.jmesa.limit.Sort; import org.jmesa.limit.SortSet; import org.jmesa.view.component.Row; import org.jmesa.view.html.AbstractHtmlView; import org.jmesa.view.html.HtmlBuilder; import org.jmesa.view.html.HtmlSnippets; import org.jmesa.view.html.component.HtmlColumn; import org.jmesa.view.html.component.HtmlRow; import org.jmesa.view.html.component.HtmlTable; import org.jmesa.web.WebContext; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; /** * A Jmesa table that represents study subjects in each row. */ public class SubjectIdSDVFactory extends AbstractTableFactory { private DataSource dataSource; private int studyId; private String contextPath; private ResourceBundle resword; private final static String ICON_FORCRFSTATUS_SUFFIX = ".gif'/>"; public boolean showMoreLink; public SubjectIdSDVFactory() { } public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override protected String getTableName() { //This name creates the underlying id of the HTML table return "s_sdv"; } @Override public void configureTableFacadeCustomView(TableFacade tableFacade) { tableFacade.setView(new SubjectSDVView(getLocale())); } @Override protected void configureColumns(TableFacade tableFacade, Locale locale) { tableFacade.setColumnProperties("sdvStatus", "studySubjectId", "siteId", "personId", "studySubjectStatus", "group", "numberCRFComplete", "numberOfCRFsSDV", "totalEventCRF", "actions"); resword = ResourceBundleProvider.getWordsBundle(locale); Row row = tableFacade.getTable().getRow(); SDVUtil sdvUtil = new SDVUtil(); String[] allTitles = new String[] { resword.getString("SDV_status"), resword.getString("study_subject_ID"), resword.getString("site_id"), resword.getString("person_ID"), resword.getString("study_subject_status"), resword.getString("group"), resword.getString("num_CRFs_completed"), resword.getString("num_CRFs_SDV"), resword.getString("total_events_CRF"), resword.getString("actions") }; sdvUtil.setTitles(allTitles, (HtmlTable) tableFacade.getTable()); sdvUtil.turnOffFilters(tableFacade, new String[] { "personId", "studySubjectStatus", "group", "numberCRFComplete", "numberOfCRFsSDV", "totalEventCRF", "actions" }); sdvUtil.turnOffSorts(tableFacade, new String[] { "sdvStatus", "studySubjectId", "siteId", "personId", "studySubjectStatus", "group", "numberCRFComplete", "numberOfCRFsSDV", "totalEventCRF" }); sdvUtil.setHtmlCellEditors(tableFacade, new String[] { "sdvStatus", "actions" }, false); HtmlColumn sdvStatus = ((HtmlRow) row).getColumn("sdvStatus"); sdvStatus.getFilterRenderer().setFilterEditor(new SdvStatusFilter()); String actionsHeader = resword.getString("rule_actions") + "                            "; configureColumn(row.getColumn("actions"), actionsHeader, sdvUtil.getCellEditorNoEscapes(), new DefaultActionsEditor(locale), true, false); } @Override public void configureTableFacade(HttpServletResponse response, TableFacade tableFacade) { super.configureTableFacade(response, tableFacade); tableFacade.addFilterMatcher(new MatcherKey(String.class, "sdvStatus"), new SdvStatusMatcher()); } @Override public void setDataAndLimitVariables(TableFacade tableFacade) { Limit limit = tableFacade.getLimit(); StudySubjectSDVFilter studySubjectSDVFilter = getStudySubjectSDVFilter(limit); WebContext context = tableFacade.getWebContext(); if (context != null) { studyId = Integer.parseInt(context.getParameter("studyId")); contextPath = context.getContextPath(); } String restore = context.getRequestAttribute(limit.getId()+"_restore") + ""; if (!limit.isComplete()) { int totalRows = getTotalRowCount(studySubjectSDVFilter); tableFacade.setTotalRows(totalRows); } else if (restore != null && "true".equalsIgnoreCase(restore)) { int totalRows = getTotalRowCount(studySubjectSDVFilter); int pageNum = limit.getRowSelect().getPage(); int maxRows = limit.getRowSelect().getMaxRows(); tableFacade.setMaxRows(maxRows); tableFacade.setTotalRows(totalRows); limit.getRowSelect().setPage(pageNum); } StudySubjectSDVSort studySubjectSDVSort = getStudySubjectSDVSort(limit); int rowStart = limit.getRowSelect().getRowStart(); int rowEnd = limit.getRowSelect().getRowEnd(); //Collection<StudySubjectBean> items = getStudySubjectDAO().getWithFilterAndSort(getStudyBean(), studySubjectSDVFilter, subjectSort, rowStart, rowEnd); Collection<SubjectAggregateContainer> items = getFilteredItems(studySubjectSDVFilter, studySubjectSDVSort, rowStart, rowEnd); tableFacade.setItems(items); /* Limit limit = tableFacade.getLimit(); FilterSet filterSet = limit.getFilterSet(); WebContext context = tableFacade.getWebContext(); if (context != null) { studyId = Integer.parseInt(context.getParameter("studyId")); contextPath = context.getContextPath(); } int totalRows = getTotalRowCount(); tableFacade.setTotalRows(totalRows); SortSet sortSet = limit.getSortSet(); int rowStart = limit.getRowSelect().getRowStart(); int rowEnd = limit.getRowSelect().getRowEnd(); Collection<SubjectAggregateContainer> items = getFilteredItems(filterSet, sortSet, rowStart, rowEnd); ; tableFacade.setItems(items); */ } protected StudySubjectSDVFilter getStudySubjectSDVFilter(Limit limit) { StudySubjectSDVFilter studySubjectSDVFilter = new StudySubjectSDVFilter(); FilterSet filterSet = limit.getFilterSet(); Collection<Filter> filters = filterSet.getFilters(); for (Filter filter : filters) { String property = filter.getProperty(); String value = filter.getValue(); studySubjectSDVFilter.addFilter(property, value); } return studySubjectSDVFilter; } public StudySubjectSDVFilter createStudySubjectSDVFilter(Limit limit) { return getStudySubjectSDVFilter(limit); } protected StudySubjectSDVSort getStudySubjectSDVSort(Limit limit) { StudySubjectSDVSort studySubjectSDVSort = new StudySubjectSDVSort(); SortSet sortSet = limit.getSortSet(); Collection<Sort> sorts = sortSet.getSorts(); for (Sort sort : sorts) { String property = sort.getProperty(); String order = sort.getOrder().toParam(); studySubjectSDVSort.addSort(property, order); } return studySubjectSDVSort; } /* Returns how many subjects exist in the study. */ public int getTotalRowCount(StudySubjectSDVFilter studySubjectSDVFilter) { StudySubjectDAO studySubDAO = new StudySubjectDAO(dataSource); return studySubDAO.countAllByStudySDV(studyId, studyId, studySubjectSDVFilter); } @Override public void configureTableFacadePostColumnConfiguration(TableFacade tableFacade) { tableFacade.setToolbar(new SDVToolbarSubject(showMoreLink)); } @SuppressWarnings("unchecked") private Collection<SubjectAggregateContainer> getFilteredItems(StudySubjectSDVFilter filterSet, StudySubjectSDVSort sortSet, int rowStart, int rowEnd) { List<SubjectAggregateContainer> rows = new ArrayList<SubjectAggregateContainer>(); StudySubjectDAO studySubjectDAO = new StudySubjectDAO(dataSource); List<StudySubjectBean> studySubjectBeans = studySubjectDAO.findAllByStudySDV(studyId, studyId, filterSet, sortSet, rowStart, rowEnd); SubjectAggregateContainer containerTmp = null; for (StudySubjectBean studSubjBean : studySubjectBeans) { containerTmp = getRow(studSubjBean); rows.add(containerTmp); } return rows; } String getIconForCrfStatusPrefix() { String prefix = "../"; return "<img hspace='2' border='0' title='SDV Complete' alt='SDV Status' src='" + prefix + "images/icon_"; } private SubjectAggregateContainer getRow(StudySubjectBean studySubjectBean) { SubjectAggregateContainer row = new SubjectAggregateContainer(); EventCRFDAO eventCRFDAO = new EventCRFDAO(dataSource); StudyDAO studyDAO = new StudyDAO(dataSource); StudySubjectDAO studySubjectDAO = new StudySubjectDAO(dataSource); StudyGroupDAO studyGroupDAO = new StudyGroupDAO(dataSource); row.setStudySubjectId(studySubjectBean.getLabel()); row.setPersonId(studySubjectBean.getUniqueIdentifier()); row.setStudySubjectStatus(studySubjectBean.getStatus().getName()); int numberEventCRFs = eventCRFDAO.countEventCRFsByStudySubject(studySubjectBean.getId(), studySubjectBean.getStudyId(), studySubjectBean.getStudyId()); row.setTotalEventCRF(numberEventCRFs + ""); StudyBean studyBean = (StudyBean) studyDAO.findByPK(studySubjectBean.getStudyId()); row.setSiteId(studyBean.getIdentifier()); List<EventCRFBean> eventCRFBeans = eventCRFDAO.getEventCRFsByStudySubject(studySubjectBean.getId(), studySubjectBean.getStudyId(), studySubjectBean.getStudyId()); HashMap<String, Integer> stats = getEventCRFStats(eventCRFBeans, studySubjectBean); //int numberCRFComplete = getNumberCompletedEventCRFs(eventCRFBeans); //row.setNumberCRFComplete(numberCRFComplete + ""); row.setNumberCRFComplete(stats.get("numberOfCompletedEventCRFs") + ""); row.setNumberOfCRFsSDV(stats.get("numberOfSDVdEventCRFs") + ""); //row.setNumberOfCRFsSDV(getNumberSDVdEventCRFs(eventCRFBeans) + ""); //boolean studySubjectSDVd = eventCRFDAO.countEventCRFsByByStudySubjectCompleteOrLockedAndNotSDVd(studySubjectBean.getId()) == 0 && numberCRFComplete > 0; boolean studySubjectSDVd = stats.get("areEventCRFsSDVd") == -1 || stats.get("areEventCRFsSDVd") == 1 ? false : true; StringBuilder sdvStatus = new StringBuilder(""); if (stats.get("shouldDisplaySDVButton") == 0) { sdvStatus.append(""); } else if (studySubjectSDVd) { sdvStatus.append("<center><a href='javascript:void(0)' onclick='prompt(document.sdvForm,"); sdvStatus.append(studySubjectBean.getId()); sdvStatus.append(")'>"); sdvStatus.append(getIconForCrfStatusPrefix()).append("DoubleCheck").append(ICON_FORCRFSTATUS_SUFFIX).append("</a></center>"); } else { sdvStatus.append("<center><input style='margin-right: 5px' type='checkbox' ").append("class='sdvCheck'").append(" name='").append("sdvCheck_") .append(studySubjectBean.getId()).append("' /></center>"); } row.setSdvStatus(sdvStatus.toString()); List<StudyGroupBean> studyGroupBeans = studyGroupDAO.getGroupByStudySubject(studySubjectBean.getId(), studySubjectBean.getStudyId(), studySubjectBean.getStudyId()); if (studyGroupBeans != null && !studyGroupBeans.isEmpty()) { row.setGroup(studyGroupBeans.get(0).getName()); } StringBuilder actions = new StringBuilder("<table><tr><td>"); StringBuilder urlPrefix = new StringBuilder("<a href=\""); StringBuilder path = new StringBuilder(contextPath).append("/pages/viewAllSubjectSDVtmp?studyId=").append(studyId).append("&sdv_f_studySubjectId="); path.append(studySubjectBean.getLabel()); urlPrefix.append(path).append("\">"); actions.append(urlPrefix).append(SDVUtil.VIEW_ICON_HTML).append("</a></td>"); if (!studySubjectSDVd && stats.get("shouldDisplaySDVButton") == 1) { StringBuilder jsCodeString = new StringBuilder("this.form.method='GET'; this.form.action='").append(contextPath).append("/pages/sdvStudySubject").append("';").append( "this.form.theStudySubjectId.value='").append(studySubjectBean.getId()).append("';").append("this.form.submit();"); actions.append("<td><input type=\"submit\" class=\"button\" value=\"SDV\" name=\"sdvSubmit\" ").append("onclick=\"") .append(jsCodeString.toString()).append("\" /></td>"); } else if (!studySubjectSDVd) { actions.append("<td>     SDV N/A</td>"); } actions.append("</tr></table>"); row.setActions(actions.toString()); return row; } private int getNumberCompletedEventCRFs(List<EventCRFBean> eventCRFBeans) { StudyEventDAO studyEventDAO = new StudyEventDAO(dataSource); StudyEventBean studyEventBean = null; int counter = 0; int statusId = 0; for (EventCRFBean eventBean : eventCRFBeans) { studyEventBean = (StudyEventBean) studyEventDAO.findByPK(eventBean.getStudyEventId()); statusId = studyEventBean.getSubjectEventStatus().getId(); if (statusId == 4) { counter++; } } return counter; } private int getNumberSDVdEventCRFs(List<EventCRFBean> eventCRFBeans) { int counter = 0; for (EventCRFBean eventBean : eventCRFBeans) { if (eventBean.isSdvStatus()) { counter++; } } return counter; } private HashMap<String, Integer> getEventCRFStats(List<EventCRFBean> eventCRFBeans, StudySubjectBean studySubject) { StudyEventDAO studyEventDAO = new StudyEventDAO(dataSource); EventDefinitionCRFDAO eventDefinitionCrfDAO = new EventDefinitionCRFDAO(dataSource); CRFDAO crfDAO = new CRFDAO(dataSource); StudyEventBean studyEventBean = null; Integer numberOfCompletedEventCRFs = 0; Integer numberOfSDVdEventCRFs = 0; Integer areEventCRFsSDVd = eventCRFBeans.size() > 0 ? 0 : -1; Boolean partialOrHundred = false; Integer shouldDisplaySDVButton = 0; for (EventCRFBean eventBean : eventCRFBeans) { studyEventBean = (StudyEventBean) studyEventDAO.findByPK(eventBean.getStudyEventId()); CRFBean crfBean = crfDAO.findByVersionId(eventBean.getCRFVersionId()); // get number of completed event crfs if (eventBean.getStatus() == Status.UNAVAILABLE || eventBean.getStatus() == Status.LOCKED) { numberOfCompletedEventCRFs++; } /* if (studyEventBean.getSubjectEventStatus() == SubjectEventStatus.COMPLETED) { numberOfCompletedEventCRFs++; }*/ // get number of completed event SDVd events if (eventBean.isSdvStatus()) { numberOfSDVdEventCRFs++; } // get number of all non SDVd events that are 100% or partial required EventDefinitionCRFBean eventDefinitionCrf = eventDefinitionCrfDAO.findByStudyEventDefinitionIdAndCRFIdAndStudyId(studyEventBean.getStudyEventDefinitionId(), crfBean.getId(), studySubject .getStudyId()); if (eventDefinitionCrf.getId() == 0) { eventDefinitionCrf = eventDefinitionCrfDAO.findForStudyByStudyEventDefinitionIdAndCRFId(studyEventBean.getStudyEventDefinitionId(), crfBean.getId()); } if ((eventDefinitionCrf.getSourceDataVerification() == SourceDataVerification.AllREQUIRED || eventDefinitionCrf.getSourceDataVerification() == SourceDataVerification.PARTIALREQUIRED) && (eventBean.getStatus() == Status.UNAVAILABLE || eventBean.getStatus() == Status.LOCKED)) { partialOrHundred = true; } if ((eventDefinitionCrf.getSourceDataVerification() == SourceDataVerification.AllREQUIRED || eventDefinitionCrf.getSourceDataVerification() == SourceDataVerification.PARTIALREQUIRED) && eventBean.isSdvStatus() == false && (eventBean.getStatus() == Status.UNAVAILABLE || eventBean.getStatus() == Status.LOCKED)) { areEventCRFsSDVd = 1; } } HashMap<String, Integer> stats = new HashMap<String, Integer>(); stats.put("numberOfCompletedEventCRFs", numberOfCompletedEventCRFs); stats.put("numberOfSDVdEventCRFs", numberOfSDVdEventCRFs); stats.put("areEventCRFsSDVd", partialOrHundred == false ? 1 : areEventCRFsSDVd); stats.put("shouldDisplaySDVButton", numberOfCompletedEventCRFs > 0 && partialOrHundred == true ? 1 : 0); return stats; } class SubjectSDVView extends AbstractHtmlView { private final ResourceBundle resword; public SubjectSDVView(Locale locale) { resword = ResourceBundleProvider.getWordsBundle(locale); } public Object render() { HtmlSnippets snippets = getHtmlSnippets(); HtmlBuilder html = new HtmlBuilder(); html.append(snippets.themeStart()); html.append(snippets.tableStart()); html.append(snippets.theadStart()); html.append(snippets.toolbar()); html.append(selectAll()); html.append(snippets.header()); html.append(snippets.filter()); html.append(snippets.theadEnd()); html.append(snippets.tbodyStart()); html.append(snippets.body()); html.append(snippets.tbodyEnd()); html.append(snippets.footer()); html.append(snippets.statusBar()); html.append(snippets.tableEnd()); html.append(snippets.themeEnd()); html.append(snippets.initJavascriptLimit()); return html.toString(); } String selectAll() { HtmlBuilder html = new HtmlBuilder(); html.tr(1).styleClass("logic").close().td(1).colspan("100%").style("font-size: 12px;").close(); html.append("<b>" + resword.getString("table_sdv_select") + "</b>  "); html.append("<a name='checkSDVAll' href='javascript:selectAllChecks(document.sdvForm,true)'>" + resword.getString("table_sdv_all")); html.append(",</a>"); html.append("   "); html.append("<a name='checkSDVAll' href='javascript:selectAllChecks(document.sdvForm,false)'>" + resword.getString("table_sdv_none")); html.append("</a>"); html.tdEnd().trEnd(1); return html.toString(); } } }