1 package org.incava.java;
2 
3 import java.util.*;
4 import net.sourceforge.pmd.ast.*;
5 import org.incava.util.ReverseComparator;
6 
7 
8 /**
9  * Miscellaneous routines for type declarations.
10  */
11 public class TypeDeclarationUtil extends SimpleNodeUtil
12 {
getName(ASTTypeDeclaration typeDecl)13     public static Token getName(ASTTypeDeclaration typeDecl)
14     {
15         ASTClassOrInterfaceDeclaration cidecl = (ASTClassOrInterfaceDeclaration)findChild(typeDecl, ASTClassOrInterfaceDeclaration.class);
16         return cidecl == null ? null : cidecl.getFirstToken().next;
17     }
18 
getType(ASTTypeDeclaration typeDecl)19     public static ASTClassOrInterfaceDeclaration getType(ASTTypeDeclaration typeDecl)
20     {
21         return (ASTClassOrInterfaceDeclaration)SimpleNodeUtil.findChild(typeDecl, ASTClassOrInterfaceDeclaration.class);
22     }
23 
findTypeDeclaration(String name, ASTTypeDeclaration[] types)24     public static ASTTypeDeclaration findTypeDeclaration(String name, ASTTypeDeclaration[] types)
25     {
26         for (int i = 0; i < types.length; ++i) {
27             ASTTypeDeclaration type      = types[i];
28             Token              otherName = getName(type);
29 
30             if ((otherName == null && name == null) ||
31                 (otherName != null && otherName.image.equals(name))) {
32                 return type;
33             }
34         }
35 
36         return null;
37     }
38 
39     /**
40      * Returns a list of all methods, fields, constructors, and inner classes
41      * and interfaces.
42      */
getDeclarations(ASTTypeDeclaration tdecl)43     public static ASTClassOrInterfaceBodyDeclaration[] getDeclarations(ASTTypeDeclaration tdecl)
44     {
45         ASTClassOrInterfaceDeclaration cidecl = (ASTClassOrInterfaceDeclaration)findChild(tdecl, ASTClassOrInterfaceDeclaration.class);
46         return getDeclarations(cidecl);
47     }
48 
49     /**
50      * Returns a list of all methods, fields, constructors, and inner classes
51      * and interfaces.
52      */
getDeclarations(ASTClassOrInterfaceDeclaration coid)53     public static ASTClassOrInterfaceBodyDeclaration[] getDeclarations(ASTClassOrInterfaceDeclaration coid)
54     {
55         ASTClassOrInterfaceBody body = (ASTClassOrInterfaceBody)findChild(coid, ASTClassOrInterfaceBody.class);
56         return (ASTClassOrInterfaceBodyDeclaration[])findChildren(body, ASTClassOrInterfaceBodyDeclaration.class);
57     }
58 
59     /**
60      * Returns the real declaration, which is a method, field, constructor, or
61      * inner class or interface.
62      */
getDeclaration(ASTClassOrInterfaceBodyDeclaration bdecl)63     public static SimpleNode getDeclaration(ASTClassOrInterfaceBodyDeclaration bdecl)
64     {
65         return hasChildren(bdecl) ? findChild(bdecl, null) : null;
66     }
67 
matchDeclarations(ASTClassOrInterfaceBodyDeclaration[] aDecls, ASTClassOrInterfaceBodyDeclaration[] bDecls)68     public static TreeMap matchDeclarations(ASTClassOrInterfaceBodyDeclaration[] aDecls, ASTClassOrInterfaceBodyDeclaration[] bDecls)
69     {
70         // keys (scores) maintained in reversed order:
71         TreeMap byScore = new TreeMap(new ReverseComparator());
72 
73         // map b by declaration types
74 
75         tr.Ace.log("aDecls", aDecls);
76         tr.Ace.log("bDecls", bDecls);
77 
78         for (int ai = 0; ai < aDecls.length; ++ai) {
79             ASTClassOrInterfaceBodyDeclaration aNode = aDecls[ai];
80             SimpleNode an     = getDeclaration(aNode);
81             List       scores = new ArrayList();
82 
83             for (int bi = 0; bi < bDecls.length; ++bi) {
84                 ASTClassOrInterfaceBodyDeclaration bNode = bDecls[bi];
85 
86                 double     score = getMatchScore(aNode, bNode);
87                 if (score > 0.0) {
88                     Double dScore  = new Double(score);
89                     List   atScore = (List)byScore.get(dScore);
90                     if (atScore == null) {
91                         atScore = new ArrayList();
92                         byScore.put(dScore, atScore);
93                     }
94                     atScore.add(new Object[] { aNode, bNode });
95                 }
96             }
97         }
98 
99         List     aSeen  = new ArrayList();
100         List     bSeen  = new ArrayList();
101         Set      scores = byScore.keySet();
102         Iterator sit    = scores.iterator();
103 
104         while (sit.hasNext()) {
105             Double   dScore  = (Double)sit.next();
106             List     atScore = (List)byScore.get(dScore);
107             Iterator vit     = atScore.iterator();
108 
109             while (vit.hasNext()) {
110                 Object[]   values = (Object[])vit.next();
111                 SimpleNode a      = (SimpleNode)values[0];
112                 SimpleNode b      = (SimpleNode)values[1];
113 
114                 if (aSeen.contains(a)) {
115                     // a already seen
116                     vit.remove();
117                 }
118                 else if (bSeen.contains(b)) {
119                     // b already seen
120                     vit.remove();
121                 }
122                 else {
123                     // neither already seen
124                     aSeen.add(a);
125                     bSeen.add(b);
126                 }
127             }
128 
129             if (atScore.size() == 0) {
130                 // remove the empty list
131                 sit.remove();
132             }
133         }
134 
135         return byScore;
136     }
137 
getMatchScore(ASTClassOrInterfaceBodyDeclaration aDecl, ASTClassOrInterfaceBodyDeclaration bDecl)138     public static double getMatchScore(ASTClassOrInterfaceBodyDeclaration aDecl, ASTClassOrInterfaceBodyDeclaration bDecl)
139     {
140         SimpleNode a = getDeclaration(aDecl);
141         SimpleNode b = getDeclaration(bDecl);
142 
143         double score = 0.0;
144         if (a == null && b == null) {
145             score = 1.0;
146         }
147         else if (a == null || b == null) {
148             // not a match.
149         }
150         else if (a.getClass().equals(b.getClass())) {
151             if (a instanceof ASTMethodDeclaration) {
152                 score = MethodUtil.getMatchScore((ASTMethodDeclaration)a, (ASTMethodDeclaration)b);
153             }
154             else if (a instanceof ASTFieldDeclaration) {
155                 // compare by name
156                 score = FieldUtil.getMatchScore((ASTFieldDeclaration)a, (ASTFieldDeclaration)b);
157             }
158             else if (a instanceof ASTConstructorDeclaration) {
159                 score = CtorUtil.getMatchScore((ASTConstructorDeclaration)a, (ASTConstructorDeclaration)b);
160             }
161             else if (a instanceof ASTClassOrInterfaceDeclaration) {
162                 ASTClassOrInterfaceDeclaration acoid = (ASTClassOrInterfaceDeclaration)a;
163                 ASTClassOrInterfaceDeclaration bcoid = (ASTClassOrInterfaceDeclaration)b;
164                 score = ClassUtil.getMatchScore(acoid, bcoid);
165             }
166             else {
167                 // WTF?
168                 tr.Ace.stack(tr.Ace.RED, "a", a);
169             }
170         }
171 
172         return score;
173     }
174 
175 }
176