Clover coverage report - Dependency Finder
Coverage timestamp: Mon Nov 29 2010 15:00:50 PST
file stats: LOC: 244   Methods: 6
NCLOC: 150   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DifferencesFactory.java 95% 98% 100% 97.2%
coverage coverage
 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.log4j.*;
 38   
 39    import com.jeantessier.classreader.*;
 40   
 41    public class DifferencesFactory {
 42    private Classfile oldClass;
 43    private Classfile newClass;
 44   
 45    private DifferenceStrategy strategy;
 46   
 47    /**
 48    * For tests only.
 49    */
 50  36 DifferencesFactory() {
 51  36 this(new APIDifferenceStrategy(new CodeDifferenceStrategy()));
 52    }
 53   
 54  60 public DifferencesFactory(DifferenceStrategy strategy) {
 55  60 this.strategy = strategy;
 56    }
 57   
 58  36 public Differences createProjectDifferences(String name, String oldVersion, PackageMapper oldPackages, String newVersion, PackageMapper newPackages) {
 59  36 Logger.getLogger(getClass()).debug("Begin " + name + " (" + oldVersion + " -> " + newVersion + ")");
 60   
 61  36 ProjectDifferences projectDifferences = new ProjectDifferences(name, oldVersion, newVersion);
 62   
 63  36 Logger.getLogger(getClass()).debug(" Collecting packages ...");
 64   
 65  36 Collection<String> packageNames = new TreeSet<String>();
 66  36 packageNames.addAll(oldPackages.getPackageNames());
 67  36 packageNames.addAll(newPackages.getPackageNames());
 68   
 69  36 Logger.getLogger(getClass()).debug(" Diff'ing packages ...");
 70   
 71  36 for (String packageName : packageNames) {
 72  133 Map<String, Classfile> oldPackage = oldPackages.getPackage(packageName);
 73  133 if (oldPackage == null) {
 74  33 oldPackage = Collections.emptyMap();
 75    }
 76   
 77  133 Map<String, Classfile> newPackage = newPackages.getPackage(packageName);
 78  133 if (newPackage == null) {
 79  33 newPackage = Collections.emptyMap();
 80    }
 81   
 82  133 if (strategy.isPackageDifferent(oldPackage, newPackage)) {
 83  95 projectDifferences.getPackageDifferences().add(createPackageDifferences(packageName, oldPackage, newPackage));
 84    }
 85    }
 86   
 87  36 Logger.getLogger(getClass()).debug("End " + name + " (" + oldVersion + " -> " + newVersion + ")");
 88   
 89  36 return projectDifferences;
 90    }
 91   
 92  95 public Differences createPackageDifferences(String name, Map<String, Classfile> oldPackage, Map<String, Classfile> newPackage) {
 93  95 Logger.getLogger(getClass()).debug("Begin " + name);
 94   
 95  95 PackageDifferences packageDifferences = new PackageDifferences(name, oldPackage, newPackage);
 96   
 97  95 if (oldPackage != null && !oldPackage.isEmpty() && newPackage != null && !newPackage.isEmpty()) {
 98  33 Logger.getLogger(getClass()).debug(" Diff'ing classes ...");
 99   
 100  33 Collection<String> classNames = new TreeSet<String>();
 101  33 classNames.addAll(oldPackage.keySet());
 102  33 classNames.addAll(newPackage.keySet());
 103   
 104  33 for (String className : classNames) {
 105  417 Classfile oldClass = oldPackage.get(className);
 106  417 Classfile newClass = newPackage.get(className);
 107   
 108  417 if (strategy.isClassDifferent(oldClass, newClass)) {
 109  405 packageDifferences.getClassDifferences().add(createClassDifferences(className, oldClass, newClass));
 110    }
 111    }
 112   
 113  33 Logger.getLogger(getClass()).debug(" " + name + " has " + packageDifferences.getClassDifferences().size() + " class(es) that changed.");
 114    }
 115   
 116  95 Logger.getLogger(getClass()).debug("End " + name);
 117   
 118  95 return packageDifferences;
 119    }
 120   
 121  425 public Differences createClassDifferences(String name, Classfile oldClass, Classfile newClass) {
 122  425 Logger.getLogger(getClass()).debug("Begin " + name);
 123   
 124  425 ClassDifferences classDifferences;
 125  425 if (((oldClass != null) && oldClass.isInterface()) || ((newClass != null) && newClass.isInterface())) {
 126  192 classDifferences = new InterfaceDifferences(name, oldClass, newClass);
 127    } else {
 128  233 classDifferences = new ClassDifferences(name, oldClass, newClass);
 129    }
 130   
 131  425 if (!classDifferences.isRemoved() && !classDifferences.isNew() && strategy.isDeclarationModified(oldClass, newClass)) {
 132  62 classDifferences.setDeclarationModified(true);
 133    }
 134   
 135  425 Differences result = classDifferences;
 136   
 137  425 this.oldClass = oldClass;
 138  425 this.newClass = newClass;
 139   
 140  425 if (oldClass != null && newClass != null) {
 141  301 Logger.getLogger(getClass()).debug(" Collecting fields ...");
 142   
 143  301 Map<String, String> fieldLevel = new TreeMap<String, String>();
 144   
 145  301 for (Field_info field : oldClass.getAllFields()) {
 146  1069 fieldLevel.put(field.getName(), field.getFullSignature());
 147    }
 148   
 149  301 for (Field_info field : newClass.getAllFields()) {
 150  1069 fieldLevel.put(field.getName(), field.getFullSignature());
 151    }
 152   
 153  301 Logger.getLogger(getClass()).debug(" Diff'ing fields ...");
 154   
 155  301 for (Map.Entry<String, String> fieldEntry : fieldLevel.entrySet()) {
 156  1421 Field_info oldField = oldClass.getField(fieldEntry.getKey());
 157  1421 Field_info newField = newClass.getField(fieldEntry.getKey());
 158   
 159  1421 if (strategy.isFieldDifferent(oldField, newField)) {
 160  1195 classDifferences.getFeatureDifferences().add(createFeatureDifferences(fieldEntry.getValue(), oldField, newField));
 161    }
 162    }
 163   
 164  301 Logger.getLogger(getClass()).debug(" Collecting methods ...");
 165   
 166  301 Map<String, String> methodLevel = new TreeMap<String, String>();
 167   
 168  301 for (Method_info method : oldClass.getAllMethods()) {
 169  1042 methodLevel.put(method.getSignature(), method.getFullSignature());
 170    }
 171   
 172  301 for (Method_info method : newClass.getAllMethods()) {
 173  1104 methodLevel.put(method.getSignature(), method.getFullSignature());
 174    }
 175   
 176  301 Logger.getLogger(getClass()).debug(" Diff'ing methods ...");
 177   
 178  301 for (Map.Entry<String, String> methodEntry : methodLevel.entrySet()) {
 179  1231 Method_info oldMethod = oldClass.getMethod(methodEntry.getKey());
 180  1231 Method_info newMethod = newClass.getMethod(methodEntry.getKey());
 181   
 182  1231 if (strategy.isMethodDifferent(oldMethod, newMethod)) {
 183  742 classDifferences.getFeatureDifferences().add(createFeatureDifferences(methodEntry.getValue(), oldMethod, newMethod));
 184    }
 185    }
 186   
 187  301 Logger.getLogger(getClass()).debug(name + " has " + classDifferences.getFeatureDifferences().size() + " feature(s) that changed.");
 188   
 189  301 if (oldClass.isDeprecated() != newClass.isDeprecated()) {
 190  124 result = new DeprecatableDifferences(result, oldClass, newClass);
 191    }
 192    }
 193   
 194  425 Logger.getLogger(getClass()).debug("End " + name);
 195   
 196  425 return result;
 197    }
 198   
 199  1937 public Differences createFeatureDifferences(String name, Feature_info oldFeature, Feature_info newFeature) {
 200  1937 Logger.getLogger(getClass()).debug("Begin " + name);
 201   
 202  1937 FeatureDifferences featureDifferences;
 203  1937 if (oldFeature instanceof Field_info || newFeature instanceof Field_info) {
 204  1195 featureDifferences = new FieldDifferences(name, (Field_info) oldFeature, (Field_info) newFeature);
 205   
 206  1195 if (!featureDifferences.isRemoved() && !featureDifferences.isNew() && strategy.isConstantValueDifferent(((Field_info) oldFeature).getConstantValue(), ((Field_info) newFeature).getConstantValue())) {
 207  282 ((FieldDifferences) featureDifferences).setConstantValueDifference(true);
 208    }
 209   
 210  1195 if (featureDifferences.isRemoved() && newClass.locateField(name) != null) {
 211  0 featureDifferences.setInherited(true);
 212    }
 213    } else {
 214  742 if (((oldFeature instanceof Method_info) && ((Method_info) oldFeature).isConstructor()) || ((newFeature instanceof Method_info) && ((Method_info) newFeature).isConstructor())) {
 215  248 featureDifferences = new ConstructorDifferences(name, (Method_info) oldFeature, (Method_info) newFeature);
 216    } else {
 217  494 featureDifferences = new MethodDifferences(name, (Method_info) oldFeature, (Method_info) newFeature);
 218    }
 219   
 220  742 if (!featureDifferences.isRemoved() && !featureDifferences.isNew() && strategy.isCodeDifferent(((Method_info) oldFeature).getCode(), ((Method_info) newFeature).getCode())) {
 221  108 ((CodeDifferences) featureDifferences).setCodeDifference(true);
 222    }
 223   
 224  742 if (featureDifferences.isRemoved()) {
 225  125 Method_info attempt = newClass.locateMethod(name);
 226  125 if ((attempt != null) && (oldFeature.getClassfile().isInterface() == attempt.getClassfile().isInterface())) {
 227  0 featureDifferences.setInherited(true);
 228    }
 229    }
 230    }
 231   
 232  1937 Differences result = featureDifferences;
 233   
 234  1937 if (oldFeature != null && newFeature != null) {
 235  975 if (oldFeature.isDeprecated() != newFeature.isDeprecated()) {
 236  396 result = new DeprecatableDifferences(result, oldFeature, newFeature);
 237    }
 238    }
 239   
 240  1937 Logger.getLogger(getClass()).debug("End " + name);
 241   
 242  1937 return result;
 243    }
 244    }