Table.java revision 2ccb2fc041b228cec72a256a64bc992f4f7bc331
1/******************************************************************************* 2 * Copyright (c) 2009, 2011 Mountainminds GmbH & Co. KG and Contributors 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Marc R. Hoffmann - initial API and implementation 10 * 11 *******************************************************************************/ 12package org.jacoco.report.internal.html.table; 13 14import java.io.IOException; 15import java.util.ArrayList; 16import java.util.Collections; 17import java.util.Comparator; 18import java.util.List; 19 20import org.jacoco.core.analysis.ICoverageNode; 21import org.jacoco.report.ReportOutputFolder; 22import org.jacoco.report.internal.html.HTMLElement; 23import org.jacoco.report.internal.html.resources.Resources; 24import org.jacoco.report.internal.html.resources.Styles; 25 26/** 27 * Renderer for a table of {@link ITableItem}s. 28 */ 29public class Table { 30 31 private final List<Column> columns; 32 33 private Comparator<ITableItem> defaultComparator; 34 35 /** 36 * Create a new table without any columns yet. 37 */ 38 public Table() { 39 this.columns = new ArrayList<Table.Column>(); 40 } 41 42 /** 43 * Adds a new column with the given properties to the table. 44 * 45 * @param header 46 * column header caption 47 * @param style 48 * optional CSS style class name for the td-Elements of this 49 * column 50 * @param renderer 51 * callback for column rendering 52 * @param defaultSorting 53 * If <code>true</code>, this column is the default sorting 54 * column. Only one column can be selected for default sorting. 55 * 56 */ 57 public void add(final String header, final String style, 58 final IColumnRenderer renderer, final boolean defaultSorting) { 59 columns.add(new Column(columns.size(), header, style, renderer, 60 defaultSorting)); 61 if (defaultSorting) { 62 if (defaultComparator != null) { 63 throw new IllegalStateException( 64 "Default sorting only allowed for one column."); 65 } 66 this.defaultComparator = renderer.getComparator(); 67 } 68 } 69 70 /** 71 * Renders a table for the given icon 72 * 73 * @param parent 74 * parent element in which the table is created 75 * @param items 76 * items that will make the table rows 77 * @param total 78 * the summary of all coverage data items in the table static 79 * resources that might be referenced 80 * @param resources 81 * static resources that might be referenced 82 * @param base 83 * base folder of the table 84 * @throws IOException 85 * in case of IO problems with the element output 86 */ 87 public void render(final HTMLElement parent, 88 final List<? extends ITableItem> items, final ICoverageNode total, 89 final Resources resources, final ReportOutputFolder base) 90 throws IOException { 91 final List<? extends ITableItem> sortedItems = sort(items); 92 final HTMLElement table = parent.table(Styles.COVERAGETABLE); 93 table.attr("id", "coveragetable"); 94 header(table, sortedItems, total, resources, base); 95 footer(table, total, resources, base); 96 body(table, sortedItems, resources, base); 97 } 98 99 private void header(final HTMLElement table, 100 final List<? extends ITableItem> items, final ICoverageNode total, 101 final Resources resources, final ReportOutputFolder base) 102 throws IOException { 103 final HTMLElement tr = table.thead().tr(); 104 for (final Column c : columns) { 105 c.init(tr, items, total); 106 } 107 } 108 109 private void footer(final HTMLElement table, final ICoverageNode total, 110 final Resources resources, final ReportOutputFolder base) 111 throws IOException { 112 final HTMLElement tr = table.tfoot().tr(); 113 for (final Column c : columns) { 114 c.footer(tr, total, resources, base); 115 } 116 } 117 118 private void body(final HTMLElement table, 119 final List<? extends ITableItem> items, final Resources resources, 120 final ReportOutputFolder base) throws IOException { 121 final HTMLElement tbody = table.tbody(); 122 int idx = 0; 123 for (final ITableItem item : items) { 124 final HTMLElement tr = tbody.tr(); 125 for (final Column c : columns) { 126 c.body(tr, idx, item, resources, base); 127 } 128 idx++; 129 } 130 } 131 132 private List<? extends ITableItem> sort( 133 final List<? extends ITableItem> items) { 134 if (defaultComparator != null) { 135 final ArrayList<ITableItem> result = new ArrayList<ITableItem>( 136 items); 137 Collections.sort(result, defaultComparator); 138 return result; 139 } 140 return items; 141 } 142 143 private static class Column { 144 145 private final char idprefix; 146 private final String header; 147 private final IColumnRenderer renderer; 148 private final SortIndex<ITableItem> index; 149 private final String style, headerStyle; 150 151 private boolean visible; 152 153 Column(final int idx, final String header, final String style, 154 final IColumnRenderer renderer, final boolean defaultSorting) { 155 this.idprefix = (char) ('a' + idx); 156 this.header = header; 157 this.renderer = renderer; 158 index = new SortIndex<ITableItem>(renderer.getComparator()); 159 this.style = style; 160 this.headerStyle = Styles.combine(defaultSorting ? Styles.DOWN 161 : null, Styles.SORTABLE, style); 162 } 163 164 void init(final HTMLElement tr, final List<? extends ITableItem> items, 165 final ICoverageNode total) throws IOException { 166 visible = renderer.init(items, total); 167 if (visible) { 168 if (index != null) { 169 index.init(items); 170 } 171 final HTMLElement td = tr.td(headerStyle); 172 td.attr("id", String.valueOf(idprefix)); 173 if (index != null) { 174 td.attr("onclick", "toggleSort(this)"); 175 } 176 td.text(header); 177 } 178 } 179 180 void footer(final HTMLElement tr, final ICoverageNode total, 181 final Resources resources, final ReportOutputFolder base) 182 throws IOException { 183 if (visible) { 184 renderer.footer(tr.td(style), total, resources, base); 185 } 186 } 187 188 void body(final HTMLElement tr, final int idx, final ITableItem item, 189 final Resources resources, final ReportOutputFolder base) 190 throws IOException { 191 if (visible) { 192 final HTMLElement td = tr.td(style); 193 if (index != null) { 194 td.attr("id", 195 idprefix + String.valueOf(index.getPosition(idx))); 196 } 197 renderer.item(td, item, resources, base); 198 } 199 } 200 201 } 202 203} 204