package org.akaza.openclinica.view.form; import org.akaza.openclinica.bean.core.NullValue; import org.akaza.openclinica.bean.managestudy.EventDefinitionCRFBean; import org.akaza.openclinica.bean.managestudy.StudyBean; import org.akaza.openclinica.bean.submit.DisplayItemBean; import org.akaza.openclinica.bean.submit.DisplayItemGroupBean; import org.akaza.openclinica.bean.submit.DisplayItemWithGroupBean; import org.akaza.openclinica.bean.submit.DisplaySectionBean; import org.akaza.openclinica.bean.submit.EventCRFBean; import org.akaza.openclinica.bean.submit.ItemBean; import org.akaza.openclinica.bean.submit.ItemDataBean; import org.akaza.openclinica.bean.submit.ItemFormMetadataBean; import org.akaza.openclinica.bean.submit.ItemGroupBean; import org.akaza.openclinica.bean.submit.ItemGroupMetadataBean; import org.akaza.openclinica.bean.submit.ResponseOptionBean; import org.akaza.openclinica.bean.submit.SectionBean; import org.akaza.openclinica.control.SpringServletAccess; import org.akaza.openclinica.control.core.CoreSecureController; import org.akaza.openclinica.core.SessionManager; import org.akaza.openclinica.dao.managestudy.EventDefinitionCRFDAO; import org.akaza.openclinica.dao.submit.ItemDAO; import org.akaza.openclinica.dao.submit.ItemDataDAO; import org.akaza.openclinica.dao.submit.ItemFormMetadataDAO; import org.akaza.openclinica.dao.submit.ItemGroupDAO; import org.akaza.openclinica.dao.submit.ItemGroupMetadataDAO; import org.akaza.openclinica.dao.submit.SectionDAO; import org.akaza.openclinica.exception.OpenClinicaException; import org.akaza.openclinica.service.crfdata.DynamicsMetadataService; import org.jdom.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.ServletContext; import javax.sql.DataSource; /** * This class builds DisplayFormGroupBeans and DisplayItemBeans in preparation * for displaying a form. The DisplayFormGroupBean contains the * DisplayItemBeans, and is itself contained by a DisplaySectionBean. */ public class FormBeanUtil { private static Logger logger = LoggerFactory.getLogger(FormBeanUtil.class); public static final String UNGROUPED = "Ungrouped"; public static final String ADMIN_EDIT = "administrativeEditing"; private static DynamicsMetadataService itemMetadataService; private ServletContext context; private static DynamicsMetadataService getItemMetadataService(ServletContext context) { itemMetadataService = itemMetadataService != null ? itemMetadataService : (DynamicsMetadataService) SpringServletAccess.getApplicationContext(context).getBean( "dynamicsMetadataService"); return itemMetadataService; } public static ItemFormMetadataBean runDynamicsCheck(ItemFormMetadataBean metadataBean, EventCRFBean eventCrfBean, ItemDataBean itemDataBean, ServletContext context) { if (!metadataBean.isShowItem()) { // if the base case is not already shown, let's check it boolean showItem = getItemMetadataService(context).isShown(new Integer(metadataBean.getItemId()), eventCrfBean, itemDataBean); metadataBean.setShowItem(showItem); // System.out.println("running is shown to the db..." + showItem + " for " + metadataBean.getItemId()); // setting true or false here, tbh } // however, we run into a puzzle here at the last section, apparently we might take a deep-copy again, resetting this to false return metadataBean; } /** * Create a List of DisplayItemBeans from a List of Items. * * @param itemBeans * A List of ItemBeans that will provide the source of each * DisplayItemBean * @param dataSource * A DataSource for the DAO classes. * @param crfVersionId * The CRF version Id for fetching associated * ItemFormMetadataBeans. * @param sectionId * The section ID associated with the Items. * @param nullValuesList * A List of Strings containing "null values" such as "not * applicable" or NA. * @return A List of DisplayItemBeans. */ public static List<DisplayItemBean> getDisplayBeansFromItems(List<ItemBean> itemBeans, DataSource dataSource, EventCRFBean eventCrfBean, int sectionId, List<String> nullValuesList, ServletContext context) { // logger = LoggerFactory.getLogger(getClass().getName()); List<DisplayItemBean> disBeans = new ArrayList<DisplayItemBean>(); if (itemBeans == null || itemBeans.isEmpty()) return disBeans; ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(dataSource); ItemDataDAO itemDataDAO = new ItemDataDAO(dataSource); DisplayItemBean displayBean; ItemFormMetadataBean meta; // Add any null values to checks or radios String responseName; List<ResponseOptionBean> respOptions; ResponseOptionBean respBean; boolean hasNullValues = nullValuesList != null && !nullValuesList.isEmpty(); String tmpVal = ""; // findByItemIdAndCRFVersionId for (ItemBean iBean : itemBeans) { displayBean = new DisplayItemBean(); meta = metaDao.findByItemIdAndCRFVersionId(iBean.getId(), eventCrfBean.getCRFVersionId());//TODO: eventcrfBean is not valid?? // Only include Items that belong to the associated section if (meta.getSectionId() == sectionId) { displayBean.setItem(iBean); ItemDataBean itemDataBean = itemDataDAO.findByItemIdAndEventCRFId(iBean.getId(), eventCrfBean.getId());//findByItemIdAndEventCRFIdAndOrdinal(iBean.getId(), eventCrfBean.getId(), ordinal) // null values is set by adding the event def. crf bean, but // here we have taken a different approach, tbh // displayBean.setEventDefinitionCRF(); displayBean.setMetadata(runDynamicsCheck(meta, eventCrfBean, itemDataBean, context)); displayBean.setData(itemDataBean); displayBean.setDbData(itemDataBean); // System.out.println("just set: " + itemDataBean.getValue() + " from " + itemDataBean.getItemId()); responseName = displayBean.getMetadata().getResponseSet().getResponseType().getName(); respOptions = displayBean.getMetadata().getResponseSet().getOptions(); if (hasNullValues && respOptions != null && ("checkbox".equalsIgnoreCase(responseName) || "radio".equalsIgnoreCase(responseName) || "single-select".equalsIgnoreCase(responseName) || "multi-select" .equalsIgnoreCase(responseName))) { for (String val : nullValuesList) { respBean = new ResponseOptionBean(); // BWP>> set text to the extended version, "not // applicable"? tmpVal = DataEntryInputGenerator.NULL_VALUES_LONGVERSION.get(val); if (tmpVal != null && tmpVal.length() > 0) { respBean.setText(tmpVal); } else { respBean.setText(val); } respBean.setValue(val); respOptions.add(respBean); } } disBeans.add(displayBean); // logger.info("### respOptions size // "+respOptions.size()+" of item name "+iBean.getName()); } // logger.info("### found name "+iBean.getName()+" and found // response size: "+ // displayBean.getMetadata().getResponseSet().getOptions().size()); } // sort the List of DisplayItemBeans on their ordinal Collections.sort(disBeans); return disBeans; } public static List<DisplayItemBean> getDisplayBeansFromItemsForPrint(List<ItemBean> itemBeans, DataSource dataSource, EventCRFBean eventCrfBean, int sectionId, List<String> nullValuesList, ServletContext context, int crfVersionId) { // logger = LoggerFactory.getLogger(getClass().getName()); List<DisplayItemBean> disBeans = new ArrayList<DisplayItemBean>(); if (itemBeans == null || itemBeans.isEmpty()) return disBeans; ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(dataSource); ItemDataDAO itemDataDAO = new ItemDataDAO(dataSource); DisplayItemBean displayBean; ItemFormMetadataBean meta; // Add any null values to checks or radios String responseName; List<ResponseOptionBean> respOptions; ResponseOptionBean respBean; boolean hasNullValues = nullValuesList != null && !nullValuesList.isEmpty(); String tmpVal = ""; // findByItemIdAndCRFVersionId for (ItemBean iBean : itemBeans) { displayBean = new DisplayItemBean(); meta = metaDao.findByItemIdAndCRFVersionId(iBean.getId(), crfVersionId);//TODO: eventcrfBean is not valid?? // Only include Items that belong to the associated section if (meta.getSectionId() == sectionId) { displayBean.setItem(iBean); ItemDataBean itemDataBean = itemDataDAO.findByItemIdAndEventCRFId(iBean.getId(), eventCrfBean.getId());//findByItemIdAndEventCRFIdAndOrdinal(iBean.getId(), eventCrfBean.getId(), ordinal) // null values is set by adding the event def. crf bean, but // here we have taken a different approach, tbh // displayBean.setEventDefinitionCRF(); displayBean.setMetadata(runDynamicsCheck(meta, eventCrfBean, itemDataBean, context)); displayBean.setData(itemDataBean); displayBean.setDbData(itemDataBean); // System.out.println("just set: " + itemDataBean.getValue() + " from " + itemDataBean.getItemId()); responseName = displayBean.getMetadata().getResponseSet().getResponseType().getName(); respOptions = displayBean.getMetadata().getResponseSet().getOptions(); if (hasNullValues && respOptions != null && ("checkbox".equalsIgnoreCase(responseName) || "radio".equalsIgnoreCase(responseName) || "single-select".equalsIgnoreCase(responseName) || "multi-select" .equalsIgnoreCase(responseName))) { for (String val : nullValuesList) { respBean = new ResponseOptionBean(); // BWP>> set text to the extended version, "not // applicable"? tmpVal = DataEntryInputGenerator.NULL_VALUES_LONGVERSION.get(val); if (tmpVal != null && tmpVal.length() > 0) { respBean.setText(tmpVal); } else { respBean.setText(val); } respBean.setValue(val); respOptions.add(respBean); } } disBeans.add(displayBean); // logger.info("### respOptions size // "+respOptions.size()+" of item name "+iBean.getName()); } // logger.info("### found name "+iBean.getName()+" and found // response size: "+ // displayBean.getMetadata().getResponseSet().getOptions().size()); } // sort the List of DisplayItemBeans on their ordinal Collections.sort(disBeans); return disBeans; } public static List<DisplayItemBean> getDisplayBeansFromItems(List<ItemBean> itemBeans, DataSource dataSource, EventCRFBean eventCrfBean, int sectionId, EventDefinitionCRFBean edcb, int test, ServletContext context) { //int test is for method overloading. List<DisplayItemBean> disBeans = new ArrayList<DisplayItemBean>(); if (itemBeans == null || itemBeans.isEmpty()) return disBeans; ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(dataSource); ItemDataDAO itemDataDao = new ItemDataDAO(dataSource); DisplayItemBean displayBean; ItemFormMetadataBean meta; for (ItemBean iBean : itemBeans) { displayBean = new DisplayItemBean(); displayBean.setEventDefinitionCRF(edcb); meta = metaDao.findByItemIdAndCRFVersionId(iBean.getId(), eventCrfBean.getCRFVersionId()); ItemDataBean itemDataBean = itemDataDao.findByItemIdAndEventCRFId(iBean.getId(), eventCrfBean.getId()); if (meta.getSectionId() == sectionId) { displayBean.setItem(iBean); displayBean.setMetadata(runDynamicsCheck(meta, eventCrfBean, itemDataBean, context)); displayBean.setData(itemDataBean); // << tbh 05/2010 disBeans.add(displayBean); } } Collections.sort(disBeans); return disBeans; } public void addBeansToResponseOptions(List<String> values, List<ResponseOptionBean> respOptions) { ResponseOptionBean respBean; String tmpVal = ""; // Only add the values if the ResponseOptionBeans do not already contain // them for (String val : values) { respBean = new ResponseOptionBean(); // BWP>> set text to the extended version, "not applicable"? tmpVal = DataEntryInputGenerator.NULL_VALUES_LONGVERSION.get(val); if (tmpVal != null && tmpVal.length() > 0) { respBean.setText(tmpVal); } else { respBean.setText(val); } respBean.setValue(val); respOptions.add(respBean); } } public List<ResponseOptionBean> getNullValuesListAsOptionBeans(List<NullValue> nullValues) { List<ResponseOptionBean> responseOptionBeans = new ArrayList<ResponseOptionBean>(); if (nullValues == null || nullValues.isEmpty()) { return responseOptionBeans; } ResponseOptionBean respBean; String name; for (NullValue nullVal : nullValues) { name = nullVal.getName(); respBean = new ResponseOptionBean(); respBean.setText(name); respBean.setValue(name); responseOptionBeans.add(respBean); } return responseOptionBeans; } public DisplayItemBean getDisplayBeanFromSingleItem(ItemFormMetadataBean itemFBean, int sectionId, DataSource dataSource, EventCRFBean eventCrfBean, List<String> nullValuesList, ServletContext context) { DisplayItemBean disBean = new DisplayItemBean(); ItemBean itemBean = new ItemBean(); ItemDAO itemDAO = new ItemDAO(dataSource); ItemDataDAO itemDataDao = new ItemDataDAO(dataSource); if (itemFBean == null) return disBean; itemBean = (ItemBean) itemDAO.findByPK(itemFBean.getItemId()); if (itemBean == null) { itemBean = new ItemBean(); } // Add any null values to checks or radios String responseName; List<ResponseOptionBean> respOptions; ResponseOptionBean respBean; boolean hasNullValues = nullValuesList != null && !nullValuesList.isEmpty(); // Only include Items that belong to the associated section if (itemFBean.getSectionId() == sectionId) { ItemDataBean itemDataBean = itemDataDao.findByItemIdAndEventCRFId(itemBean.getId(), eventCrfBean.getId()); disBean.setItem(itemBean); disBean.setMetadata(runDynamicsCheck(itemFBean, eventCrfBean, itemDataBean, context)); disBean.setData(itemDataBean); logger.debug("3. just set: " + itemDataBean.getValue()); responseName = disBean.getMetadata().getResponseSet().getResponseType().getName(); respOptions = disBean.getMetadata().getResponseSet().getOptions(); if (hasNullValues && respOptions != null && ("checkbox".equalsIgnoreCase(responseName) || "radio".equalsIgnoreCase(responseName) || "single-select".equalsIgnoreCase(responseName) || "multi-select" .equalsIgnoreCase(responseName))) { this.addBeansToResponseOptions(nullValuesList, respOptions); } } return disBean; } /** * Create an XHTML table that encompasses the Items that are not part of a * group. * * @param items * A List of DisplayItemBeans that make up the table content. * @param tabindex * The tab index for any form fields created in the table. * @param hasDiscrepancyMgt * 'true' is the items should be accompanied by discrepancy * notes. * @param hasDBValues * 'true' if the items within the table are pre-filled with * database values. * @param forPrinting * @return The org.jdom Element that represents the table. */ public Element createXHTMLTableFromNonGroup(List<DisplayItemBean> items, Integer tabindex, boolean hasDiscrepancyMgt, boolean hasDBValues, boolean forPrinting) { Element table = new Element("table"); String cssClasses = CssRules.getClassNamesForTag(table.getName()); table.setAttribute("class", cssClasses); /* * Don't add header cells to orphan-type tables, because when the header * is empty, Firefox does not show any borders: Element thead = new * Element("thead"); table.addContent(thead); */ Element tbody = new Element("tbody"); table.addContent(tbody); // divide up items into columns int numberOfColumns = getNumberOfColumnsFromItems(items); // numberOfColumns = 5; // Fixing table width for orphan table Mantis issue: 9087. // ToDo recheck why the main table getting fixed // int tableWidth = numberOfColumns*300; // table.setAttribute("style", "width:" + tableWidth + "px;"); // A Map designed to hold DisplayItemBeans according to their column // number // The Map index is the column number; it is sorted so it begins with // column 1 SortedMap<Integer, List<DisplayItemBean>> colMap = new TreeMap<Integer, List<DisplayItemBean>>(); // A row by row Map for multi-col tables; the index is sorted and begins // with the first row of DisplayItemBeans SortedMap<Integer, List<DisplayItemBean>> multiRowMap = new TreeMap<Integer, List<DisplayItemBean>>(); // This isn't necessary unless there is more than one column if (numberOfColumns > 1) { int column; for (DisplayItemBean displayItem : items) { column = displayItem.getMetadata().getColumnNumber(); if (colMap.get(column) == null) { colMap.put(column, new ArrayList<DisplayItemBean>()); } colMap.get(column).add(displayItem); } int numberOfRows = getNumberOfTableRows(colMap); // numberOfRows = 2; List<DisplayItemBean> itemsList; // the list inside multiRowMap List<DisplayItemBean> rowsList; for (int i = 1; i <= numberOfRows; i++) { rowsList = new ArrayList<DisplayItemBean>(); for (int j = 1; j <= colMap.size(); j++) { itemsList = colMap.get(j); if (itemsList != null && itemsList.size() >= i) { rowsList.add(itemsList.get(i - 1)); } // iterate through the columns map } multiRowMap.put(i, rowsList); } } // Handle the Items in a single column // or several columns // The last boolean parameter specifies whether the displayed items // are involved with printing, in which discrepancy note icons are not // made clickable if (numberOfColumns == 1) { createSingleColumn(tbody, items, tabindex, hasDiscrepancyMgt, hasDBValues, forPrinting); } else { createMultipleCols(tbody, multiRowMap, tabindex, hasDiscrepancyMgt, numberOfColumns, hasDBValues, forPrinting); } return table; } /** * Calculate the number of rows in a structure (table) of DisplayItemBeans. * * @param columnsMap * A Map that maps the column number to the List of * DisplayItemBeans in that column. * @return The number of rows in the table. */ private int getNumberOfTableRows(Map<Integer, List<DisplayItemBean>> columnsMap) { int highestRowNumber = 0; int temp; Map.Entry<Integer, List<DisplayItemBean>> me; List<DisplayItemBean> beanList; for (Iterator<Map.Entry<Integer, List<DisplayItemBean>>> iter = columnsMap.entrySet().iterator(); iter.hasNext();) { me = iter.next(); beanList = me.getValue(); temp = beanList.size(); highestRowNumber = temp > highestRowNumber ? temp : highestRowNumber; } return 1; } /** * Get the highest column number for a List of DisplayItemBeans. * * @param displayItems * The List of DisplayItemBeans. * @return An int representing the highest column number in the List, * obained by getting the ItemFormMetadataBean columnNumber * property. */ public int getNumberOfColumnsFromItems(List<DisplayItemBean> displayItems) { if (displayItems == null) return 0; // one column is the default int highestColumnNum = 1; int temp; for (DisplayItemBean displayItem : displayItems) { temp = displayItem.getMetadata().getColumnNumber(); highestColumnNum = highestColumnNum < temp ? temp : highestColumnNum; } return highestColumnNum; } /** * Create a table containing a single column of Items. * * @param tbody * The JDOM Element representing a tbody tag for the XHTML table. * @param items * The DisplayItemBeans representing the Items for the table. * @param tabindex * The Integer representing the form field's tab index. * @param hasDiscrepancyMgt * A boolean value specifying whether discrepancy icons should be * displayed. * @param hasDBValues * A boolean value specifying whether the input elements are * prefiled with database values. * @param forPrinting * A boolean value specifying whether the CRF is being displayed * for printing (therefore, the D Note icons should not be * enabled or clickable). */ private void createSingleColumn(Element tbody, List<DisplayItemBean> items, Integer tabindex, boolean hasDiscrepancyMgt, boolean hasDBValues, boolean forPrinting) { CellFactory cellFactory = new CellFactory(); // Use this decorator class to generate vertical checkboxes, if any of // the // items have this type of layout CellFactoryPrintDecorator cellFactoryPrintDecorator = new CellFactoryPrintDecorator(); // Create header/subheader rows, if necessary String tmpName; for (DisplayItemBean disBean : items) { tmpName = disBean.getMetadata().getHeader(); if (tmpName != null && tmpName.length() > 0) { Element tr = createHeaderSubheaderCell(disBean, true); // add the row to the tbody element] tbody.addContent(tr); } // Does the row tag need a subheader type background? tmpName = disBean.getMetadata().getSubHeader(); if (tmpName != null && tmpName.length() > 0) { Element tr2 = createHeaderSubheaderCell(disBean, false); tbody.addContent(tr2); } // Create the row containing the item + form field Element trRow = new Element("tr"); String leftSideTxt = ""; String questNumber = ""; tbody.addContent(trRow); String responseName = disBean.getMetadata().getResponseSet().getResponseType().getName(); Element tdCell = new Element("td"); String classNames = CssRules.getClassNamesForTag("td"); tdCell.setAttribute("class", classNames); // use vertical-alignment for these TD cells tdCell.setAttribute("style", "vertical-align:top"); boolean horizontalLayout = "horizontal".equalsIgnoreCase(disBean.getMetadata().getResponseLayout()); // Just use this method for vertical checkboxes and radio buttons if (("checkbox".equalsIgnoreCase(responseName) || "radio".equalsIgnoreCase(responseName)) && !horizontalLayout) { cellFactoryPrintDecorator.createCellContentsForVerticalLayout(tdCell, responseName, disBean, ++tabindex, hasDiscrepancyMgt, hasDBValues, forPrinting); } else { cellFactory.createCellContents(tdCell, responseName, disBean, ++tabindex, hasDiscrepancyMgt, hasDBValues, forPrinting); } questNumber = disBean.getMetadata().getQuestionNumberLabel(); boolean hasQuestion = questNumber.length() > 0; leftSideTxt = disBean.getMetadata().getLeftItemText(); cellFactory.addTextToCell(tdCell, leftSideTxt, CellFactory.LEFT); if (hasQuestion) { addQuestionNumbers(tdCell, questNumber); } trRow.addContent(tdCell); } } /* Add question numbers to the left of existing cell content */ private Element addQuestionNumbers(Element tdCell, String questNumber) { Element existingSpan = tdCell.getChild("span"); Element newSpan = new Element("span"); newSpan.setAttribute("style", "margin-right:1em"); newSpan.addContent(questNumber); existingSpan.addContent(0, newSpan); return tdCell; } private Element createHeaderSubheaderCell(DisplayItemBean disBean, boolean isHeader) { CellFactory cellFactory = new CellFactory(); Element tr = new Element("tr"); Element td = new Element("td"); String cssClassNames = CssRules.getClassNamesForTag("tr header"); tr.setAttribute("class", cssClassNames); cssClassNames = CssRules.getClassNamesForTag("td header"); td.setAttribute("class", cssClassNames); if (isHeader) { td = cellFactory.addTextToCell(td, disBean.getMetadata().getHeader(), CellFactory.LEFT); } else { td = cellFactory.addTextToCell(td, disBean.getMetadata().getSubHeader(), CellFactory.LEFT); } tr.addContent(td); return tr; } private Element createHeaderCellMultiColumn(DisplayItemBean disBean, boolean isHeader, Element row, int numberOfColumns) { // At this point, the row could already contain td cells with headers or // subheaders CellFactory cellFactory = new CellFactory(); if (row == null) { row = new Element("tr"); } Element td = new Element("td"); String cssClassNames = ""; // Does the row have the class attribute yet? if (row.getAttribute("class") == null) { cssClassNames = CssRules.getClassNamesForTag("tr header"); row.setAttribute("class", cssClassNames); } cssClassNames = CssRules.getClassNamesForTag("td header"); td.setAttribute("class", cssClassNames); if (isHeader) { td = cellFactory.addTextToCell(td, disBean.getMetadata().getHeader(), CellFactory.LEFT); } else { td = cellFactory.addTextToCell(td, disBean.getMetadata().getSubHeader(), CellFactory.LEFT); } row.addContent(td); return row; } /** * Create a multiple column XHTML table from a list of display items. * * @param tbody * The Element to add the rows to. * @param displayItemRows * The list of DisplayItemBean and the column they should appear * in. * @param tabindex * The tab index of the form field. * @param hasDiscrepancyMgt * A flag indicating whether or not the Item is involved with * @param numberOfColumns * An integer representing the highest number of columns with * cell content in this group of rows (e.g., one row has five td * cells with content, the highest number of any * @param hasDBValues * @param forPrinting */ private void createMultipleCols(Element tbody, Map<Integer, List<DisplayItemBean>> displayItemRows, Integer tabindex, boolean hasDiscrepancyMgt, int numberOfColumns, boolean hasDBValues, boolean forPrinting) { CellFactory cellFactory = new CellFactory(); // Use this decorator class to generate vertical checkboxes or radios, // if any of the // items have this type of layout CellFactoryPrintDecorator cellFactoryPrintDecorator = new CellFactoryPrintDecorator(); // Create header/subheader rows, if necessary Map.Entry<Integer, List<DisplayItemBean>> me; List<DisplayItemBean> itemsList; int numberOfBeansInRow; Element formFieldRow = new Element("tr");; Element headerRow; Element subHeaderRow; for (Iterator<Map.Entry<Integer, List<DisplayItemBean>>> iter = displayItemRows.entrySet().iterator(); iter.hasNext();) { me = iter.next(); itemsList = me.getValue(); numberOfBeansInRow = itemsList.size(); // Each Entry points to a List of DisplayItemBeans that are in the // rows // Create the row containing the item + form field headerRow = new Element("tr"); subHeaderRow = new Element("tr"); String leftSideTxt = ""; // keep track of the last bean in the row, so we can fill the row // with any necessary empty td cells for (DisplayItemBean disBean : me.getValue()) { // Each row has its own instance of headerRow and subHeaderRow if (disBean.getMetadata().getHeader().length() > 0) { headerRow = createHeaderCellMultiColumn(disBean, true, headerRow, numberOfBeansInRow); } if (disBean.getMetadata().getSubHeader().length() > 0) { subHeaderRow = createHeaderCellMultiColumn(disBean, false, subHeaderRow, numberOfBeansInRow); } String responseName = disBean.getMetadata().getResponseSet().getResponseType().getName(); Element tdCell = new Element("td"); String classNames = CssRules.getClassNamesForTag("td"); tdCell.setAttribute("class", classNames); String questNumber = ""; questNumber = disBean.getMetadata().getQuestionNumberLabel(); boolean hasQuestion = questNumber.length() > 0; leftSideTxt = disBean.getMetadata().getLeftItemText(); // use vertical-alignment for these TD cells tdCell.setAttribute("style", "vertical-align:top"); boolean horizontalLayout = "horizontal".equalsIgnoreCase(disBean.getMetadata().getResponseLayout()); // Just use this method for vertically arranged checkboxes and // radio buttons // The final "forPrinting" parameter is a boolean specifying // whether the CRF // is a print view; therefore, disable the clicking of // discrepancy note icons if (("checkbox".equalsIgnoreCase(responseName) || "radio".equalsIgnoreCase(responseName)) && !horizontalLayout) { cellFactoryPrintDecorator.createCellContentsForVerticalLayout(tdCell, responseName, disBean, ++tabindex, hasDiscrepancyMgt, hasDBValues, forPrinting); } else { cellFactory.createCellContents(tdCell, responseName, disBean, ++tabindex, hasDiscrepancyMgt, hasDBValues, forPrinting); } cellFactory.addTextToCell(tdCell, leftSideTxt, CellFactory.LEFT); if (hasQuestion) { addQuestionNumbers(tdCell, questNumber); } formFieldRow.addContent(tdCell); } int cellCountDif; int childrenCount; // if the header/subheader rows have content, // then add them to the tbody element if ((childrenCount = headerRow.getChildren("td").size()) > 0) { // if the header row has fewer cells then the number of item TD // cells, // then pad the header row with empty td cells to make up the // difference cellCountDif = numberOfBeansInRow - childrenCount; if (cellCountDif > 0) { headerRow = addEmptyTDcells(headerRow, cellCountDif); } tbody.addContent(headerRow); } if ((childrenCount = subHeaderRow.getChildren("td").size()) > 0) { cellCountDif = numberOfBeansInRow - childrenCount; if (cellCountDif > 0) { subHeaderRow = addEmptyTDcells(subHeaderRow, cellCountDif); } tbody.addContent(subHeaderRow); } // pad the actual row of form fields with td cells, to make the // columns equivalent cellCountDif = numberOfColumns - numberOfBeansInRow; if (cellCountDif > 0) { formFieldRow = addEmptyTDcells(formFieldRow, cellCountDif); } } tbody.addContent(formFieldRow); } private Element addEmptyTDcells(Element row, int numberOfCellsToAdd) { Element td; for (int i = 1; i <= numberOfCellsToAdd; i++) { td = new Element("td"); row.addContent(td); } return row; } /** * Create a DisplayFormGroupBean from a List of DisplayItemBeans and a * FormGroupBean. * * @param displayItems * The DisplayItemBeans that provide the table content. * @param itemGroup * The FormGroupBean that represents the Group information from * the spreadsheet template.. * @return A DisplayFormGroupBean. */ public DisplayItemGroupBean createDisplayFormGroup(List<DisplayItemBean> displayItems, ItemGroupBean itemGroup) { DisplayItemGroupBean fgBean = new DisplayItemGroupBean(); fgBean.setItems(displayItems); fgBean.setItemGroupBean(itemGroup); fgBean.setGroupMetaBean(itemGroup.getMeta()); return fgBean; } /** * Create a DisplaySectionBean with a list of ItemGroupBeans. This List will * include any ItemGroupBeans that are associated with ungrouped items; in * other words, the DisplaySectionBean will represent a section that has * both ungrouped and grouped tables. * * @param sectionId * The Section ID associated with the Items, which end up * providing the content of the tables. * @param crfVersionId * The CRF version ID associated with the Items. * @param dataSource * @param eventCRFDefId * The id for the Event CRF Definition. * @return A DisplaySectionBean with sorted ItemGroupBeans, meaning the * ItemGroupBeans should be listed in the order that they appear on * the CRF section. * @return A DisplaySectionBean representing a CRF section. */ public DisplaySectionBean createDisplaySectionBWithFormGroups(int sectionId, int crfVersionId, DataSource dataSource, int eventCRFDefId, EventCRFBean eventCrfBean, ServletContext context) { DisplaySectionBean displaySectionBean = new DisplaySectionBean(); ItemGroupDAO formGroupDAO = new ItemGroupDAO(dataSource); ItemGroupMetadataDAO igMetaDAO = new ItemGroupMetadataDAO(dataSource); ItemDAO itemDao = new ItemDAO(dataSource); ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(dataSource); SectionDAO sectionDao = new SectionDAO(dataSource); // Give the DisplaySectionBean a legitimate SectionBean SectionBean secBean = (SectionBean) sectionDao.findByPK(sectionId); displaySectionBean.setSection(secBean); // changed from: findGroupBySectionId List<ItemGroupBean> itemGroupBeans = formGroupDAO.findLegitGroupAllBySectionId(sectionId); // all items associated with the section, including those not in a group List<ItemFormMetadataBean> allMetas = new ArrayList<ItemFormMetadataBean>(); try { allMetas = metaDao.findAllBySectionId(sectionId); } catch (OpenClinicaException oce) { logger.info("oce.getOpenClinicaMessage() = " + oce.getOpenClinicaMessage()); } // Sort these items according to their position on the CRF; their // ordinal Collections.sort(allMetas); // The DisplayItemGroupBean(s) for "nongrouped" items List<DisplayItemGroupBean> nonGroupBeans = null; // if(itemGroupBeans.isEmpty()) return displaySectionBean; // Find out whether there are any checkboxes/radios/select elements // and if so, get any null values // associated with them List<String> nullValuesList = new ArrayList<String>(); boolean itemsHaveChecksRadios = itemsIncludeChecksRadiosSelects(allMetas); if (itemsHaveChecksRadios && eventCRFDefId > 0) { // method returns null values as a List<String> nullValuesList = this.getNullValuesByEventCRFDefId(eventCRFDefId, dataSource); } // Get the items associated with each group List<ItemBean> itBeans; List<DisplayItemBean> displayItems; List<DisplayItemGroupBean> displayFormBeans = new ArrayList<DisplayItemGroupBean>(); DisplayItemGroupBean displayItemGBean; for (ItemGroupBean itemGroup : itemGroupBeans) { itBeans = itemDao.findAllItemsByGroupId(itemGroup.getId(), crfVersionId); logger.debug("just ran find all by group id " + itemGroup.getId() + " found " + itBeans.size() + " item beans"); List<ItemGroupMetadataBean> metadata = igMetaDAO.findMetaByGroupAndSection(itemGroup.getId(), crfVersionId, sectionId); if (!metadata.isEmpty()) { // for a given crf version, all the items in the same group // have the same group metadata info // so we can get one of the metadata and set the metadata for // the group ItemGroupMetadataBean meta = metadata.get(0); itemGroup.setMeta(meta); } displayItems = getDisplayBeansFromItems(itBeans, dataSource, eventCrfBean, sectionId, nullValuesList, context); displayItemGBean = this.createDisplayFormGroup(displayItems, itemGroup); displayFormBeans.add(displayItemGBean); } // We still have to sort these display item group beans on their // ItemGroupMetadataBean? // then number their ordinals accordingly Collections.sort(displayFormBeans, new Comparator<DisplayItemGroupBean>() { public int compare(DisplayItemGroupBean displayItemGroupBean, DisplayItemGroupBean displayItemGroupBean1) { return displayItemGroupBean.getGroupMetaBean().compareTo(displayItemGroupBean1.getGroupMetaBean()); } }); // Now provide the display item group beans with an ordinal int digOrdinal = 0; for (DisplayItemGroupBean digBean : displayFormBeans) { digBean.setOrdinal(++digOrdinal); } // find out whether there are any ungrouped items by comparing the // number of // grouped items to allMetas.size() // List<DisplayItemGroupBean> nonGroupBeans=null; int tempCount = 0; for (DisplayItemGroupBean groupBean : displayFormBeans) { tempCount += groupBean.getItems().size(); } if (tempCount < allMetas.size()) { nonGroupBeans = createGroupBeansForNongroupedItems(allMetas, displayFormBeans, sectionId, dataSource, nullValuesList, eventCrfBean, context); } if (nonGroupBeans != null) { displayFormBeans.addAll(nonGroupBeans); } // sort the list according to the ordinal of the contained // DisplayItemGroupBeans Collections.sort(displayFormBeans, new Comparator<DisplayItemGroupBean>() { public int compare(DisplayItemGroupBean disFormGroupBean, DisplayItemGroupBean disFormGroupBean1) { Integer compInt = disFormGroupBean1.getOrdinal(); Integer compInt2 = disFormGroupBean.getOrdinal(); return compInt2.compareTo(compInt); } }); displaySectionBean.setDisplayFormGroups(displayFormBeans); return displaySectionBean; } public DisplaySectionBean createDisplaySectionBWithFormGroupsForPrint(int sectionId, int crfVersionId, DataSource dataSource, int eventCRFDefId, EventCRFBean eventCrfBean, ServletContext context) { DisplaySectionBean displaySectionBean = new DisplaySectionBean(); ItemGroupDAO formGroupDAO = new ItemGroupDAO(dataSource); ItemGroupMetadataDAO igMetaDAO = new ItemGroupMetadataDAO(dataSource); ItemDAO itemDao = new ItemDAO(dataSource); ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(dataSource); SectionDAO sectionDao = new SectionDAO(dataSource); // Give the DisplaySectionBean a legitimate SectionBean SectionBean secBean = (SectionBean) sectionDao.findByPK(sectionId); displaySectionBean.setSection(secBean); // changed from: findGroupBySectionId List<ItemGroupBean> itemGroupBeans = formGroupDAO.findLegitGroupAllBySectionId(sectionId); // all items associated with the section, including those not in a group List<ItemFormMetadataBean> allMetas = new ArrayList<ItemFormMetadataBean>(); try { allMetas = metaDao.findAllBySectionId(sectionId); } catch (OpenClinicaException oce) { logger.info("oce.getOpenClinicaMessage() = " + oce.getOpenClinicaMessage()); } // Sort these items according to their position on the CRF; their // ordinal Collections.sort(allMetas); // The DisplayItemGroupBean(s) for "nongrouped" items List<DisplayItemGroupBean> nonGroupBeans = null; // if(itemGroupBeans.isEmpty()) return displaySectionBean; // Find out whether there are any checkboxes/radios/select elements // and if so, get any null values // associated with them List<String> nullValuesList = new ArrayList<String>(); boolean itemsHaveChecksRadios = itemsIncludeChecksRadiosSelects(allMetas); if (itemsHaveChecksRadios && eventCRFDefId > 0) { // method returns null values as a List<String> nullValuesList = this.getNullValuesByEventCRFDefId(eventCRFDefId, dataSource); } // Get the items associated with each group List<ItemBean> itBeans; List<DisplayItemBean> displayItems; List<DisplayItemGroupBean> displayFormBeans = new ArrayList<DisplayItemGroupBean>(); DisplayItemGroupBean displayItemGBean; for (ItemGroupBean itemGroup : itemGroupBeans) { itBeans = itemDao.findAllItemsByGroupIdForPrint(itemGroup.getId(), crfVersionId,sectionId);//TODO:fix me! logger.debug("just ran find all by group id " + itemGroup.getId() + " found " + itBeans.size() + " item beans"); List<ItemGroupMetadataBean> metadata = igMetaDAO.findMetaByGroupAndSectionForPrint(itemGroup.getId(), crfVersionId, sectionId);//TODO:fix me add item_form_metadata.section_id to the query if (!metadata.isEmpty()) { // for a given crf version, all the items in the same group // have the same group metadata info // so we can get one of the metadata and set the metadata for // the group ItemGroupMetadataBean meta = metadata.get(0); itemGroup.setMeta(meta); } displayItems = getDisplayBeansFromItemsForPrint(itBeans, dataSource, eventCrfBean, sectionId, nullValuesList, context,crfVersionId); displayItemGBean = this.createDisplayFormGroup(displayItems, itemGroup); displayFormBeans.add(displayItemGBean); } // We still have to sort these display item group beans on their // ItemGroupMetadataBean? // then number their ordinals accordingly Collections.sort(displayFormBeans, new Comparator<DisplayItemGroupBean>() { public int compare(DisplayItemGroupBean displayItemGroupBean, DisplayItemGroupBean displayItemGroupBean1) { return displayItemGroupBean.getGroupMetaBean().compareTo(displayItemGroupBean1.getGroupMetaBean()); } }); // Now provide the display item group beans with an ordinal int digOrdinal = 0; for (DisplayItemGroupBean digBean : displayFormBeans) { digBean.setOrdinal(++digOrdinal); } // find out whether there are any ungrouped items by comparing the // number of // grouped items to allMetas.size() // List<DisplayItemGroupBean> nonGroupBeans=null; int tempCount = 0; for (DisplayItemGroupBean groupBean : displayFormBeans) { tempCount += groupBean.getItems().size(); } if (tempCount < allMetas.size()) { nonGroupBeans = createGroupBeansForNongroupedItems(allMetas, displayFormBeans, sectionId, dataSource, nullValuesList, eventCrfBean, context); } if (nonGroupBeans != null) { displayFormBeans.addAll(nonGroupBeans); } // sort the list according to the ordinal of the contained // DisplayItemGroupBeans Collections.sort(displayFormBeans, new Comparator<DisplayItemGroupBean>() { public int compare(DisplayItemGroupBean disFormGroupBean, DisplayItemGroupBean disFormGroupBean1) { Integer compInt = disFormGroupBean1.getOrdinal(); Integer compInt2 = disFormGroupBean.getOrdinal(); return compInt2.compareTo(compInt); } }); displaySectionBean.setDisplayFormGroups(displayFormBeans); return displaySectionBean; } /** * This method is designed to make it easier to order grouped and nongrouped * items on a CRF. This method generates a List of DisplayItemGroupBeans * representing the items that are not formally part of a group-type * horizontal table (they have a name in the database of 'Ungrouped' ). The * DisplayItemGroupBeans are ordered according to the position of the items * on the CRF, compared with the CRF items that are in groups. When this * List is combined with a List of DisplayItemGroupBeans representing * *grouped* items, the combined List can be sorted and displayed in the * proper order on a CRF. * * @param allItems * A List of the ItemFormMetadataBeans associated with the CRF. * @param displayFormBeans * The List of DisplayItemGroupBeans * @param sectionId * The section ID associated with the items * @param dataSource * The DataSource used to acquire the DAO-related connections * @param nullValuesList * The list of any "null values" associated with the items (like * "not applicable") * @return An ArrayList of DisplayItemGroupBeans for 'Ungrouped' items. */ private List<DisplayItemGroupBean> createGroupBeansForNongroupedItems(List<ItemFormMetadataBean> allItems, List<DisplayItemGroupBean> displayFormBeans, int sectionId, DataSource dataSource, List<String> nullValuesList, EventCRFBean eventCrfBean, ServletContext context) { // This will hold the List of placeholder groupBeans for orphaned items List<DisplayItemGroupBean> groupBeans = new ArrayList<DisplayItemGroupBean>(); // Now create a Map that maps the item to the group ordinal // (e.g., 1) or 0 (non-group), // as a convenient way to position an item on a CRF // and associate an item with the ordinal of its group. // The inner Map maps the ItemFormMetadataBean to its group ordinal; // The Integer index to this Map represents the order of the item on the // CRF. SortedMap<Integer, Map<ItemFormMetadataBean, Integer>> groupMapping = new TreeMap<Integer, Map<ItemFormMetadataBean, Integer>>(); Map<ItemFormMetadataBean, Integer> innerMap; int counter = 0; int tmpOrdinal; for (ItemFormMetadataBean imetaBean : allItems) { innerMap = new HashMap<ItemFormMetadataBean, Integer>(); if (isGrouped(imetaBean, displayFormBeans)) { tmpOrdinal = getGroupOrdinal(imetaBean, displayFormBeans); innerMap.put(imetaBean, tmpOrdinal); } else { innerMap.put(imetaBean, 0); } groupMapping.put(++counter, innerMap); } // The groupMapping Map maps the index position of the item on the CRF // form (1,2,3...) to // the ItemFormMetadataBean and its associated group ordinal, if it has // one // If the ordinal is 0, then the associated ItemFormMetadataBean // represents an // ungrouped or orphaned item DisplayItemGroupBean nongroupedBean; ItemGroupBean itemGroup = new ItemGroupBean(); ItemGroupMetadataBean metaBean = new ItemGroupMetadataBean(); metaBean.setName(UNGROUPED); List<DisplayItemBean> items; // Now cycle through the groupMapping and create default groups or // DisplayItemGroupBeans, in order, for // the orphaned items. // A DisplayItemGroupBean is only created and stored in the returned // List // if its contents or associated items are nongrouped. // This int tracks the ordinal associated with each grouped item's // associated // DisplayItemGroupBean // as that item is incremented int ordinalTracker = 0; // This int is set to the latest DisplayItemGroupBean ordinal containing // nongrouped beans, so that it can be incremented and used to change // the ordinal of any DisplayItemGroupBeans (containing *grouped* items) // that follow this bean on the CRF // int nonGroupOrdinal=0; Map.Entry<Integer, Map<ItemFormMetadataBean, Integer>> entry; Map<ItemFormMetadataBean, Integer> beanMap; nongroupedBean = new DisplayItemGroupBean(); ItemFormMetadataBean tempItemMeta; int tempOrdinal; // a flag indicating that the last item handled was an orphaned one // so that if the next item is grouped, that's a signal to store the // new itemgroupbean just created for orphaned items in in the // itemgroupbean List. boolean isOrphaned = false; // cycle through each item and create DisplayItemGroupBean(s) for // any of the orphaned items for (Iterator<Map.Entry<Integer, Map<ItemFormMetadataBean, Integer>>> iter = groupMapping.entrySet().iterator(); iter.hasNext();) { entry = iter.next(); beanMap = entry.getValue(); // the ItemFormMetadataBean and any // group ordinal tempItemMeta = beanMap.keySet().iterator().next(); // the // ItemFormMetadataBean // If this value is 0, the item is orphaned; if > 0 the item is // grouped // and doesn't need a new itemgroupbean tempOrdinal = beanMap.get(tempItemMeta); // we need to create a new itemgroupbean if tempOrdinal == 0 and // ordinalTracker != 0 if (tempOrdinal == 0) { // an orphaned item if (ordinalTracker == 0 || !isOrphaned) { // initialize a new group for the item nongroupedBean = new DisplayItemGroupBean(); itemGroup = new ItemGroupBean(); itemGroup.setName(UNGROUPED); nongroupedBean.setItemGroupBean(itemGroup); // set this flag, so that if the next item is orphaned, then // the code can place it in the existing itemgroupbean isOrphaned = true; ordinalTracker++; nongroupedBean.setOrdinal(ordinalTracker); // nonGroupOrdinal=nongroupedBean.getOrdinal(); // nonGroupOrdinal= ordinalTracker; } // Add the item as a displayitem to the itemgroupbean nongroupedBean.getItems().add(getDisplayBeanFromSingleItem(tempItemMeta, sectionId, dataSource, eventCrfBean, nullValuesList, context)); } else { // a grouped item // if the last item was orphaned then a new itemgroupbean had to // have // been created; therefore, store it in the List. if (isOrphaned) { groupBeans.add(nongroupedBean); // We also know that the ordinal has changed, because a // nongroupedBean // has been created ordinalTracker++; incrementOrdinal(tempItemMeta, displayFormBeans, ordinalTracker); } else { ordinalTracker = getGroupOrdinal(tempItemMeta, displayFormBeans); } isOrphaned = false; } }// end for // If the last item was orphaned, then we know that a new itemgroup // is leftover and must be added to the List if (isOrphaned) { groupBeans.add(nongroupedBean); } return groupBeans; } private void incrementOrdinal(ItemFormMetadataBean itemFormBean, List<DisplayItemGroupBean> displayFormBeans, int ordinalTracker) { outer: for (DisplayItemGroupBean digBean : displayFormBeans) { for (DisplayItemBean diBean : digBean.getItems()) { if (itemFormBean.getItemId() == diBean.getItem().getId()) { // int tmp = digBean.getOrdinal(); // ++tmp // The DisplayItemGroupBean's ordinal should be one more // than any // preceding DisplayItemGroupBeans involving nongrouped // items digBean.setOrdinal(ordinalTracker); break outer; } } } } private boolean isGrouped(ItemFormMetadataBean itemFormBean, List<DisplayItemGroupBean> displayFormBeans) { boolean grouped = false; outer: for (DisplayItemGroupBean digBean : displayFormBeans) { for (DisplayItemBean diBean : digBean.getItems()) { if (itemFormBean.getItemId() == diBean.getItem().getId()) { grouped = true; break outer; } } } return grouped; } /** * This method returns the ordinal of the DisplayItemGroupBean that contains * ItemFormMetadataBean passed in as the parameter. It is a utility method * used for finding out the group table ordinal associated with a particular * item. * * @param itemFBean * An ItemFormMetadataBean. * @param displayFormBeans * An ArrayList of DisplayItemGroupBeans associated with a * particular CRF. * @return The ordinal of the DisplayItemGroupBean that contains * ItemFormMetadataBean passed in as the parameter; an int. */ private int getGroupOrdinal(ItemFormMetadataBean itemFBean, List<DisplayItemGroupBean> displayFormBeans) { int ordinal = 0; outer: for (DisplayItemGroupBean digBean : displayFormBeans) { for (DisplayItemBean diBean : digBean.getItems()) { if (itemFBean.getItemId() == diBean.getItem().getId()) { ordinal = digBean.getOrdinal(); break outer; } } } return ordinal; } /** * Create a DisplaySectionBean with a list of FormGroupBeans. * * @param crfVersionId * The CRF version ID associated with the Items. * @param sectionBean * The SectionBean with an ID associated with the Items, which * end up providing the content of the tables. * @param sm * A SessionManager, from which DataSources are acquired for the * DAO objects. * @return A DisplaySectionBean. */ public DisplaySectionBean createDisplaySectionBeanWithItemGroups(int sectionId, EventCRFBean eventCrfBean, SectionBean sectionBean, SessionManager sm, ServletContext context) { DisplaySectionBean dBean = new DisplaySectionBean(); ItemGroupDAO formGroupDAO = new ItemGroupDAO(sm.getDataSource()); ItemGroupMetadataDAO igMetaDAO = new ItemGroupMetadataDAO(sm.getDataSource()); ItemDAO itemDao = new ItemDAO(sm.getDataSource()); // Get all items associated with this crfVersion ID; divide them up into // items with a group, and those without a group. // get all items associated with a section id, then split them up into // grouped // and non-grouped items List<ItemBean> allItems = itemDao.findAllParentsBySectionId(sectionId); // Get a List of FormGroupBeans for each group associated with // this crfVersionId. // List<ItemGroupBean> arrList = // formGroupDAO.findGroupByCRFVersionIDMap(crfVersionId); List<ItemGroupBean> arrList = formGroupDAO.findLegitGroupBySectionId(sectionId); if (arrList.isEmpty()) return dBean; // Get the items associated with each group List<ItemBean> itBeans; List<DisplayItemBean> displayItems; List<DisplayItemGroupBean> displayFormBeans = new ArrayList<DisplayItemGroupBean>(); DisplayItemGroupBean displayFormGBean; for (ItemGroupBean itemGroup : arrList) { itBeans = itemDao.findAllItemsByGroupId(itemGroup.getId(), eventCrfBean.getCRFVersionId()); List<ItemGroupMetadataBean> metadata = igMetaDAO.findMetaByGroupAndSection(itemGroup.getId(), eventCrfBean.getCRFVersionId(), sectionId); // Create DisplayItemBeans out of the found items; we have to // further // delineate the items by section label. The following method // includes // this requirement if (!metadata.isEmpty()) { // for a given crf version, all the items in the same group have // the same group metadata // so we can get one of them and set metadata for the group ItemGroupMetadataBean meta = metadata.get(0); itemGroup.setMeta(meta); } // TODO: the last arg is a list of null value strings displayItems = getDisplayBeansFromItems(itBeans, sm.getDataSource(), eventCrfBean, sectionBean.getId(), null, context); displayFormGBean = this.createDisplayFormGroup(displayItems, itemGroup); displayFormBeans.add(displayFormGBean); } // sort the list according to the ordinal of the contained // FormGroupBeans Collections.sort(displayFormBeans, new Comparator<DisplayItemGroupBean>() { public int compare(DisplayItemGroupBean disFormGroupBean, DisplayItemGroupBean disFormGroupBean1) { return disFormGroupBean.getGroupMetaBean().getOrdinal().compareTo(disFormGroupBean1.getGroupMetaBean().getOrdinal()); } }); dBean.setDisplayFormGroups(displayFormBeans); return dBean; } /** * Create a DisplaySectionBean with a list of ItemGroupBeans. NOTE: * unGrouped Items are not included * * @param study * The StudyBean * @param sectionId * The Section ID associated with the Items, which end up * providing the content of the tables. * @param crfVersionId * The CRF version ID associated with the Items. * @param studyEventId * The Study Event ID associated with the CRF Version ID. * @param sm * A SessionManager, from which DataSources are acquired for the * DAO objects. * @return A DisplaySectionBean. */ public DisplaySectionBean createDisplaySectionWithItemGroups(StudyBean study, int sectionId, EventCRFBean eventCrfBean, int studyEventId, SessionManager sm, int eventDefinitionCRFId, ServletContext context) { DisplaySectionBean dBean = new DisplaySectionBean(); ItemGroupDAO formGroupDAO = new ItemGroupDAO(sm.getDataSource()); ItemGroupMetadataDAO igMetaDAO = new ItemGroupMetadataDAO(sm.getDataSource()); ItemDAO itemDao = new ItemDAO(sm.getDataSource()); ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(sm.getDataSource()); List<ItemGroupBean> arrList = formGroupDAO.findLegitGroupBySectionId(sectionId); // all items associated with the section, including those not in a group List<ItemFormMetadataBean> allMetas = new ArrayList<ItemFormMetadataBean>(); try { allMetas = metaDao.findAllBySectionId(sectionId); } catch (OpenClinicaException oce) { logger.info("oce.getOpenClinicaMessage() = " + oce.getOpenClinicaMessage()); } // Sort these items according to their position on the CRF // Collections.sort(allMetas); if (arrList.isEmpty()) return dBean; // Find out whether there are any checkboxes/radios/select elements // and if so, get any null values // associated with them List<String> nullValuesList = new ArrayList<String>(); boolean itemsHaveChecksRadios = itemsIncludeChecksRadiosSelects(allMetas); // tbh>> // logger.info("line 923, found event def crf id // "+eventDefinitionCRFId); if (eventDefinitionCRFId <= 0) { EventDefinitionCRFDAO edcdao = new EventDefinitionCRFDAO(sm.getDataSource()); EventDefinitionCRFBean edcBean = edcdao.findByStudyEventIdAndCRFVersionId(study, studyEventId, eventCrfBean.getCRFVersionId()); eventDefinitionCRFId = edcBean.getId(); } // tbh, 112007, added above because the id was not passed properly for // DDE // if the id is zero, horizontal result sets do not display null values // logger.info("line 933, found event def crf id // "+eventDefinitionCRFId); if (itemsHaveChecksRadios && eventDefinitionCRFId > 0) { // method returns null values as a List<String> nullValuesList = this.getNullValuesByEventCRFDefId(eventDefinitionCRFId, sm.getDataSource()); } // Get the items associated with each group List<ItemBean> itBeans; List<DisplayItemBean> displayItems; List<DisplayItemGroupBean> displayFormBeans = new ArrayList<DisplayItemGroupBean>(); DisplayItemGroupBean displayItemGBean; for (ItemGroupBean itemGroup : arrList) { itBeans = itemDao.findAllItemsByGroupId(itemGroup.getId(), eventCrfBean.getCRFVersionId()); List<ItemGroupMetadataBean> metadata = igMetaDAO.findMetaByGroupAndSection(itemGroup.getId(), eventCrfBean.getCRFVersionId(), sectionId); if (!metadata.isEmpty()) { // for a given crf version, all the items in the same group // have the same group metadata // so we can get one of them and set metadata for the group ItemGroupMetadataBean meta = metadata.get(0); itemGroup.setMeta(meta); } // include arrayList parameter until I determine difference in // classes displayItems = getDisplayBeansFromItems(itBeans, sm.getDataSource(), eventCrfBean, sectionId, nullValuesList, context); displayItemGBean = this.createDisplayFormGroup(displayItems, itemGroup); displayFormBeans.add(displayItemGBean); } // We still have to sort these display item group beans on their // ItemGroupMetadataBean? // then number their ordinals accordingly Collections.sort(displayFormBeans, new Comparator<DisplayItemGroupBean>() { public int compare(DisplayItemGroupBean displayItemGroupBean, DisplayItemGroupBean displayItemGroupBean1) { return displayItemGroupBean.getGroupMetaBean().compareTo(displayItemGroupBean1.getGroupMetaBean()); } }); // Now provide the display item group beans with an ordinal int digOrdinal = 0; for (DisplayItemGroupBean digBean : displayFormBeans) { digBean.setOrdinal(++digOrdinal); } dBean.setDisplayFormGroups(displayFormBeans); return dBean; } public boolean sectionHasUngroupedItems(DataSource dataSource, int sectionId, List<DisplayItemGroupBean> displayFormBeans) { ItemFormMetadataDAO metaDao = new ItemFormMetadataDAO(dataSource); List<ItemFormMetadataBean> allMetas = new ArrayList<ItemFormMetadataBean>(); try { allMetas = metaDao.findAllBySectionId(sectionId); } catch (OpenClinicaException oce) { logger.info("oce.getOpenClinicaMessage() = " + oce.getOpenClinicaMessage()); } int size = allMetas.size(); int tempCount = 0; String grpName = ""; // Only count grouped items for (DisplayItemGroupBean groupBean : displayFormBeans) { grpName = groupBean.getItemGroupBean().getName(); if (!(grpName.equalsIgnoreCase("Ungrouped") || grpName.length() < 1)) { tempCount += groupBean.getItems().size(); } } return tempCount < size; } public List<String> getNullValuesByEventCRFDefId(int eventDefinitionCRFId, DataSource dataSource) { if (eventDefinitionCRFId < 1 || dataSource == null) { return new ArrayList<String>(); } List<String> nullValuesList = new ArrayList<String>(); // hold the bean's return value List<NullValue> nullObjectList = new ArrayList<NullValue>(); EventDefinitionCRFBean eventCRFDefBean; EventDefinitionCRFDAO eventDefinitionCRFDAO = new EventDefinitionCRFDAO(dataSource); eventCRFDefBean = (EventDefinitionCRFBean) eventDefinitionCRFDAO.findByPK(eventDefinitionCRFId); nullObjectList = eventCRFDefBean.getNullValuesList(); if (nullObjectList == null) { return new ArrayList<String>(); } for (NullValue nullVal : nullObjectList) { nullValuesList.add(nullVal.getName()); } return nullValuesList; } private boolean itemsIncludeChecksRadiosSelects(List<ItemFormMetadataBean> metaBeans) { String responseName; for (ItemFormMetadataBean fbean : metaBeans) { responseName = fbean.getResponseSet().getResponseType().getName(); if (responseName == null || responseName.length() < 1) { return false; } if (responseName.equalsIgnoreCase("checkbox") || responseName.equalsIgnoreCase("radio") || responseName.equalsIgnoreCase("single-select") || responseName.equalsIgnoreCase("multi-select")) { return true; } } return false; } public void addNullValuesToDisplayItemWithGroupBeans(List<DisplayItemWithGroupBean> groupBeans, List<String> nullValuesList) { if (nullValuesList == null || nullValuesList.isEmpty() || groupBeans == null || groupBeans.isEmpty()) { return; } DisplayItemGroupBean displayItemGroupBean = null; List<DisplayItemBean> disBeans = new ArrayList<DisplayItemBean>(); String responseName = ""; List<ResponseOptionBean> respOptions; for (DisplayItemWithGroupBean withGroupBean : groupBeans) { displayItemGroupBean = withGroupBean.getItemGroup(); disBeans = displayItemGroupBean.getItems(); for (DisplayItemBean singleBean : disBeans) { responseName = singleBean.getMetadata().getResponseSet().getResponseType().getName(); respOptions = singleBean.getMetadata().getResponseSet().getOptions(); if (respOptions != null && ("checkbox".equalsIgnoreCase(responseName) || "radio".equalsIgnoreCase(responseName) || "single-select".equalsIgnoreCase(responseName) || "multi-select" .equalsIgnoreCase(responseName))) { this.addBeansToResponseOptions(nullValuesList, respOptions); } } } } }