001: package org.incava.java;
002:
003: import java.util.*;
004: import net.sourceforge.pmd.ast.*;
005:
006: /**
007: * Miscellaneous routines for parameters.
008: */
009: public class ParameterUtil extends SimpleNodeUtil {
010: public static ASTFormalParameter[] getParameters(
011: ASTFormalParameters params) {
012: return (ASTFormalParameter[]) findChildren(params,
013: ASTFormalParameter.class);
014: }
015:
016: public static Token[] getParameterNames(ASTFormalParameters params) {
017: ASTFormalParameter[] fps = getParameters(params);
018: List names = new ArrayList();
019:
020: for (int pi = 0; pi < fps.length; ++pi) {
021: ASTFormalParameter fp = fps[pi];
022: Token name = getParameterName(fp);
023: names.add(name);
024: }
025:
026: return (Token[]) names.toArray(new Token[0]);
027: }
028:
029: public static ASTFormalParameter getParameter(
030: ASTFormalParameters params, int index) {
031: return (ASTFormalParameter) findChild(params,
032: ASTFormalParameter.class, index);
033: }
034:
035: public static Token getParameterName(ASTFormalParameters params,
036: int index) {
037: ASTFormalParameter param = getParameter(params, index);
038: return getParameterName(param);
039: }
040:
041: public static String getParameterType(ASTFormalParameters params,
042: int index) {
043: ASTFormalParameter param = getParameter(params, index);
044: return getParameterType(param);
045: }
046:
047: public static List getParameterTypes(ASTFormalParameters params) {
048: List types = new ArrayList();
049: int nParams = params.jjtGetNumChildren();
050: for (int i = 0; i < nParams; ++i) {
051: ASTFormalParameter param = (ASTFormalParameter) params
052: .jjtGetChild(i);
053: String type = getParameterType(param);
054: types.add(type);
055: }
056: return types;
057: }
058:
059: public static List getParameterList(ASTFormalParameters params) {
060: List paramList = new ArrayList();
061: int nParams = params.jjtGetNumChildren();
062:
063: for (int i = 0; i < nParams; ++i) {
064: ASTFormalParameter param = getParameter(params, i);
065: String name = getParameterName(param).image;
066: String type = getParameterType(param);
067: // tr.Ace.log("type: " + type + "; name: " + name);
068: Object[] values = new Object[] { param, type, name };
069: paramList.add(values);
070: }
071:
072: return paramList;
073: }
074:
075: public static Token getParameterName(ASTFormalParameter param) {
076: if (param == null) {
077: return null;
078: } else {
079: ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) param
080: .jjtGetChild(1);
081: return vid.getFirstToken();
082: }
083: }
084:
085: public static String getParameterType(ASTFormalParameter param) {
086: if (param == null) {
087: return null;
088: } else {
089: // type is the first child, but we also have to look for the
090: // variable ID including brackets, for arrays
091: StringBuffer typeBuf = new StringBuffer();
092: ASTType type = (ASTType) SimpleNodeUtil.findChild(param,
093: ASTType.class);
094: Token ttk = type.getFirstToken();
095:
096: while (true) {
097: typeBuf.append(ttk.image);
098: if (ttk == type.getLastToken()) {
099: break;
100: } else {
101: ttk = ttk.next;
102: }
103: }
104:
105: ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) SimpleNodeUtil
106: .findChild(param, ASTVariableDeclaratorId.class);
107:
108: Token vtk = vid.getFirstToken();
109: while (vtk != vid.getLastToken()) {
110: vtk = vtk.next;
111: typeBuf.append(vtk.image);
112: }
113:
114: return typeBuf.toString();
115: }
116: }
117:
118: public static int[] getMatch(List aParameters, int aIndex,
119: List bParameters) {
120: int typeMatch = -1;
121: int nameMatch = -1;
122:
123: Object[] aValues = (Object[]) aParameters.get(aIndex);
124:
125: for (int bi = 0; bi < bParameters.size(); ++bi) {
126: Object[] bValues = (Object[]) bParameters.get(bi);
127:
128: if (bValues == null) {
129: // tr.Ace.log("already consumed");
130: } else {
131: if (aValues[1].equals(bValues[1])) {
132: typeMatch = bi;
133: }
134:
135: if (aValues[2].equals(bValues[2])) {
136: nameMatch = bi;
137: }
138:
139: if (typeMatch == bi && nameMatch == bi) {
140: aParameters.set(aIndex, null);
141: bParameters.set(bi, null);
142: return new int[] { typeMatch, nameMatch };
143: }
144: }
145: }
146:
147: int bestMatch = typeMatch;
148: if (bestMatch < 0) {
149: bestMatch = nameMatch;
150: }
151:
152: if (bestMatch >= 0) {
153: // make sure there isn't an exact match for this somewhere else in
154: // aParameters
155: Object[] bValues = (Object[]) bParameters.get(bestMatch);
156: int aMatch = getExactMatch(aParameters, bValues);
157: if (aMatch >= 0) {
158: return new int[] { -1, -1 };
159: } else {
160: aParameters.set(aIndex, null);
161: bParameters.set(bestMatch, null);
162: return new int[] { typeMatch, nameMatch };
163: }
164: } else {
165: return new int[] { -1, -1 };
166: }
167: }
168:
169: public static double getMatchScore(ASTFormalParameters a,
170: ASTFormalParameters b) {
171: double score;
172:
173: if (a.jjtGetNumChildren() == 0 && b.jjtGetNumChildren() == 0) {
174: score = 1.0;
175: } else {
176: // (int[], double, String) <=> (int[], double, String) ==> 100% (3 of 3)
177: // (int[], double, String) <=> (double, int[], String) ==> 80% (3 of 3 - 10% * misordered)
178: // (int[], double) <=> (double, int[], String) ==> 46% (2 of 3 - 10% * misordered)
179: // (int[], double, String) <=> (String) ==> 33% (1 of 3 params)
180: // (int[], double) <=> (String) ==> 0 (0 of 3)
181:
182: List aParamTypes = ParameterUtil.getParameterTypes(a);
183: List bParamTypes = ParameterUtil.getParameterTypes(b);
184:
185: int aSize = aParamTypes.size();
186: int bSize = bParamTypes.size();
187:
188: int exactMatches = 0;
189: int misorderedMatches = 0;
190:
191: for (int ai = 0; ai < aSize; ++ai) {
192: int paramMatch = getListMatch(aParamTypes, ai,
193: bParamTypes);
194: if (paramMatch == ai) {
195: ++exactMatches;
196: } else if (paramMatch >= 0) {
197: ++misorderedMatches;
198: }
199: }
200:
201: for (int bi = 0; bi < bSize; ++bi) {
202: int paramMatch = getListMatch(bParamTypes, bi,
203: aParamTypes);
204: if (paramMatch == bi) {
205: ++exactMatches;
206: } else if (paramMatch >= 0) {
207: ++misorderedMatches;
208: }
209: }
210:
211: int numParams = Math.max(aSize, bSize);
212: double match = (double) exactMatches / numParams;
213: match += (double) misorderedMatches / (2 * numParams);
214:
215: score = 0.5 + (match / 2.0);
216: }
217:
218: return score;
219: }
220:
221: /**
222: * Returns 0 for exact match, +1 for misordered match, -1 for no match.
223: */
224: protected static int getListMatch(List aList, int aIndex, List bList) {
225: int aSize = aList.size();
226: int bSize = bList.size();
227: String aStr = aIndex < aSize ? (String) aList.get(aIndex)
228: : null;
229: String bStr = aIndex < bSize ? (String) bList.get(aIndex)
230: : null;
231:
232: if (aStr == null) {
233: return -1;
234: }
235: if (aStr.equals(bStr)) {
236: aList.set(aIndex, null);
237: bList.set(aIndex, null);
238: return aIndex;
239: } else {
240: for (int bi = 0; bi < bSize; ++bi) {
241: bStr = (String) bList.get(bi);
242: if (aStr.equals(bStr)) {
243: aList.set(aIndex, null);
244: bList.set(bi, null);
245: return bi;
246: }
247: }
248: return -1;
249: }
250: }
251:
252: protected static int getExactMatch(List parameters, Object[] values) {
253: for (int i = 0; i < parameters.size(); ++i) {
254: Object[] pv = (Object[]) parameters.get(i);
255: if (pv == null) {
256: // tr.Ace.log("null parameters");
257: } else if (pv[1].equals(values[1])
258: && pv[2].equals(values[2])) {
259: return i;
260: }
261: }
262: return -1;
263: }
264:
265: }
|