1   package com.stateofflow.eclipse.metrics.calculators.cohesion;
2   
3   import java.util.Collection;
4   
5   import com.stateofflow.eclipse.metrics.util.CounterMap;
6   
7   class TotalCorrelationEvaluator {
8       private static final double LOG_TWO = Math.log(2.0);
9   
10      private CounterMap<String> fieldOccurrenceCounts;
11      private CounterMap<FieldSet> fieldSetOccurrenceCounts;
12  
13      private void accumulateFieldOccurrences(final CounterMap<String> fieldOccurrenceCounts, final FieldSet method) {
14          for (final String fieldName : method) {
15              fieldOccurrenceCounts.increment(fieldName);
16          }
17      }
18  
19      private double calculateTotalCorrelation(final int numberOfMethods) {
20          double totalCorrelation = 0;
21  
22          for (final FieldSet fieldSet : fieldSetOccurrenceCounts.keySet()) {
23              final double fieldSetProbability = (double) fieldSetOccurrenceCounts.get(fieldSet) / numberOfMethods;
24              totalCorrelation += fieldSetProbability * log(fieldSetProbability / getTotalFieldProbabilityProduct(fieldSet, numberOfMethods));
25          }
26  
27          return totalCorrelation;
28      }
29  
30      public double evaluate(final Collection<FieldSet> methods) {
31          initialiseOccurrenceCounts(methods);
32          return calculateTotalCorrelation(methods.size());
33      }
34  
35      private double getTotalFieldProbabilityProduct(final FieldSet fieldSet, final int numberOfMethods) {
36          double product = 1;
37          for (final String field : fieldOccurrenceCounts.keySet()) {
38              final double fieldProbability = (double) fieldOccurrenceCounts.get(field) / numberOfMethods;
39              product *= fieldSet.contains(field) ? fieldProbability : (1.0 - fieldProbability);
40          }
41  
42          return product;
43      }
44  
45      private void initialiseOccurrenceCounts(final Collection<FieldSet> methods) {
46          fieldOccurrenceCounts = new CounterMap<String>();
47          fieldSetOccurrenceCounts = new CounterMap<FieldSet>();
48  
49          for (final FieldSet method : methods) {
50              accumulateFieldOccurrences(fieldOccurrenceCounts, method);
51              fieldSetOccurrenceCounts.put(method, 1);
52          }
53      }
54  
55      private double log(final double x) {
56          return Math.log(x) / LOG_TWO;
57      }
58  }
59