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 }