package jdiff;

import java.util.*;

/**
 * This class contains method to compare two API objects.
 * The differences are stored in an APIDiff object.
 *
 * See the file LICENSE.txt for copyright details.
 * @author Matthew Doar, mdoar@pobox.com
 */
public class APIComparator {

    /** 
     * Top-level object representing the differences between two APIs. 
     * It is this object which is used to generate the report later on.
     */
    public APIDiff apiDiff;

    /** 
     * Package-level object representing the differences between two packages. 
     * This object is also used to determine which file to write documentation
     * differences into.
     */
    public PackageDiff pkgDiff;

    /** Default constructor. */
    public APIComparator() {
        apiDiff = new APIDiff();
    }   

    /** For easy local access to the old API object. */
    private static API oldAPI_;
    /** For easy local access to the new API object. */
    private static API newAPI_;

    /** 
     * Compare two APIs. 
     */
    public void compareAPIs(API oldAPI, API newAPI) {
        System.out.println("JDiff: comparing the old and new APIs ...");
        oldAPI_ = oldAPI;
        newAPI_ = newAPI;

        double differs = 0.0;

        apiDiff.oldAPIName_ = oldAPI.name_;
        apiDiff.newAPIName_ = newAPI.name_;

        Collections.sort(oldAPI.packages_);
        Collections.sort(newAPI.packages_);

        // Find packages which were removed in the new API
        Iterator iter = oldAPI.packages_.iterator();
        while (iter.hasNext()) {
            PackageAPI oldPkg = (PackageAPI)(iter.next());
            // This search is looking for an *exact* match. This is true in
            // all the *API classes.
            int idx = Collections.binarySearch(newAPI.packages_, oldPkg);
            if (idx < 0) {
                // If there an instance of a package with the same name 
                // in both the old and new API, then treat it as changed,
                // rather than removed and added. There will never be more than
                // one instance of a package with the same name in an API.
                int existsNew = newAPI.packages_.indexOf(oldPkg);
                if (existsNew != -1) {
                    // Package by the same name exists in both APIs
                    // but there has been some or other change.
                    differs += 2.0 * comparePackages(oldPkg, (PackageAPI)(newAPI.packages_.get(existsNew)));
                }  else {
                    if (trace)
                        System.out.println("Package " + oldPkg.name_ + " was removed");
                    apiDiff.packagesRemoved.add(oldPkg);
                    differs += 1.0;
                }
            } else {
                // The package exists unchanged in name or doc, but may 
                // differ in classes and their members, so it still needs to 
                // be compared.
                differs += 2.0 * comparePackages(oldPkg, (PackageAPI)(newAPI.packages_.get(idx)));
            }
        } // while (iter.hasNext())

        // Find packages which were added or changed in the new API
        iter = newAPI.packages_.iterator();
        while (iter.hasNext()) {
            PackageAPI newPkg = (PackageAPI)(iter.next());
            int idx = Collections.binarySearch(oldAPI.packages_, newPkg);
            if (idx < 0) {
                // See comments above
                int existsOld = oldAPI.packages_.indexOf(newPkg);
                if (existsOld != -1) {
                    // Don't mark a package as added or compare it 
                    // if it was already marked as changed
                } else {
                    if (trace)
                        System.out.println("Package " + newPkg.name_ + " was added");
                    apiDiff.packagesAdded.add(newPkg);
                    differs += 1.0;
                }
            } else {
                // It will already have been compared above.
            }
        } // while (iter.hasNext())

        // Now that the numbers of members removed and added are known
        // we can deduce more information about changes.
        MergeChanges.mergeRemoveAdd(apiDiff);

// The percent change statistic reported for all elements in each API is  
// defined recursively as follows:
// 
// %age change = 100 * (added + removed + 2*changed)
//               -----------------------------------
//               sum of public elements in BOTH APIs
//
// The definition ensures that if all classes are removed and all new classes
// added, the change will be 100%.
// Evaluation of the visibility of elements has already been done when the 
// XML was written out.
// Note that this doesn't count changes in the modifiers of classes and 
// packages. Other changes in members are counted.
        Long denom = new Long(oldAPI.packages_.size() + newAPI.packages_.size());
        // This should never be zero because an API always has packages?
        if (denom.intValue() == 0) {
            System.out.println("Error: no packages found in the APIs.");
            return;
        }
        if (trace)
            System.out.println("Top level changes: " + differs + "/" + denom.intValue());
        differs = (100.0 * differs)/denom.doubleValue();

        // Some differences such as documentation changes are not tracked in 
        // the difference statistic, so a value of 0.0 does not mean that there
        // were no differences between the APIs.
        apiDiff.pdiff = differs;
        Double percentage = new Double(differs);
        int approxPercentage = percentage.intValue();
        if (approxPercentage == 0)
            System.out.println(" Approximately " + percentage + "% difference between the APIs");
        else
            System.out.println(" Approximately " + approxPercentage + "% difference between the APIs");

        Diff.closeDiffFile();
    }   

    /** 
     * Compare two packages.
     */
    public double comparePackages(PackageAPI oldPkg, PackageAPI newPkg) {
        if (trace)
            System.out.println("Comparing old package " + oldPkg.name_ + 
                               " and new package " + newPkg.name_);
        pkgDiff = new PackageDiff(oldPkg.name_);
        double differs = 0.0;

        Collections.sort(oldPkg.classes_);
        Collections.sort(newPkg.classes_);
      
        // Find classes which were removed in the new package
        Iterator iter = oldPkg.classes_.iterator();
        while (iter.hasNext()) {
            ClassAPI oldClass = (ClassAPI)(iter.next());
            // This search is looking for an *exact* match. This is true in
            // all the *API classes.
            int idx = Collections.binarySearch(newPkg.classes_, oldClass);
            if (idx < 0) {
                // If there an instance of a class with the same name 
                // in both the old and new package, then treat it as changed,
                // rather than removed and added. There will never be more than
                // one instance of a class with the same name in a package.
                int existsNew = newPkg.classes_.indexOf(oldClass);
                if (existsNew != -1) {
                    // Class by the same name exists in both packages
                    // but there has been some or other change.
                    differs += 2.0 * compareClasses(oldClass, (ClassAPI)(newPkg.classes_.get(existsNew)), pkgDiff);
                }  else {
                    if (trace)
                        System.out.println("  Class " + oldClass.name_ + " was removed");
                    pkgDiff.classesRemoved.add(oldClass);
                    differs += 1.0;
                }
            } else {
                // The class exists unchanged in name or modifiers, but may 
                // differ in members, so it still needs to be compared.
                differs += 2.0 * compareClasses(oldClass, (ClassAPI)(newPkg.classes_.get(idx)), pkgDiff);
            }
        } // while (iter.hasNext())

        // Find classes which were added or changed in the new package
        iter = newPkg.classes_.iterator();
        while (iter.hasNext()) {
            ClassAPI newClass = (ClassAPI)(iter.next());
            int idx = Collections.binarySearch(oldPkg.classes_, newClass);
            if (idx < 0) {
                // See comments above
                int existsOld = oldPkg.classes_.indexOf(newClass);
                if (existsOld != -1) {
                    // Don't mark a class as added or compare it 
                    // if it was already marked as changed
                } else {
                    if (trace)
                        System.out.println("  Class " + newClass.name_ + " was added");
                    pkgDiff.classesAdded.add(newClass);
                    differs += 1.0;
                }
            } else {
                // It will already have been compared above.
            }
        } // while (iter.hasNext())

        // Check if the only change was in documentation. Bug 472521.
        boolean differsFlag = false;
        if (docChanged(oldPkg.doc_, newPkg.doc_)) {
            String link = "<a href=\"pkg_" + oldPkg.name_ + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">";
            String id = oldPkg.name_ + "!package";
            String title = link + "Package <b>" + oldPkg.name_ + "</b></a>";
            pkgDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, null, oldPkg.doc_, newPkg.doc_, id, title);
            differsFlag = true;
        }

        // Only add to the parent Diff object if some difference has been found
        if (differs != 0.0 || differsFlag) 
            apiDiff.packagesChanged.add(pkgDiff);

        Long denom = new Long(oldPkg.classes_.size() + newPkg.classes_.size());
        // This should never be zero because a package always has classes?
        if (denom.intValue() == 0) {
            System.out.println("Warning: no classes found in the package " + oldPkg.name_);
            return 0.0;
        }
        if (trace)
            System.out.println("Package " + pkgDiff.name_ + " had a difference of " + differs + "/" + denom.intValue());
        pkgDiff.pdiff = 100.0 * differs/denom.doubleValue();
        return differs/denom.doubleValue();
    } // comparePackages()

    /** 
     * Compare two classes. 
     *
     * Need to compare constructors, methods and fields.
     */
    public double compareClasses(ClassAPI oldClass, ClassAPI newClass, PackageDiff pkgDiff) {
        if (trace)
            System.out.println("  Comparing old class " + oldClass.name_ + 
                               " and new class " + newClass.name_);
        boolean differsFlag = false;
        double differs = 0.0;
        ClassDiff classDiff = new ClassDiff(oldClass.name_);
        classDiff.isInterface_ = newClass.isInterface_; // Used in the report

        // Track changes in modifiers - class or interface
        if (oldClass.isInterface_ != newClass.isInterface_) {
            classDiff.modifiersChange_  = "Changed from ";
            if (oldClass.isInterface_)
                classDiff.modifiersChange_ += "an interface to a class.";
            else
                classDiff.modifiersChange_ += "a class to an interface.";
            differsFlag = true;
        }
        // Track changes in inheritance
        String inheritanceChange = ClassDiff.diff(oldClass, newClass);
        if (inheritanceChange != null) {
            classDiff.inheritanceChange_ = inheritanceChange;
            differsFlag = true;
        }
        // Abstract or not
        if (oldClass.isAbstract_ != newClass.isAbstract_) {
            String changeText = "";
            if (oldClass.isAbstract_)
                changeText += "Changed from abstract to non-abstract.";
            else
                changeText += "Changed from non-abstract to abstract.";
            classDiff.addModifiersChange(changeText);
            differsFlag = true;
        }
        // Track changes in documentation
        if (docChanged(oldClass.doc_, newClass.doc_)) {
            String fqName = pkgDiff.name_ + "." + classDiff.name_;
            String link = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">";
            String id = pkgDiff.name_ + "." + classDiff.name_ + "!class";
            String title = link + "Class <b>" + classDiff.name_ + "</b></a>";
            classDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_,
 classDiff.name_, oldClass.doc_, newClass.doc_, id, title);
            differsFlag = true;
        }
        // All other modifiers
        String modifiersChange = oldClass.modifiers_.diff(newClass.modifiers_);
        if (modifiersChange != null) {
            differsFlag = true;
            if (modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) {
                System.out.println("JDiff: warning: change from deprecated to undeprecated for class " + pkgDiff.name_ + "." + newClass.name_);
                
            }
        }
        classDiff.addModifiersChange(modifiersChange);
        
        // Track changes in members
        boolean differsCtors = 
            compareAllCtors(oldClass, newClass, classDiff);
        boolean differsMethods = 
            compareAllMethods(oldClass, newClass, classDiff);
        boolean differsFields = 
            compareAllFields(oldClass, newClass, classDiff);
        if (differsCtors || differsMethods || differsFields) 
            differsFlag = true;
        
        if (trace) {
            System.out.println("  Ctors differ? " + differsCtors + 
                ", Methods differ? " + differsMethods + 
                ", Fields differ? " + differsFields);
        }

        // Only add to the parent if some difference has been found
        if (differsFlag) 
            pkgDiff.classesChanged.add(classDiff);

        // Get the numbers of affected elements from the classDiff object
         differs = 
            classDiff.ctorsRemoved.size() + classDiff.ctorsAdded.size() +
            classDiff.ctorsChanged.size() +
            classDiff.methodsRemoved.size() + classDiff.methodsAdded.size() +
            classDiff.methodsChanged.size() +
            classDiff.fieldsRemoved.size() + classDiff.fieldsAdded.size() +
            classDiff.fieldsChanged.size();
         Long denom = new Long(
             oldClass.ctors_.size() + 
             numLocalMethods(oldClass.methods_) + 
             numLocalFields(oldClass.fields_) +
             newClass.ctors_.size() + 
             numLocalMethods(newClass.methods_) + 
             numLocalFields(newClass.fields_));
         if (denom.intValue() == 0) {
             // This is probably a placeholder interface, but documentation
             // or modifiers etc may have changed
             if (differsFlag) {
                 classDiff.pdiff = 0.0; // 100.0 is too much
                 return 1.0;
             } else {
                 return 0.0;
             }
         }
         // Handle the case where the only change is in documentation or
         // the modifiers
         if (differsFlag && differs == 0.0) {
             differs = 1.0;
         }
         if (trace)
             System.out.println("  Class " + classDiff.name_ + " had a difference of " + differs + "/" + denom.intValue());
         classDiff.pdiff = 100.0 * differs/denom.doubleValue();
         return differs/denom.doubleValue();
    } // compareClasses()

    /** 
     * Compare all the constructors in two classes. 
     *
     * The compareTo method in the ConstructorAPI class acts only upon the type.
     */
    public boolean compareAllCtors(ClassAPI oldClass, ClassAPI newClass, 
                                   ClassDiff classDiff) {
        if (trace)
            System.out.println("    Comparing constructors: #old " + 
              oldClass.ctors_.size() + ", #new " + newClass.ctors_.size());
        boolean differs = false;
        boolean singleCtor = false; // Set if there is only one ctor
        
        Collections.sort(oldClass.ctors_);
        Collections.sort(newClass.ctors_);
      
        // Find ctors which were removed in the new class
        Iterator iter = oldClass.ctors_.iterator();
        while (iter.hasNext()) {
            ConstructorAPI oldCtor = (ConstructorAPI)(iter.next());
            int idx = Collections.binarySearch(newClass.ctors_, oldCtor);
            if (idx < 0) {
                int oldSize = oldClass.ctors_.size();
                int newSize = newClass.ctors_.size();
                if (oldSize == 1 && oldSize == newSize) {
                    // If there is one constructor in the oldClass and one
                    // constructor in the new class, then mark it as changed
                    MemberDiff memberDiff = new MemberDiff(oldClass.name_);
                    memberDiff.oldType_ = oldCtor.getSignature();
                    memberDiff.oldExceptions_ = oldCtor.exceptions_;
                    ConstructorAPI newCtor  = (ConstructorAPI)(newClass.ctors_.get(0));
                    memberDiff.newType_ = newCtor.getSignature();
                    memberDiff.newExceptions_ = newCtor.exceptions_;
                    // Track changes in documentation
                    if (docChanged(oldCtor.doc_, newCtor.doc_)) {
                        String type = memberDiff.newType_;
                        if (type.compareTo("void") == 0)
                            type = "";
                        String fqName = pkgDiff.name_ + "." + classDiff.name_;
                        String link1 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">";
                        String link2 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "#" + fqName + ".ctor_changed(" + type + ")\" class=\"hiddenlink\">";
                        String id = pkgDiff.name_ + "." + classDiff.name_ + ".ctor(" + HTMLReportGenerator.simpleName(type) + ")";
                        String title = link1 + "Class <b>" + classDiff.name_ + 
                            "</b></a>, " + link2 + "constructor <b>" + classDiff.name_ + "(" + HTMLReportGenerator.simpleName(type) + ")</b></a>";
                        memberDiff.documentationChange_ = Diff.saveDocDiffs(
                            pkgDiff.name_, classDiff.name_, oldCtor.doc_, newCtor.doc_, id, title);
                    }
                    String modifiersChange = oldCtor.modifiers_.diff(newCtor.modifiers_);
                    if (modifiersChange != null && modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) {
                        System.out.println("JDiff: warning: change from deprecated to undeprecated for a constructor in class" + newClass.name_);
                    }
                    memberDiff.addModifiersChange(modifiersChange);
                    if (trace)
                        System.out.println("    The single constructor was changed");
                    classDiff.ctorsChanged.add(memberDiff);
                    singleCtor = true;
                } else {
                    if (trace)
                        System.out.println("    Constructor " + oldClass.name_ + " was removed");
                    classDiff.ctorsRemoved.add(oldCtor);
                }
                differs = true;
            }
        } // while (iter.hasNext())

        // Find ctors which were added in the new class
        iter = newClass.ctors_.iterator();
        while (iter.hasNext()) {
            ConstructorAPI newCtor = (ConstructorAPI)(iter.next());
            int idx = Collections.binarySearch(oldClass.ctors_, newCtor);
            if (idx < 0) {
                if (!singleCtor) {
                    if (trace)
                        System.out.println("    Constructor " + oldClass.name_ + " was added");
                    classDiff.ctorsAdded.add(newCtor);
                    differs = true;
                }
            }
        } // while (iter.hasNext())

        return differs;
    } // compareAllCtors()

    /** 
     * Compare all the methods in two classes. 
     *
     * We have to deal with the cases where:
     *  - there is only one method with a given name, but its signature changes
     *  - there is more than one method with the same name, and some of them 
     *    may have signature changes
     * The simplest way to deal with this is to make the MethodAPI comparator
     * check the params and return type, as well as the name. This means that
     * changing a parameter's type would cause the method to be seen as 
     * removed and added. To avoid this for the simple case, check for before 
     * recording a method as removed or added.
     */
    public boolean compareAllMethods(ClassAPI oldClass, ClassAPI newClass, ClassDiff classDiff) {
        if (trace)
            System.out.println("    Comparing methods: #old " + 
                               oldClass.methods_.size() + ", #new " +
                               newClass.methods_.size());
        boolean differs = false;
        
        Collections.sort(oldClass.methods_);
        Collections.sort(newClass.methods_);
      
        // Find methods which were removed in the new class
        Iterator iter = oldClass.methods_.iterator();
        while (iter.hasNext()) {
            MethodAPI oldMethod = (MethodAPI)(iter.next());
            int idx = -1;
            MethodAPI[] methodArr = new MethodAPI[newClass.methods_.size()];
            methodArr = (MethodAPI[])newClass.methods_.toArray(methodArr);
            for (int methodIdx = 0; methodIdx < methodArr.length; methodIdx++) {
                MethodAPI newMethod = methodArr[methodIdx];
                if (oldMethod.compareTo(newMethod) == 0) {
                    idx  = methodIdx;
                    break;
                }
            }
// NOTE: there was a problem with the binarySearch for 
// java.lang.Byte.toString(byte b) returning -16 when the compareTo method
// returned 0 on entry 13. Changed to use arrays instead, so maybe it was
// an issue with methods having another List of params used indirectly by 
// compareTo(), unlike constructors and fields?
//            int idx = Collections.binarySearch(newClass.methods_, oldMethod);
            if (idx < 0) {
                // If there is only one instance of a method with this name 
                // in both the old and new class, then treat it as changed,
                // rather than removed and added.
                // Find how many instances of this method name there are in
                // the old and new class. The equals comparator is just on 
                // the method name.
                int startOld = oldClass.methods_.indexOf(oldMethod); 
                int endOld = oldClass.methods_.lastIndexOf(oldMethod);
                int startNew = newClass.methods_.indexOf(oldMethod); 
                int endNew = newClass.methods_.lastIndexOf(oldMethod);

                if (startOld != -1 && startOld == endOld && 
                    startNew != -1 && startNew == endNew) {
                    MethodAPI newMethod = (MethodAPI)(newClass.methods_.get(startNew));
                    // Only one method with that name exists in both packages,
                    // so it is valid to compare the two methods. We know it 
                    // has changed, because the binarySearch did not find it.
                    if (oldMethod.inheritedFrom_ == null || 
                        newMethod.inheritedFrom_ == null) {
                        // We also know that at least one of the methods is 
                        // locally defined.
                        compareMethods(oldMethod, newMethod, classDiff);
                        differs = true;
                    }
                } else if (oldMethod.inheritedFrom_ == null) {
                    // Only concerned with locally defined methods
                    if (trace)
                        System.out.println("    Method " + oldMethod.name_ + 
                                           "(" + oldMethod.getSignature() + 
                                           ") was removed");
                    classDiff.methodsRemoved.add(oldMethod);
                    differs = true;
                }
            }
        } // while (iter.hasNext())

        // Find methods which were added in the new class
        iter = newClass.methods_.iterator();
        while (iter.hasNext()) {
            MethodAPI newMethod = (MethodAPI)(iter.next());
            // Only concerned with locally defined methods
            if (newMethod.inheritedFrom_ != null)
                continue;
            int idx = -1;
            MethodAPI[] methodArr = new MethodAPI[oldClass.methods_.size()];
            methodArr = (MethodAPI[])oldClass.methods_.toArray(methodArr);
            for (int methodIdx = 0; methodIdx < methodArr.length; methodIdx++) {
                MethodAPI oldMethod = methodArr[methodIdx];
                if (newMethod.compareTo(oldMethod) == 0) {
                    idx  = methodIdx;
                    break;
                }
            }
// See note above about searching an array instead of binarySearch
//            int idx = Collections.binarySearch(oldClass.methods_, newMethod);
            if (idx < 0) {
                // See comments above
                int startOld = oldClass.methods_.indexOf(newMethod); 
                int endOld = oldClass.methods_.lastIndexOf(newMethod);
                int startNew = newClass.methods_.indexOf(newMethod); 
                int endNew = newClass.methods_.lastIndexOf(newMethod);

                if (startOld != -1 && startOld == endOld && 
                    startNew != -1 && startNew == endNew) {
                    // Don't mark a method as added if it was marked as changed
                    // The comparison will have been done just above here.
                } else {
                    if (trace)
                        System.out.println("    Method " + newMethod.name_ + 
                                           "(" + newMethod.getSignature() + ") was added");
                    classDiff.methodsAdded.add(newMethod);
                    differs = true;
                }
            }
        } // while (iter.hasNext())

        return differs;
    } // compareAllMethods()

    /** 
     * Compare two methods which have the same name. 
     */
    public boolean compareMethods(MethodAPI oldMethod, MethodAPI newMethod, ClassDiff classDiff) {
        MemberDiff methodDiff = new MemberDiff(oldMethod.name_);
        boolean differs = false;
        // Check changes in return type
        methodDiff.oldType_ = oldMethod.returnType_;
        methodDiff.newType_ = newMethod.returnType_;
        if (oldMethod.returnType_.compareTo(newMethod.returnType_) != 0) {
            differs = true;
        }
        // Check changes in signature
        String oldSig = oldMethod.getSignature();
        String newSig = newMethod.getSignature();
        methodDiff.oldSignature_ = oldSig;
        methodDiff.newSignature_ = newSig;
        if (oldSig.compareTo(newSig) != 0) {
            differs = true;
        }
        // Changes in inheritance
        int inh = changedInheritance(oldMethod.inheritedFrom_, newMethod.inheritedFrom_);
        if (inh != 0)
            differs = true;
        if (inh == 1) {
            methodDiff.addModifiersChange("Method was locally defined, but is now inherited from " + linkToClass(newMethod, true) + ".");
            methodDiff.inheritedFrom_ = newMethod.inheritedFrom_;
        } else if (inh == 2) {
            methodDiff.addModifiersChange("Method was inherited from " + linkToClass(oldMethod, false) + ", but is now defined locally.");
        } else if (inh == 3) {
            methodDiff.addModifiersChange("Method was inherited from " + 
                                          linkToClass(oldMethod, false) + ", and is now inherited from " + linkToClass(newMethod, true) + ".");
            methodDiff.inheritedFrom_ = newMethod.inheritedFrom_;
        }
        // Abstract or not
        if (oldMethod.isAbstract_ != newMethod.isAbstract_) {
            String changeText = "";
            if (oldMethod.isAbstract_)
                changeText += "Changed from abstract to non-abstract.";
            else
                changeText += "Changed from non-abstract to abstract.";
            methodDiff.addModifiersChange(changeText);
            differs = true;
        }
        // Native or not
        if (Diff.showAllChanges && 
	    oldMethod.isNative_ != newMethod.isNative_) {
            String changeText = "";
            if (oldMethod.isNative_)
                changeText += "Changed from native to non-native.";
            else
                changeText += "Changed from non-native to native.";
            methodDiff.addModifiersChange(changeText);
            differs = true;
        }
        // Synchronized or not
        if (Diff.showAllChanges && 
	    oldMethod.isSynchronized_ != newMethod.isSynchronized_) {
            String changeText = "";
            if (oldMethod.isSynchronized_)
                changeText += "Changed from synchronized to non-synchronized.";
            else
                changeText += "Changed from non-synchronized to synchronized.";
            methodDiff.addModifiersChange(changeText);
            differs = true;
        }

        // Check changes in exceptions thrown
        methodDiff.oldExceptions_ = oldMethod.exceptions_;
        methodDiff.newExceptions_ = newMethod.exceptions_;
        if (oldMethod.exceptions_.compareTo(newMethod.exceptions_) != 0) {
            differs = true;
        }

        // Track changes in documentation
        if (docChanged(oldMethod.doc_, newMethod.doc_)) {
            String sig = methodDiff.newSignature_;
            if (sig.compareTo("void") == 0)
                sig = "";
            String fqName = pkgDiff.name_ + "." + classDiff.name_;
            String link1 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">";
            String link2 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "#" + fqName + "." + newMethod.name_ + "_changed(" + sig + ")\" class=\"hiddenlink\">";
            String id = pkgDiff.name_ + "." + classDiff.name_ + ".dmethod." + newMethod.name_ + "(" + HTMLReportGenerator.simpleName(sig) + ")";
            String title = link1 + "Class <b>" + classDiff.name_ + "</b></a>, " +
                link2 + HTMLReportGenerator.simpleName(methodDiff.newType_) + " <b>" + newMethod.name_ + "(" + HTMLReportGenerator.simpleName(sig) + ")</b></a>";
            methodDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, classDiff.name_, oldMethod.doc_, newMethod.doc_, id, title);
            differs = true;
        }

        // All other modifiers
        String modifiersChange = oldMethod.modifiers_.diff(newMethod.modifiers_);
        if (modifiersChange != null) {
            differs = true;
            if (modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) {
                System.out.println("JDiff: warning: change from deprecated to undeprecated for method " +  classDiff.name_ + "." + newMethod.name_);
                
            }
        }
        methodDiff.addModifiersChange(modifiersChange);

        // Only add to the parent if some difference has been found
        if (differs) {
            if (trace) {
                System.out.println("    Method " + newMethod.name_ + 
                    " was changed: old: " + 
                   oldMethod.returnType_ + "(" + oldSig + "), new: " +
                   newMethod.returnType_ + "(" + newSig + ")");
                if (methodDiff.modifiersChange_ != null)
                    System.out.println("    Modifier change: " + methodDiff.modifiersChange_);
            }
            classDiff.methodsChanged.add(methodDiff);
        }

        return differs;
    } // compareMethods()

    /** 
     * Compare all the fields in two classes. 
     */
    public boolean compareAllFields(ClassAPI oldClass, ClassAPI newClass, 
                                    ClassDiff classDiff) {
        if (trace)
            System.out.println("    Comparing fields: #old " + 
                               oldClass.fields_.size() + ", #new " 
                               + newClass.fields_.size());
        boolean differs = false;
        
        Collections.sort(oldClass.fields_);
        Collections.sort(newClass.fields_);
      
        // Find fields which were removed in the new class
        Iterator iter = oldClass.fields_.iterator();
        while (iter.hasNext()) {
            FieldAPI oldField = (FieldAPI)(iter.next());
            int idx = Collections.binarySearch(newClass.fields_, oldField);
            if (idx < 0) {
                // If there an instance of a field with the same name 
                // in both the old and new class, then treat it as changed,
                // rather than removed and added. There will never be more than
                // one instance of a field with the same name in a class.
                int existsNew = newClass.fields_.indexOf(oldField);
                if (existsNew != -1) {
                    FieldAPI newField = (FieldAPI)(newClass.fields_.get(existsNew));
                    if (oldField.inheritedFrom_ == null || 
                        newField.inheritedFrom_ == null) {
                        // We also know that one of the fields is locally defined.
                        MemberDiff memberDiff = new MemberDiff(oldField.name_);
                        memberDiff.oldType_ = oldField.type_;
                        memberDiff.newType_ = newField.type_;
                        // Changes in inheritance
                        int inh = changedInheritance(oldField.inheritedFrom_, newField.inheritedFrom_);
                        if (inh != 0)
                            differs = true;
                        if (inh == 1) {
                            memberDiff.addModifiersChange("Field was locally defined, but is now inherited from " + linkToClass(newField, true) + ".");
                            memberDiff.inheritedFrom_ = newField.inheritedFrom_;
                        } else if (inh == 2) {
                            memberDiff.addModifiersChange("Field was inherited from " + linkToClass(oldField, false) + ", but is now defined locally.");
                        } else if (inh == 3) {
                            memberDiff.addModifiersChange("Field was inherited from " + linkToClass(oldField, false) + ", and is now inherited from " + linkToClass(newField, true) + ".");
                            memberDiff.inheritedFrom_ = newField.inheritedFrom_;
                        }
                        // Transient or not
                        if (oldField.isTransient_ != newField.isTransient_) {
                            String changeText = "";
                            if (oldField.isTransient_)
                                changeText += "Changed from transient to non-transient.";
                            else
                                changeText += "Changed from non-transient to transient.";
                            memberDiff.addModifiersChange(changeText);
                            differs = true;
                        }
                        // Volatile or not
                        if (oldField.isVolatile_ != newField.isVolatile_) {
                            String changeText = "";
                            if (oldField.isVolatile_)
                                changeText += "Changed from volatile to non-volatile.";
                            else
                                changeText += "Changed from non-volatile to volatile.";
                            memberDiff.addModifiersChange(changeText);
                            differs = true;
                        }
                        // Change in value of the field
                        if (oldField.value_ != null &&
                            newField.value_ != null &&
                            oldField.value_.compareTo(newField.value_) != 0) {
                            String changeText = "Changed in value from " + oldField.value_
                                + " to " + newField.value_ +".";
                            memberDiff.addModifiersChange(changeText);
                            differs = true;
                        }
                        // Track changes in documentation
                        if (docChanged(oldField.doc_, newField.doc_)) {
                            String fqName = pkgDiff.name_ + "." + classDiff.name_;
                            String link1 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">";
                            String link2 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "#" + fqName + "." + newField.name_ + "\" class=\"hiddenlink\">";
                            String id = pkgDiff.name_ + "." + classDiff.name_ + ".field." + newField.name_;
                            String title = link1 + "Class <b>" + classDiff.name_ + "</b></a>, " +
                                link2 + HTMLReportGenerator.simpleName(memberDiff.newType_) + " <b>" + newField.name_ + "</b></a>";
                            memberDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, classDiff.name_, oldField.doc_, newField.doc_, id, title);
                            differs = true;
                        }
                        
                        // Other differences
                        String modifiersChange = oldField.modifiers_.diff(newField.modifiers_);
                        memberDiff.addModifiersChange(modifiersChange);
                        if (modifiersChange != null && modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) {
                            System.out.println("JDiff: warning: change from deprecated to undeprecated for class " + newClass.name_ + ", field " + newField.name_);
                        }
                        if (trace)
                            System.out.println("    Field " + newField.name_ + " was changed");
                        classDiff.fieldsChanged.add(memberDiff);
                        differs = true;
                    }
                } else if (oldField.inheritedFrom_ == null) {
                    if (trace)
                        System.out.println("    Field " + oldField.name_ + " was removed");
                    classDiff.fieldsRemoved.add(oldField);
                    differs = true;
                }
            }
        } // while (iter.hasNext())

        // Find fields which were added in the new class
        iter = newClass.fields_.iterator();
        while (iter.hasNext()) {
            FieldAPI newField = (FieldAPI)(iter.next());
            // Only concerned with locally defined fields
            if (newField.inheritedFrom_ != null)
                continue;
            int idx = Collections.binarySearch(oldClass.fields_, newField);
            if (idx < 0) {
                // See comments above
                int existsOld = oldClass.fields_.indexOf(newField);
                if (existsOld != -1) {
                    // Don't mark a field as added if it was marked as changed
                } else {
                    if (trace)
                        System.out.println("    Field " + newField.name_ + " was added");
                    classDiff.fieldsAdded.add(newField);
                    differs = true;
                }
            }
        } // while (iter.hasNext())

        return differs;
    } // compareFields()

    /** 
     * Decide if two blocks of documentation changed. 
     *
     * @return true if both are non-null and differ, 
     *              or if one is null and the other is not.
     */
    public static boolean docChanged(String oldDoc, String newDoc) {
        if (!HTMLReportGenerator.reportDocChanges)
            return false; // Don't even count doc changes as changes
        if (oldDoc == null && newDoc != null)
            return true;
        if (oldDoc != null && newDoc == null)
            return true;
        if (oldDoc != null && newDoc != null && oldDoc.compareTo(newDoc) != 0)
            return true;
        return false;
    }

    /** 
     * Decide if two elements changed where they were defined. 
     *
     * @return 0 if both are null, or both are non-null and are the same.
     *         1 if the oldInherit was null and newInherit is non-null.
     *         2 if the oldInherit was non-null and newInherit is null.
     *         3 if the oldInherit was non-null and newInherit is non-null 
     *           and they differ.
     */
    public static int changedInheritance(String oldInherit, String newInherit) {
        if (oldInherit == null && newInherit == null)
            return 0;
        if (oldInherit == null && newInherit != null)
            return 1;
        if (oldInherit != null && newInherit == null)
            return 2;
        if (oldInherit.compareTo(newInherit) == 0)
            return 0;
        else
            return 3;
    }

    /** 
     * Generate a link to the Javadoc page for the given method.
     */
    public static String linkToClass(MethodAPI m, boolean useNew) {
        String sig = m.getSignature();
        if (sig.compareTo("void") == 0)
            sig = "";
        return linkToClass(m.inheritedFrom_, m.name_, sig, useNew);
    }

    /** 
     * Generate a link to the Javadoc page for the given field.
     */
    public static String linkToClass(FieldAPI m, boolean useNew) {
        return linkToClass(m.inheritedFrom_, m.name_, null, useNew);
    }

    /** 
     * Given the name of the class, generate a link to a relevant page.
     * This was originally for inheritance changes, so the JDiff page could 
     * be a class changes page, or a section in a removed or added classes 
     * table. Since there was no easy way to tell which type the link
     * should be, it is now just a link to the relevant Javadoc page.
     */
    public static String linkToClass(String className, String memberName, 
                                     String memberType, boolean useNew) {
        if (!useNew && HTMLReportGenerator.oldDocPrefix == null) {
            return "<tt>" + className + "</tt>"; // No link possible
        }
        API api = oldAPI_;
        String prefix = HTMLReportGenerator.oldDocPrefix;
        if (useNew) {
            api = newAPI_;
            prefix = HTMLReportGenerator.newDocPrefix;
        }
        ClassAPI cls = (ClassAPI)api.classes_.get(className);
        if (cls == null) {
            if (useNew)
                System.out.println("Warning: class " + className + " not found in the new API when creating Javadoc link");
            else
                System.out.println("Warning: class " + className + " not found in the old API when creating Javadoc link");
            return "<tt>" + className + "</tt>";
        }
        int clsIdx = className.indexOf(cls.name_);
        if (clsIdx != -1) {
            String pkgRef = className.substring(0, clsIdx);
            pkgRef = pkgRef.replace('.', '/');
            String res = "<a href=\"" + prefix + pkgRef + cls.name_ + ".html#" + memberName;
            if (memberType != null)
                res += "(" + memberType + ")";
            res += "\" target=\"_top\">" + "<tt>" + cls.name_ + "</tt></a>";
            return res;
        }
        return "<tt>" + className + "</tt>";
    }    

    /** 
     * Return the number of methods which are locally defined.
     */
    public int numLocalMethods(List methods) {
        int res = 0;
        Iterator iter = methods.iterator();
        while (iter.hasNext()) {
            MethodAPI m = (MethodAPI)(iter.next());
            if (m.inheritedFrom_ == null) 
                res++;
        }
        return res;
    }

    /** 
     * Return the number of fields which are locally defined.
     */
    public int numLocalFields(List fields) {
        int res = 0;
        Iterator iter = fields.iterator();
        while (iter.hasNext()) {
            FieldAPI f = (FieldAPI)(iter.next());
            if (f.inheritedFrom_ == null) 
                res++;
        }
        return res;
    }

    /** Set to enable increased logging verbosity for debugging. */
    private boolean trace = false;
}
