CSVPrinter.java

  1. /*
  2.  *  Copyright (c) 2001-2024, Jean Tessier
  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
  7.  *  are met:
  8.  *  
  9.  *      * Redistributions of source code must retain the above copyright
  10.  *        notice, this list of conditions and the following disclaimer.
  11.  *  
  12.  *      * Redistributions in binary form must reproduce the above copyright
  13.  *        notice, this list of conditions and the following disclaimer in the
  14.  *        documentation and/or other materials provided with the distribution.
  15.  *  
  16.  *      * Neither the name of Jean Tessier nor the names of his contributors
  17.  *        may be used to endorse or promote products derived from this software
  18.  *        without specific prior written permission.
  19.  *  
  20.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21.  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22.  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23.  *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
  24.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25.  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26.  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27.  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28.  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29.  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31.  */

  32. package com.jeantessier.metrics;

  33. import java.io.*;
  34. import java.util.*;
  35. import java.util.stream.*;

  36. import static java.util.stream.Collectors.*;

  37. public class CSVPrinter extends Printer {
  38.     private final List<MeasurementDescriptor> descriptors;
  39.    
  40.     public CSVPrinter(PrintWriter out, List<MeasurementDescriptor> descriptors) {
  41.         super(out);
  42.        
  43.         this.descriptors = descriptors;
  44.     }

  45.     public void visitMetrics(Collection<Metrics> metrics) {
  46.         appendHeader();
  47.         super.visitMetrics(metrics);
  48.     }

  49.     public void visitMetrics(Metrics metrics) {
  50.         if (isVisibleMetrics(metrics)) {
  51.             append("\"").append(metrics.getName()).append("\", ");
  52.            
  53.             Iterator<MeasurementDescriptor> i = descriptors.iterator();
  54.             while (i.hasNext()) {
  55.                 MeasurementDescriptor descriptor = i.next();
  56.                
  57.                 if (isVisibleMeasurement(descriptor)) {
  58.                     Measurement measurement = metrics.getMeasurement(descriptor.getShortName());
  59.                    
  60.                     measurement.accept(this);
  61.                    
  62.                     if (i.hasNext()) {
  63.                         append(", ");
  64.                     }
  65.                 }
  66.             }
  67.            
  68.             eol();
  69.         }
  70.     }

  71.     public void visitStatisticalMeasurement(StatisticalMeasurement measurement) {
  72.         append(
  73.                 Stream.concat(
  74.                         Stream.of(
  75.                                 measurement.getMinimum(),
  76.                                 measurement.getMedian(),
  77.                                 measurement.getAverage(),
  78.                                 measurement.getStandardDeviation(),
  79.                                 measurement.getMaximum(),
  80.                                 measurement.getSum(),
  81.                                 measurement.getNbDataPoints()
  82.                         ),
  83.                         measurement.getRequestedPercentiles().stream().map(measurement::getPercentile)
  84.                 )
  85.                 .map(String::valueOf)
  86.                 .collect(joining(", ")));
  87.     }
  88.    
  89.     protected void visitMeasurement(Measurement measurement) {
  90.         append(measurement.getValue());
  91.     }

  92.     private void appendHeader() {
  93.         appendLongNames();
  94.         appendShortNames();
  95.         appendStatSubNames();
  96.     }

  97.     private void appendLongNames() {
  98.         append(
  99.                 Stream.concat(
  100.                                 Stream.of("name"),
  101.                                 descriptors.stream()
  102.                                         .filter(this::isVisibleMeasurement)
  103.                                         .flatMap(descriptor -> {
  104.                                             if (descriptor.getClassFor().equals(StatisticalMeasurement.class)) {
  105.                                                 return IntStream.rangeClosed(1, StatisticalMeasurement.countValues(descriptor.getInitText())).mapToObj(n -> descriptor.getLongName());
  106.                                             } else {
  107.                                                 return Stream.of(descriptor.getLongName());
  108.                                             }
  109.                                         })
  110.                         )
  111.                         .map(name -> name.isEmpty() ? "" : "\"" + name + "\"")
  112.                         .collect(joining(", ")));
  113.         eol();
  114.     }

  115.     private void appendShortNames() {
  116.         append(
  117.                 Stream.concat(
  118.                                 Stream.of(""),
  119.                                 descriptors.stream()
  120.                                         .filter(this::isVisibleMeasurement)
  121.                                         .flatMap(descriptor -> {
  122.                                             if (descriptor.getClassFor().equals(StatisticalMeasurement.class)) {
  123.                                                 return IntStream.rangeClosed(1, StatisticalMeasurement.countValues(descriptor.getInitText())).mapToObj(n -> descriptor.getShortName());
  124.                                             } else {
  125.                                                 return Stream.of(descriptor.getShortName());
  126.                                             }
  127.                                         })
  128.                         )
  129.                         .map(name -> name.isEmpty() ? "" : "\"" + name + "\"")
  130.                         .collect(joining(", ")));
  131.         eol();
  132.     }

  133.     private void appendStatSubNames() {
  134.         append(
  135.                 Stream.concat(
  136.                                 Stream.of(""),
  137.                                 descriptors.stream()
  138.                                         .filter(this::isVisibleMeasurement)
  139.                                         .flatMap(descriptor -> {
  140.                                             if (descriptor.getClassFor().equals(StatisticalMeasurement.class)) {
  141.                                                 try {
  142.                                                     return Stream.concat(
  143.                                                             Stream.of("minimum", "median", "average", "std dev", "maximum", "sum", "nb"),
  144.                                                             StatisticalMeasurement.parseRequestedPercentiles(descriptor.getInitText()).stream().map(percentile -> "p" + percentile)
  145.                                                     );
  146.                                                 } catch (IOException e) {
  147.                                                     return Stream.of("minimum", "median", "average", "std dev", "maximum", "sum", "nb");
  148.                                                 }
  149.                                             } else {
  150.                                                 return Stream.of("");
  151.                                             }
  152.                                         })
  153.                         )
  154.                         .map(name -> name.isEmpty() ? "" : "\"" + name + "\"")
  155.                         .collect(joining(", ")));
  156.         eol();
  157.     }
  158. }