001/* 002 * All rights reserved. This program and the accompanying materials 003 * are made available under the terms of the GNU Lesser General Public License 004 * (LGPL) version 2.1 which accompanies this distribution, and is available at 005 * http://www.gnu.org/licenses/lgpl.html 006 * 007 * This library is distributed in the hope that it will be useful, 008 * but WITHOUT ANY WARRANTY; without even the implied warranty of 009 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 010 * Lesser General Public License for more details. 011 * 012 * Contributors: 013 * Original file from org.jboss.seam.excel.ui.UIColumn.java in jboss-seam-excel 014 * Anahide Tchertchian 015 */ 016package org.nuxeo.ecm.platform.ui.web.component.seam; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.Iterator; 021import java.util.List; 022 023import javax.faces.component.UIComponent; 024import javax.faces.context.FacesContext; 025 026import org.jboss.seam.excel.ExcelWorkbook; 027import org.jboss.seam.excel.ExcelWorkbookException; 028import org.jboss.seam.excel.WorksheetItem; 029import org.jboss.seam.excel.ui.UIWorksheet; 030import org.jboss.seam.excel.ui.command.Command; 031 032/** 033 * Overrides default column for better introspection of children. 034 * <p> 035 * If e:column tags are not direct children, the work sheet will not find them. As layout templating adds additional JSF 036 * components, the children tree has to be introspected further on, and other children components need to be processed 037 * (UIAliasHolder components used in layout rendering for instance). 038 * 039 * @since 5.4.2 040 */ 041public class UIColumn extends org.jboss.seam.excel.ui.UIColumn { 042 043 public static final String COMPONENT_TYPE = UIColumn.class.getName(); 044 045 public static final String FOOTER_FACET_NAME = "footer"; 046 047 @SuppressWarnings("rawtypes") 048 @Override 049 public void encodeBegin(FacesContext facesContext) throws IOException { 050 // Get workbook and worksheet 051 ExcelWorkbook excelWorkbook = getWorkbook(getParent()); 052 053 if (excelWorkbook == null) { 054 throw new ExcelWorkbookException("Could not find excel workbook"); 055 } 056 057 // Column width etc. 058 excelWorkbook.applyColumnSettings(this); 059 060 UIWorksheet sheet = (UIWorksheet) getParentByClass(getParent(), UIWorksheet.class); 061 if (sheet == null) { 062 throw new ExcelWorkbookException("Could not find worksheet"); 063 } 064 065 // Add header items (if any) 066 WorksheetItem headerItem = (WorksheetItem) getFacet(HEADER_FACET_NAME); 067 if (headerItem != null) { 068 excelWorkbook.addItem(headerItem); 069 } 070 071 // Execute commands (if any) 072 List<Command> commands = getCommands(getChildren()); 073 for (Command command : commands) { 074 excelWorkbook.executeCommand(command); 075 } 076 077 // Get UiCell template this column's data cells and iterate over sheet 078 // data 079 // XXX: process all components instead of just UICell ones. 080 for (UIComponent child : getChildren()) { 081 Object oldValue = null; 082 Iterator iterator = null; 083 // Store away the old value for the sheet binding var (if there is 084 // one) 085 if (sheet.getVar() != null) { 086 oldValue = FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get(sheet.getVar()); 087 iterator = sheet.getDataIterator(); 088 } else { 089 // No var, no iteration... 090 iterator = new ArrayList().iterator(); 091 } 092 093 while (iterator.hasNext()) { 094 // Store the bound data in the request map and add the cell 095 FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(sheet.getVar(), 096 iterator.next()); 097 098 encodeChild(facesContext, sheet, excelWorkbook, child); 099 } 100 101 // No iteration, nothing to restore 102 if (sheet.getVar() == null) { 103 return; 104 } 105 // Restore the previously modified request map (if there was a var) 106 if (oldValue == null) { 107 FacesContext.getCurrentInstance().getExternalContext().getRequestMap().remove(sheet.getVar()); 108 } else { 109 FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(sheet.getVar(), oldValue); 110 } 111 112 } 113 114 // Add footer items (if any) 115 WorksheetItem footerItem = (WorksheetItem) getFacet(FOOTER_FACET_NAME); 116 if (footerItem != null) { 117 excelWorkbook.addItem(footerItem); 118 } 119 120 // Move column pointer to next column 121 excelWorkbook.nextColumn(); 122 123 } 124 125 @SuppressWarnings("rawtypes") 126 protected void encodeChild(FacesContext facesContext, UIWorksheet sheet, ExcelWorkbook excelWorkbook, 127 UIComponent child) throws IOException { 128 // XXX make sure other components are processed 129 if (child instanceof WorksheetItem) { 130 excelWorkbook.addItem((WorksheetItem) child); 131 } else { 132 if (child.isRendered()) { 133 child.encodeBegin(facesContext); 134 // do not let component handling render of its children 135 List subChildren = child.getChildren(); 136 for (int j = 0, size = child.getChildCount(); j < size; j++) { 137 UIComponent subChild = (UIComponent) subChildren.get(j); 138 encodeChild(facesContext, sheet, excelWorkbook, subChild); 139 } 140 child.encodeEnd(facesContext); 141 } 142 } 143 144 } 145 146 @SuppressWarnings("unchecked") 147 public static <T> List<T> getAllChildrenOfType(List<UIComponent> children, Class<T> childType) { 148 List<T> matches = new ArrayList<T>(); 149 for (UIComponent child : children) { 150 if (childType.isAssignableFrom(child.getClass())) { 151 matches.add((T) child); 152 } else { 153 // XXX introspect children 154 List<T> subChildren = getAllChildrenOfType(child.getChildren(), childType); 155 if (subChildren != null && !subChildren.isEmpty()) { 156 matches.addAll(subChildren); 157 } 158 } 159 } 160 return matches; 161 } 162 163 /** 164 * Returns all commands from a child list 165 * 166 * @param children The list to search 167 * @return The commands 168 */ 169 protected static List<Command> getCommands(List<UIComponent> children) { 170 return getAllChildrenOfType(children, Command.class); 171 } 172 173}