Coverage Report - com.jeantessier.diff.ClassReport
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassReport
85%
358/418
81%
181/222
2.623
 
 1  
 /*
 2  
  *  Copyright (c) 2001-2009, Jean Tessier
 3  
  *  All rights reserved.
 4  
  *  
 5  
  *  Redistribution and use in source and binary forms, with or without
 6  
  *  modification, are permitted provided that the following conditions
 7  
  *  are met:
 8  
  *  
 9  
  *      * Redistributions of source code must retain the above copyright
 10  
  *        notice, this list of conditions and the following disclaimer.
 11  
  *  
 12  
  *      * Redistributions in binary form must reproduce the above copyright
 13  
  *        notice, this list of conditions and the following disclaimer in the
 14  
  *        documentation and/or other materials provided with the distribution.
 15  
  *  
 16  
  *      * Neither the name of Jean Tessier nor the names of his contributors
 17  
  *        may be used to endorse or promote products derived from this software
 18  
  *        without specific prior written permission.
 19  
  *  
 20  
  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 21  
  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 22  
  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 23  
  *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
 24  
  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 25  
  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 26  
  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 27  
  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 28  
  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 29  
  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 30  
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 31  
  */
 32  
 
 33  
 package com.jeantessier.diff;
 34  
 
 35  
 import java.util.*;
 36  
 
 37  
 import org.apache.oro.text.perl.*;
 38  
 
 39  
 import com.jeantessier.classreader.*;
 40  
 
 41  24
 public class ClassReport extends Printer implements Comparable, com.jeantessier.classreader.Visitor {
 42  1
     private static final Perl5Util perl = new Perl5Util();
 43  
 
 44  
     private ClassDifferences differences;
 45  
 
 46  24
     private Collection<FeatureDifferences> removedFields = new TreeSet<FeatureDifferences>();
 47  24
     private Collection<FeatureDifferences> removedConstructors = new TreeSet<FeatureDifferences>();
 48  24
     private Collection<FeatureDifferences> removedMethods = new TreeSet<FeatureDifferences>();
 49  
 
 50  24
     private Collection<FeatureDifferences> deprecatedFields = new TreeSet<FeatureDifferences>();
 51  24
     private Collection<FeatureDifferences> deprecatedConstructors = new TreeSet<FeatureDifferences>();
 52  24
     private Collection<FeatureDifferences> deprecatedMethods = new TreeSet<FeatureDifferences>();
 53  
 
 54  24
     private Collection<FieldDifferences> modifiedFields = new TreeSet<FieldDifferences>();
 55  24
     private Collection<CodeDifferences> modifiedConstructors = new TreeSet<CodeDifferences>();
 56  24
     private Collection<CodeDifferences> modifiedMethods = new TreeSet<CodeDifferences>();
 57  
 
 58  24
     private Collection<FeatureDifferences> undeprecatedFields = new TreeSet<FeatureDifferences>();
 59  24
     private Collection<FeatureDifferences> undeprecatedConstructors = new TreeSet<FeatureDifferences>();
 60  24
     private Collection<FeatureDifferences> undeprecatedMethods = new TreeSet<FeatureDifferences>();
 61  
 
 62  24
     private Collection<FeatureDifferences> newFields = new TreeSet<FeatureDifferences>();
 63  24
     private Collection<FeatureDifferences> newConstructors = new TreeSet<FeatureDifferences>();
 64  24
     private Collection<FeatureDifferences> newMethods = new TreeSet<FeatureDifferences>();
 65  
 
 66  
     public void visitClassDifferences(ClassDifferences differences) {
 67  22
         this.differences = differences;
 68  
 
 69  22
         for (Differences featureDifference : differences.getFeatureDifferences()) {
 70  56
             featureDifference.accept(this);
 71  
         }
 72  22
     }
 73  
 
 74  
     public void visitInterfaceDifferences(InterfaceDifferences differences) {
 75  2
         this.differences = differences;
 76  
 
 77  2
         for (Differences featureDifference : differences.getFeatureDifferences()) {
 78  11
             featureDifference.accept(this);
 79  
         }
 80  2
     }
 81  
 
 82  
     public void visitFieldDifferences(FieldDifferences differences) {
 83  47
         if (differences.isRemoved()) {
 84  14
             removedFields.add(differences);
 85  
         }
 86  
     
 87  47
         if (differences.isModified()) {
 88  15
             modifiedFields.add(differences);
 89  
         }
 90  
     
 91  47
         if (differences.isNew()) {
 92  14
             newFields.add(differences);
 93  
         }
 94  
 
 95  47
         if (isDeprecated()) {
 96  2
             deprecatedFields.add(differences);
 97  
         }
 98  
 
 99  47
         if (isUndeprecated()) {
 100  2
             undeprecatedFields.add(differences);
 101  
         }
 102  47
     }
 103  
 
 104  
     public void visitConstructorDifferences(ConstructorDifferences differences) {
 105  6
         if (differences.isRemoved()) {
 106  1
             removedConstructors.add(differences);
 107  
         }
 108  
     
 109  6
         if (differences.isModified()) {
 110  2
             modifiedConstructors.add(differences);
 111  
         }
 112  
     
 113  6
         if (differences.isNew()) {
 114  1
             newConstructors.add(differences);
 115  
         }
 116  
 
 117  6
         if (isDeprecated()) {
 118  1
             deprecatedConstructors.add(differences);
 119  
         }
 120  
 
 121  6
         if (isUndeprecated()) {
 122  1
             undeprecatedConstructors.add(differences);
 123  
         }
 124  6
     }
 125  
 
 126  
     public void visitMethodDifferences(MethodDifferences differences) {
 127  14
         if (differences.isRemoved()) {
 128  2
             removedMethods.add(differences);
 129  
         }
 130  
     
 131  14
         if (differences.isModified()) {
 132  4
             modifiedMethods.add(differences);
 133  
         }
 134  
     
 135  14
         if (differences.isNew()) {
 136  4
             newMethods.add(differences);
 137  
         }
 138  
 
 139  14
         if (isDeprecated()) {
 140  2
             deprecatedMethods.add(differences);
 141  
         }
 142  
 
 143  14
         if (isUndeprecated()) {
 144  2
             undeprecatedMethods.add(differences);
 145  
         }
 146  14
     }
 147  
 
 148  
     public void visitClassfiles(Collection<Classfile> classfiles) {
 149  
         // Do nothing
 150  0
     }
 151  
 
 152  
     public void visitClassfile(Classfile classfile) {
 153  
         // Do nothing
 154  0
     }
 155  
 
 156  
     public void visitConstantPool(ConstantPool constantPool) {
 157  
         // Do nothing
 158  0
     }
 159  
 
 160  
     public void visitClass_info(Class_info entry) {
 161  
         // Do nothing
 162  0
     }
 163  
 
 164  
     public void visitFieldRef_info(FieldRef_info entry) {
 165  
         // Do nothing
 166  0
     }
 167  
 
 168  
     public void visitMethodRef_info(MethodRef_info entry) {
 169  
         // Do nothing
 170  0
     }
 171  
 
 172  
     public void visitInterfaceMethodRef_info(InterfaceMethodRef_info entry) {
 173  
         // Do nothing
 174  0
     }
 175  
 
 176  
     public void visitString_info(String_info entry) {
 177  36
         entry.getRawValue().accept(this);
 178  36
     }
 179  
 
 180  
     public void visitInteger_info(Integer_info entry) {
 181  17
         append(entry.getValue());
 182  17
     }
 183  
 
 184  
     public void visitFloat_info(Float_info entry) {
 185  1
         append(entry.getValue());
 186  1
     }
 187  
 
 188  
     public void visitLong_info(Long_info entry) {
 189  0
         append(entry.getValue());
 190  0
     }
 191  
 
 192  
     public void visitDouble_info(Double_info entry) {
 193  0
         append(entry.getValue());
 194  0
     }
 195  
 
 196  
     public void visitNameAndType_info(NameAndType_info entry) {
 197  
         // Do nothing
 198  0
     }
 199  
 
 200  
     public void visitUTF8_info(UTF8_info entry) {
 201  36
         append(escapeXMLCharactersInAttributeValue(entry.getValue()));
 202  36
     }
 203  
 
 204  
     public void visitField_info(Field_info entry) {
 205  58
         if (entry.isPublic())     append(" visibility=\"public\"");
 206  58
         if (entry.isProtected())  append(" visibility=\"protected\"");
 207  58
         if (entry.isPackage())    append(" visibility=\"package\"");
 208  58
         if (entry.isPrivate())    append(" visibility=\"private\"");
 209  58
         if (entry.isStatic())     append(" static=\"yes\"");
 210  58
         if (entry.isFinal())      append(" final=\"yes\"");
 211  58
         if (entry.isVolatile())   append(" volatile=\"yes\"");
 212  58
         if (entry.isTransient())  append(" transient=\"yes\"");
 213  58
         if (entry.isSynthetic())  append(" synthetic=\"yes\"");
 214  58
         if (entry.isDeprecated()) append(" deprecated=\"yes\"");
 215  
 
 216  58
         append(" type=\"").append(entry.getType()).append("\"");
 217  58
         append(" name=\"").append(entry.getName()).append("\"");
 218  58
         append(" signature=\"").append(entry.getSignature()).append("\"");
 219  58
         append(" full-signature=\"").append(entry.getFullSignature()).append("\"");
 220  
 
 221  58
         if (entry.getConstantValue() != null) {
 222  54
             append(" value=\"");
 223  54
             entry.getConstantValue().accept(this);
 224  54
             append("\"");
 225  
         }
 226  58
     }
 227  
 
 228  
     public void visitMethod_info(Method_info entry) {
 229  
         // Do nothing
 230  0
     }
 231  
 
 232  
     public void visitConstantValue_attribute(ConstantValue_attribute attribute) {
 233  54
         attribute.getRawValue().accept(this);
 234  54
     }
 235  
 
 236  
     public void visitCode_attribute(Code_attribute attribute) {
 237  
         // Do nothing
 238  0
     }
 239  
 
 240  
     public void visitExceptions_attribute(Exceptions_attribute attribute) {
 241  
         // Do nothing
 242  0
     }
 243  
 
 244  
     public void visitInnerClasses_attribute(InnerClasses_attribute attribute) {
 245  
         // Do nothing
 246  0
     }
 247  
 
 248  
     public void visitEnclosingMethod_attribute(EnclosingMethod_attribute attribute) {
 249  
         // Do nothing
 250  0
     }
 251  
 
 252  
     public void visitSynthetic_attribute(Synthetic_attribute attribute) {
 253  
         // Do nothing
 254  0
     }
 255  
 
 256  
     public void visitSignature_attribute(Signature_attribute attribute) {
 257  
         // Do nothing
 258  0
     }
 259  
 
 260  
     public void visitSourceFile_attribute(SourceFile_attribute attribute) {
 261  
         // Do nothing
 262  0
     }
 263  
 
 264  
     public void visitSourceDebugExtension_attribute(SourceDebugExtension_attribute attribute) {
 265  
         // Do nothing
 266  0
     }
 267  
 
 268  
     public void visitLineNumberTable_attribute(LineNumberTable_attribute attribute) {
 269  
         // Do nothing
 270  0
     }
 271  
 
 272  
     public void visitLocalVariableTable_attribute(LocalVariableTable_attribute attribute) {
 273  
         // Do nothing
 274  0
     }
 275  
 
 276  
     public void visitLocalVariableTypeTable_attribute(LocalVariableTypeTable_attribute attribute) {
 277  
         // Do nothing
 278  0
     }
 279  
 
 280  
     public void visitDeprecated_attribute(Deprecated_attribute attribute) {
 281  
         // Do nothing
 282  0
     }
 283  
 
 284  
     public void visitRuntimeVisibleAnnotations_attribute(RuntimeVisibleAnnotations_attribute attribute) {
 285  
         // Do nothing
 286  0
     }
 287  
 
 288  
     public void visitRuntimeInvisibleAnnotations_attribute(RuntimeInvisibleAnnotations_attribute attribute) {
 289  
         // Do nothing
 290  0
     }
 291  
 
 292  
     public void visitRuntimeVisibleParameterAnnotations_attribute(RuntimeVisibleParameterAnnotations_attribute attribute) {
 293  
         // Do nothing
 294  0
     }
 295  
 
 296  
     public void visitRuntimeInvisibleParameterAnnotations_attribute(RuntimeInvisibleParameterAnnotations_attribute attribute) {
 297  
         // Do nothing
 298  0
     }
 299  
 
 300  
     public void visitAnnotationDefault_attribute(AnnotationDefault_attribute attribute) {
 301  
         // Do nothing
 302  0
     }
 303  
 
 304  
     public void visitCustom_attribute(Custom_attribute attribute) {
 305  
         // Do nothing
 306  0
     }
 307  
 
 308  
     public void visitInstruction(Instruction instruction) {
 309  
         // Do nothing
 310  0
     }
 311  
 
 312  
     public void visitExceptionHandler(ExceptionHandler helper) {
 313  
         // Do nothing
 314  0
     }
 315  
 
 316  
     public void visitInnerClass(InnerClass helper) {
 317  
         // Do nothing
 318  0
     }
 319  
 
 320  
     public void visitLineNumber(LineNumber helper) {
 321  
         // Do nothing
 322  0
     }
 323  
 
 324  
     public void visitLocalVariable(LocalVariable helper) {
 325  
         // Do nothing
 326  0
     }
 327  
 
 328  
     public void visitLocalVariableType(LocalVariableType helper) {
 329  
         // Do nothing
 330  0
     }
 331  
 
 332  
     public void visitParameter(Parameter helper) {
 333  
         // Do nothing
 334  0
     }
 335  
 
 336  
     public void visitAnnotation(Annotation helper) {
 337  
         // Do nothing
 338  0
     }
 339  
 
 340  
     public void visitElementValuePair(ElementValuePair helper) {
 341  
         // Do nothing
 342  0
     }
 343  
 
 344  
     public void visitByteConstantElementValue(ByteConstantElementValue helper) {
 345  
         // Do nothing
 346  0
     }
 347  
 
 348  
     public void visitCharConstantElementValue(CharConstantElementValue helper) {
 349  
         // Do nothing
 350  0
     }
 351  
 
 352  
     public void visitDoubleConstantElementValue(DoubleConstantElementValue helper) {
 353  
         // Do nothing
 354  0
     }
 355  
 
 356  
     public void visitFloatConstantElementValue(FloatConstantElementValue helper) {
 357  
         // Do nothing
 358  0
     }
 359  
 
 360  
     public void visitIntegerConstantElementValue(IntegerConstantElementValue helper) {
 361  
         // Do nothing
 362  0
     }
 363  
 
 364  
     public void visitLongConstantElementValue(LongConstantElementValue helper) {
 365  
         // Do nothing
 366  0
     }
 367  
 
 368  
     public void visitShortConstantElementValue(ShortConstantElementValue helper) {
 369  
         // Do nothing
 370  0
     }
 371  
 
 372  
     public void visitBooleanConstantElementValue(BooleanConstantElementValue helper) {
 373  
         // Do nothing
 374  0
     }
 375  
 
 376  
     public void visitStringConstantElementValue(StringConstantElementValue helper) {
 377  
         // Do nothing
 378  0
     }
 379  
 
 380  
     public void visitEnumElementValue(EnumElementValue helper) {
 381  
         // Do nothing
 382  0
     }
 383  
 
 384  
     public void visitClassElementValue(ClassElementValue helper) {
 385  
         // Do nothing
 386  0
     }
 387  
 
 388  
     public void visitAnnotationElementValue(AnnotationElementValue helper) {
 389  
         // Do nothing
 390  0
     }
 391  
 
 392  
     public void visitArrayElementValue(ArrayElementValue helper) {
 393  
         // Do nothing
 394  0
     }
 395  
 
 396  
     public String render() {
 397  24
         raiseIndent();
 398  24
         raiseIndent();
 399  
 
 400  24
         indent().append("<class>").eol();
 401  24
         raiseIndent();
 402  
 
 403  24
         indent().append("<name>").append(differences.getName()).append("</name>").eol();
 404  
 
 405  24
         if (differences.isDeclarationModified()) {
 406  2
             indent().append("<modified-declaration>").eol();
 407  2
             raiseIndent();
 408  
 
 409  2
             indent().append("<old-declaration").append(breakdownDeclaration(differences.getOldClass())).append(">").append(differences.getOldDeclaration()).append("</old-declaration>").eol();
 410  2
             indent().append("<new-declaration").append(breakdownDeclaration(differences.getNewClass())).append(">").append(differences.getNewDeclaration()).append("</new-declaration>").eol();
 411  
 
 412  2
             lowerIndent();
 413  2
             indent().append("</modified-declaration>").eol();
 414  
         }
 415  
 
 416  24
         if (removedFields.size() != 0) {
 417  8
             indent().append("<removed-fields>").eol();
 418  8
             raiseIndent();
 419  
 
 420  8
             for (FeatureDifferences fd : removedFields) {
 421  14
                 indent();
 422  14
                 append("<declaration");
 423  14
                 fd.getOldFeature().accept(this);
 424  14
                 if (fd.isInherited()) {
 425  0
                     append(" inherited=\"yes\"");
 426  
                 }
 427  14
                 append(">");
 428  14
                 append(fd.getOldDeclaration());
 429  14
                 append("</declaration>");
 430  14
                 eol();
 431  
             }
 432  
 
 433  8
             lowerIndent();
 434  8
             indent().append("</removed-fields>").eol();
 435  
         }
 436  
 
 437  24
         if (removedConstructors.size() != 0) {
 438  1
             indent().append("<removed-constructors>").eol();
 439  1
             raiseIndent();
 440  
 
 441  1
             for (FeatureDifferences fd : removedConstructors) {
 442  1
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getOldFeature())).append(fd.isInherited() ? " inherited=\"yes\"" : "").append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 443  
             }
 444  
 
 445  1
             lowerIndent();
 446  1
             indent().append("</removed-constructors>").eol();
 447  
         }
 448  
 
 449  24
         if (removedMethods.size() != 0) {
 450  2
             indent().append("<removed-methods>").eol();
 451  2
             raiseIndent();
 452  
 
 453  2
             for (FeatureDifferences fd : removedMethods) {
 454  2
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getOldFeature())).append(fd.isInherited() ? " inherited=\"yes\"" : "").append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 455  
             }
 456  
 
 457  2
             lowerIndent();
 458  2
             indent().append("</removed-methods>").eol();
 459  
         }
 460  
 
 461  24
         if (deprecatedFields.size() != 0) {
 462  2
             indent().append("<deprecated-fields>").eol();
 463  2
             raiseIndent();
 464  
 
 465  2
             for (FeatureDifferences fd : deprecatedFields) {
 466  2
                 indent().append("<declaration").append(breakdownDeclaration((Field_info) fd.getNewFeature())).append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 467  
             }
 468  
 
 469  2
             lowerIndent();
 470  2
             indent().append("</deprecated-fields>").eol();
 471  
         }
 472  
 
 473  24
         if (deprecatedConstructors.size() != 0) {
 474  1
             indent().append("<deprecated-constructors>").eol();
 475  1
             raiseIndent();
 476  
 
 477  1
             for (FeatureDifferences fd : deprecatedConstructors) {
 478  1
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getNewFeature())).append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 479  
             }
 480  
 
 481  1
             lowerIndent();
 482  1
             indent().append("</deprecated-constructors>").eol();
 483  
         }
 484  
 
 485  24
         if (deprecatedMethods.size() != 0) {
 486  2
             indent().append("<deprecated-methods>").eol();
 487  2
             raiseIndent();
 488  
 
 489  2
             for (FeatureDifferences fd : deprecatedMethods) {
 490  2
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getNewFeature())).append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 491  
             }
 492  
 
 493  2
             lowerIndent();
 494  2
             indent().append("</deprecated-methods>").eol();
 495  
         }
 496  
 
 497  24
         if (modifiedFields.size() != 0) {
 498  8
             indent().append("<modified-fields>").eol();
 499  8
             raiseIndent();
 500  
 
 501  8
             for (FieldDifferences fd : modifiedFields) {
 502  15
                 indent().append("<feature>").eol();
 503  15
                 raiseIndent();
 504  
 
 505  15
                 indent().append("<name>").append(fd.getName()).append("</name>").eol();
 506  
 
 507  15
                 indent().append("<modified-declaration>").eol();
 508  15
                 raiseIndent();
 509  
 
 510  15
                 Field_info oldField = (Field_info) fd.getOldFeature();
 511  15
                 indent();
 512  15
                 append("<old-declaration");
 513  15
                 oldField.accept(this);
 514  15
                 append(">");
 515  15
                 if (fd.isConstantValueDifference()) {
 516  14
                     append(escapeXMLCharactersInTagContent(oldField.getFullDeclaration()));
 517  
                 } else {
 518  1
                     append(oldField.getDeclaration());
 519  
                 }
 520  15
                 append("</old-declaration>");
 521  15
                 eol();
 522  
 
 523  15
                 Field_info newField = (Field_info) fd.getNewFeature();
 524  15
                 indent();
 525  15
                 append("<new-declaration");
 526  15
                 newField.accept(this);
 527  15
                 append(">");
 528  15
                 if (fd.isConstantValueDifference()) {
 529  14
                     append(escapeXMLCharactersInTagContent(newField.getFullDeclaration()));
 530  
                 } else {
 531  1
                     append(newField.getDeclaration());
 532  
                 }
 533  15
                 append("</new-declaration>");
 534  15
                 eol();
 535  
 
 536  15
                 lowerIndent();
 537  15
                 indent().append("</modified-declaration>").eol();
 538  
 
 539  15
                 lowerIndent();
 540  15
                 indent().append("</feature>").eol();
 541  15
             }
 542  
 
 543  8
             lowerIndent();
 544  8
             indent().append("</modified-fields>").eol();
 545  
         }
 546  
 
 547  24
         if (modifiedConstructors.size() != 0) {
 548  1
             indent().append("<modified-constructors>").eol();
 549  1
             raiseIndent();
 550  
 
 551  1
             for (CodeDifferences cd : modifiedConstructors) {
 552  2
                 indent().append("<feature>").eol();
 553  2
                 raiseIndent();
 554  
 
 555  2
                 indent().append("<name>").append(cd.getName()).append("</name>").eol();
 556  
 
 557  2
                 if (!cd.getOldDeclaration().equals(cd.getNewDeclaration())) {
 558  1
                     indent().append("<modified-declaration>").eol();
 559  1
                     raiseIndent();
 560  1
                     indent().append("<old-declaration").append(breakdownDeclaration((Method_info) cd.getOldFeature())).append(">").append(cd.getOldDeclaration()).append("</old-declaration>").eol();
 561  1
                     indent().append("<new-declaration").append(breakdownDeclaration((Method_info) cd.getNewFeature())).append(">").append(cd.getNewDeclaration()).append("</new-declaration>").eol();
 562  1
                     lowerIndent();
 563  1
                     indent().append("</modified-declaration>").eol();
 564  
                 }
 565  
 
 566  2
                 if (cd.isCodeDifference()) {
 567  1
                     indent().append("<modified-code").append(breakdownDeclaration((Method_info) cd.getNewFeature())).append(">").append(cd.getNewDeclaration()).append("</modified-code>").eol();
 568  
                 }
 569  
 
 570  2
                 lowerIndent();
 571  2
                 indent().append("</feature>").eol();
 572  
             }
 573  
 
 574  1
             lowerIndent();
 575  1
             indent().append("</modified-constructors>").eol();
 576  
         }
 577  
 
 578  24
         if (modifiedMethods.size() != 0) {
 579  3
             indent().append("<modified-methods>").eol();
 580  3
             raiseIndent();
 581  
 
 582  3
             for (CodeDifferences md : modifiedMethods) {
 583  4
                 indent().append("<feature>").eol();
 584  4
                 raiseIndent();
 585  
 
 586  4
                 indent().append("<name>").append(md.getName()).append("</name>").eol();
 587  
 
 588  4
                 if (!md.getOldDeclaration().equals(md.getNewDeclaration())) {
 589  3
                     indent().append("<modified-declaration>").eol();
 590  3
                     raiseIndent();
 591  3
                     indent().append("<old-declaration").append(breakdownDeclaration((Method_info) md.getOldFeature())).append(">").append(md.getOldDeclaration()).append("</old-declaration>").eol();
 592  3
                     indent().append("<new-declaration").append(breakdownDeclaration((Method_info) md.getNewFeature())).append(">").append(md.getNewDeclaration()).append("</new-declaration>").eol();
 593  3
                     lowerIndent();
 594  3
                     indent().append("</modified-declaration>").eol();
 595  
                 }
 596  
 
 597  4
                 if (md.isCodeDifference()) {
 598  2
                     indent().append("<modified-code").append(breakdownDeclaration((Method_info) md.getNewFeature())).append(">").append(md.getNewDeclaration()).append("</modified-code>").eol();
 599  
                 }
 600  
 
 601  4
                 lowerIndent();
 602  4
                 indent().append("</feature>").eol();
 603  
             }
 604  
 
 605  3
             lowerIndent();
 606  3
             indent().append("</modified-methods>").eol();
 607  
         }
 608  
 
 609  24
         if (undeprecatedFields.size() != 0) {
 610  2
             indent().append("<undeprecated-fields>").eol();
 611  2
             raiseIndent();
 612  
 
 613  2
             for (FeatureDifferences fd : undeprecatedFields) {
 614  2
                 indent().append("<declaration").append(breakdownDeclaration((Field_info) fd.getNewFeature())).append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 615  
             }
 616  
 
 617  2
             lowerIndent();
 618  2
             indent().append("</undeprecated-fields>").eol();
 619  
         }
 620  
 
 621  24
         if (undeprecatedConstructors.size() != 0) {
 622  1
             indent().append("<undeprecated-constructors>").eol();
 623  1
             raiseIndent();
 624  
 
 625  1
             for (FeatureDifferences fd : undeprecatedConstructors) {
 626  1
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getNewFeature())).append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 627  
             }
 628  
 
 629  1
             lowerIndent();
 630  1
             indent().append("</undeprecated-constructors>").eol();
 631  
         }
 632  
 
 633  24
         if (undeprecatedMethods.size() != 0) {
 634  2
             indent().append("<undeprecated-methods>").eol();
 635  2
             raiseIndent();
 636  
 
 637  2
             for (FeatureDifferences fd : undeprecatedMethods) {
 638  2
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getNewFeature())).append(">").append(fd.getOldDeclaration()).append("</declaration>").eol();
 639  
             }
 640  
 
 641  2
             lowerIndent();
 642  2
             indent().append("</undeprecated-methods>").eol();
 643  
         }
 644  
 
 645  24
         if (newFields.size() != 0) {
 646  8
             indent().append("<new-fields>").eol();
 647  8
             raiseIndent();
 648  
 
 649  8
             for (FeatureDifferences fd : newFields) {
 650  14
                 indent();
 651  14
                 append("<declaration");
 652  14
                 fd.getNewFeature().accept(this);
 653  14
                 append(">");
 654  14
                 append(fd.getNewDeclaration());
 655  14
                 append("</declaration>");
 656  14
                 eol();
 657  
             }
 658  
 
 659  8
             lowerIndent();
 660  8
             indent().append("</new-fields>").eol();
 661  
         }
 662  
 
 663  24
         if (newConstructors.size() != 0) {
 664  1
             indent().append("<new-constructors>").eol();
 665  1
             raiseIndent();
 666  
 
 667  1
             for (FeatureDifferences fd : newConstructors) {
 668  1
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getNewFeature())).append(">").append(fd.getNewDeclaration()).append("</declaration>").eol();
 669  
             }
 670  
 
 671  1
             lowerIndent();
 672  1
             indent().append("</new-constructors>").eol();
 673  
         }
 674  
 
 675  24
         if (newMethods.size() != 0) {
 676  3
             indent().append("<new-methods>").eol();
 677  3
             raiseIndent();
 678  
 
 679  3
             for (FeatureDifferences fd : newMethods) {
 680  4
                 indent().append("<declaration").append(breakdownDeclaration((Method_info) fd.getNewFeature())).append(">").append(fd.getNewDeclaration()).append("</declaration>").eol();
 681  
             }
 682  
 
 683  3
             lowerIndent();
 684  3
             indent().append("</new-methods>").eol();
 685  
         }
 686  
 
 687  24
         lowerIndent();
 688  24
         indent().append("</class>").eol();
 689  
 
 690  24
         lowerIndent();
 691  24
         lowerIndent();
 692  
 
 693  24
         return super.toString();
 694  
     }
 695  
 
 696  
     private String breakdownDeclaration(Classfile element) {
 697  4
         StringBuffer result = new StringBuffer();
 698  
 
 699  4
         if (element != null) {
 700  4
             if (element.isPublic())     result.append(" visibility=\"public\"");
 701  4
             if (element.isPackage())    result.append(" visibility=\"package\"");
 702  4
             if (element.isFinal())      result.append(" final=\"yes\"");
 703  4
             if (element.isSuper())      result.append(" super=\"yes\"");
 704  4
             if (element.isSynthetic())  result.append(" synthetic=\"yes\"");
 705  4
             if (element.isDeprecated()) result.append(" deprecated=\"yes\"");
 706  
 
 707  4
             result.append(" name=\"").append(element.getClassName()).append("\"");
 708  
 
 709  4
             if (element.isInterface()) {
 710  2
                 result.append(" interface=\"yes\"");
 711  
 
 712  2
                 result.append(" extends=\"");
 713  2
                 Iterator i = element.getAllInterfaces().iterator();
 714  3
                 while (i.hasNext()) {
 715  1
                     result.append(i.next());
 716  1
                     if (i.hasNext()) {
 717  0
                         result.append(", ");
 718  
                     }
 719  
                 }
 720  2
                 result.append("\"");
 721  2
             } else {
 722  2
                 if (element.isAbstract()) result.append(" abstract=\"yes\"");
 723  
 
 724  2
                 result.append(" extends=\"").append(element.getSuperclassName()).append("\"");
 725  
 
 726  2
                 result.append(" implements=\"");
 727  2
                 Iterator i = element.getAllInterfaces().iterator();
 728  3
                 while (i.hasNext()) {
 729  1
                     result.append(i.next());
 730  1
                     if (i.hasNext()) {
 731  0
                         result.append(", ");
 732  
                     }
 733  
                 }
 734  2
                 result.append("\"");
 735  
             }
 736  
         }
 737  
 
 738  4
         return result.toString();
 739  
     }
 740  
 
 741  
     private String breakdownDeclaration(Field_info element) {
 742  4
         StringBuffer result = new StringBuffer();
 743  
 
 744  4
         if (element != null) {
 745  4
             if (element.isPublic())     result.append(" visibility=\"public\"");
 746  4
             if (element.isProtected())  result.append(" visibility=\"protected\"");
 747  4
             if (element.isPackage())    result.append(" visibility=\"package\"");
 748  4
             if (element.isPrivate())    result.append(" visibility=\"private\"");
 749  4
             if (element.isStatic())     result.append(" static=\"yes\"");
 750  4
             if (element.isFinal())      result.append(" final=\"yes\"");
 751  4
             if (element.isVolatile())   result.append(" volatile=\"yes\"");
 752  4
             if (element.isTransient())  result.append(" transient=\"yes\"");
 753  4
             if (element.isSynthetic())  result.append(" synthetic=\"yes\"");
 754  4
             if (element.isDeprecated()) result.append(" deprecated=\"yes\"");
 755  
 
 756  4
             result.append(" type=\"").append(element.getType()).append("\"");
 757  4
             result.append(" name=\"").append(element.getName()).append("\"");
 758  4
             result.append(" signature=\"").append(element.getSignature()).append("\"");
 759  4
             result.append(" full-signature=\"").append(element.getFullSignature()).append("\"");
 760  
 
 761  4
             if (element.getConstantValue() != null) {
 762  2
                 result.append(" value=\"").append(element.getConstantValue().getRawValue()).append("\"");
 763  
             }
 764  
         }
 765  
 
 766  4
         return result.toString();
 767  
     }
 768  
 
 769  
     private String breakdownDeclaration(Method_info element) {
 770  25
         StringBuffer result = new StringBuffer();
 771  
 
 772  25
         if (element != null) {
 773  25
             if (element.isPublic())       result.append(" visibility=\"public\"");
 774  25
             if (element.isProtected())    result.append(" visibility=\"protected\"");
 775  25
             if (element.isPackage())      result.append(" visibility=\"package\"");
 776  25
             if (element.isPrivate())      result.append(" visibility=\"private\"");
 777  25
             if (element.isStatic())       result.append(" static=\"yes\"");
 778  25
             if (element.isFinal())        result.append(" final=\"yes\"");
 779  25
             if (element.isSynchronized()) result.append(" synchronized=\"yes\"");
 780  25
             if (element.isNative())       result.append(" native=\"yes\"");
 781  25
             if (element.isAbstract())     result.append(" abstract=\"yes\"");
 782  25
             if (element.isStrict())       result.append(" strict=\"yes\"");
 783  25
             if (element.isSynthetic())    result.append(" synthetic=\"yes\"");
 784  25
             if (element.isDeprecated())   result.append(" deprecated=\"yes\"");
 785  
 
 786  25
             if (!element.getName().equals("<init>") && !element.getName().equals("<clinit>")) {
 787  18
                 result.append(" return-type=\"").append(element.getReturnType()).append("\"");
 788  
             }
 789  
 
 790  25
             result.append(" signature=\"").append(element.getSignature()).append("\"");
 791  25
             result.append(" full-signature=\"").append(element.getFullSignature()).append("\"");
 792  
 
 793  25
             result.append(" throws=\"");
 794  25
             Iterator i = element.getExceptions().iterator();
 795  25
             while (i.hasNext()) {
 796  0
                 result.append(i.next());
 797  0
                 if (i.hasNext()) {
 798  0
                     result.append(", ");
 799  
                 }
 800  
             }
 801  25
             result.append("\"");
 802  
         }
 803  
 
 804  25
         return result.toString();
 805  
     }
 806  
 
 807  
     public int compareTo(Object other) {
 808  
         int result;
 809  
 
 810  4
         if (other instanceof ClassReport) {
 811  4
             result = differences.compareTo(((ClassReport) other).differences);
 812  
         } else {
 813  0
             throw new ClassCastException("Unable to compare ClassReport to " + other.getClass().getName());
 814  
         }
 815  
 
 816  4
         return result;
 817  
     }
 818  
 
 819  
     private String escapeXMLCharactersInTagContent(String text) {
 820  64
         String result = text;
 821  
 
 822  64
         result = perl.substitute("s/&/&amp;/g", result);
 823  64
         result = perl.substitute("s/</&lt;/g", result);
 824  64
         result = perl.substitute("s/>/&gt;/g", result);
 825  
 
 826  64
         return result;
 827  
     }
 828  
 
 829  
     private String escapeXMLCharactersInAttributeValue(String text) {
 830  36
         String result = escapeXMLCharactersInTagContent(text);
 831  
 
 832  36
         result = perl.substitute("s/\"/&quot;/g", result);
 833  36
         result = perl.substitute("s/'/&apos;/g", result);
 834  
 
 835  36
         return result;
 836  
     }
 837  
 }