XMLReportNodeHandler.java

    1/*******************************************************************************
    2 * Copyright (c) 2009, 2010 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 *    Brock Janiczak - initial API and implementation
   10 *    Marc R. Hoffmann - generalized structure 
   11 *    
   12 * $Id: $
   13 *******************************************************************************/
   14package org.jacoco.report.xml;
   15
   16import java.io.IOException;
   17
   18import org.jacoco.core.analysis.ClassCoverage;
   19import org.jacoco.core.analysis.ICounter;
   20import org.jacoco.core.analysis.ICoverageNode;
   21import org.jacoco.core.analysis.MethodCoverage;
   22import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
   23import org.jacoco.core.analysis.ICoverageNode.ElementType;
   24import org.jacoco.report.IReportVisitor;
   25import org.jacoco.report.ISourceFileLocator;
   26
   27/**
   28 * Report visitor that transforms the report structure into XML elements.
   29 * 
   30 * @author Brock Janiczak
   31 * @version $Revision: $
   32 */
   33class XMLReportNodeHandler implements IReportVisitor {
   34
   35    protected final XMLElement element;
   36
   37    protected final ICoverageNode node;
   38
   39    /**
   40     * New handler for the given coverage node.
   41     * 
   42     * @param element
   43     *            XML-Element representing this coverage node. The start tag
   44     *            must not be closed yet to allow adding additional attributes.
   45     * @param node
   46     *            corresponding coverage node
   47     * @throws IOException
   48     *             in case of problems with the underlying writer
   49     */
   50    public XMLReportNodeHandler(final XMLElement element,
   51            final ICoverageNode node) throws IOException {
   52        this.element = element;
   53        this.node = node;
   54        element.attr("name", node.getName());
   55    }
   56
   57    public IReportVisitor visitChild(final ICoverageNode node)
   58            throws IOException {
   59        final ElementType type = node.getElementType();
   60        switch (type) {
   61        case GROUP:
   62        case BUNDLE:
   63            return new XMLReportNodeHandler(element.element("group"), node);
   64        case PACKAGE:
   65            return new XMLReportNodeHandler(element.element("package"), node);
   66        case CLASS:
   67            final XMLElement classChild = element.element("class");
   68            addClassAttributes(classChild, (ClassCoverage) node);
   69            return new XMLReportNodeHandler(classChild, node);
   70        case METHOD:
   71            final XMLElement methodChild = element.element("method");
   72            addMethodAttributes(methodChild, (MethodCoverage) node);
   73            return new XMLReportNodeHandler(methodChild, node);
   74        }
   75        return IReportVisitor.NOP;
   76    }
   77
   78    public void visitEnd(final ISourceFileLocator sourceFileLocator)
   79            throws IOException {
   80        for (final CounterEntity counterEntity : CounterEntity.values()) {
   81            createCounterElement(counterEntity);
   82        }
   83        this.element.close();
   84    }
   85
   86    private void createCounterElement(final CounterEntity counterEntity)
   87            throws IOException {
   88        final ICounter counter = node.getCounter(counterEntity);
   89        if (counter.getTotalCount() > 0) {
   90            final XMLElement counterNode = this.element.element("counter");
   91            counterNode.attr("type", counterEntity.name());
   92            counterNode.attr("covered", counter.getCoveredCount());
   93            counterNode.attr("missed", counter.getMissedCount());
   94            counterNode.close();
   95        }
   96    }
   97
   98    private static void addClassAttributes(final XMLElement element,
   99            final ClassCoverage node) throws IOException {
  100        if (node.getSignature() != null) {
  101            element.attr("signature", node.getSignature());
  102        }
  103        if (node.getSuperName() != null) {
  104            element.attr("superclass", node.getSuperName());
  105        }
  106        if (node.getInterfaceNames() != null) {
  107            boolean first = true;
  108            final StringBuilder builder = new StringBuilder();
  109            for (final String iface : node.getInterfaceNames()) {
  110                if (first) {
  111                    first = false;
  112                } else {
  113                    builder.append(' ');
  114                }
  115                builder.append(iface);
  116            }
  117            element.attr("interfaces", builder.toString());
  118        }
  119    }
  120
  121    private static void addMethodAttributes(final XMLElement element,
  122            final MethodCoverage node) throws IOException {
  123        element.attr("desc", node.getDesc());
  124        final String signature = node.getSignature();
  125        if (signature != null) {
  126            element.attr("signature", signature);
  127        }
  128    }
  129
  130}