EMMA Coverage Report (generated Mon Nov 29 14:43:38 PST 2010)
[all classes][com.jeantessier.diff]

COVERAGE SUMMARY FOR SOURCE FILE [DifferencesFactory.java]

nameclass, %method, %block, %line, %
DifferencesFactory.java100% (1/1)100% (6/6)98%  (696/710)98%  (100.5/103)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DifferencesFactory100% (1/1)100% (6/6)98%  (696/710)98%  (100.5/103)
createFeatureDifferences (String, Feature_info, Feature_info): Differences 100% (1/1)91%  (150/164)89%  (19.5/22)
DifferencesFactory (): void 100% (1/1)100% (9/9)100% (2/2)
DifferencesFactory (DifferenceStrategy): void 100% (1/1)100% (6/6)100% (3/3)
createClassDifferences (String, Classfile, Classfile): Differences 100% (1/1)100% (294/294)100% (41/41)
createPackageDifferences (String, Map, Map): Differences 100% (1/1)100% (118/118)100% (16/16)
createProjectDifferences (String, String, PackageMapper, String, PackageMappe... 100% (1/1)100% (119/119)100% (19/19)

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

[all classes][com.jeantessier.diff]
EMMA 2.0.5312 (C) Vladimir Roubtsov