PageRenderTime 67ms CodeModel.GetById 50ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://testability-explorer.googlecode.com/
Java | 123 lines | 96 code | 21 blank | 6 comment | 27 complexity | d37dedc34e06e039545f5e1757aec6f6 MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.google.test.metric.report;
  2. import static com.google.test.metric.report.XMLReportGenerator.CLASS_COST_ATTRIBUTE;
  3. import static com.google.test.metric.report.XMLReportGenerator.CLASS_NAME_ATTRIBUTE;
  4. import static com.google.test.metric.report.XMLReportGenerator.CLASS_NODE;
  5. import static com.google.test.metric.report.XMLReportGenerator.METHOD_NAME_ATTRIBUTE;
  6. import static com.google.test.metric.report.XMLReportGenerator.METHOD_OVERALL_COST_ATTRIBUTE;
  7. import java.util.Collections;
  8. import java.util.HashMap;
  9. import java.util.HashSet;
  10. import java.util.LinkedList;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Set;
  14. import java.util.logging.Level;
  15. import java.util.logging.Logger;
  16. import org.w3c.dom.Document;
  17. import org.w3c.dom.Node;
  18. import org.w3c.dom.NodeList;
  19. /**
  20. * Calculate the differences between classes and methods in two XML
  21. * testability reports.
  22. *
  23. * @author alexeagle@google.com (Alex Eagle)
  24. */
  25. public class XMLReportDiffer {
  26. Logger logger = Logger.getLogger(XMLReportDiffer.class.getCanonicalName());
  27. public Diff diff(Document oldDoc, Document newDoc) {
  28. List<Diff.ClassDiff> result = new LinkedList<Diff.ClassDiff>();
  29. NodeList oldClasses = oldDoc.getElementsByTagName(CLASS_NODE);
  30. NodeList newClasses = newDoc.getElementsByTagName(CLASS_NODE);
  31. Map<String, Node> oldClassMap = buildChildMap(oldClasses, CLASS_NAME_ATTRIBUTE);
  32. Map<String, Node> newClassMap = buildChildMap(newClasses, CLASS_NAME_ATTRIBUTE);
  33. Set<String> classNames = new HashSet<String>();
  34. classNames.addAll(oldClassMap.keySet());
  35. classNames.addAll(newClassMap.keySet());
  36. for (String className : classNames) {
  37. Integer oldCost = getNumericalAttributeOfNode(oldClassMap, className, CLASS_COST_ATTRIBUTE);
  38. Integer newCost = getNumericalAttributeOfNode(newClassMap, className, CLASS_COST_ATTRIBUTE);
  39. List<Diff.MethodDiff> methodDiffs = diffMethods(oldClassMap.get(className), newClassMap.get(className));
  40. if (!methodDiffs.isEmpty() || different(oldCost, newCost)) {
  41. result.add(new Diff.ClassDiff(className, oldCost, newCost, methodDiffs));
  42. }
  43. }
  44. return new Diff(result);
  45. }
  46. private boolean different(Integer oldCost, Integer newCost) {
  47. return (oldCost == null && newCost != null) || (oldCost != null && (newCost == null || !oldCost.equals(newCost)));
  48. }
  49. @SuppressWarnings("unchecked")
  50. private List<Diff.MethodDiff> diffMethods(Node oldClassNode, Node newClassNode) {
  51. List<Diff.MethodDiff> result = new LinkedList<Diff.MethodDiff>();
  52. Set<String> methodNames = new HashSet<String>();
  53. Map<String, Node> oldMethodMap = Collections.EMPTY_MAP;
  54. Map<String, Node> newMethodMap = Collections.EMPTY_MAP;
  55. if (oldClassNode != null) {
  56. oldMethodMap = buildChildMap(oldClassNode.getChildNodes(), METHOD_NAME_ATTRIBUTE);
  57. methodNames.addAll(oldMethodMap.keySet());
  58. }
  59. if (newClassNode != null) {
  60. newMethodMap = buildChildMap(newClassNode.getChildNodes(), METHOD_NAME_ATTRIBUTE);
  61. methodNames.addAll(newMethodMap.keySet());
  62. }
  63. for (String methodName : methodNames) {
  64. Integer oldCost = getNumericalAttributeOfNode(oldMethodMap, methodName, METHOD_OVERALL_COST_ATTRIBUTE);
  65. Integer newCost = getNumericalAttributeOfNode(newMethodMap, methodName, METHOD_OVERALL_COST_ATTRIBUTE);
  66. if (different(oldCost, newCost)) {
  67. result.add(new Diff.MethodDiff(methodName, oldCost, newCost));
  68. }
  69. }
  70. return result;
  71. }
  72. private Integer getNumericalAttributeOfNode(Map<String, Node> newClassMap, String className, String attribute) {
  73. Integer newCost = null;
  74. if (newClassMap.containsKey(className)) {
  75. try {
  76. String stringValue = extractAttribute(newClassMap.get(className), attribute);
  77. if (stringValue != null) {
  78. newCost = Integer.valueOf(stringValue);
  79. }
  80. } catch (NumberFormatException e) {
  81. logger.log(Level.WARNING,
  82. String.format("Invalid cost attribute for class %s", className), e);
  83. }
  84. }
  85. return newCost;
  86. }
  87. private Map<String, Node> buildChildMap(NodeList nodeList, String keyAttributeName) {
  88. Map<String, Node> childMap = new HashMap<String, Node>();
  89. for (int count = 0; count < nodeList.getLength(); count++) {
  90. Node node = nodeList.item(count);
  91. String keyValue = extractAttribute(node, keyAttributeName);
  92. childMap.put(keyValue, node);
  93. }
  94. return childMap;
  95. }
  96. private String extractAttribute(Node node, String classNameAttribute) {
  97. if (node == null || node.getAttributes() == null || node.getAttributes().getNamedItem(classNameAttribute) == null) {
  98. return null;
  99. }
  100. return node.getAttributes().getNamedItem(classNameAttribute).getNodeValue();
  101. }
  102. }