View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  package ch.elca.el4j.services.statistics.detailed.processing;
18  
19  import java.io.FileNotFoundException;
20  import java.io.FileOutputStream;
21  import java.io.PrintStream;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  
27  import com.zanthan.sequence.Fasade;
28  
29  import ch.elca.el4j.services.statistics.detailed.MeasureItem;
30  import ch.elca.el4j.util.codingsupport.Reject;
31  
32  /**
33   * This class provides methods for visualizing measurement data. This class was
34   * ported from Leaf 2. Original authors: WHO,SHO. Leaf2 package name:
35   * ch.elca.leaf.services.measuring
36   *
37   * @svnLink $Revision: 4010 $;$Date: 2009-12-01 10:59:54 +0100 (Di, 01. Dez 2009) $;$Author: jonasha $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/detailed_statistics/common/src/main/java/ch/elca/el4j/services/statistics/detailed/processing/StatisticsOutputter.java $
38   *
39   * @author David Stefan (DST)
40   */
41  public class StatisticsOutputter {
42  	
43  	/**
44  	 * List of MeasureItems.
45  	 */
46  	private List<MeasureItem> m_measures;
47  
48  
49  	/**
50  	 * The constructor.
51  	 *
52  	 * @param measures
53  	 *            The measures.
54  	 */
55  	public StatisticsOutputter(List<MeasureItem> measures) {
56  		m_measures = measures;
57  	}
58  
59  	/**
60  	 * Compute SVGGraph and write it to filename given.
61  	 *
62  	 * @param filename
63  	 *            Name of file to write
64  	 * @param measureId
65  	 *            Id of measurements that graph is computed
66  	 * @param width
67  	 *            Width of the diagram
68  	 * @param height
69  	 *            Height of the diagram
70  	 */
71  	public void createDiagFile(String filename, String measureId,
72  		int width, int height) {
73  		Reject.ifNull(filename);
74  		String newFilename = filename;
75  		
76  		// Check for existing file ending
77  		if (!newFilename.endsWith(".png")) {
78  			newFilename = newFilename.concat(".png");
79  		}
80  		
81  		Fasade fasade = new Fasade();
82  		// Check if width and height were set, else use defaults
83  		if (width == 0 || height == 0) {
84  			fasade.createSequenceDiagram(convertData(measureId), newFilename);
85  		} else {
86  			fasade.createSequenceDiagram(convertData(measureId), newFilename,
87  				width, height);
88  		}
89  	}
90  	
91  	/**
92  	 * Write CSV file with measures to filename given.
93  	 *
94  	 * @param filename
95  	 *            Name of file to write
96  	 * @param measureId
97  	 *            Id of measurements that graph is computed
98  	 */
99  	public void createCVSFile(String filename, String measureId) {
100 		Reject.ifNull(filename);
101 		String newFilename = filename;
102 		
103 		if (!newFilename.endsWith(".txt")) {
104 			newFilename = newFilename.concat(".txt");
105 		}
106 		
107 		try {
108 			PrintStream out
109 				= new PrintStream(new FileOutputStream(newFilename));
110 			
111 			Iterator<MeasureItem> iter = m_measures.iterator();
112 			while (iter.hasNext()) {
113 				MeasureItem item = iter.next();
114 				if (item.getID().getFormattedString().equals(measureId)) {
115 					out.println(item.getCsvString(","));
116 				}
117 			}
118 			out.close();
119 		} catch (FileNotFoundException e) {
120 			e.printStackTrace();
121 		}
122 	}
123 	
124 	/**
125 	 * Converts the data into the format needed by the library that generates
126 	 * the diagram.
127 	 *
128 	 * @param id
129 	 *            The MeasureId we want to generate a diagram for
130 	 * @return String representation of the graph
131 	 */
132 	private String convertData(String id) {
133 		Map<Integer, MeasureItem> myMap = new HashMap<Integer, MeasureItem>();
134 		int i = 1;
135 		MeasureItem elem;
136 		String hierarchy = "";
137 		String oldHierarchy = "";
138 		StringBuilder resBuilder = new StringBuilder();
139 		
140 		// Get the measure items with our id
141 		for (MeasureItem m : m_measures) {
142 			if (id.equalsIgnoreCase(m.getID().toString())) {
143 				myMap.put(m.getSequence(), m);
144 			}
145 		}
146 		// Check if there is a measure item with the sequence no 1
147 		if (myMap.get(i) == null) {
148 			throw new RuntimeException("Measurement are messed up");
149 		}
150 		
151 		// Convert the graph. Goes through all measure items and adds them to
152 		// the string representation by distinguishing the hierarchical level.
153 		while ((elem = myMap.get(i)) != null) {
154 			hierarchy = elem.getHierarchy();
155 			// Check if hierarchy increased. If so, open a new bracket
156 			if (hierarchy.length() > oldHierarchy.length()) {
157 				resBuilder.append(printCall(elem));
158 			// Check if hierarchy is the same. If so, close the bracket and open
159 			// another one.
160 			} else if (hierarchy.length() == oldHierarchy.length()) {
161 				resBuilder.append(")").append(printCall(elem));
162 			// Check if hierarchy has decreased. If so, close brackets.
163 			} else if (hierarchy.length() < oldHierarchy.length()) {
164 				while (hierarchy.length() != oldHierarchy.length()) {
165 					resBuilder.append(") ");
166 					oldHierarchy
167 						= oldHierarchy.substring(0, oldHierarchy.length() - 2);
168 				}
169 				resBuilder.append(")").append(printCall(elem));
170 			// hopefully we'll never get here
171 			} else {
172 				throw new RuntimeException("Measurements messed up");
173 			}
174 			oldHierarchy = elem.getHierarchy();
175 			i++;
176 		}
177 		// Finally, close the remaining brackets
178 		while (oldHierarchy.length() > 1) {
179 			resBuilder.append(")");
180 			oldHierarchy = oldHierarchy.substring(0, oldHierarchy.length() - 2);
181 		}
182 		// Close the last bracket
183 		resBuilder.append(")");
184 		return resBuilder.toString();
185 	}
186 	
187 	/**
188 	 * Removes the package declaration in front of a Class name.
189 	 *
190 	 * @param className
191 	 *            the class name to trim.
192 	 * @return The class name without package prefix
193 	 */
194 	private String trimClassNames(String className) {
195 		int i = className.lastIndexOf('.');
196 		if (i  > -1) {
197 			return className.substring(i + 1);
198 		} else {
199 			return className;
200 		}
201 	}
202 	
203 	/**
204 	 * Print a method call in the new format for the given Measure Item.
205 	 *
206 	 * @param elem
207 	 *            The Measure Item
208 	 * @return The method call string
209 	 */
210 	private String printCall(MeasureItem elem) {
211 		return "(" + trimClassNames(elem.getEjbName())
212 			+ " " + elem.getMethodName()
213 			+ ":" + elem.getDuration() + "ms" + " " + "\"\"";
214 	}
215 }