KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > junit > ClassMap


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.junit;
21
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.MethodTree;
24 import com.sun.source.tree.Tree;
25 import com.sun.source.util.TreePath;
26 import com.sun.source.util.Trees;
27 import java.util.ArrayList JavaDoc;
28 import java.util.List JavaDoc;
29 import javax.lang.model.element.AnnotationMirror;
30 import javax.lang.model.element.Element;
31 import javax.lang.model.element.ElementKind;
32 import javax.lang.model.element.Name;
33 import javax.lang.model.element.TypeElement;
34
35 /**
36  * Data structure that holds overview of class' members and their positions
37  * within the class.
38  * <p>To get an instance for a class, use static method
39  * {@link #forClass}.</p>
40  *
41  * @author Marian Petras
42  */

43 final class ClassMap {
44     
45     private static final int SETUP_POS_INDEX = 0;
46     private static final int TEARDOWN_POS_INDEX = 1;
47     private static final int FIRST_METHOD_POS_INDEX = 2;
48     private static final int LAST_INIT_POS_INDEX = 3;
49     private static final int FIRST_NESTED_POS_INDEX = 4;
50     private static final int BEFORE_POS_INDEX = 5;
51     private static final int AFTER_POS_INDEX = 6;
52     private static final int BEFORE_CLASS_POS_INDEX = 7;
53     private static final int AFTER_CLASS_POS_INDEX = 8;
54     
55     private static final String JavaDoc JUNIT4_PKG_PREFIX = "org.junit."; //NOI18N
56

57     /**
58      */

59     private final List JavaDoc<String JavaDoc> signatures;
60     /** */
61     private final int[] positions;
62     
63     /** Creates a new instance of ClassMap */
64     private ClassMap(List JavaDoc<String JavaDoc> signatures) {
65         this.signatures = signatures;
66     }
67     
68     {
69         positions = new int[9];
70         for (int i = 0; i < positions.length; i++) {
71             positions[i] = -1;
72         }
73     }
74     
75     /**
76      *
77      * @exception java.lang.IllegalArgumentException
78      * if any of the arguments is {@code null}
79      * or if the specified {@code ClassTree} is not a leaf
80      * of the specified {@code TreePath}
81      */

82     static ClassMap forClass(ClassTree cls, TreePath clsTreePath,
83                              Trees trees) {
84         if (cls == null) {
85             throw new IllegalArgumentException JavaDoc("ClassTree: null"); //NOI18N
86
}
87         if (clsTreePath == null) {
88             throw new IllegalArgumentException JavaDoc("TreePath: null"); //NOI18N
89
}
90         if (clsTreePath.getLeaf() != cls) {
91             throw new IllegalArgumentException JavaDoc(
92                   "given ClassTree is not leaf of the given TreePath"); //NOI18N
93
}
94         
95         List JavaDoc<? extends Tree> members = cls.getMembers();
96         if (members.isEmpty()) {
97             return new ClassMap(new ArrayList JavaDoc<String JavaDoc>());
98         }
99
100         List JavaDoc<String JavaDoc> entries = new ArrayList JavaDoc<String JavaDoc>(members.size());
101         ClassMap map = new ClassMap(entries);
102
103         int index = 0;
104         for (Tree member : members) {
105             String JavaDoc signature;
106             switch (member.getKind()) {
107                 case BLOCK:
108                     signature = "* "; //NOI18N
109
map.setLastInitializerIndex(index);
110                     break;
111                 case VARIABLE:
112                     signature = "- "; //NOI18N
113
break;
114                 case CLASS:
115                     signature = "[ "; //NOI18N
116
if (map.getFirstNestedClassIndex() == -1) {
117                         map.setFirstNestedClassIndex(index);
118                     }
119                     break;
120                 case METHOD:
121                     MethodTree method = (MethodTree) member;
122                     boolean hasParams = !method.getParameters().isEmpty();
123                     Name methodName = method.getName();
124                     if (methodName.contentEquals("<init>")) { //NOI18N
125
signature = hasParams ? "*+" : "* "; //NOI18N
126
map.setLastInitializerIndex(index);
127                     } else {
128                         if (!hasParams) {
129                             if ((map.getSetUpIndex() == -1)
130                                     && methodName.contentEquals("setUp")) { //NOI18N
131
map.setSetUpIndex(index);
132                             }
133                             if ((map.getTearDownIndex() == -1)
134                                     && methodName.contentEquals("tearDown")) { //NOI18N
135
map.setTearDownIndex(index);
136                             }
137                         }
138                         signature = (hasParams ? "!+" : "! ") //NOI18N
139
+ methodName.toString();
140                         if (map.getFirstMethodIndex() == -1) {
141                             map.setFirstMethodIndex(index);
142                         }
143                         
144                         /* annotations: */
145                         if (!method.getModifiers().getAnnotations().isEmpty()) {
146                             TreePath methodTreePath = new TreePath(clsTreePath,
147                                                                    method);
148                             Element methodElement = trees.getElement(methodTreePath);
149                             for (AnnotationMirror annMirror : methodElement.getAnnotationMirrors()) {
150                                 Element annElem = annMirror.getAnnotationType().asElement();
151                                 assert annElem.getKind() == ElementKind.ANNOTATION_TYPE;
152                                 assert annElem instanceof TypeElement;
153                                 String JavaDoc fullName = ((TypeElement) annElem).getQualifiedName().toString();
154                                 if (fullName.startsWith(JUNIT4_PKG_PREFIX)) {
155                                     String JavaDoc shortName = fullName.substring(JUNIT4_PKG_PREFIX.length());
156                                     int posIndex;
157                                     if (shortName.equals("Before")) { //NOI18N
158
posIndex = BEFORE_POS_INDEX;
159                                     } else if (shortName.equals("After")) { //NOI18N
160
posIndex = AFTER_POS_INDEX;
161                                     } else if (shortName.equals("BeforeClass")) { //NOI18N
162
posIndex = BEFORE_CLASS_POS_INDEX;
163                                     } else if (shortName.equals("AfterClass")) { //NOI18N
164
posIndex = AFTER_CLASS_POS_INDEX;
165                                     } else {
166                                         continue; //next annotation
167
}
168                                     
169                                     if (map.positions[posIndex] == -1) {
170                                         map.positions[posIndex] = index;
171                                     }
172                                 }
173                             }
174                         }
175                     }
176                     break;
177                 default:
178                     signature = "x "; //NOI18N
179
}
180             entries.add(signature);
181             index++;
182         }
183         
184         return map;
185     }
186     
187     /**
188      */

189     int getSetUpIndex() {
190         return positions[SETUP_POS_INDEX];
191     }
192     
193     /**
194      */

195     private void setSetUpIndex(int setUpIndex) {
196         positions[SETUP_POS_INDEX] = setUpIndex;
197     }
198     
199     /**
200      */

201     int getTearDownIndex() {
202         return positions[TEARDOWN_POS_INDEX];
203     }
204     
205     /**
206      */

207     private void setTearDownIndex(int tearDownIndex) {
208         positions[TEARDOWN_POS_INDEX] = tearDownIndex;
209     }
210     
211     /**
212      * Returns an index of a method annotated with annotation
213      * {@code org.junit.Before}. If there are more such methods
214      * index of any of these methods may be returned.
215      *
216      * @return index of a {@code @Before}-annotated method,
217      * or {@code -1} if there is no such method
218      */

219     int getBeforeIndex() {
220         return positions[BEFORE_POS_INDEX];
221     }
222     
223     /**
224      */

225     private void setBeforeIndex(int index) {
226         positions[BEFORE_POS_INDEX] = index;
227     }
228     
229     /**
230      * Returns an index of a method annotated with annotation
231      * {@code org.junit.After}. If there are more such methods
232      * index of any of these methods may be returned.
233      *
234      * @return index of a {@code @After}-annotated method,
235      * or {@code -1} if there is no such method
236      */

237     int getAfterIndex() {
238         return positions[AFTER_POS_INDEX];
239     }
240     
241     /**
242      */

243     private void setAfterIndex(int index) {
244         positions[AFTER_POS_INDEX] = index;
245     }
246     
247     /**
248      * Returns an index of a method annotated with annotation
249      * {@code org.junit.BeforeClass}. If there are more such methods
250      * index of any of these methods may be returned.
251      *
252      * @return index of a {@code @BeforeClass}-annotated method,
253      * or {@code -1} if there is no such method
254      */

255     int getBeforeClassIndex() {
256         return positions[BEFORE_CLASS_POS_INDEX];
257     }
258     
259     /**
260      */

261     private void setBeforeClassIndex(int index) {
262         positions[BEFORE_CLASS_POS_INDEX] = index;
263     }
264     
265     /**
266      * Returns an index of a method annotated with annotation
267      * {@code org.junit.AfterClass}. If there are more such methods
268      * index of any of these methods may be returned.
269      *
270      * @return index of a {@code @AfterClass}-annotated method,
271      * or {@code -1} if there is no such method
272      */

273     int getAfterClassIndex() {
274         return positions[AFTER_CLASS_POS_INDEX];
275     }
276     
277     /**
278      */

279     private void setAfterClassIndex(int index) {
280         positions[AFTER_CLASS_POS_INDEX] = index;
281     }
282     
283     /**
284      */

285     int getFirstMethodIndex() {
286         return positions[FIRST_METHOD_POS_INDEX];
287     }
288     
289     /**
290      */

291     private void setFirstMethodIndex(int firstMethodIndex) {
292         positions[FIRST_METHOD_POS_INDEX] = firstMethodIndex;
293     }
294     
295     /**
296      */

297     int getFirstNestedClassIndex() {
298         return positions[FIRST_NESTED_POS_INDEX];
299     }
300     
301     /**
302      */

303     private void setFirstNestedClassIndex(int firstNestedClassIndex) {
304         positions[FIRST_NESTED_POS_INDEX] = firstNestedClassIndex;
305     }
306     
307     /**
308      */

309     int getLastInitializerIndex() {
310         return positions[LAST_INIT_POS_INDEX];
311     }
312     
313     /**
314      */

315     private void setLastInitializerIndex(int lastInitializerIndex) {
316         positions[LAST_INIT_POS_INDEX] = lastInitializerIndex;
317     }
318     
319     /**
320      */

321     boolean containsSetUp() {
322         return getSetUpIndex() != -1;
323     }
324     
325     /**
326      */

327     boolean containsTearDown() {
328         return getTearDownIndex() != -1;
329     }
330     
331     /**
332      */

333     boolean containsBefore() {
334         return getBeforeIndex() != -1;
335     }
336     
337     /**
338      */

339     boolean containsAfter() {
340         return getAfterIndex() != -1;
341     }
342     
343     /**
344      */

345     boolean containsBeforeClass() {
346         return getBeforeClassIndex() != -1;
347     }
348     
349     /**
350      */

351     boolean containsAfterClass() {
352         return getAfterClassIndex() != -1;
353     }
354     
355     /**
356      */

357     boolean containsNoArgMethod(String JavaDoc name) {
358         return findNoArgMethod(name) != -1;
359     }
360     
361     /**
362      */

363     boolean containsMethods() {
364         return getFirstMethodIndex() != -1;
365     }
366     
367     /**
368      */

369     boolean containsInitializers() {
370         return getLastInitializerIndex() != -1;
371     }
372     
373     /**
374      */

375     boolean containsNestedClasses() {
376         return getFirstNestedClassIndex() != -1;
377     }
378     
379     /**
380      */

381     int findNoArgMethod(String JavaDoc name) {
382         if (!containsMethods()) {
383             return -1;
384         }
385         if (name.equals("setUp")) { //NOI18N
386
return getSetUpIndex();
387         }
388         if (name.equals("tearDown")) { //NOI18N
389
return getTearDownIndex();
390         }
391         
392         return signatures.indexOf("! " + name); //NOI18N
393
}
394     
395     /**
396      */

397     void addNoArgMethod(String JavaDoc name) {
398         addNoArgMethod(name, size());
399     }
400     
401     /**
402      */

403     void addNoArgMethod(String JavaDoc name, int index) {
404         int currSize = size();
405         
406         if (index > currSize) {
407             throw new IndexOutOfBoundsException JavaDoc("index: " + index //NOI18N
408
+ ", size: " + currSize);//NOI18N
409
}
410         
411         String JavaDoc signature = "! " + name; //NOI18N
412
if (index != currSize) {
413             signatures.add(index, signature);
414             shiftPositions(index, 1);
415         } else {
416             signatures.add(signature); //NOI18N
417
}
418         
419         if (name.equals("setUp")) { //NOI18N
420
setSetUpIndex(index);
421         } else if (name.equals("tearDown")) { //NOI18N
422
setTearDownIndex(index);
423         }
424         if (getFirstMethodIndex() == -1) {
425             setFirstMethodIndex(index);
426         }
427     }
428     
429     /**
430      */

431     void addNoArgMethod(String JavaDoc name, String JavaDoc annotationName) {
432         addNoArgMethod(name, annotationName, size());
433     }
434     
435     /**
436      */

437     void addNoArgMethod(String JavaDoc name, String JavaDoc annotationName, int index) {
438         addNoArgMethod(name, index);
439         
440         if (annotationName.equals(JUnit4TestGenerator.ANN_BEFORE)) {
441             setBeforeIndex(index);
442         } else if (annotationName.equals(JUnit4TestGenerator.ANN_AFTER)) {
443             setAfterIndex(index);
444         } else if (annotationName.equals(JUnit4TestGenerator.ANN_BEFORE_CLASS)) {
445             setBeforeClassIndex(index);
446         } else if (annotationName.equals(JUnit4TestGenerator.ANN_AFTER_CLASS)) {
447             setAfterClassIndex(index);
448         }
449     }
450     
451     /**
452      */

453     void removeNoArgMethod(int index) {
454         if (index < 0) {
455             throw new IndexOutOfBoundsException JavaDoc("negative index (" //NOI18N
456
+ index + ')');
457         }
458         if (index >= size()) {
459             throw new IndexOutOfBoundsException JavaDoc("index: " + index //NOI18N
460
+ ", size: " + size()); //NOI18N
461
}
462         
463         String JavaDoc signature = signatures.get(index);
464         
465         if (!signature.startsWith("! ")) { //NOI18N
466
throw new IllegalArgumentException JavaDoc(
467                     "not a no-arg method at the given index (" //NOI18N
468
+ index + ')');
469         }
470         
471         if (index == getSetUpIndex()) {
472             setSetUpIndex(-1);
473         } else if (index == getTearDownIndex()) {
474             setTearDownIndex(-1);
475         }
476         if (index == getFirstMethodIndex()) {
477             int currSize = size();
478             if (index == (currSize - 1)) {
479                 setFirstMethodIndex(-1);
480             } else {
481                 int newFirstMethodIndex = -1;
482                 int memberIndex = index + 1;
483                 for (String JavaDoc sign : signatures.subList(index + 1, currSize)) {
484                     if (sign.startsWith("! ")) {
485                         newFirstMethodIndex = memberIndex;
486                         break;
487                     }
488                     memberIndex++;
489                 }
490                 setFirstMethodIndex(newFirstMethodIndex);
491             }
492         }
493         shiftPositions(index + 1, -1);
494     }
495     
496     /**
497      */

498     int size() {
499         return signatures.size();
500     }
501     
502     /**
503      */

504     private void shiftPositions(int fromIndex,
505                                 int shiftSize) {
506         for (int i = 0; i < positions.length; i++) {
507             int pos = positions[i];
508             if ((pos != -1) && (pos >= fromIndex)) {
509                 positions[i] = pos + shiftSize;
510             }
511         }
512     }
513     
514 }
515
Popular Tags