1 19 package org.netbeans.modules.java.source.save; 20 21 import com.sun.source.tree.Tree; 22 import com.sun.source.tree.MethodTree; 23 import com.sun.source.tree.Tree; 24 import com.sun.source.tree.VariableTree; 25 26 import static com.sun.source.tree.Tree.Kind; 27 28 36 class Measure { 37 38 41 static final Measure DEFAULT = new Measure(); 42 43 47 static final MethodMeasure METHOD = new MethodMeasure(); 48 49 52 static final VariableMeasure FIELD = new VariableMeasure(); 53 54 58 static final MemberMeasure MEMBER = new MemberMeasure(); 59 60 63 static final VariableMeasure PARAMETER = FIELD; 64 65 68 static final ClassNameMeasure CLASS_NAME = new ClassNameMeasure(); 69 70 75 static final int INFINITE_DISTANCE = 1000; 76 77 80 static final int OBJECTS_MATCH = 0; 81 82 91 int getDistance(Object first, Object second) { 92 assert first != null && second != null : "Shouldn't pass null value!"; 93 94 if (first == second || first.equals(second)) { 95 return OBJECTS_MATCH; 97 } else { 98 return INFINITE_DISTANCE; 100 } 101 } 102 103 private static final StringMeasure STRING = new StringMeasure(); 107 108 private static final class MemberMeasure extends Measure { 110 int getDistance(Object first, Object second) { 111 Tree t1 = (Tree) first; 112 Tree t2 = (Tree) second; 113 114 switch (t1.getKind()) { 115 case METHOD: 116 return METHOD.getDistance(first, second); 117 118 case VARIABLE: 119 return FIELD.getDistance(first, second); 120 121 124 default: 125 return DEFAULT.getDistance(first, second); 126 } 127 } 128 } 129 130 private static final class MethodMeasure extends Measure { 132 133 private static final int NAME_WEIGHT = 60; 134 private static final int PARAMETERS_WEIGHT = 40; 135 136 int getDistance(Object first, Object second) { 137 if (super.getDistance(first, second) == OBJECTS_MATCH) { 139 return OBJECTS_MATCH; 140 } 141 int result = 100; 146 Tree t1 = (Tree) first; 147 Tree t2 = (Tree) second; 148 149 if (t1.getKind() != Kind.METHOD || t2.getKind() != Kind.METHOD) { 153 return INFINITE_DISTANCE; 154 } 155 MethodTree tree1 = (MethodTree) first; 157 MethodTree tree2 = (MethodTree) second; 158 159 if (!"<init>".contentEquals(tree1.getName()) && 162 !"<init>".contentEquals(tree2.getName())) 163 { 164 result += Measure.STRING.getDistance( 165 tree1.getName().toString(), 166 tree2.getName().toString() 167 ) * NAME_WEIGHT; 168 } else { 169 result += 60000; 170 } 171 172 Tree[] types1 = new Tree[tree1.getParameters().size()]; 173 Tree[] types2 = new Tree[tree2.getParameters().size()]; 174 175 int i = 0; 176 for (VariableTree item : tree1.getParameters()) 177 types1[i++] = item.getType(); 178 179 i = 0; 180 for (VariableTree item : tree2.getParameters()) 181 types2[i++] = item.getType(); 182 183 result += new OrderedArrayMeasure(Measure.CLASS_NAME). 184 getDistance(types1, types2) * PARAMETERS_WEIGHT; 185 result /= 100; 186 return result > INFINITE_DISTANCE ? INFINITE_DISTANCE : result; 187 } 188 } 189 190 private final static class VariableMeasure extends Measure { 192 193 private static final int NAME_WEIGHT = 40; 194 private static final int TYPE_WEIGHT = 60; 195 196 public int getDistance(Object first, Object second) { 197 if (super.getDistance(first, second) == OBJECTS_MATCH) { 199 return OBJECTS_MATCH; 200 } 201 int result = 100; 206 Tree t1 = (Tree) first; 207 Tree t2 = (Tree) second; 208 209 if (t1.getKind() != Kind.VARIABLE || t2.getKind() != Kind.VARIABLE) { 213 return INFINITE_DISTANCE; 214 } 215 216 VariableTree vt1 = (VariableTree) first; 217 VariableTree vt2 = (VariableTree) second; 218 219 int nameDist = Measure.STRING.getDistance(vt1.getName().toString(), vt2.getName().toString()); 220 int typeDist = Measure.CLASS_NAME.getDistance(vt1.getType(), vt2.getType()); 221 222 if (nameDist > 0 && typeDist > 0) { 223 return INFINITE_DISTANCE; 226 } 227 result += nameDist * NAME_WEIGHT; 228 result += typeDist * TYPE_WEIGHT; 229 result /= 100; 230 231 return result > INFINITE_DISTANCE ? INFINITE_DISTANCE : result; 232 } 233 } 234 235 private static final class StringMeasure extends Measure { 237 238 private static final int SAME = 0; 239 private static final int CASE_SAME = 1; 240 private static final int DIFFERENT = 10; 241 242 250 public final int getDistance(final Object first, final Object second) { 251 if (first == second) 252 return SAME; 253 254 if (first == null || second == null) 255 return INFINITE_DISTANCE; 256 257 final String x = (String ) first; 258 final String y = (String ) second; 259 final int xlen = x.length(); 260 final int ylen = y.length(); 261 int errors = 0; 262 int xindex = 0, yindex = 0; 263 final char xarr[] = new char[xlen+1]; 264 final char yarr[] = new char[ylen+1]; 265 266 x.getChars(0, xlen, xarr, 0); 267 y.getChars(0, ylen, yarr, 0); 268 269 while (xindex < xlen && yindex < ylen) { 270 final char xchar = xarr[xindex]; 271 final char ychar = yarr[yindex]; 272 final int cherr = compareChars(xchar, ychar); 273 274 if (cherr != DIFFERENT) { 275 errors += cherr; 276 xindex++; 277 yindex++; 278 continue; 279 } 280 final char xchar1 = xarr[xindex+1]; 281 final char ychar1 = yarr[yindex+1]; 282 if (xchar1 != 0 && ychar1 != 0) { 283 final int cherr1 = compareChars(xchar1, ychar1); 284 285 if (cherr1 != DIFFERENT) { 286 errors += DIFFERENT + cherr1; 287 xindex += 2; 288 yindex += 2; 289 continue; 290 } 291 final int xerr = compareChars(xchar, ychar1); 292 final int xerr1= compareChars(xchar1, ychar); 293 294 if (xerr != DIFFERENT && xerr1 != DIFFERENT) { 295 errors += DIFFERENT + xerr + xerr1; 296 xindex += 2; 297 yindex += 2; 298 continue; 299 } 300 } 301 if (xlen-xindex > ylen-yindex) { 302 xindex++; 303 } else if (xlen-xindex < ylen-yindex) { 304 yindex++; 305 } else { 306 xindex++; 307 yindex++; 308 } 309 errors += DIFFERENT; 310 } 311 errors += (xlen-xindex+ylen-yindex) * DIFFERENT; 312 return (INFINITE_DISTANCE*errors)/Math.max(ylen,xlen)/DIFFERENT; 313 } 314 315 private static final int compareChars(final char xc, final char yc) { 316 if (xc == yc) 317 return SAME; 318 319 char xlower = Character.toLowerCase(xc); 320 char ylower = Character.toLowerCase(yc); 321 322 return xlower == ylower ? CASE_SAME : DIFFERENT; 323 } 324 } 325 326 private static final class ClassNameMeasure extends Measure { 328 329 public int getDistance(Object first, Object second) { 330 if (first == second) return OBJECTS_MATCH; 331 if (first == null || second == null) { 332 return INFINITE_DISTANCE; 333 } 334 335 Tree t1 = (Tree) first; 336 Tree t2 = (Tree) second; 337 338 if (t1.getKind() == t2.getKind()) 339 return Measure.STRING.getDistance(t1.toString(), t2.toString()); 342 343 return INFINITE_DISTANCE; 344 } 345 } 346 347 private static final class OrderedArrayMeasure extends Measure { 349 350 private final Measure measure; 351 352 OrderedArrayMeasure(Measure elementsMeasure) { 353 measure = elementsMeasure; 354 } 355 356 public int getDistance(Object first, Object second) { 357 Object [] array1 = (Object []) first; 358 Object [] array2 = (Object []) second; 359 int minSize = Math.min(array1.length, array2.length); 360 int difference = Math.abs(array1.length - array2.length); 361 int result = 0; 362 363 if (minSize == 0) { 364 if (difference != 0) 365 result = INFINITE_DISTANCE; 366 return result; 367 } 368 for (int i = 0; i < minSize; i++) { 369 result += measure.getDistance(array1[i], array2[i]); 370 } 371 result += difference * INFINITE_DISTANCE; 372 result /= (minSize+difference); 373 return result > INFINITE_DISTANCE ? INFINITE_DISTANCE : result; 374 } 375 } 376 } 377 | Popular Tags |