ReportPage.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 *    Marc R. Hoffmann - initial API and implementation
   10 *    
   11 *******************************************************************************/
   12package org.jacoco.report.html;
   13
   14import java.io.IOException;
   15
   16import org.jacoco.core.JaCoCo;
   17import org.jacoco.report.ReportOutputFolder;
   18import org.jacoco.report.html.resources.Resources;
   19import org.jacoco.report.html.resources.Styles;
   20
   21/**
   22 * Base class for HTML page generators. It renders the page skeleton with the
   23 * breadcrumb, the title and the footer. Every report page is part of a
   24 * hierarchy and has a parent page (except the root page).
   25 * 
   26 * @author Marc R. Hoffmann
   27 * @version 0.4.1.20101007204400
   28 */
   29public abstract class ReportPage implements ILinkable {
   30
   31    private final ReportPage parent;
   32
   33    /** output folder for this node */
   34    protected final ReportOutputFolder folder;
   35
   36    /** context for this report */
   37    protected final IHTMLReportContext context;
   38
   39    /**
   40     * Creates a new report page.
   41     * 
   42     * @param parent
   43     *            optional hierarchical parent
   44     * @param folder
   45     *            base folder to create this report in
   46     * @param context
   47     *            settings context
   48     */
   49    protected ReportPage(final ReportPage parent,
   50            final ReportOutputFolder folder, final IHTMLReportContext context) {
   51        this.parent = parent;
   52        this.context = context;
   53        this.folder = folder;
   54    }
   55
   56    /**
   57     * Renders the page content. This method must be called at most once.
   58     * 
   59     * @throws IOException
   60     */
   61    public final void renderDocument() throws IOException {
   62        final HTMLDocument doc = new HTMLDocument(
   63                folder.createFile(getFileName()), context.getOutputEncoding());
   64        head(doc.head());
   65        body(doc.body());
   66        doc.close();
   67    }
   68
   69    private void head(final HTMLElement head) throws IOException {
   70        head.meta("Content-Type", "text/html;charset=UTF-8");
   71        head.link("stylesheet",
   72                context.getResources().getLink(folder, Resources.STYLESHEET),
   73                "text/css");
   74        head.link("shortcut icon",
   75                context.getResources().getLink(folder, "report.gif"),
   76                "image/gif");
   77        head.title().text(getLinkLabel());
   78        headExtra(head);
   79    }
   80
   81    private void body(final HTMLElement body) throws IOException {
   82        body.attr("onload", getOnload());
   83        final HTMLElement navigation = body.div(Styles.BREADCRUMB);
   84        navigation.attr("id", "breadcrumb");
   85        infoLinks(navigation.span(Styles.RIGHT));
   86        breadcrumb(navigation, folder);
   87        body.h1().text(getLinkLabel());
   88        content(body);
   89        footer(body);
   90    }
   91
   92    /**
   93     * Hook to add extra content into the head tag.
   94     * 
   95     * @param head
   96     *            enclosing head element
   97     * @throws IOException
   98     *             in case of IO problems with the report writer
   99     */
  100    protected void headExtra(final HTMLElement head) throws IOException {
  101    }
  102
  103    /**
  104     * Returns the onload handler for this page.
  105     * 
  106     * @return handler or <code>null</code>
  107     */
  108    protected String getOnload() {
  109        return null;
  110    }
  111
  112    private void infoLinks(final HTMLElement span) throws IOException {
  113        span.a(context.getSessionsPage(), folder);
  114    }
  115
  116    private void breadcrumb(final HTMLElement div, final ReportOutputFolder base)
  117            throws IOException {
  118        breadcrumbParent(parent, div, base);
  119        div.span(getLinkStyle()).text(getLinkLabel());
  120    }
  121
  122    private static void breadcrumbParent(final ReportPage page,
  123            final HTMLElement div, final ReportOutputFolder base)
  124            throws IOException {
  125        if (page != null) {
  126            breadcrumbParent(page.parent, div, base);
  127            div.a(page, base);
  128            div.text(" > ");
  129        }
  130    }
  131
  132    private void footer(final HTMLElement body) throws IOException {
  133        final HTMLElement footer = body.div(Styles.FOOTER);
  134        final HTMLElement versioninfo = footer.span(Styles.RIGHT);
  135        versioninfo.text("Created with ");
  136        versioninfo.a(JaCoCo.HOMEURL).text("JaCoCo");
  137        versioninfo.text(" ").text(JaCoCo.VERSION);
  138        footer.text(context.getFooterText());
  139    }
  140
  141    /**
  142     * Specifies the local file name of this page.
  143     * 
  144     * @return local file name
  145     */
  146    protected abstract String getFileName();
  147
  148    /**
  149     * Creates the actual content of the page.
  150     * 
  151     * @param body
  152     *            body tag of the page
  153     * @throws IOException
  154     *             in case of IO problems with the report writer
  155     */
  156    protected abstract void content(final HTMLElement body) throws IOException;
  157
  158    // === ILinkable ===
  159
  160    public final String getLink(final ReportOutputFolder base) {
  161        return folder.getLink(base, getFileName());
  162    }
  163
  164}