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    }