View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.layout.collections;
17  
18  import org.kuali.rice.krad.uif.container.CollectionGroup;
19  import org.kuali.rice.krad.uif.element.Label;
20  import org.kuali.rice.krad.uif.field.Field;
21  import org.kuali.rice.krad.uif.layout.TableLayoutManager;
22  import org.kuali.rice.krad.util.KRADUtils;
23  
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  /**
30   * @author Kuali Rice Team (rice.collab@kuali.org)
31   */
32  public class TableExporter {
33  
34      /**
35       * Generates formatted table data based on the posted view results and format type.
36       *
37       * @param collectionGroup collection group instance that should be exported
38       * @param model top level object containing the data
39       * @param formatType format which the table should be generated in
40       * @return generated table data
41       */
42      public static String buildExportTableData(CollectionGroup collectionGroup, Object model, String formatType) {
43          // load table format elements used for generated particular style
44          Map<String, String> exportTableFormatOptions = getExportTableFormatOptions(formatType);
45          String startTable = exportTableFormatOptions.get("startTable");
46          String endTable = exportTableFormatOptions.get("endTable");
47  
48          StringBuilder tableRows = new StringBuilder("");
49  
50          TableLayoutManager layoutManager = (TableLayoutManager) collectionGroup.getLayoutManager();
51  
52          List<Label> headerLabels = layoutManager.getHeaderLabels();
53          List<Field> rowFields = layoutManager.getAllRowFields();
54          int numberOfColumns = layoutManager.getNumberOfColumns();
55  
56          List<Integer> ignoredColumns = findIgnoredColumns(layoutManager, collectionGroup);
57  
58          // append table header data as first row
59          if (!headerLabels.isEmpty()) {
60              List<String> labels = new ArrayList<String>();
61  
62              for (Label label : headerLabels) {
63                  labels.add(label.getLabelText());
64              }
65  
66              tableRows.append(buildExportTableRow(labels, exportTableFormatOptions, ignoredColumns));
67          }
68  
69          // load all subsequent rows to the table
70          if (!rowFields.isEmpty()) {
71              List<String> columnData = new ArrayList<String>();
72  
73              for (Field field : rowFields) {
74                  columnData.add(KRADUtils.getSimpleFieldValue(model, field));
75  
76                  if (columnData.size() >= numberOfColumns) {
77                      tableRows.append(buildExportTableRow(columnData, exportTableFormatOptions, ignoredColumns));
78                      columnData.clear();
79                  }
80              }
81          }
82  
83          return startTable + tableRows.toString() + endTable;
84      }
85  
86      /**
87       * Helper function to determine whether if column should be displayed. Used to help extract
88       * columns used in screen format such as action or select that is not needed for export.
89       *
90       * @param layoutManager The layout manager.
91       * @param collectionGroup The collection group.
92       * @return Index numbers for all columns that should be ignored.
93       */
94      protected static List<Integer> findIgnoredColumns(TableLayoutManager layoutManager,
95              CollectionGroup collectionGroup) {
96          List<Integer> ignoreColumns = new ArrayList<Integer>();
97  
98          int actionColumnIndex = layoutManager.getActionColumnIndex();
99          int numberOfColumns = layoutManager.getNumberOfColumns();
100         boolean renderActions = collectionGroup.isRenderLineActions() && !Boolean.TRUE.equals(collectionGroup.getReadOnly());
101         boolean renderSelectField = collectionGroup.isIncludeLineSelectionField();
102         boolean renderSequenceField = layoutManager.isRenderSequenceField();
103 
104         if (renderActions || renderSelectField || renderSequenceField) {
105             int shiftColumn = 0;
106 
107             if (renderSelectField) {
108                 ignoreColumns.add(shiftColumn);
109                 shiftColumn++;
110             }
111             if (renderSequenceField) {
112                 ignoreColumns.add(shiftColumn);
113                 shiftColumn++;
114             }
115             if (renderActions) {
116                 if (actionColumnIndex == 1) {
117                     ignoreColumns.add(shiftColumn);
118                 } else if (actionColumnIndex == -1) {
119                     ignoreColumns.add(numberOfColumns - 1);
120                 } else if (actionColumnIndex > 1) {
121                     ignoreColumns.add(actionColumnIndex);
122                 }
123             }
124         }
125 
126         return ignoreColumns;
127     }
128 
129     /**
130      * Helper method used to build formatted table row data for export.
131      *
132      * @param columnData Formatted column data.
133      * @param tableFormatOptions Format options: startRow and endRow are added to the row,
134      * startColumn and endColumn are added to each column.
135      * @param ignoredColumns Index numbers of columns to ignore.
136      * @return Formatted table data for one row.
137      */
138     protected static String buildExportTableRow(List<String> columnData, Map<String, String> tableFormatOptions,
139             List<Integer> ignoredColumns) {
140         String startRow = tableFormatOptions.get("startRow");
141         String endRow = tableFormatOptions.get("endRow");
142         String startColumn = tableFormatOptions.get("startColumn");
143         String endColumn = tableFormatOptions.get("endColumn");
144         boolean appendLastColumn = Boolean.valueOf(tableFormatOptions.get("appendLastColumn"));
145         int columnIndex = 0;
146 
147         StringBuilder builder = new StringBuilder();
148         for (String columnItem : columnData) {
149             boolean displayColumn = !ignoredColumns.contains(columnIndex);
150             if (displayColumn) {
151                 builder.append(startColumn + columnItem + endColumn);
152             }
153             if (columnIndex >= columnData.size() - 1 && !appendLastColumn) {
154                 builder.delete(builder.length() - endColumn.length(), builder.length());
155             }
156             columnIndex++;
157         }
158 
159         return startRow + builder.toString() + endRow;
160     }
161 
162     /**
163      * Identify table formatting elements based on formatType. Defaults to txt format if not found
164      *
165      * @param formatType The format type: csv, xls, or xml.
166      * @return The format options for to use with the indicated format type.
167      */
168     protected static Map<String, String> getExportTableFormatOptions(String formatType) {
169         HashMap<String, String> map = new HashMap<String, String>();
170 
171         map.put("contentType", "text/plain");
172         map.put("formatType", "txt");
173         map.put("startTable", "");
174         map.put("endTable", "");
175         map.put("startRow", "");
176         map.put("endRow", "\n");
177         map.put("startColumn", "");
178         map.put("endColumn", ", ");
179         map.put("appendLastColumn", "false");
180 
181         if ("csv".equals(formatType)) {
182             map.put("contentType", "text/csv");
183             map.put("formatType", "csv");
184             map.put("startTable", "");
185             map.put("endTable", "");
186             map.put("startRow", "");
187             map.put("endRow", "\n");
188             map.put("startColumn", "");
189             map.put("endColumn", ", ");
190             map.put("appendLastColumn", "false");
191 
192         } else if ("xls".equals(formatType)) {
193             map.put("contentType", "application/vnd.ms-excel");
194             map.put("formatType", "xls");
195             map.put("startTable", "");
196             map.put("endTable", "");
197             map.put("startRow", "");
198             map.put("endRow", "\n");
199             map.put("startColumn", "\"");
200             map.put("endColumn", "\"\t");
201             map.put("appendLastColumn", "true");
202 
203         } else if ("xml".equals(formatType)) {
204             map.put("contentType", "application/xml");
205             map.put("formatType", "xml");
206             map.put("startTable", "<table>\n");
207             map.put("endTable", "</table>\n");
208             map.put("startRow", "  <row>\n");
209             map.put("endRow", "  </row>\n");
210             map.put("startColumn", "    <column>");
211             map.put("endColumn", "</column>\n");
212             map.put("appendLastColumn", "true");
213 
214         }
215 
216         return map;
217     }
218 }