Coverage Report - org.perfidix.ouput.CSVOutput
 
Classes in this File Line Coverage Branch Coverage Complexity
CSVOutput
75%
65/86
57%
22/38
3.625
 
 1  
 /**
 2  
  * Copyright (c) 2012, University of Konstanz, Distributed Systems Group
 3  
  * All rights reserved.
 4  
  * 
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions are met:
 7  
  * * Redistributions of source code must retain the above copyright
 8  
  * notice, this list of conditions and the following disclaimer.
 9  
  * * Redistributions in binary form must reproduce the above copyright
 10  
  * notice, this list of conditions and the following disclaimer in the
 11  
  * documentation and/or other materials provided with the distribution.
 12  
  * * Neither the name of the University of Konstanz nor the
 13  
  * names of its contributors may be used to endorse or promote products
 14  
  * derived from this software without specific prior written permission.
 15  
  * 
 16  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 17  
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 18  
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 19  
  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 20  
  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 21  
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 22  
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 23  
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24  
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25  
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26  
  */
 27  
 package org.perfidix.ouput;
 28  
 
 29  
 import java.io.File;
 30  
 import java.io.FileNotFoundException;
 31  
 import java.io.FileOutputStream;
 32  
 import java.io.PrintStream;
 33  
 import java.lang.reflect.Method;
 34  
 import java.util.Hashtable;
 35  
 import java.util.Map;
 36  
 
 37  
 import org.perfidix.exceptions.AbstractPerfidixMethodException;
 38  
 import org.perfidix.meter.AbstractMeter;
 39  
 import org.perfidix.result.BenchmarkResult;
 40  
 import org.perfidix.result.ClassResult;
 41  
 import org.perfidix.result.MethodResult;
 42  
 
 43  
 /**
 44  
  * Getting out the raw-data as csv.
 45  
  * 
 46  
  * @author Sebastian Graf, University of Konstanz
 47  
  */
 48  
 public final class CSVOutput extends AbstractOutput {
 49  
 
 50  
     /**
 51  
      * Separator to distinguish between class, meter and method.
 52  
      */
 53  
     private static final String SEPARATOR = "-";
 54  
 
 55  
     /** Print stream where the result should end. */
 56  
     private transient final File folder;
 57  
 
 58  
     /**
 59  
      * Flag for correct commata for results.
 60  
      */
 61  
     private transient boolean firstResult;
 62  
 
 63  
     /**
 64  
      * Flag for correct commata for exceptions.
 65  
      */
 66  
     private transient boolean firstException;
 67  
 
 68  
     /**
 69  
      * Set for deleting old files in the beginning.
 70  
      */
 71  
     private transient final Map<File, PrintStream> usedFiles;
 72  
 
 73  
     /**
 74  
      * Constructor for piping the result to elsewhere.
 75  
      * 
 76  
      * @param paramFolder
 77  
      *            an {@link File} object which has to be a folder to write to
 78  
      */
 79  
     public CSVOutput(final File paramFolder) {
 80  20
         super();
 81  20
         folder = paramFolder;
 82  20
         if (folder != null && !folder.isDirectory()) {
 83  0
             throw new IllegalStateException(new StringBuilder(paramFolder.toString()).append(
 84  
                 " has to be a folder!").toString());
 85  
         }
 86  20
         firstResult = true;
 87  20
         firstException = true;
 88  20
         usedFiles = new Hashtable<File, PrintStream>();
 89  20
     }
 90  
 
 91  
     /**
 92  
      * Constructor for output to {@link System#out}.
 93  
      */
 94  
     public CSVOutput() {
 95  20
         this(null);
 96  20
     }
 97  
 
 98  
     /**
 99  
      * {@inheritDoc}
 100  
      */
 101  
     @Override
 102  
     public boolean listenToResultSet(final Method meth, final AbstractMeter meter, final double data) {
 103  200
         final PrintStream stream =
 104  
             setUpNewPrintStream(false, meth.getDeclaringClass().getSimpleName(), meth.getName(), meter
 105  
                 .getName());
 106  200
         if (!firstResult) {
 107  190
             stream.append(",");
 108  
         }
 109  200
         stream.append(Double.toString(data));
 110  200
         stream.flush();
 111  200
         firstResult = false;
 112  200
         return true;
 113  
 
 114  
     }
 115  
 
 116  
     /** {@inheritDoc} */
 117  
     @Override
 118  
     public boolean listenToException(final AbstractPerfidixMethodException exec) {
 119  5
         final PrintStream currentWriter = setUpNewPrintStream(false, "Exceptions");
 120  5
         if (!firstException) {
 121  0
             currentWriter.append("\n");
 122  
         }
 123  5
         currentWriter.append(exec.getRelatedAnno().getSimpleName());
 124  5
         currentWriter.append(",");
 125  5
         if (exec.getMethod() != null) {
 126  5
             currentWriter.append(exec.getMethod().getDeclaringClass().getSimpleName());
 127  5
             currentWriter.append("#");
 128  5
             currentWriter.append(exec.getMethod().getName());
 129  5
             currentWriter.append(",");
 130  
         }
 131  5
         exec.getExec().printStackTrace(currentWriter);
 132  5
         currentWriter.flush();
 133  5
         firstException = false;
 134  5
         return true;
 135  
 
 136  
     }
 137  
 
 138  
     /** {@inheritDoc} */
 139  
     @Override
 140  
     public void visitBenchmark(final BenchmarkResult res) {
 141  
         // Printing the data
 142  10
         for (final ClassResult classRes : res.getIncludedResults()) {
 143  10
             for (final MethodResult methRes : classRes.getIncludedResults()) {
 144  20
                 for (final AbstractMeter meter : methRes.getRegisteredMeters()) {
 145  20
                     final PrintStream currentWriter =
 146  
                         setUpNewPrintStream(true, classRes.getElementName(), methRes.getElementName(), meter
 147  
                             .getName());
 148  20
                     boolean first = true;
 149  20
                     for (final Double d : methRes.getResultSet(meter)) {
 150  200
                         if (first) {
 151  20
                             currentWriter.append(d.toString());
 152  20
                             first = false;
 153  
                         } else {
 154  180
                             currentWriter.append(new StringBuilder(",").append(d.toString()).toString());
 155  
                         }
 156  200
                     }
 157  
 
 158  20
                     currentWriter.flush();
 159  20
                 }
 160  20
             }
 161  10
         }
 162  
         // Printing the exceptions
 163  10
         final PrintStream currentWriter = setUpNewPrintStream(true, "Exceptions");
 164  
 
 165  10
         for (final AbstractPerfidixMethodException exec : res.getExceptions()) {
 166  10
             currentWriter.append(exec.getRelatedAnno().getSimpleName());
 167  10
             if (exec.getMethod() != null) {
 168  10
                 currentWriter.append(":");
 169  10
                 currentWriter.append(exec.getMethod().getDeclaringClass().getSimpleName());
 170  10
                 currentWriter.append("#");
 171  10
                 currentWriter.append(exec.getMethod().getName());
 172  
             }
 173  10
             currentWriter.append("\n");
 174  10
             exec.getExec().printStackTrace(currentWriter);
 175  10
         }
 176  
 
 177  10
         currentWriter.flush();
 178  10
         tearDownAllStreams();
 179  10
     }
 180  
 
 181  
     private void tearDownAllStreams() {
 182  10
         for (final PrintStream stream : usedFiles.values()) {
 183  0
             stream.close();
 184  0
         }
 185  10
     }
 186  
 
 187  
     /**
 188  
      * Setting up a new {@link PrintStream}.
 189  
      * 
 190  
      * @param visitorStream
 191  
      *            is the stream for the visitor? Because of line breaks after
 192  
      *            the results.
 193  
      * @param names
 194  
      *            the elements of the filename
 195  
      * @return a {@link PrintStream} instance
 196  
      * @throws FileNotFoundException
 197  
      *             if something goes wrong with the file
 198  
      */
 199  
     private PrintStream setUpNewPrintStream(final boolean visitorStream, final String... names) {
 200  
 
 201  235
         PrintStream out = System.out;
 202  
 
 203  235
         if (folder == null) {
 204  235
             if (visitorStream) {
 205  30
                 out.println();
 206  
             }
 207  
         } else {
 208  0
             final File toWriteTo = new File(folder, buildFileName(names));
 209  
             try {
 210  0
                 if (usedFiles.containsKey(toWriteTo)) {
 211  0
                     out = usedFiles.get(toWriteTo);
 212  
                 } else {
 213  0
                     toWriteTo.delete();
 214  0
                     out = new PrintStream(new FileOutputStream(toWriteTo, !visitorStream));
 215  0
                     usedFiles.put(toWriteTo, out);
 216  0
                     firstResult = true;
 217  
                 }
 218  0
             } catch (final FileNotFoundException e) {
 219  0
                 throw new IllegalStateException(e);
 220  0
             }
 221  
 
 222  
         }
 223  235
         return out;
 224  
 
 225  
     }
 226  
 
 227  
     /**
 228  
      * Helper method to build suitable fileNames.
 229  
      * 
 230  
      * @param names
 231  
      *            different names to be combined
 232  
      * @return a String for a suitable file name
 233  
      */
 234  
     private String buildFileName(final String... names) {
 235  0
         final StringBuilder builder = new StringBuilder();
 236  0
         for (int i = 0; i < names.length; i++) {
 237  0
             builder.append(names[i]);
 238  0
             if (i < names.length - 1) {
 239  0
                 builder.append(SEPARATOR);
 240  
             }
 241  
         }
 242  0
         builder.append(".").append("csv");
 243  0
         return builder.toString();
 244  
     }
 245  
 
 246  
 }