ReportOutputFolder.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 * $Id: $
   12 *******************************************************************************/
   13package org.jacoco.report;
   14
   15import java.io.IOException;
   16import java.io.OutputStream;
   17import java.util.HashMap;
   18import java.util.Map;
   19
   20/**
   21 * Logical representation of a folder in the output structure. This utility
   22 * ensures valid and unique file names and helps to create relative links.
   23 * 
   24 * @author Marc R. Hoffmann
   25 * @version $Revision: $
   26 */
   27public class ReportOutputFolder {
   28
   29    private final IMultiReportOutput output;
   30
   31    private final ReportOutputFolder parent;
   32
   33    private final String path;
   34
   35    /** Cached sub-folder instances to guarantee stable normalization */
   36    private final Map<String, ReportOutputFolder> subFolders = new HashMap<String, ReportOutputFolder>();
   37
   38    private final NormalizedFileNames fileNames;
   39
   40    /**
   41     * Creates a new root folder for the given output.
   42     * 
   43     * @param output
   44     *            output for generated files
   45     */
   46    public ReportOutputFolder(final IMultiReportOutput output) {
   47        this(output, null, "");
   48    }
   49
   50    /**
   51     * Creates a new root folder for the given output.
   52     * 
   53     * @param output
   54     *            output for generated files
   55     */
   56    private ReportOutputFolder(final IMultiReportOutput output,
   57            final ReportOutputFolder parent, final String path) {
   58        this.output = output;
   59        this.parent = parent;
   60        this.path = path;
   61        fileNames = new NormalizedFileNames();
   62    }
   63
   64    /**
   65     * Creates a sub-folder with the given name.
   66     * 
   67     * @param name
   68     *            name of the sub-folder
   69     * @return handle for output into the sub-folder
   70     */
   71    public ReportOutputFolder subFolder(final String name) {
   72        final String normalizedName = normalize(name);
   73        ReportOutputFolder folder = subFolders.get(normalizedName);
   74        if (folder != null) {
   75            return folder;
   76        }
   77        folder = new ReportOutputFolder(output, this, path + normalizedName
   78                + "/");
   79        subFolders.put(normalizedName, folder);
   80        return folder;
   81    }
   82
   83    /**
   84     * Creates a new file in this folder with the given local name.
   85     * 
   86     * @param name
   87     *            name of the sub-folder
   88     * @return handle for output into the sub-folder
   89     * @throws IOException
   90     *             if the file creation fails
   91     */
   92    public OutputStream createFile(final String name) throws IOException {
   93        return output.createFile(path + normalize(name));
   94    }
   95
   96    /**
   97     * Returns a link relative to this folder to the given resource within this
   98     * folder.
   99     * 
  100     * @param name
  101     *            name of the file or folder
  102     * @return relative link
  103     */
  104    public String getLink(final String name) {
  105        return normalize(name);
  106    }
  107
  108    /**
  109     * Returns a link relative to a given base to a resource within this folder.
  110     * 
  111     * @param base
  112     *            base to create the relative link from
  113     * @param name
  114     *            name of the file or folder in this folder
  115     * @return relative link
  116     * @throws IllegalArgumentException
  117     *             if this folder and the base do not have the same root
  118     */
  119    public String getLink(final ReportOutputFolder base, final String name) {
  120        if (base.isAncestorOf(this)) {
  121            return this.path.substring(base.path.length()) + normalize(name);
  122        }
  123        if (base.parent == null) {
  124            throw new IllegalArgumentException("Folders with different roots.");
  125        }
  126        return "../" + this.getLink(base.parent, name);
  127    }
  128
  129    private boolean isAncestorOf(final ReportOutputFolder folder) {
  130        if (this == folder) {
  131            return true;
  132        }
  133        return folder.parent == null ? false : isAncestorOf(folder.parent);
  134    }
  135
  136    private String normalize(final String name) {
  137        return fileNames.getFileName(name);
  138    }
  139
  140}