1 /******************************************************************************* 2 * Copyright (c) 2009, 2018 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 *******************************************************************************/ 12 package org.jacoco.report.internal.html.table; 13 14 import java.io.IOException; 15 import java.text.DecimalFormat; 16 import java.text.NumberFormat; 17 import java.util.Comparator; 18 import java.util.List; 19 import java.util.Locale; 20 21 import org.jacoco.core.analysis.CounterComparator; 22 import org.jacoco.core.analysis.ICounter; 23 import org.jacoco.core.analysis.ICoverageNode; 24 import org.jacoco.core.analysis.ICoverageNode.CounterEntity; 25 import org.jacoco.report.internal.ReportOutputFolder; 26 import org.jacoco.report.internal.html.HTMLElement; 27 import org.jacoco.report.internal.html.resources.Resources; 28 29 /** 30 * Column with a graphical bar that represents the total amount of items in with 31 * length, and the coverage ratio with a red/green sections. The implementation 32 * is stateful, instances must not be used in parallel. 33 */ 34 public class BarColumn implements IColumnRenderer { 35 36 private static final int WIDTH = 120; 37 38 private final CounterEntity entity; 39 40 private final NumberFormat integerFormat; 41 42 private int max; 43 44 private final Comparator<ITableItem> comparator; 45 46 /** 47 * Creates a new column that is based on the {@link ICounter} for the given 48 * entity. 49 * 50 * @param entity 51 * counter entity for visualization 52 * @param locale 53 * locale for rendering numbers 54 */ 55 public BarColumn(final CounterEntity entity, final Locale locale) { 56 this.entity = entity; 57 this.integerFormat = DecimalFormat.getIntegerInstance(locale); 58 this.comparator = new TableItemComparator(CounterComparator.MISSEDITEMS 59 .reverse().on(entity) 60 .second(CounterComparator.TOTALITEMS.reverse().on(entity))); 61 } 62 63 public boolean init(final List<? extends ITableItem> items, 64 final ICoverageNode total) { 65 this.max = 0; 66 for (final ITableItem item : items) { 67 final int count = item.getNode().getCounter(entity).getTotalCount(); 68 if (count > this.max) { 69 this.max = count; 70 } 71 } 72 return true; 73 } 74 75 public void footer(final HTMLElement td, final ICoverageNode total, 76 final Resources resources, final ReportOutputFolder base) 77 throws IOException { 78 final ICounter counter = total.getCounter(entity); 79 td.text(integerFormat.format(counter.getMissedCount())).text(" of ") 80 .text(integerFormat.format(counter.getTotalCount())); 81 } 82 83 public void item(final HTMLElement td, final ITableItem item, 84 final Resources resources, final ReportOutputFolder base) 85 throws IOException { 86 if (max > 0) { 87 final ICounter counter = item.getNode().getCounter(entity); 88 final int missed = counter.getMissedCount(); 89 bar(td, missed, Resources.REDBAR, resources, base); 90 final int covered = counter.getCoveredCount(); 91 bar(td, covered, Resources.GREENBAR, resources, base); 92 } 93 } 94 95 private void bar(final HTMLElement td, final int count, final String image, 96 final Resources resources, final ReportOutputFolder base) 97 throws IOException { 98 final int width = count * WIDTH / max; 99 if (width > 0) { 100 td.img(resources.getLink(base, image), width, 10, 101 integerFormat.format(count)); 102 } 103 } 104 105 public Comparator<ITableItem> getComparator() { 106 return comparator; 107 } 108 109 } 110