001 package com.hammurapi.review; 002 003 import java.util.ArrayList; 004 import java.util.Collection; 005 import java.util.Collections; 006 import java.util.Comparator; 007 import java.util.List; 008 import java.util.Map; 009 import java.util.TreeMap; 010 011 import org.eclipse.emf.common.util.TreeIterator; 012 import org.eclipse.emf.ecore.EObject; 013 014 import com.hammurapi.review.Inspector; 015 import com.hammurapi.review.Measurement; 016 import com.hammurapi.review.Observation; 017 import com.hammurapi.review.Violation; 018 import com.hammurapi.review.Warning; 019 020 /** 021 * Aggregates violations by severity and inspector and measurements 022 * by name into metrics. 023 * @author Pavel Vlasov 024 * 025 */ 026 public class Aggregator implements ObservationSink { 027 028 public Aggregator() { 029 // Default constructor. 030 } 031 032 /** 033 * Aggregates findings reported by the given language element and its children. 034 * @param languageElement 035 * @throws ReviewException 036 */ 037 public Aggregator(LanguageElement languageElement) throws ReviewException { 038 for (Observation o: languageElement.getObservations()) { 039 consumeObservation(o); 040 } 041 TreeIterator<EObject> it = languageElement.eAllContents(); 042 while (it.hasNext()) { 043 EObject next = it.next(); 044 if (next instanceof LanguageElement) { 045 for (Observation o: ((LanguageElement) next).getObservations()) { 046 consumeObservation(o); 047 } 048 } 049 } 050 } 051 052 @Override 053 public void close() throws ReviewException { 054 // NOP 055 056 } 057 058 private List<Warning> warnings = new ArrayList<Warning>(); 059 060 public static class Metric { 061 private String name; 062 063 public Metric(String name) { 064 this.name = name; 065 } 066 067 public String getName() { 068 return name; 069 } 070 071 private double min; 072 private double max; 073 private int total; 074 private List<Measurement> measurements = new ArrayList<Measurement>(); 075 076 synchronized void addMeasurement(Measurement measurement) { 077 if (measurements.isEmpty() || measurement.getValue()<min) { 078 min = measurement.getValue(); 079 } 080 if (measurements.isEmpty() || measurement.getValue()>max) { 081 max = measurement.getValue(); 082 } 083 measurements.add(measurement); 084 total+=measurement.getValue(); 085 } 086 087 public List<Measurement> getMeasurements() { 088 Collections.sort(measurements, new Comparator<Measurement>() { 089 090 @Override 091 public int compare(Measurement o1, Measurement o2) { 092 if (o1==o2) { 093 return 0; 094 } 095 if (o1.getValue()<o2.getValue()) { 096 return -1; 097 } 098 if (o1.getValue()>o2.getValue()) { 099 return 1; 100 } 101 return o1.hashCode()-o2.hashCode(); 102 } 103 }); 104 return measurements; 105 } 106 107 public double getMax() { 108 return max; 109 } 110 111 public double getMin() { 112 return min; 113 } 114 115 public int getTotal() { 116 return total; 117 } 118 119 public double getAverage() { 120 return total/measurements.size(); 121 } 122 } 123 124 private Map<Integer, Severity> severities = new TreeMap<Integer, Severity>(); 125 126 public static class Severity { 127 Integer severity; 128 129 public Severity(Integer severity) { 130 this.severity = severity; 131 } 132 133 Map<String, InspectorEntry> inspectors = new TreeMap<String, InspectorEntry>(); 134 135 public Collection<InspectorEntry> getInspectors() { 136 return inspectors.values(); 137 } 138 139 public Integer getSeverity() { 140 return severity; 141 } 142 } 143 144 public static class InspectorEntry { 145 List<Violation> violations = new ArrayList<Violation>(); 146 Inspector inspector; 147 148 public Inspector getInspector() { 149 return inspector; 150 } 151 152 public List<Violation> getViolations() { 153 return violations; 154 } 155 } 156 157 private Map<String, Metric> metrics = new TreeMap<String, Metric>(); 158 159 @Override 160 public synchronized void consumeObservation(Observation observation) throws ReviewException { 161 if (observation instanceof Violation) { 162 Violation violation = (Violation) observation; 163 Inspector reportedBy = violation.getReportedBy(); 164 if (reportedBy!=null) { 165 Severity severity = severities.get(reportedBy.getSeverity()); 166 if (severity==null) { 167 severity = new Severity(reportedBy.getSeverity()); 168 severities.put(reportedBy.getSeverity(), severity); 169 } 170 InspectorEntry ie = severity.inspectors.get(reportedBy.getName()); 171 if (ie==null) { 172 ie = new InspectorEntry(); 173 ie.inspector = reportedBy; 174 severity.inspectors.put(reportedBy.getName(), ie); 175 } 176 ie.violations.add(violation); 177 } 178 } else if (observation instanceof Warning) { 179 warnings.add((Warning) observation); 180 } else if (observation instanceof Measurement) { 181 Measurement measurement = (Measurement) observation; 182 Metric metric = metrics.get(measurement.getName()); 183 if (metric==null) { 184 metric = new Metric(measurement.getName()); 185 metrics.put(measurement.getName(), metric); 186 } 187 metric.addMeasurement(measurement); 188 } 189 } 190 191 public Collection<Severity> getSeverities() { 192 return severities.values(); 193 } 194 195 public Collection<Metric> getMetrics() { 196 return metrics.values(); 197 } 198 199 public List<Warning> getWarnings() { 200 return warnings; 201 } 202 203 }