1402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*******************************************************************************
2402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Copyright (c) 2000, 2009 IBM Corporation and others.
3402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * All rights reserved. This program and the accompanying materials
4402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * are made available under the terms of the Eclipse Public License v1.0
5402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * which accompanies this distribution, and is available at
6402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * http://www.eclipse.org/legal/epl-v10.html
7402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
8402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Contributors:
9402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *     IBM Corporation - initial API and implementation
10402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *******************************************************************************/
11402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpackage org.eclipse.test.internal.performance.results.utils;
12402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
13402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.File;
14402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.FileInputStream;
15402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.FileNotFoundException;
16402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.FileOutputStream;
17402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.IOException;
18402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.InputStream;
19402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.io.OutputStream;
20402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.text.NumberFormat;
21402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.text.ParseException;
22402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.text.SimpleDateFormat;
23402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.ArrayList;
24402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.Calendar;
25402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.Comparator;
26402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.Date;
27402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.GregorianCalendar;
28402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.List;
29402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.Locale;
30402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.StringTokenizer;
31402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
32402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.core.runtime.preferences.IEclipsePreferences;
33402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.db.BuildResults;
34402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.db.DB_Results;
35402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
36402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
37402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Utility methods for statistics. Got from org.eclipse.test.performance
38402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * framework
39402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
40402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic final class Util implements IPerformancesConstants {
41402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
42402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Percentages
43402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final NumberFormat PERCENTAGE_FORMAT = NumberFormat.getPercentInstance(Locale.US);
44402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static {
45402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		PERCENTAGE_FORMAT.setMaximumFractionDigits(2);
46402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
47402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final NumberFormat DOUBLE_FORMAT = NumberFormat.getNumberInstance(Locale.US);
48402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static {
49402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		DOUBLE_FORMAT.setMaximumFractionDigits(2);
50402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
51402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
52402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Strings
53402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final String LINE_SEPARATOR = System.getProperty("line.separator");
54402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
55402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Build prefixes
56402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final List ALL_BUILD_PREFIXES = new ArrayList(3);
57402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static {
58402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		ALL_BUILD_PREFIXES.add("I");
59402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		ALL_BUILD_PREFIXES.add("N");
60402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		ALL_BUILD_PREFIXES.add("M");
61402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
62402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final List BUILD_PREFIXES = new ArrayList(2);
63402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static {
64402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		BUILD_PREFIXES.add("I");
65402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		BUILD_PREFIXES.add("N");
66402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
67402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final List MAINTENANCE_BUILD_PREFIXES = new ArrayList(2);
68402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static {
69402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		MAINTENANCE_BUILD_PREFIXES.add("I");
70402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		MAINTENANCE_BUILD_PREFIXES.add("M");
71402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
72402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final List BASELINE_BUILD_PREFIXES = new ArrayList(1);
73402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static {
74402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		BASELINE_BUILD_PREFIXES.add(DB_Results.getDbBaselinePrefix());
75402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
76402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
77402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Milestones constants
78402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private static String[] MILESTONES;
79402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public static final BuildDateComparator BUILD_DATE_COMPARATOR = new BuildDateComparator();
80402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
81402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollstatic class BuildDateComparator implements Comparator {
82402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	public int compare(Object o1, Object o2) {
83402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String s1 = (String) o1;
84402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String s2 = (String) o2;
85402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return getBuildDate(s1).compareTo(getBuildDate(s2));
86402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
87402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
88402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
89402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollprivate static void initMilestones() {
90402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String version = DB_Results.getDbVersion();
91402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
92402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Initialize reference version and database directory
93402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	char mainVersion = version.charAt(1);
94402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	char minorVersion = version.charAt(2);
95402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
96402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Initialize milestones
97402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (mainVersion == '3') {
98402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		switch (minorVersion) {
99402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			case '3':
100402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			case '4':
101402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				throw new RuntimeException("Version "+mainVersion+'.'+minorVersion+" is no longer supported!");
102402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			case '5':
103402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				MILESTONES = V35_MILESTONES;
104402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				break;
105402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			case '6':
106402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				MILESTONES = V36_MILESTONES;
107402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				break;
108402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			default:
109402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				throw new RuntimeException("Version "+mainVersion+'.'+minorVersion+" is not supported yet!");
110402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
111402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else {
112402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		throw new RuntimeException("Version "+mainVersion+'.'+minorVersion+" is not supported yet!");
113402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
114402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
115402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
116402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll// Static information for time and date
117402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static final int ONE_MINUTE = 60000;
118402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static final long ONE_HOUR = 3600000L;
119402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmm"); //$NON-NLS-1$
120402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
121402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
122402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Compute the student t-test values.
123402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
124402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @see "http://en.wikipedia.org/wiki/Student's_t-test"
125402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
126402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param baselineResults The baseline build
127402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildResults The current build
128402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The student t-test value as a double.
129402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
130402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static double computeTTest(BuildResults baselineResults, BuildResults buildResults) {
131402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
132402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double ref = baselineResults.getValue();
133402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double val = buildResults.getValue();
134402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
135402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double delta = ref - val;
136402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	long dfRef = baselineResults.getCount() - 1;
137402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double sdRef = baselineResults.getDeviation();
138402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	long dfVal = buildResults.getCount() - 1;
139402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double sdVal = buildResults.getDeviation();
140402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// TODO if the stdev's are not sufficiently similar, we have to take a
141402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// different approach
142402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
143402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (!Double.isNaN(sdRef) && !Double.isNaN(sdVal) && dfRef > 0 && dfVal > 0) {
144402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		long df = dfRef + dfVal;
145402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		double sp_square = (dfRef * sdRef * sdRef + dfVal * sdVal * sdVal) / df;
146402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
147402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		double se_diff = Math.sqrt(sp_square * (1.0 / (dfRef + 1) + 1.0 / (dfVal + 1)));
148402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		double t = Math.abs(delta / se_diff);
149402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return t;
150402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
151402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
152402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return -1;
153402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
154402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
155402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
156402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Copy a file to another location.
157402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
158402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param src the source file.
159402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param dest the destination.
160402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return <code>true</code> if the file was successfully copied,
161402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * 	<code>false</code> otherwise.
162402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
163402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static boolean copyFile(File src, File dest) {
164402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
165402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	try {
166402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		InputStream in = new FileInputStream(src);
167402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		OutputStream out = new FileOutputStream(dest);
168402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		byte[] buf = new byte[1024];
169402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int len;
170402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		while ((len = in.read(buf)) > 0) {
171402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			out.write(buf, 0, len);
172402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
173402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		in.close();
174402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		out.close();
175402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} catch (FileNotFoundException e) {
176402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		e.printStackTrace();
177402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return false;
178402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} catch (IOException e) {
179402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		e.printStackTrace();
180402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return false;
181402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
182402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return true;
183402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
184402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
185402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
186402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Copy a file content to another location.
187402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
188402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param in the input stream.
189402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param dest the destination.
190402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return <code>true</code> if the file was successfully copied,
191402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * 	<code>false</code> otherwise.
192402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
193402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static boolean copyStream(InputStream in, File dest) {
194402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
195402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	try {
196402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		OutputStream out = new FileOutputStream(dest);
197402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		byte[] buf = new byte[1024];
198402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int len;
199402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		while ((len = in.read(buf)) > 0) {
200402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			out.write(buf, 0, len);
201402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
202402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		in.close();
203402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		out.close();
204402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} catch (FileNotFoundException e) {
205402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		e.printStackTrace();
206402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return false;
207402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} catch (IOException e) {
208402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		e.printStackTrace();
209402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return false;
210402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
211402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return true;
212402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
213402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
214402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
215402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Return the build date as yyyyMMddHHmm.
216402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
217402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildName The build name (e.g. I20090806-0100)
218402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The date as a string.
219402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
220402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String getBuildDate(String buildName) {
221402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return getBuildDate(buildName, DB_Results.getDbBaselinePrefix());
222402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
223402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
224402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
225402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Return the build date as yyyyMMddHHmm.
226402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
227402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildName The build name (e.g. I20090806-0100)
228402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param baselinePrefix The baseline prefix (e.g. {@link DB_Results#getDbBaselinePrefix()})
229402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The date as a string.
230402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
231402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String getBuildDate(String buildName, String baselinePrefix) {
232402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
233402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Baseline name
234402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (baselinePrefix != null && buildName.startsWith(baselinePrefix)) {
235402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int length = buildName.length();
236402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return buildName.substring(length-12, length);
237402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
238402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
239402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Build name
240402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	char first = buildName.charAt(0);
241402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (first == 'N' || first == 'I' || first == 'M') { // TODO (frederic) should be buildIdPrefixes...
242402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return buildName.substring(1, 9)+buildName.substring(10, 14);
243402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
244402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
245402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Try with date format
246402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int length = buildName.length() - 12 /* length of date */;
247402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	for (int i=0; i<=length; i++) {
248402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		try {
249402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			String substring = i == 0 ? buildName : buildName.substring(i);
250402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Util.DATE_FORMAT.parse(substring);
251402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			return substring; // if no exception is raised then the substring has a correct date format => return it
252402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		} catch(ParseException ex) {
253402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// skip
254402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
255402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
256402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return null;
257402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
258402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
259402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
260402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns the date of the milestone corresponding at the given index.
261402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
262402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param index The index of the milestone
263402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The date as a YYYYMMDD-hhmm string.
264402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
265402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String getMilestoneDate(int index) {
266402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int length = getMilestonesLength();
267402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (index >= length) return null;
268402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int dash = MILESTONES[index].indexOf('-');
269402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return MILESTONES[index].substring(dash+1);
270402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
271402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
272402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
273402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns the milestone matching the given build name.
274402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
275402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildName The name of the build
276402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The milestone as a string (e.g. M1)
277402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
278402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String getMilestone(String buildName) {
279402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (buildName != null && buildName.length() >= 12) {
280402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int length = getMilestonesLength();
281402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String buildDate = getBuildDate(buildName, DB_Results.getDbBaselinePrefix());
282402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		for (int i=0; i<length; i++) {
283402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int start = MILESTONES[i].indexOf(buildDate);
284402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (start > 0) {
285402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				return MILESTONES[i];
286402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
287402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
288402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
289402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return null;
290402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
291402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
292402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
293402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns the name the milestone matching the given build name.
294402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
295402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildName The name of the build
296402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The milestone name as a string (e.g. M1)
297402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
298402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String getMilestoneName(String buildName) {
299402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (buildName != null && buildName.length() >= 12) {
300402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int length = getMilestonesLength();
301402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String buildDate = getBuildDate(buildName, DB_Results.getDbBaselinePrefix());
302402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		for (int i=0; i<length; i++) {
303402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int start = MILESTONES[i].indexOf(buildDate);
304402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (start > 0) {
305402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				return MILESTONES[i].substring(0, start - 1);
306402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
307402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
308402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
309402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return null;
310402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
311402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
312402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
313402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns whether the given build name is a milestone or not.
314402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
315402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildName The build name
316402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return <code>true</code> if the build name matches a milestone one,
317402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * 	<code>false</code> otherwise.
318402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
319402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static boolean isMilestone(String buildName) {
320402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return getMilestoneName(buildName) != null;
321402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
322402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
323402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
324402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns the name of the milestone which run after the given build name
325402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * or <code>null</code> if there's no milestone since the build has run.
326402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
327402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param buildName The build name
328402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return <code>true</code> if the build name matches a milestone one,
329402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * 	<code>false</code> otherwise.
330402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
331402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String getNextMilestone(String buildName) {
332402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int length = getMilestonesLength();
333402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String buildDate = getBuildDate(buildName);
334402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	for (int i=0; i<length; i++) {
335402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String milestoneDate = MILESTONES[i].substring(MILESTONES[i].indexOf('-')+1);
336402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (milestoneDate.compareTo(buildDate) > 0) {
337402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			return milestoneDate;
338402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
339402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
340402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return null;
341402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
342402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
343402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
344402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Return the number of milestones.
345402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
346402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The number as an int
347402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
348402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static int getMilestonesLength() {
349402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (MILESTONES == null) initMilestones();
350402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int length = MILESTONES.length;
351402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return length;
352402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
353402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
354402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
355402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @deprecated
356402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
357402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static boolean matchPattern(String name, String pattern) {
358402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (pattern.equals("*")) return true; //$NON-NLS-1$
359402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (pattern.indexOf('*') < 0 && pattern.indexOf('?') < 0) {
360402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		pattern += "*"; //$NON-NLS-1$
361402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
362402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	StringTokenizer tokenizer = new StringTokenizer(pattern, "*?", true); //$NON-NLS-1$
363402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int start = 0;
364402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String previous = ""; //$NON-NLS-1$
365402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	while (tokenizer.hasMoreTokens()) {
366402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String token = tokenizer.nextToken();
367402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (!token.equals("*") && !token.equals("?")) { //$NON-NLS-1$ //$NON-NLS-2$
368402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (previous.equals("*")) { //$NON-NLS-1$
369402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				int idx = name.substring(start).indexOf(token);
370402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (idx < 0) return false;
371402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				start += idx;
372402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			} else {
373402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (previous.equals("?")) start++; //$NON-NLS-1$
374402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (!name.substring(start).startsWith(token)) return false;
375402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
376402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			start += token.length();
377402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
378402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		previous = token;
379402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
380402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (previous.equals("*")) { //$NON-NLS-1$
381402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return true;
382402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else if (previous.equals("?")) { //$NON-NLS-1$
383402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return name.length() == start;
384402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
385402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return name.endsWith(previous);
386402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
387402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
388402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
389402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @deprecated
390402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
391402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static double round(double value) {
392402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return Math.round(value * 10000) / 10000.0;
393402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
394402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
395402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
396402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @deprecated
397402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
398402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static double round(double value, int precision) {
399402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (precision < 0) {
400402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		throw new IllegalArgumentException("Should have a precision at least greater than 0!");
401402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
402402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (precision == 0) return (long) Math.floor(value);
403402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double factor = 10;
404402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int n = 1;
405402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	while (n++ < precision)
406402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		factor *= 10;
407402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return Math.round(value * factor) / factor;
408402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
409402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
410402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
411402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns a string to display the given time as a duration
412402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * formatted as "hh:mm:ss".
413402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
414402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param time The time to format as a long.
415402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The formatted string.
416402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
417402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String timeChrono(long time) {
418402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (time < 1000) { // less than 1s
419402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return "00:00:00"; //$NON-NLS-1$
420402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
421402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	StringBuffer buffer = new StringBuffer();
422402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int seconds = (int) (time / 1000);
423402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (seconds < 60) {
424402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append("00:00:"); //$NON-NLS-1$
425402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (seconds < 10) buffer.append('0');
426402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(seconds);
427402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else {
428402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int minutes = seconds / 60;
429402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (minutes < 60) {
430402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append("00:"); //$NON-NLS-1$
431402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (minutes < 10) buffer.append('0');
432402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(minutes);
433402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(':');
434402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			seconds = seconds % 60;
435402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (seconds < 10) buffer.append('0');
436402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(seconds);
437402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		} else {
438402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int hours = minutes / 60;
439402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (hours < 10) buffer.append('0');
440402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(hours);
441402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(':');
442402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			minutes = minutes % 60;
443402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (minutes < 10) buffer.append('0');
444402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(minutes);
445402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(':');
446402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			seconds = seconds % 60;
447402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (seconds < 10) buffer.append('0');
448402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(seconds);
449402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
450402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
451402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return buffer.toString();
452402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
453402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
454402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
455402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns a string to display the given time as the hour of the day
456402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * formatted as "hh:mm:ss".
457402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
458402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param time The time to format as a long.
459402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The formatted string.
460402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
461402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String timeEnd(long time) {
462402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	GregorianCalendar calendar = new GregorianCalendar();
463402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	calendar.add(Calendar.SECOND, (int)(time/1000));
464402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Date date = calendar.getTime();
465402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	SimpleDateFormat dateFormat = new SimpleDateFormat("KK:mm:ss"); //$NON-NLS-1$
466402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return dateFormat.format(date);
467402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
468402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
469402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
470402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Returns a string to display the given time as a duration
471402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * formatted as:
472402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	<ul>
473402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	<li>"XXXms" if the duration is less than 0.1s (e.g. "543ms")</li>
474402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	<li>"X.YYs" if the duration is less than 1s (e.g. "5.43s")</li>
475402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	<li>"XX.Ys" if the duration is less than 1mn (e.g. "54.3s")</li>
476402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	<li>"XXmn XXs" if the duration is less than 1h (e.g. "54mn 3s")</li>
477402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	<li>"XXh XXmn XXs" if the duration is over than 1h (e.g. "5h 4mn 3s")</li>
478402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *	</ul>
479402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
480402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param time The time to format as a long.
481402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return The formatted string.
482402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
483402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static String timeString(long time) {
484402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	NumberFormat format = NumberFormat.getInstance();
485402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	format.setMaximumFractionDigits(1);
486402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	StringBuffer buffer = new StringBuffer();
487402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (time == 0) {
488402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// print nothing
489402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} if (time < 100) { // less than 0.1s
490402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(time);
491402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append("ms"); //$NON-NLS-1$
492402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else if (time < 1000) { // less than 1s
493402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if ((time%100) != 0) {
494402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			format.setMaximumFractionDigits(2);
495402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
496402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(format.format(time/1000.0));
497402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append("s"); //$NON-NLS-1$
498402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else if (time < Util.ONE_MINUTE) {  // less than 1mn
499402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if ((time%1000) == 0) {
500402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(time/1000);
501402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		} else {
502402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			buffer.append(format.format(time/1000.0));
503402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
504402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append("s"); //$NON-NLS-1$
505402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else if (time < Util.ONE_HOUR) {  // less than 1h
506402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(time/Util.ONE_MINUTE).append("mn "); //$NON-NLS-1$
507402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		long seconds = time%Util.ONE_MINUTE;
508402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(seconds/1000);
509402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append("s"); //$NON-NLS-1$
510402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	} else {  // more than 1h
511402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		long h = time / Util.ONE_HOUR;
512402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(h).append("h "); //$NON-NLS-1$
513402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		long m = (time % Util.ONE_HOUR) / Util.ONE_MINUTE;
514402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(m).append("mn "); //$NON-NLS-1$
515402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		long seconds = m%Util.ONE_MINUTE;
516402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append(seconds/1000);
517402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		buffer.append("s"); //$NON-NLS-1$
518402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
519402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return buffer.toString();
520402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
521402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
522402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollprivate Util() {
523402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// don't instantiate
524402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
525402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
526402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
527402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Set the milestones.
528402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
529402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param items The milestones list (e.g. {@link IPerformancesConstants#V35_MILESTONES}).
530402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
531402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static void setMilestones(String[] items) {
532402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	MILESTONES = items;
533402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
534402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
535402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
536402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Init the milestones from preferences
537402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
538402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param preferences The preferences from which got milestones list
539402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
540402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic static void initMilestones(IEclipsePreferences preferences) {
541402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int eclipseVersion = preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
542402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String prefix = IPerformancesConstants.PRE_MILESTONE_BUILDS + "." + eclipseVersion;
543402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int index = 0;
544402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String milestone = preferences.get(prefix + index, null);
545402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String[] milestones = new String[20];
546402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	while (milestone != null) {
547402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		milestones[index] = milestone;
548402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		index++;
549402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		milestone = preferences.get(prefix + index, null);
550402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
551402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int length = milestones.length;
552402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (index < length) {
553402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		System.arraycopy(milestones, 0, milestones = new String[index], 0, index);
554402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
555402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	MILESTONES = milestones;
556402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
557402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
558