Java tutorial
/* * ################################################################ * * ProActive Parallel Suite(TM): The Java(TM) library for * Parallel, Distributed, Multi-Core Computing for * Enterprise Grids & Clouds * * Copyright (C) 1997-2012 INRIA/University of * Nice-Sophia Antipolis/ActiveEon * Contact: proactive@ow2.org or contact@activeeon.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; version 3 of * the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. * * Initial developer(s): The ProActive Team * http://proactive.inria.fr/team_members.htm * Contributor(s): * * ################################################################ * $$PROACTIVE_INITIAL_DEV$$ */ package org.objectweb.proactive.benchmarks.timit.util.charts; import java.awt.Color; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryLabelPositions; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.category.BarRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.category.DefaultCategoryDataset; /** * A class used to generate comparative charts based on the xml output of * basic timers. * * @author The ProActive Team */ public class BasicComparativeChartBuilder { public static final String TIME_ATTRIBUTE_NAME = "totalTimeInMillis"; public static final String CLASSNAME_ATTRIBUTE_NAME = "className"; public static final String DEFAULT_Y_AXIS_NAME = "Time in milliseconds"; private String chartTitle; private String subtitle; private File[] series; private DefaultCategoryDataset dataset; private Map<String, Document> documentCache; private java.util.List<String> classNamesList; /** * Constructor of this class * @param file1 The first file containing the results * @param file2 The second file containing the resutls that will be compared with the first one * @param chartTitle The title of the chart * @param subtitle The subtitle of the chart */ public BasicComparativeChartBuilder(File[] files, String chartTitle, String subtitle) { this.series = files; this.chartTitle = chartTitle; this.subtitle = subtitle; this.documentCache = new HashMap<String, Document>(); } /** * Generates in the specified folder a chart based on given data * * @param outputFolder The output folder */ public void buildComparativeChart(File outputFolder) { // Check the series of files if ((this.series == null) || (this.series.length < 2)) { throw new RuntimeException( "Cannot generate a comparative chart. You must provide at least 2 different files with the same structure."); } // Build new dataset this.dataset = new DefaultCategoryDataset(); // This list will be used to store in this.classNamesList = new java.util.ArrayList<String>(); // Collect all possible classNames from the first serie this.collectAllClassNamesFrom(this.series[0]); // For each found className make a comparison between series Iterator<String> classNamesIterator = this.classNamesList.iterator(); String className; int i; while (classNamesIterator.hasNext()) { className = classNamesIterator.next(); // Iterate through all series to get their values for (i = 0; i < this.series.length; i++) { // First generate chart for classname1 // Fill the series (ie filename1) values fillDataset(this.series[i], className); } if (classNamesIterator.hasNext()) { // Put some white space fillWhiteSpace(); } } String forChartName = ""; // Iterate through all series to get their values for (i = 0; i < this.series.length; i++) { forChartName += (this.series[i].getName() + (((i + 1) >= this.series.length) ? "" : "-")); } final JFreeChart chart = createChart(); try { javax.imageio.ImageIO.write(chart.createBufferedImage(800, 600), "png", new java.io.File(outputFolder.getAbsoluteFile() + "/compareChart_" + forChartName + ".png")); } catch (Exception ex) { ex.printStackTrace(); } } private Document getDocumentFromCache(File file) { Document res = null; // Check if the file was already parsed if (this.documentCache.containsKey(file.getName())) { res = this.documentCache.get(file.getName()); } else { // Read the xml document res = readFile(file); this.documentCache.put(file.getName(), res); } return res; } /** * Get XML Document thanks to its filename * * @param the XML file * @return the XML Document */ public static Document readFile(File file) { try { return new SAXBuilder().build(file); } catch (Exception e) { e.printStackTrace(); return null; } } private void collectAllClassNamesFrom(File file) { Document d = getDocumentFromCache(file); // Supposed to be the timit element Element root = d.getRootElement(); if (root == null) { throw new RuntimeException("No root element for xml file " + file.getAbsolutePath()); } // Get values from XML tree (Element) List<?> children = root.getChildren(); if (children.size() == 0) { throw new RuntimeException("Nothing to collect from " + file.getAbsolutePath() + ". There is no children for " + root.getName() + " element."); } // Collect all available classNames String val = null; for (Object e : children) { val = ((Element) e).getAttributeValue(CLASSNAME_ATTRIBUTE_NAME); // If already known className if (this.classNamesList.contains(val)) { throw new RuntimeException( "Found a className repetition " + val + " in the file " + file.getAbsolutePath()); } this.classNamesList.add(val); } } private void fillDataset(File file, String className) { Document d = getDocumentFromCache(file); // Supposed to be the timit element Element root = d.getRootElement(); // Get values from XML tree (Element) List<?> aos = root.getChildren(); // Search for the element with the specified className attribute value Element ao = null; for (Object e : aos) { String val = ""; if ((val = ((Element) e).getAttributeValue(CLASSNAME_ATTRIBUTE_NAME)).equals(className) || (val.indexOf(className) >= 0)) { ao = (Element) e; break; } } // If not found return if (ao == null) { throw new RuntimeException("The following classname : " + className + " was not found in the file " + file.getAbsolutePath()); } String[] splittedClassname = className.split("\\."); String classNameWithoutPackage = splittedClassname[splittedClassname.length - 1]; // Search for asked ao // Get timers Element timers = ao.getChild("timers"); Iterator<?> it = timers.getDescendants(); while (it.hasNext()) { Object o = it.next(); if (o instanceof Element) { Element current = (Element) o; String name = current.getAttributeValue("name") + "_" + classNameWithoutPackage; double timeInMillis = Double.parseDouble(current.getAttributeValue(TIME_ATTRIBUTE_NAME)); // Add information to the datasets this.dataset.addValue(timeInMillis, file.getName(), name); } } } /** * Puts some white space do separate bars on the charts. */ private void fillWhiteSpace() { // Add some dummy infromation this.dataset.addValue(0, this.series[0].getName(), ""); } /** * Creates a sample chart. * * @param dataset a dataset. * * @return The chart. */ private JFreeChart createChart() { // create the chart... final JFreeChart chart = ChartFactory.createBarChart(this.chartTitle, // chart title "", // x axis label DEFAULT_Y_AXIS_NAME, // y axis label this.dataset, // data PlotOrientation.VERTICAL, true, // include legend true, // tooltips false // urls ); // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART... chart.setBackgroundPaint(Color.white); chart.addSubtitle(new TextTitle(this.subtitle + "Time used is : " + TIME_ATTRIBUTE_NAME)); // get a reference to the plot for further customisation... final CategoryPlot plot = chart.getCategoryPlot(); plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); plot.setBackgroundPaint(Color.WHITE); plot.setDomainGridlinePaint(Color.BLACK); plot.setRangeGridlinePaint(Color.black); plot.getRangeAxis().setLabelAngle((0 * Math.PI) / 2.0); ((BarRenderer) plot.getRenderer()).setItemMargin(0); // OPTIONAL CUSTOMISATION COMPLETED. return chart; } }