1 /******************************************************************************* 2 * Copyright (c) 2009, 2019 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.xml; 13 14 import java.io.IOException; 15 import java.io.OutputStream; 16 17 import org.jacoco.core.analysis.IClassCoverage; 18 import org.jacoco.core.analysis.ICounter; 19 import org.jacoco.core.analysis.ICoverageNode.CounterEntity; 20 import org.jacoco.core.analysis.ILine; 21 import org.jacoco.core.analysis.IMethodCoverage; 22 import org.jacoco.core.data.SessionInfo; 23 24 /** 25 * A {@link XMLElement} with utility methods to create JaCoCo XML reports. 26 */ 27 public class ReportElement extends XMLElement { 28 29 private static final String PUBID = "-//JACOCO//DTD Report 1.1//EN"; 30 31 private static final String SYSTEM = "report.dtd"; 32 33 /** 34 * Creates a <code>report</code> root element for a XML report. 35 * 36 * @param name 37 * value for the name attribute 38 * @param encoding 39 * character encoding used for output 40 * @param output 41 * output stream will be closed if the root element is closed 42 * @throws IOException 43 * in case of problems with the underlying output 44 */ ReportElement(final String name, final OutputStream output, final String encoding)45 public ReportElement(final String name, final OutputStream output, 46 final String encoding) throws IOException { 47 super("report", PUBID, SYSTEM, true, encoding, output); 48 attr("name", name); 49 } 50 ReportElement(final String name, final ReportElement parent)51 private ReportElement(final String name, final ReportElement parent) 52 throws IOException { 53 super(name, parent); 54 } 55 56 @Override element(final String name)57 public ReportElement element(final String name) throws IOException { 58 return new ReportElement(name, this); 59 } 60 namedElement(final String elementName, final String name)61 private ReportElement namedElement(final String elementName, 62 final String name) throws IOException { 63 final ReportElement element = element(elementName); 64 element.attr("name", name); 65 return element; 66 } 67 68 /** 69 * Creates a 'sessioninfo' element. 70 * 71 * @param info 72 * info object to write out 73 * @throws IOException 74 * in case of problems with the underlying output 75 */ sessioninfo(final SessionInfo info)76 public void sessioninfo(final SessionInfo info) throws IOException { 77 final ReportElement sessioninfo = element("sessioninfo"); 78 sessioninfo.attr("id", info.getId()); 79 sessioninfo.attr("start", info.getStartTimeStamp()); 80 sessioninfo.attr("dump", info.getDumpTimeStamp()); 81 } 82 83 /** 84 * Creates a 'group' element. 85 * 86 * @param name 87 * value for the name attribute 88 * @return 'group' element 89 * @throws IOException 90 * in case of problems with the underlying output 91 */ group(final String name)92 public ReportElement group(final String name) throws IOException { 93 return namedElement("group", name); 94 } 95 96 /** 97 * Creates a 'package' element. 98 * 99 * @param name 100 * value for the name attribute 101 * @return 'package' element 102 * @throws IOException 103 * in case of problems with the underlying output 104 */ packageElement(final String name)105 public ReportElement packageElement(final String name) throws IOException { 106 return namedElement("package", name); 107 } 108 109 /** 110 * Creates a 'class' element. 111 * 112 * @param coverage 113 * class coverage node to write out 114 * @return 'class' element 115 * @throws IOException 116 * in case of problems with the underlying output 117 */ classElement(final IClassCoverage coverage)118 public ReportElement classElement(final IClassCoverage coverage) 119 throws IOException { 120 final ReportElement element = namedElement("class", coverage.getName()); 121 element.attr("sourcefilename", coverage.getSourceFileName()); 122 return element; 123 } 124 125 /** 126 * Creates a 'method' element. 127 * 128 * @param coverage 129 * method coverage node to write out 130 * @return 'method' element 131 * @throws IOException 132 * in case of problems with the underlying output 133 */ method(final IMethodCoverage coverage)134 public ReportElement method(final IMethodCoverage coverage) 135 throws IOException { 136 final ReportElement element = namedElement("method", 137 coverage.getName()); 138 element.attr("desc", coverage.getDesc()); 139 final int line = coverage.getFirstLine(); 140 if (line != -1) { 141 element.attr("line", line); 142 } 143 return element; 144 } 145 146 /** 147 * Creates a 'sourcefile' element. 148 * 149 * @param name 150 * value for the name attribute 151 * @return 'sourcefile' element 152 * @throws IOException 153 * in case of problems with the underlying output 154 */ sourcefile(final String name)155 public ReportElement sourcefile(final String name) throws IOException { 156 return namedElement("sourcefile", name); 157 } 158 159 /** 160 * Creates a 'line' element. 161 * 162 * @param nr 163 * line number 164 * @param line 165 * line object to write out 166 * 167 * @throws IOException 168 * in case of problems with the underlying output 169 */ line(final int nr, final ILine line)170 public void line(final int nr, final ILine line) throws IOException { 171 final ReportElement element = element("line"); 172 element.attr("nr", nr); 173 counterAttributes(element, "mi", "ci", line.getInstructionCounter()); 174 counterAttributes(element, "mb", "cb", line.getBranchCounter()); 175 } 176 177 /** 178 * Creates a 'counter' element. 179 * 180 * @param counterEntity 181 * entity of this counter 182 * 183 * @param counter 184 * counter object to write out 185 * 186 * @throws IOException 187 * in case of problems with the underlying output 188 */ counter(final CounterEntity counterEntity, final ICounter counter)189 public void counter(final CounterEntity counterEntity, 190 final ICounter counter) throws IOException { 191 final ReportElement counterNode = element("counter"); 192 counterNode.attr("type", counterEntity.name()); 193 counterAttributes(counterNode, "missed", "covered", counter); 194 } 195 counterAttributes(final XMLElement element, final String missedattr, final String coveredattr, final ICounter counter)196 private static void counterAttributes(final XMLElement element, 197 final String missedattr, final String coveredattr, 198 final ICounter counter) throws IOException { 199 element.attr(missedattr, counter.getMissedCount()); 200 element.attr(coveredattr, counter.getCoveredCount()); 201 } 202 203 } 204