KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > uka > ipd > coverage > natures > all_uses > UsesCoverage


1 /*
2  * Created on Apr 21, 2005
3  *
4  * written by Matthias Kempka
5  */

6 package de.uka.ipd.coverage.natures.all_uses;
7
8 import java.util.*;
9
10 import org.apache.bcel.classfile.LineNumberTable;
11 import org.apache.bcel.classfile.Method;
12
13 /**
14  * Created on Apr 21, 2005
15  * Data holding object to define the Uses of a DefinitionFreePath.
16  * @author Matthias Kempka
17  */

18 public class UsesCoverage {
19
20     // contains Integer objects pointing to sourceCode positions.
21
private ArrayList coveredUses = new ArrayList();
22     // contains Integer objects pointing to sourceCode positions.
23
private ArrayList uncoveredUses = new ArrayList();
24     private DefinitionFreePath dfp;
25     
26     public UsesCoverage(DefinitionFreePath dfp) {
27         this.dfp = dfp;
28     }
29     
30     public void addCoveredUsesByteCodePositions(Integer JavaDoc[] byteCodePositions) {
31         List byteCodeList = Arrays.asList(byteCodePositions);
32         this.coveredUses.addAll(getSourceLineNumbers(byteCodeList));
33     }
34     
35     public void addUncoveredUsesByteCodePositions(Integer JavaDoc[] byteCodePositions) {
36         List byteCodeList = Arrays.asList(byteCodePositions);
37         this.uncoveredUses.addAll(getSourceLineNumbers(byteCodeList));
38     }
39     
40     
41     /**
42      * @return returns the sourcecode line numbers of covered uses.
43      */

44     public int[] getCoveredUsesSourceLineNumbers() {
45         return convertToIntArray(coveredUses);
46     }
47
48     /**
49      * @return returns the sourcecode line numbers of covered uses.
50      */

51     public int[] getUncoveredUsesSourceLineNumbers() {
52         return convertToIntArray(uncoveredUses);
53     }
54     
55     private int[] convertToIntArray(List sourceLineList) {
56         int[] result = new int[sourceLineList.size()];
57         for (int i = 0; i < result.length; i++) {
58             result[i] = ((Integer JavaDoc) sourceLineList.get(i)).intValue();
59         }
60         return result;
61     }
62
63     /**
64      * translates a list containing bytecode positions to source code
65      * line numbers.
66      * @param byteCodePositions
67      * @return returns an array with source code line numbers.
68      */

69     private List getSourceLineNumbers(List byteCodePositions) {
70         LineNumberTable lnt = dfp.getRegisteredMethod().getMethod().getLineNumberTable();
71         List result = new ArrayList(byteCodePositions.size());
72         for (Iterator iter = byteCodePositions.iterator(); iter.hasNext();) {
73             Integer JavaDoc byteCodePos = (Integer JavaDoc) iter.next();
74             int sourcecodeLine = lnt.getSourceLine(byteCodePos.intValue());
75             result.add(new Integer JavaDoc(sourcecodeLine));
76         }
77         return result;
78     }
79
80     /**
81      * this method merges to the following conditions:<br>
82      * if a value is only in one of inventory or additionalUses its coverage stays as it is.<br>
83      * if a value is covered in one of inventory or additionalUses it stays covered no matter
84      * what the other UsesCoverage says.<br>
85      * if a value is uncovered in both inventory and additionalUses it stays uncovered.<br>
86      * if a value is contained more than once by one of inventory or additionalUses it
87      * will be carried over with the larger number of containments.
88      * @param inventory
89      * @param additionalUses
90      * @return returns a new UsesCoverage instance with the two given uses
91      * merged together.
92      */

93     public static UsesCoverage merge(UsesCoverage inventory, UsesCoverage additionalUses) {
94 //System.out.println(" Mergin uses: " + inventory + " and " + additionalUses);
95
if (!inventory.dfp.hasSameDefinitionAs(additionalUses.dfp)
96                 /* there is one case where the same definition takes place
97                  * at different places in the bytecode. this is the case
98                  * with instance variables. Those are instanciated at the
99                  * beginning of each constructor, right after the call
100                  * of the super constructor. If this is the case here,
101                  * it is ok to have different definitions, so we don't throw
102                  * an exception.
103                  */

104                 && !referenceDifferentConstructors(inventory.dfp, additionalUses.dfp)) {
105             throw new AssertionError JavaDoc(" Cannot merge Uses with different definitions. Requested merging of " + inventory.toString() + " and " + additionalUses ); //$NON-NLS-1$ //$NON-NLS-2$
106
}
107         UsesCoverage result = new UsesCoverage(inventory.dfp);
108         List addUsesCovered = (List) additionalUses.coveredUses.clone();
109         List addUsesUncovered = (List) additionalUses.uncoveredUses.clone();
110         List invUsesCovered = (List) inventory.coveredUses.clone();
111         List invUsesUncovered = (List) inventory.uncoveredUses.clone();
112
113         while (invUsesCovered.size() > 0) {
114             Object JavaDoc line = invUsesCovered.get(0);
115             addUsesCovered.remove(line);
116             addUsesUncovered.remove(line);
117             invUsesUncovered.remove(line);
118             invUsesCovered.remove(0);
119             result.coveredUses.add(line);
120         }
121         
122         while (addUsesCovered.size() > 0) {
123             Object JavaDoc line = addUsesCovered.get(0);
124             invUsesUncovered.remove(line);
125             addUsesUncovered.remove(line);
126             addUsesCovered.remove(0);
127             result.coveredUses.add(line);
128         }
129         
130         while (addUsesUncovered.size() > 0) {
131             Object JavaDoc line = addUsesUncovered.get(0);
132             invUsesUncovered.remove(line);
133             addUsesUncovered.remove(0);
134             result.uncoveredUses.add(line);
135         }
136         
137         for (Iterator iter = invUsesUncovered.iterator(); iter.hasNext();) {
138             result.uncoveredUses.add(iter.next());
139         }
140         return result;
141     }
142     
143     /**
144      * @param dfp2
145      * @param dfp3
146      * @return returns true if both dfp2 and dfp3 are paths in a constructor
147      * but the constructors are not the same.
148      */

149     private static boolean referenceDifferentConstructors(DefinitionFreePath dfp2, DefinitionFreePath dfp3) {
150         Method method2 = dfp2.getRegisteredMethod().getMethod();
151         Method method3 = dfp3.getRegisteredMethod().getMethod();
152         String JavaDoc constructorName = "<init>"; //$NON-NLS-1$
153
if (constructorName.equals(method2.getName())
154                 && constructorName.equals(method3.getName())) {
155             if (method2 != method3) {
156                 return true;
157             }
158         }
159         return false;
160     }
161
162     public String JavaDoc toString() {
163         String JavaDoc result = " def (" + dfp.getDefinition() + "), covered uses ("; //$NON-NLS-1$ //$NON-NLS-2$
164
for (Iterator iter = coveredUses.iterator(); iter.hasNext();) {
165             Integer JavaDoc element = (Integer JavaDoc) iter.next();
166             result = result + " " + element.toString(); //$NON-NLS-1$
167
}
168         result = result + "), uncovered uses ("; //$NON-NLS-1$
169
for (Iterator iter = uncoveredUses.iterator(); iter.hasNext();) {
170             Integer JavaDoc element = (Integer JavaDoc) iter.next();
171             result = result + " " + element.toString(); //$NON-NLS-1$
172
}
173         result = result + ");"; //$NON-NLS-1$
174
return result;
175     }
176 }
177
Popular Tags