1 | package de.uka.ipd.sdq.pcmsolver.visualisation; |
2 | |
3 | import java.io.BufferedReader; |
4 | import java.io.IOException; |
5 | import java.io.InputStream; |
6 | import java.io.InputStreamReader; |
7 | import java.io.Reader; |
8 | import java.io.StringWriter; |
9 | import java.io.Writer; |
10 | import java.text.DecimalFormat; |
11 | import java.text.DecimalFormatSymbols; |
12 | import java.text.ParseException; |
13 | import java.util.Locale; |
14 | |
15 | import org.eclipse.emf.common.util.EList; |
16 | import org.eclipse.swt.widgets.Display; |
17 | import org.eclipse.ui.IWorkbenchPage; |
18 | import org.eclipse.ui.PartInitException; |
19 | import org.eclipse.ui.PlatformUI; |
20 | |
21 | import LqnCore.ActivityDefType; |
22 | import LqnCore.LqnModelType; |
23 | import LqnCore.OutputResultType; |
24 | import LqnCore.ProcessorType; |
25 | import LqnCore.TaskType; |
26 | import de.uka.ipd.sdq.pcmsolver.transformations.pcm2lqn.LqnXmlHandler; |
27 | |
28 | public class LQNHtmlResultGenerator { |
29 | private LqnModelType lqnResultModel; |
30 | private StringBuilder htmlText = new StringBuilder(""); |
31 | |
32 | public LQNHtmlResultGenerator(String fileName) { |
33 | LqnModelType loadedModel = LqnXmlHandler.loadModelFromXMI(fileName); |
34 | this.lqnResultModel = loadedModel; |
35 | if (this.lqnResultModel != null){ |
36 | generateHtml(); |
37 | } else { |
38 | generateErrorMsg(fileName); |
39 | } |
40 | } |
41 | |
42 | private void generateErrorMsg(String fileName) { |
43 | appendHtmlHeader(); |
44 | htmlText.append("<h2>LQN Results</h2>"); |
45 | htmlText.append("Error retrieving results from: "+fileName+"<br>"); |
46 | htmlText.append("Check console output for error messages."); |
47 | htmlText.append("</body></html>"); |
48 | } |
49 | |
50 | /** |
51 | * Retrieves the contents of an InputStream as a String. |
52 | * |
53 | * @param is |
54 | * the InputStream |
55 | * @return the resulting String |
56 | * @throws IOException |
57 | */ |
58 | private String getInputStreamContents(final InputStream is) |
59 | throws IOException { |
60 | if (is != null) { |
61 | Writer writer = new StringWriter(); |
62 | char[] buffer = new char[1024]; |
63 | try { |
64 | Reader reader = new BufferedReader(new InputStreamReader(is, |
65 | "UTF-8")); |
66 | int n; |
67 | while ((n = reader.read(buffer)) != -1) { |
68 | writer.write(buffer, 0, n); |
69 | } |
70 | } finally { |
71 | is.close(); |
72 | } |
73 | return writer.toString(); |
74 | } else { |
75 | return ""; |
76 | } |
77 | } |
78 | |
79 | |
80 | /** |
81 | * Generates HTML code from the LQN result file |
82 | */ |
83 | private void generateHtml() { |
84 | |
85 | appendHtmlHeader(); |
86 | |
87 | htmlText.append("<h2>LQN Results</h2>"); |
88 | htmlText.append(lqnResultModel.getName()); |
89 | |
90 | htmlText.append("<table border=\"0\" style=\"margin-top: 1mm; border: 1px solid black;\">"); |
91 | htmlText.append("<thead><tr>"); |
92 | htmlText.append("<th class=\"SortString\" onselectstart=\"return false;\">Processor</th>"); |
93 | htmlText.append("<th class=\"SortString\" onselectstart=\"return false;\">Utilization</th>"); |
94 | htmlText.append("<th class=\"SortString\" onselectstart=\"return false;\">Util / #Cores</th>"); |
95 | htmlText.append("</tr></thead><tbody>"); |
96 | |
97 | DecimalFormat format = new DecimalFormat("0.000000", |
98 | DecimalFormatSymbols.getInstance(Locale.ENGLISH)); |
99 | |
100 | EList<ProcessorType> procList = lqnResultModel.getProcessor(); |
101 | for (ProcessorType pt : procList){ |
102 | EList<OutputResultType> outputResults = pt.getResultProcessor(); |
103 | |
104 | if (outputResults.size() > 0){ |
105 | OutputResultType singleResult = outputResults.get(0); |
106 | htmlText.append("<tr>"); |
107 | |
108 | String procName = pt.getName(); |
109 | htmlText.append("<td>"+procName+"</td>"); |
110 | String util = (String)singleResult.getUtilization(); |
111 | double utilDouble = convertStringToDouble(util); |
112 | htmlText.append("<td>"+format.format(utilDouble)+"</td>"); |
113 | |
114 | String multiplicity = pt.getMultiplicity().toString(); |
115 | int multInt = Integer.parseInt(multiplicity); |
116 | if (multInt != 0){ |
117 | double utilPerCore = utilDouble / multInt; |
118 | htmlText.append("<td>"+format.format(utilPerCore)+"</td>"); |
119 | } else { |
120 | htmlText.append("<td>n/a</td>"); |
121 | } |
122 | |
123 | htmlText.append("</tr>"); |
124 | } |
125 | } |
126 | htmlText.append("</tbody></table>"); |
127 | htmlText.append("<br>"); |
128 | |
129 | |
130 | htmlText.append("<table border=\"0\" style=\"margin-top: 1mm; border: 1px solid black;\">"); |
131 | htmlText.append("<thead><tr>"); |
132 | htmlText.append("<th class=\"SortString\" onselectstart=\"return false;\">UsageScenario</th>"); |
133 | htmlText.append("<th class=\"SortString\" onselectstart=\"return false;\">ServiceTime*</th>"); |
134 | htmlText.append("<th class=\"SortString\" onselectstart=\"return false;\">Throughput</th>"); |
135 | htmlText.append("</tr></thead><tbody>"); |
136 | for (ProcessorType pt : procList){ |
137 | String name = pt.getName(); |
138 | |
139 | if (name.contains("UsageScenario") && !name.contains("Loop")){ |
140 | htmlText.append("<tr>"); |
141 | TaskType tt = pt.getTask().get(0); |
142 | |
143 | String entryName = tt.getEntry().get(0).getName(); |
144 | htmlText.append("<td>"+entryName+"</td>"); |
145 | |
146 | double serviceTime = getResponseTimeOfSubActivities(tt); |
147 | htmlText.append("<td>"+format.format(serviceTime)+"</td>"); |
148 | |
149 | String throughput = (String)tt.getResultTask().get(0).getThroughput(); |
150 | double tpDouble = convertStringToDouble(throughput); |
151 | htmlText.append("<td>"+format.format(tpDouble)+"</td>"); |
152 | |
153 | htmlText.append("</tr>"); |
154 | } |
155 | } |
156 | htmlText.append("</tbody></table>"); |
157 | htmlText.append("* Does not yet support Branches in UsageScenarios"); |
158 | |
159 | htmlText.append("</body></html>"); |
160 | } |
161 | |
162 | private void appendHtmlHeader() { |
163 | // Retrieve CSS and JavaScript source code for later use in HTML page: |
164 | String cssCode = ""; |
165 | String jsCode = ""; |
166 | try { |
167 | cssCode = getInputStreamContents(this.getClass() |
168 | .getResourceAsStream("/jsComponents.css")); |
169 | jsCode = getInputStreamContents(this.getClass() |
170 | .getResourceAsStream("/jsComponents.js")); |
171 | } catch (IOException e) { |
172 | // TODO Auto-generated catch block |
173 | e.printStackTrace(); |
174 | } |
175 | // create HTML page header |
176 | htmlText = new StringBuilder( |
177 | "<html><head>" |
178 | + "<title>LQN Results</title>" |
179 | + "<script type=\"text/javascript\">" |
180 | + jsCode |
181 | + "</script>" |
182 | + "<style type=\"text/css\">" |
183 | + cssCode |
184 | + " body { font-family: Lucida Grande, Arial, Tahoma, Verdana; font-size: 12px; }" |
185 | + " td, th { font-size: 11px; }" |
186 | + " th { background-color: c0c0c0; margin: 1px; padding: 3px 5px 3px 5px; border: 1px solid black; }" |
187 | + " td { background-color: dfdfdf; margin: 1px; padding: 3px 5px 3px 5px; }" |
188 | + "</style>" + "</head><body>"); |
189 | } |
190 | |
191 | private double convertStringToDouble(String toConvert){ |
192 | double ret = Double.NaN; |
193 | |
194 | toConvert = toConvert.replaceAll("e", "E"); |
195 | toConvert = toConvert.replaceAll("\\+", ""); |
196 | DecimalFormat format = new DecimalFormat("0.0E000", |
197 | DecimalFormatSymbols.getInstance(Locale.ENGLISH)); |
198 | try { |
199 | ret = format.parse(toConvert).doubleValue(); |
200 | } catch (ParseException e) { |
201 | // TODO Auto-generated catch block |
202 | e.printStackTrace(); |
203 | } |
204 | |
205 | return ret; |
206 | } |
207 | |
208 | private double getResponseTimeOfSubActivities(TaskType task) { |
209 | // We add all result service times of the usage scenario to compute |
210 | // the response time |
211 | // TODO: check whether this works correctly if the usage scenario |
212 | // contains branches |
213 | double time = 0; |
214 | |
215 | EList<ActivityDefType> activities = task.getTaskActivities() |
216 | .getActivity(); |
217 | for (ActivityDefType activity : activities) { |
218 | EList<OutputResultType> results = activity.getResultActivity(); |
219 | |
220 | for (OutputResultType outputResultType : results) { |
221 | double serviceTime = convertStringToDouble((String) outputResultType |
222 | .getServiceTime()); |
223 | |
224 | time += serviceTime; |
225 | } |
226 | |
227 | } |
228 | return time; |
229 | } |
230 | |
231 | |
232 | |
233 | public void display() { |
234 | Display.getDefault().asyncExec(new Runnable() { |
235 | public void run() { |
236 | IWorkbenchPage page = PlatformUI.getWorkbench() |
237 | .getActiveWorkbenchWindow().getActivePage(); |
238 | if (page != null) { |
239 | try { |
240 | page.openEditor(new LQNResultEditorInput(htmlText.toString()), |
241 | "de.uka.ipd.sdq.pcmsolver.LQNResultEditor"); |
242 | } catch (PartInitException e) { |
243 | e.printStackTrace(); |
244 | } |
245 | } |
246 | } |
247 | }); |
248 | |
249 | } |
250 | |
251 | } |