1/*******************************************************************************
2 * Copyright (c) 2000, 2009 IBM Corporation and others.
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 *     IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.test.performance.ui;
12
13import java.io.BufferedOutputStream;
14import java.io.File;
15import java.io.FileNotFoundException;
16import java.io.FileOutputStream;
17import java.io.IOException;
18import java.io.OutputStream;
19import java.io.PrintStream;
20import java.util.ArrayList;
21import java.util.List;
22
23import org.eclipse.swt.SWT;
24import org.eclipse.swt.graphics.GC;
25import org.eclipse.swt.graphics.Image;
26import org.eclipse.swt.graphics.ImageData;
27import org.eclipse.swt.graphics.ImageLoader;
28import org.eclipse.swt.widgets.Display;
29import org.eclipse.test.internal.performance.results.db.ConfigResults;
30import org.eclipse.test.internal.performance.results.db.DB_Results;
31import org.eclipse.test.internal.performance.results.db.PerformanceResults;
32import org.eclipse.test.internal.performance.results.db.ScenarioResults;
33
34/**
35 * Class used to create scenario fingerprint.
36 */
37public class FingerPrint {
38
39private static final int GRAPH_WIDTH = 1000;
40
41	String component;
42	PrintStream stream;
43	File outputDir;
44
45public FingerPrint(String name, PrintStream ps, File outputDir) {
46	if (!name.startsWith("global")) this.component = name;
47	this.stream = ps;
48	this.outputDir = outputDir;
49}
50
51/**
52 * Create and save fingerprints as image and print their reference in the current stream.
53 *
54 * @param performanceResults The performance results used to print the fingerprints
55 */
56public void print(final PerformanceResults performanceResults) {
57	String buildName = performanceResults.getName();
58
59	// Compute fingerprint output file name prefix
60	int currentUnderscoreIndex = buildName.indexOf('_');
61	if  (currentUnderscoreIndex != -1){
62		buildName = buildName.substring(0, currentUnderscoreIndex);
63	}
64	StringBuffer buffer = new StringBuffer("FP_");
65	if (this.component != null) {
66		buffer.append(this.component);
67		buffer.append('_');
68	}
69	buffer.append(DB_Results.getDbBaselineRefVersion());
70	buffer.append('_');
71	buffer.append(buildName);
72	String filePrefix = buffer.toString();
73
74	// Print the legend
75	this.stream.print("The following fingerprints show results for the most representative tests of the ");
76	if (this.component == null) {
77		this.stream.print("current build.<br>\n");
78	} else {
79		this.stream.print(this.component);
80		this.stream.print(" component.<br>\n");
81	}
82	this.stream.print("<table border=\"0\">\n");
83	this.stream.print("<tr><td valign=\"top\">Select which kind of scale you want to use:</td>\n");
84	this.stream.print("<td valign=\"top\">\n");
85	this.stream.print("  <form>\n");
86	this.stream.print("    <select onChange=\"toggleFingerprints();\">\n");
87	this.stream.print("      <option>percentage</option>\n");
88	this.stream.print("      <option>time (linear)</option>\n");
89	this.stream.print("      <option>time (log)</option>\n");
90	this.stream.print("    </select>\n");
91	this.stream.print("  </form>\n");
92	this.stream.print("</td>\n");
93//	this.stream.print("<td valign=\"top\">\n");
94//	this.stream.print("<a href=\"help.html\"><img hspace=\"10\" border=\"0\" src=\""+Utils.LIGHT+"\" title=\"Some tips on fingerprints\"/></a>\n");
95//	this.stream.print("</td></tr></table>\n");
96	this.stream.print("</tr></table>\n");
97	this.stream.print("<img hspace=\"10\" border=\"0\" src=\""+Utils.LIGHT+"\"><a href=\""+Utils.HELP+"\">Help on fingerprints</a>\n");
98
99	// Print script to reset dropdown list selection
100	this.stream.print("<script type=\"text/javascript\">\n");
101	this.stream.print("	setFingerprintsType();\n");
102	this.stream.print("</script>\n");
103
104	// Create each fingerprint and save it
105	String[] configNames = performanceResults.getConfigNames(false/* not sorted*/);
106	String[] configBoxes = performanceResults.getConfigBoxes(false/* not sorted*/);
107	int length = configNames.length;
108	for (int c=0; c<length; c++) {
109		String configName  = configNames[c];
110		List scenarios = performanceResults.getComponentSummaryScenarios(this.component, configName);
111		if (scenarios == null) continue;
112
113		// Create BarGraph
114		// TODO use FingerPrintGraph instead
115		BarGraph barGraph = null;
116		List allResults = new ArrayList();
117		String defaultDimName = DB_Results.getDefaultDimension().getName();
118		for (int i=0, size=scenarios.size(); i<size; i++) {
119			ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i);
120			ConfigResults configResults = scenarioResults.getConfigResults(configName);
121			if (configResults == null || !configResults.isValid()) continue;
122			double[] results = configResults.getCurrentBuildDeltaInfo();
123			double percent = -results[0] * 100.0;
124			if (results != null && Math.abs(percent) < 200) {
125				String name = scenarioResults.getLabel() + " (" + defaultDimName + ")";
126				if (!configResults.getCurrentBuildName().equals(buildName)) {
127					continue; // the test didn't run on last build, skip it
128				}
129				if (!configResults.isBaselined()) {
130					name = "*" + name + " (" + configResults.getBaselineBuildName() + ")";
131				}
132				if (barGraph == null) {
133					barGraph = new BarGraph(null);
134				}
135				barGraph.addItem(name,
136				    results,
137				    configName + "/" + scenarioResults.getFileName() + ".html",
138				    configResults.getCurrentBuildResults().getComment(),
139				    (Utils.confidenceLevel(results) & Utils.ERR) == 0);
140
141				// add results
142				allResults.add(configResults);
143			}
144		}
145		if (barGraph == null) continue;
146
147		// Save image file
148		String fileName = filePrefix + '.' + configName ;
149		File outputFile = new File(this.outputDir, fileName+".gif");
150		save(barGraph, outputFile);
151
152		// Print image file reference in stream
153		String boxName = configBoxes[c];
154		if (outputFile.exists()) {
155			String areas = barGraph.getAreas();
156			if (areas == null) areas = "";
157			this.stream.print("<h4>");
158			this.stream.print(boxName);
159			this.stream.print("</h4>\n");
160			this.stream.print("<?php\n");
161			this.stream.print("	$type=$_SERVER['QUERY_STRING'];\n");
162			this.stream.print("	if ($type==\"\" || $type==\"fp_type=0\") {\n");
163			this.stream.print("		echo '<img src=\"");
164			this.stream.print(fileName);
165			this.stream.print(".gif\" usemap=\"#");
166			this.stream.print(fileName);
167			this.stream.print("\" name=\"");
168			this.stream.print(configName);
169			this.stream.print("\">';\n");
170			this.stream.print("		echo '<map name=\"");
171			this.stream.print(fileName);
172			this.stream.print("\">';\n");
173			this.stream.print(areas);
174			this.stream.print("		echo '</map>';\n");
175			this.stream.print("	}\n");
176		} else {
177			this.stream.print("<br><br>There is no fingerprint for ");
178			this.stream.print(boxName);
179			this.stream.print("<br><br>\n");
180		}
181
182		// Create, paint and print the time bars graph
183		FingerPrintGraph graph = new FingerPrintGraph(this.outputDir, fileName, GRAPH_WIDTH, allResults);
184		graph.paint(this.stream);
185		this.stream.print("?>\n");
186	}
187}
188
189/*
190 * Save the computed bar graph.
191 */
192private void save(BarGraph barGraph, File outputFile) {
193
194	// Create and paint image
195	Display display = Display.getDefault();
196	int height = barGraph.getHeight();
197	Image image = new Image(display, GRAPH_WIDTH, height);
198	GC gc = new GC(image);
199	barGraph.paint(display, GRAPH_WIDTH, height, gc);
200	gc.dispose();
201
202	saveImage(outputFile, image);
203}
204
205/**
206 * @param outputFile
207 * @param image
208 */
209private void saveImage(File outputFile, Image image) {
210	// Save image
211	ImageData data = Utils.downSample(image);
212	ImageLoader imageLoader = new ImageLoader();
213	imageLoader.data = new ImageData[] { data };
214
215	OutputStream out = null;
216	try {
217		out = new BufferedOutputStream(new FileOutputStream(outputFile));
218		imageLoader.save(out, SWT.IMAGE_GIF);
219	} catch (FileNotFoundException e) {
220		e.printStackTrace();
221	} finally {
222		image.dispose();
223		if (out != null) {
224			try {
225				out.close();
226			} catch (IOException e1) {
227				// silently ignored
228			}
229		}
230	}
231}
232}
233