1package jdiff;
2
3import java.util.*;
4import com.sun.javadoc.*;
5
6/**
7 * The changes between two classes.
8 *
9 * See the file LICENSE.txt for copyright details.
10 * @author Matthew Doar, mdoar@pobox.com
11 */
12class ClassDiff {
13
14    /** Name of the class. */
15    public String name_;
16
17    /** Set if this class is an interface in the new API. */
18    public boolean isInterface_;
19
20    /**
21     * A string describing the changes in inheritance.
22     */
23    public String inheritanceChange_ = null;
24
25    /**
26     * A string describing the changes in documentation.
27     */
28    public String documentationChange_ = null;
29
30    /**
31     * A string describing the changes in modifiers.
32     * Changes can be in whether this is a class or interface, whether it is
33     * abstract, static, final, and in its visibility.
34     */
35    public String modifiersChange_ = null;
36
37    /** Constructors added in the new API. */
38    public List ctorsAdded = null;
39    /** Constructors removed in the new API. */
40    public List ctorsRemoved = null;
41    /** Constructors changed in the new API. */
42    public List ctorsChanged = null;
43
44    /** Methods added in the new API. */
45    public List methodsAdded = null;
46    /** Methods removed in the new API. */
47    public List methodsRemoved = null;
48    /** Methods changed in the new API. */
49    public List methodsChanged = null;
50
51    /** Fields added in the new API. */
52    public List fieldsAdded = null;
53    /** Fields removed in the new API. */
54    public List fieldsRemoved = null;
55    /** Fields changed in the new API. */
56    public List fieldsChanged = null;
57
58    /* The percentage difference for this class. */
59    public double pdiff = 0.0;
60
61    /** Default constructor. */
62    public ClassDiff(String name) {
63        name_ = name;
64        isInterface_ = false;
65
66        ctorsAdded = new ArrayList(); // ConstructorAPI[]
67        ctorsRemoved = new ArrayList(); // ConstructorAPI[]
68        ctorsChanged = new ArrayList(); // MemberDiff[]
69
70        methodsAdded = new ArrayList(); // MethodAPI[]
71        methodsRemoved = new ArrayList(); // MethodAPI[]
72        methodsChanged = new ArrayList(); // MemberDiff[]
73
74        fieldsAdded = new ArrayList(); // FieldAPI[]
75        fieldsRemoved = new ArrayList(); // FieldAPI[]
76        fieldsChanged = new ArrayList(); // MemberDiff[]
77    }
78
79    /**
80     * Compare the inheritance details of two classes and produce
81     * a String for the inheritanceChanges_ field in this class.
82     * If there is no difference, null is returned.
83     */
84    public static String diff(ClassAPI oldClass, ClassAPI newClass) {
85        Collections.sort(oldClass.implements_);
86        Collections.sort(newClass.implements_);
87        String res = "";
88        boolean hasContent = false;
89        if (oldClass.extends_ != null && newClass.extends_ != null &&
90            oldClass.extends_.compareTo(newClass.extends_) != 0) {
91            res += "The superclass changed from <code>" + oldClass.extends_ + "</code> to <code>" + newClass.extends_ + "</code>.<br>";
92            hasContent = true;
93        }
94        // Check for implemented interfaces which were removed
95        String removedInterfaces = "";
96        int numRemoved = 0;
97        Iterator iter = oldClass.implements_.iterator();
98        while (iter.hasNext()) {
99            String oldInterface = (String)(iter.next());
100            int idx = Collections.binarySearch(newClass.implements_, oldInterface);
101            if (idx < 0) {
102                if (numRemoved != 0)
103                    removedInterfaces += ", ";
104                removedInterfaces += oldInterface;
105                numRemoved++;
106            }
107        }
108        String addedInterfaces = "";
109        int numAdded = 0;
110        iter = newClass.implements_.iterator();
111        while (iter.hasNext()) {
112            String newInterface = (String)(iter.next());
113            int idx = Collections.binarySearch(oldClass.implements_, newInterface);
114            if (idx < 0) {
115                if (numAdded != 0)
116                    addedInterfaces += ", ";
117                addedInterfaces += newInterface;
118                numAdded++;
119            }
120        }
121        if (numRemoved != 0) {
122            if (hasContent)
123                res += " ";
124            if (numRemoved == 1)
125                res += "Removed interface <code>" + removedInterfaces + "</code>.<br>";
126            else
127                res += "Removed interfaces <code>" + removedInterfaces + "</code>.<br>";
128            hasContent = true;
129        }
130        if (numAdded != 0) {
131            if (hasContent)
132                res += " ";
133            if (numAdded == 1)
134                res += "Added interface <code>" + addedInterfaces + "</code>.<br>";
135            else
136                res += "Added interfaces <code>" + addedInterfaces + "</code>.<br>";
137            hasContent = true;
138        }
139        if (res.compareTo("") == 0)
140            return null;
141        return res;
142    }
143
144    /** Add a change in the modifiers. */
145    public void addModifiersChange(String commonModifierChanges) {
146        if (commonModifierChanges != null) {
147            if (modifiersChange_ == null)
148                modifiersChange_ = commonModifierChanges;
149            else
150                modifiersChange_ += " " + commonModifierChanges;
151        }
152    }
153}
154
155