1 package com.stateofflow.eclipse.metrics.calculators.cohesion;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.eclipse.jdt.core.IType;
7 import org.eclipse.jdt.core.JavaModelException;
8
9 import com.stateofflow.eclipse.metrics.calculators.MeasurementContext;
10
11 final class ClassComposition {
12 private final List<FieldSet> methods = new ArrayList<FieldSet>();
13 private final FieldSet allFields = new FieldSet();
14
15 public void addMethod(final FieldSet fields) {
16 if (fields.size() > 0) {
17 methods.add(fields);
18 allFields.addAll(fields);
19 }
20 }
21
22 public int countMatchingMethods(final FieldSet.Predicate predicate) {
23 int count = 0;
24 for (int i = 0; i < methods.size(); i++) {
25 if (predicate.execute(methods.get(i))) {
26 count++;
27 }
28 }
29 return count;
30 }
31
32 private int getChidamberKemererLackOfCohesion() {
33 int noCommon = 0;
34 int common = 0;
35 for (int i = 1; i < methods.size(); i++) {
36 for (int j = 0; j < i; j++) {
37 if (getMethod(i).intersects(getMethod(j))) {
38 common++;
39 } else {
40 noCommon++;
41 }
42 }
43 }
44
45 return Math.max(0, noCommon - common);
46 }
47
48 public FieldSet getFields() {
49 return allFields;
50 }
51
52 private double getHendersonSellersLackOfCohesion() throws JavaModelException {
53 final int sumOfFieldCounts = getSumOfFieldsUsedPerMethod();
54
55 final double averageFieldCount = ((double) sumOfFieldCounts) / allFields.size();
56 return (averageFieldCount - methods.size()) / (1 - methods.size());
57 }
58
59 private FieldSet getMethod(final int index) {
60 return methods.get(index);
61 }
62
63 public int getNumberOfFields() {
64 return allFields.size();
65 }
66
67 int getNumberOfMethods() {
68 return methods.size();
69 }
70
71 private double getPairwiseFieldIrrelation() {
72 return new PairwiseFieldIrrelationEvaluator().evaluate(this);
73 }
74
75 private int getSumOfFieldsUsedPerMethod() {
76 int sum = 0;
77
78 for (int i = 0; i < getNumberOfMethods(); i++) {
79 sum += getMethod(i).size();
80 }
81 return sum;
82 }
83
84 private double getTotalCorrelation() {
85 return new TotalCorrelationEvaluator().evaluate(methods);
86 }
87
88 private void measureChidamberKemerer(final IType measuredClass, final MeasurementContext context) throws JavaModelException {
89 context.noteTypeValue(LackOfCohesionInMethodsCalculator.CHIDAMBER_KEMERER_METRIC_ID, getChidamberKemererLackOfCohesion(), measuredClass);
90 }
91
92 public void measureCohesion(final IType currentClass, final MeasurementContext context) throws JavaModelException {
93 if (getNumberOfMethods() > 0) {
94 measureChidamberKemerer(currentClass, context);
95 measureHendersonSellers(currentClass, context);
96 measureTotalCorrelation(currentClass, context);
97 measurePairwiseFieldIrrelation(currentClass, context);
98 }
99 }
100
101 private void measureHendersonSellers(final IType measuredClass, final MeasurementContext context) throws JavaModelException {
102 context.noteTypeValue(LackOfCohesionInMethodsCalculator.HENDERSON_SELLERS_METRIC_ID, percentage(getHendersonSellersLackOfCohesion()), measuredClass);
103 }
104
105 private void measurePairwiseFieldIrrelation(final IType measuredClass, final MeasurementContext context) throws JavaModelException {
106 context.noteTypeValue(LackOfCohesionInMethodsCalculator.PAIRWISE_FIELD_IRRELATION_METRIC_ID, percentage(getPairwiseFieldIrrelation()), measuredClass);
107 }
108
109 private void measureTotalCorrelation(final IType measuredClass, final MeasurementContext context) throws JavaModelException {
110 context.noteTypeValue(LackOfCohesionInMethodsCalculator.TOTAL_CORRELATION_METRIC_ID, percentage(getTotalCorrelation()), measuredClass);
111 }
112
113 private int percentage(final double fraction) {
114 return (int) Math.round(100.0 * fraction);
115 }
116 }
117