/testability-explorer/src/main/java/com/google/test/metric/report/SourceReportGenerator.java

http://testability-explorer.googlecode.com/ · Java · 205 lines · 175 code · 15 blank · 15 comment · 14 complexity · ff243aa8f5dbf1dacd7886680710386d MD5 · raw file

  1. /*
  2. * Copyright 2007 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.google.test.metric.report;
  17. import java.io.File;
  18. import java.io.FileOutputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.OutputStream;
  22. import java.io.OutputStreamWriter;
  23. import java.util.Date;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import com.google.test.metric.ClassCost;
  28. import com.google.test.metric.Cost;
  29. import com.google.test.metric.CostModel;
  30. import com.google.test.metric.MethodCost;
  31. import com.google.test.metric.ViolationCost;
  32. import com.google.test.metric.WeightedAverage;
  33. import com.google.test.metric.report.Source.Line;
  34. import freemarker.ext.beans.BeanModel;
  35. import freemarker.template.Configuration;
  36. import freemarker.template.DefaultObjectWrapper;
  37. import freemarker.template.SimpleNumber;
  38. import freemarker.template.Template;
  39. import freemarker.template.TemplateException;
  40. import freemarker.template.TemplateMethodModelEx;
  41. import freemarker.template.TemplateModel;
  42. import freemarker.template.TemplateModelException;
  43. public class SourceReportGenerator implements ReportGenerator {
  44. private class PrintCostMethod implements TemplateMethodModelEx {
  45. @SuppressWarnings("unchecked")
  46. public Object exec(List arguments) throws TemplateModelException {
  47. TemplateModel model = (TemplateModel) arguments.get(0);
  48. if (model instanceof SimpleNumber) {
  49. SimpleNumber number = (SimpleNumber) model;
  50. return "" + number;
  51. } else if (model instanceof BeanModel) {
  52. BeanModel arg0 = (BeanModel) model;
  53. Cost cost = (Cost) arg0.getAdaptedObject(Cost.class);
  54. return "Cost: " + costModel.computeOverall(cost) + " [" + cost + "]";
  55. } else {
  56. throw new IllegalStateException();
  57. }
  58. }
  59. }
  60. private class OverallCostMethod implements TemplateMethodModelEx {
  61. @SuppressWarnings("unchecked")
  62. public Object exec(List arguments) throws TemplateModelException {
  63. TemplateModel model = (TemplateModel) arguments.get(0);
  64. if (model instanceof SimpleNumber) {
  65. SimpleNumber number = (SimpleNumber) model;
  66. return number;
  67. } else if (model instanceof BeanModel) {
  68. BeanModel arg0 = (BeanModel) model;
  69. Cost cost = (Cost) arg0.getAdaptedObject(Cost.class);
  70. return costModel.computeOverall(cost);
  71. } else {
  72. throw new IllegalStateException();
  73. }
  74. }
  75. }
  76. private final String PREFIX = "com/google/test/metric/report/source/";
  77. private final SourceLoader sourceLoader;
  78. private final GradeCategories grades;
  79. private final File directory;
  80. private final Configuration cfg;
  81. private final Map<String, PackageReport> packageReports = new HashMap<String, PackageReport>();
  82. private final ProjectReport projectByClassReport;
  83. private final ProjectReport projectByPackageReport;
  84. private final CostModel costModel;
  85. public SourceReportGenerator(GradeCategories grades, SourceLoader sourceLoader,
  86. File outputDirectory, CostModel costModel, Date currentTime,
  87. int worstCount, Configuration cfg) {
  88. this.grades = grades;
  89. this.sourceLoader = sourceLoader;
  90. this.directory = outputDirectory;
  91. this.costModel = costModel;
  92. this.cfg = cfg;
  93. cfg.setTemplateLoader(new ClassPathTemplateLoader(PREFIX));
  94. cfg.setObjectWrapper(new DefaultObjectWrapper());
  95. try {
  96. cfg.setSharedVariable("maxExcellentCost", grades.getMaxExcellentCost());
  97. cfg.setSharedVariable("maxAcceptableCost", grades.getMaxAcceptableCost());
  98. cfg.setSharedVariable("currentTime", currentTime);
  99. cfg.setSharedVariable("computeOverallCost", new OverallCostMethod());
  100. cfg.setSharedVariable("printCost", new PrintCostMethod());
  101. } catch (TemplateModelException e) {
  102. throw new RuntimeException(e);
  103. }
  104. projectByClassReport = new ProjectReport("index", grades,
  105. new WeightedAverage());
  106. projectByClassReport.setMaxUnitCosts(worstCount);
  107. projectByPackageReport = new ProjectReport("index", grades,
  108. new WeightedAverage());
  109. }
  110. public void printHeader() {
  111. directory.mkdirs();
  112. writeCSS();
  113. }
  114. private void writeCSS() {
  115. try {
  116. InputStream is = getClass().getResourceAsStream("source/te.css");
  117. OutputStream os = new FileOutputStream(new File(directory, "te.css"));
  118. int size;
  119. byte[] buf = new byte[2048];
  120. while ((size = is.read(buf)) > 0) {
  121. os.write(buf, 0, size);
  122. }
  123. os.close();
  124. is.close();
  125. } catch (IOException e) {
  126. throw new RuntimeException(e);
  127. }
  128. }
  129. public void printFooter() {
  130. for (PackageReport packageReport : packageReports.values()) {
  131. projectByPackageReport.addPackage(packageReport.getName(), packageReport
  132. .getOverallCost());
  133. write("Package.html", packageReport, "package_");
  134. }
  135. write("Project.html", new ProjectSummaryReport(projectByClassReport,
  136. projectByPackageReport), new File(directory, "index.html"));
  137. }
  138. public void addClassCost(ClassCost classCost) {
  139. ClassReport classReport = createClassReport(classCost);
  140. write("Class.html", classReport, "class_");
  141. String packageName = classCost.getPackageName();
  142. PackageReport packageReport = packageReports.get(packageName);
  143. if (packageReport == null) {
  144. packageReport = new PackageReport(packageName, grades,
  145. new WeightedAverage());
  146. packageReports.put(packageName, packageReport);
  147. }
  148. packageReport.addClass(classCost.getClassName(), costModel
  149. .computeClass(classCost));
  150. }
  151. public void write(String templateName, SummaryGraphReport<?> report,
  152. String prefix) {
  153. File file = new File(directory, prefix + report.getName() + ".html");
  154. write(templateName, report, file);
  155. }
  156. public void write(String templateName, Object report, File file) {
  157. try {
  158. Template template = cfg.getTemplate(templateName);
  159. FileOutputStream os = new FileOutputStream(file);
  160. OutputStreamWriter out = new OutputStreamWriter(os);
  161. template.process(report, out);
  162. out.close();
  163. } catch (IOException e) {
  164. throw new RuntimeException(e);
  165. } catch (TemplateException e) {
  166. throw new RuntimeException(e);
  167. }
  168. }
  169. ClassReport createClassReport(ClassCost classCost) {
  170. Source source = sourceLoader.load(classCost.getClassName());
  171. ClassReport classReport = new ClassReport(classCost.getClassName(), source,
  172. grades, new WeightedAverage(
  173. CostModel.WEIGHT_TO_EMPHASIZE_EXPENSIVE_METHODS));
  174. for (MethodCost method : classCost.getMethods()) {
  175. int overallCost = costModel.computeOverall(method.getTotalCost());
  176. classReport.addMethod(method.getMethodName(), method
  177. .getMethodLineNumber(), overallCost, method.getTotalCost(), method
  178. .getCost());
  179. Line line = source.getLine(method.getMethodLineNumber());
  180. line.addMethodCost(method);
  181. for (ViolationCost violation : method.getExplicitViolationCosts()) {
  182. line = source.getLine(violation.getLocation().getLineNumber());
  183. line.addCost(violation.getCost());
  184. }
  185. }
  186. projectByClassReport.addClass(classCost.getClassName(), classReport
  187. .getOverallCost());
  188. return classReport;
  189. }
  190. }