1 2 12 package com.versant.core.util; 13 14 import com.versant.core.util.classhelper.ClassHelper; 15 16 import java.util.*; 17 import java.lang.reflect.Method ; 18 import java.lang.reflect.InvocationTargetException ; 19 import java.lang.reflect.Field ; 20 import java.lang.reflect.Modifier ; 21 import java.io.PrintStream ; 22 import java.io.IOException ; 23 24 import com.versant.core.common.BindingSupportImpl; 25 import com.versant.core.common.Debug; 26 27 30 public class BeanUtils { 31 32 private BeanUtils() { 33 } 34 35 private static final HashMap PRIMITIVE_NAME_MAP = new HashMap(17); 36 37 static { 38 PRIMITIVE_NAME_MAP.put(Long.TYPE.getName(), Long.TYPE); 39 PRIMITIVE_NAME_MAP.put(Integer.TYPE.getName(), Integer.TYPE); 40 PRIMITIVE_NAME_MAP.put(Short.TYPE.getName(), Short.TYPE); 41 PRIMITIVE_NAME_MAP.put(Byte.TYPE.getName(), Byte.TYPE); 42 PRIMITIVE_NAME_MAP.put(Boolean.TYPE.getName(), Boolean.TYPE); 43 PRIMITIVE_NAME_MAP.put(Character.TYPE.getName(), Character.TYPE); 44 PRIMITIVE_NAME_MAP.put(Float.TYPE.getName(), Float.TYPE); 45 PRIMITIVE_NAME_MAP.put(Double.TYPE.getName(), Double.TYPE); 46 47 48 PRIMITIVE_NAME_MAP.put(Long.TYPE.getName() + "[]", Long [].class); 49 PRIMITIVE_NAME_MAP.put(Integer.TYPE.getName() + "[]", Integer [].class); 50 PRIMITIVE_NAME_MAP.put(Short.TYPE.getName() + "[]", Short [].class); 51 PRIMITIVE_NAME_MAP.put(Byte.TYPE.getName() + "[]", Byte [].class); 52 PRIMITIVE_NAME_MAP.put(Boolean.TYPE.getName() + "[]", Boolean [].class); 53 PRIMITIVE_NAME_MAP.put(Character.TYPE.getName() + "[]", Character [].class); 54 PRIMITIVE_NAME_MAP.put(Float.TYPE.getName() + "[]", Float [].class); 55 PRIMITIVE_NAME_MAP.put(Double.TYPE.getName() + "[]", Double [].class); 56 57 } 58 59 private static final Class [] STRING_ARGS = new Class []{String .class}; 60 private static final Class [] INT_ARGS = new Class []{Integer.TYPE}; 61 private static final Class [] BOOLEAN_ARGS = new Class []{Boolean.TYPE}; 62 63 private static final String DEFAULT_PROP_FILE = "versant.properties"; 64 65 72 public static void setProperties(Object bean, Map props) 73 throws IllegalArgumentException { 74 if (props == null || bean == null) return; 75 Class cls = bean.getClass(); 76 Object [] args = new Object [1]; 77 for (Iterator i = props.entrySet().iterator(); i.hasNext(); ) { 78 Map.Entry e = (Map.Entry)i.next(); 79 String prop = (String )e.getKey(); 80 String value = (String )e.getValue(); 81 Field f = findField(prop, cls, value, args); 82 if (f != null) { 83 try { 84 f.set(bean, args); 85 } catch (Throwable x) { 86 if (x instanceof InvocationTargetException ) { 87 x = ((InvocationTargetException )x).getTargetException(); 88 } 89 throw BindingSupportImpl.getInstance().illegalArgument( 90 x.getClass() + ": " + x.getMessage()); 91 } 92 } 93 Method m = findSetMethod(prop, cls, value, args); 94 try { 95 m.invoke(bean, args); 96 } catch (IllegalArgumentException x) { 97 throw x; 98 } catch (Throwable x) { 99 if (x instanceof InvocationTargetException ) { 100 x = ((InvocationTargetException )x).getTargetException(); 101 } 102 throw BindingSupportImpl.getInstance().illegalArgument( 103 x.getClass() + ": " + x.getMessage()); 104 } 105 } 106 } 107 108 113 public static void setProperty(Object bean, String prop, String value) 114 throws IllegalArgumentException { 115 Class cls = bean.getClass(); 116 Object [] args = new Object [1]; 117 Method m = findSetMethod(prop, cls, value, args); 118 try { 119 m.invoke(bean, args); 120 } catch (IllegalArgumentException x) { 121 throw x; 122 } catch (Throwable x) { 123 if (x instanceof InvocationTargetException ) { 124 x = ((InvocationTargetException )x).getTargetException(); 125 } 126 throw BindingSupportImpl.getInstance().illegalArgument( 127 x.getClass() + ": " + x.getMessage()); 128 } 129 } 130 131 private static Field findField(String prop, Class cls, String value, 132 Object [] args) { 133 try { 134 Field f = cls.getField(prop); 135 Class t = f.getType(); 136 if (t == Integer.TYPE || t == Integer .class) { 137 args[0] = toInteger(value, prop); 138 } else if (t == Boolean.TYPE || t == Boolean .class) { 139 args[0] = toBoolean(value, prop); 140 } else if (t == String .class) { 141 args[0] = value; 142 } else { 143 throw BindingSupportImpl.getInstance().internal( 144 "Unsupported field type: " + f); 145 } 146 return f; 147 } catch (NoSuchFieldException e) { 148 return null; 149 } 150 } 151 152 private static Method findSetMethod(String prop, Class cls, String value, 153 Object [] args) { 154 String name = "set" + Character.toUpperCase(prop.charAt(0)) + 155 prop.substring(1); 156 Method m; 157 try { 158 try { 159 m = cls.getMethod(name, STRING_ARGS); 160 args[0] = value; 161 } catch (NoSuchMethodException x) { 162 try { 163 m = cls.getMethod(name, INT_ARGS); 164 args[0] = toInteger(value, prop); 165 } catch (NoSuchMethodException xx) { 166 m = cls.getMethod(name, BOOLEAN_ARGS); 167 args[0] = toBoolean(value, prop); 168 } 169 } 170 } catch (NoSuchMethodException x) { 171 String pos = getClosestProperty(prop,cls); 172 String all = getAllPropsFormatted(cls); 173 throw BindingSupportImpl.getInstance().illegalArgument( 174 "An invalid property '"+ prop +"' was set on " + 175 cls.getName() + ". " + 176 (pos != null ? 177 ("The property closely matches '" + pos + "'. ") : "")+ 178 (all != null ? 179 ("All possible properties are: " +all) : "")); 180 } 181 return m; 182 } 183 184 private static Boolean toBoolean(String value, String prop) { 185 if (value.equals("true")) { 186 return Boolean.TRUE; 187 } else if (value.equals("false")) { 188 return Boolean.FALSE; 189 } else { 190 throw BindingSupportImpl.getInstance().illegalArgument( 191 "Expected true or false value for '" + 192 prop + "' got '" + value + "'"); 193 } 194 } 195 196 private static Integer toInteger(String value, String prop) { 197 try { 198 return new Integer (value); 199 } catch (NumberFormatException xx) { 200 throw BindingSupportImpl.getInstance().illegalArgument( 201 "Expected int value for '" + prop + "' got '" + value + "'"); 202 } 203 } 204 205 212 public static void setCommandLineArgs(Object bean, String [] args, 213 String [] expected) throws IllegalArgumentException { 214 215 int n = args.length; 216 Object [] v = new Object [1]; 217 for (int i = 0; i < n; i++) { 218 String s = args[i]; 219 if (!s.startsWith("-")) { 220 throw BindingSupportImpl.getInstance().illegalArgument( 221 "Invalid argument: " + s); 222 } 223 String prop = s.substring(1); 224 int j; 225 for (j = expected.length - 1; j >= 0; j--) { 226 if (expected[j].equals(prop)) break; 227 } 228 if (j < 0) { 229 throw BindingSupportImpl.getInstance().illegalArgument( 230 "Invalid argument: " + prop); 231 } 232 if (++i == n) { 233 throw BindingSupportImpl.getInstance().illegalArgument( 234 "Expected value for " + prop); 235 } 236 String value = args[i]; 237 Method m = findSetMethod(prop, bean.getClass(), value, v); 238 try { 239 m.invoke(bean, v); 240 } catch (IllegalArgumentException x) { 241 throw x; 242 } catch (Throwable x) { 243 if (x instanceof InvocationTargetException ) { 244 x = ((InvocationTargetException )x).getTargetException(); 245 } 246 throw BindingSupportImpl.getInstance().illegalArgument( 247 "Invalid value for " + prop + ": " + 248 x.getClass().getName() + ": " + 249 x.getMessage()); 250 } 251 } 252 } 253 254 257 public static void parseProperties(String ps, Properties props) { 258 StringTokenizer t = new StringTokenizer(ps, "=", false); 259 for (;;) { 260 String key; 261 try { 262 key = t.nextToken("="); 263 if (key.startsWith(";")) key = key.substring(1); 264 } catch (NoSuchElementException e) { 265 break; 266 } 267 try { 268 String value = t.nextToken(";").substring(1); 269 props.put(key, value); 270 } catch (NoSuchElementException e) { 271 throw BindingSupportImpl.getInstance().runtime( 272 "Expected semicolon delimited property=value pairs: '" + 273 ps + "'"); 274 } 275 } 276 } 277 278 283 public static void parseProperties(String props, Object bean) { 284 if (props == null || props.length() == 0) return; 285 Class cls = bean.getClass(); 286 Object [] args = new Object [1]; 287 int last = 0; 288 for (;;) { 289 int i = props.indexOf('=', last); 290 if (i < 0) { 291 throw BindingSupportImpl.getInstance().illegalArgument( 292 "Expected property name at position " + last + ": " + props); 293 } 294 String key = props.substring(last, i); 295 int j = props.indexOf(';', ++i); 296 String value; 297 if (j < 0) value = props.substring(i); 298 else value = props.substring(i, j); 299 Method m = findSetMethod(key, cls, value, args); 300 try { 301 m.invoke(bean, args); 302 } catch (Exception e) { 303 Throwable t; 304 if (e instanceof InvocationTargetException ) { 305 t = ((InvocationTargetException )e).getTargetException(); 306 } else { 307 t = e; 308 } 309 throw BindingSupportImpl.getInstance().runtime( 310 "Error setting property '" + key + "' to '" + value + "'", 311 t); 312 } 313 if (j < 0) break; 314 last = j + 1; 315 } 316 } 317 318 322 public static Class toClass(String primitiveName) { 323 return (Class )PRIMITIVE_NAME_MAP.get(primitiveName); 324 } 325 326 330 public static Class loadClass(String name, boolean initialize, 331 ClassLoader loader) throws ClassNotFoundException { 332 Class ans = toClass(name); 333 if (ans == null) { 334 int i = name.indexOf("[]"); 335 if (i >= 0) { 336 name = "[L" + name.substring(0, i); 337 } 338 ans = ClassHelper.get().classForName(name, initialize, loader); 339 } 340 return ans; 341 } 342 343 347 public static Object newInstance(String cname, ClassLoader loader, Class mustBe) { 348 try { 349 Class cls = ClassHelper.get().classForName(cname, true, loader); 350 if (!mustBe.isAssignableFrom(cls)) { 351 throw BindingSupportImpl.getInstance().runtime( 352 cname + " is not a " + mustBe.getName()); 353 } 354 return cls.newInstance(); 355 } catch (Exception e) { 356 if( BindingSupportImpl.getInstance().isOwnException(e) ) 357 { 358 throw (RuntimeException )e; 359 } 360 throw BindingSupportImpl.getInstance().runtime( 361 "Unable to create instance of " + cname + ": " + 362 e.getMessage(), e); 363 } 364 } 365 366 369 public static Object getPropertyValue(Object bean, String property) 370 throws Exception { 371 Class cls = bean.getClass(); 372 property = Character.toUpperCase(property.charAt(0)) + 373 property.substring(1); 374 Method m; 375 try { 376 m = cls.getMethod("get" + property, null); 377 } catch (NoSuchMethodException e) { 378 m = cls.getMethod("is" + property, null); 379 } 380 return m.invoke(bean, null); 381 } 382 383 388 public static void fillFields(Object o, String prefix, Map props, 389 Set fieldsToIgnore) { 390 Field [] a = o.getClass().getFields(); 391 for (int i = 0; i < a.length; i++) { 392 Field f = a[i]; 393 int m = f.getModifiers(); 394 if (Modifier.isFinal(m) || Modifier.isStatic(m) 395 || !isSupportedFieldType(f.getType())) { 396 continue; 397 } 398 String name = f.getName(); 399 if (fieldsToIgnore != null && fieldsToIgnore.contains(name)) { 400 continue; 401 } 402 String prop = prefix + name; 403 String value = (String )props.get(prop); 404 if (value == null) { 405 continue; 406 } 407 setFieldValue(f, o, value, prop); 408 } 409 } 410 411 public static boolean isSupportedFieldType(Class t) { 412 return t == Integer.TYPE || t == Integer .class 413 || t == Boolean.TYPE || t == Boolean .class 414 || t == String .class; 415 } 416 417 421 private static void setFieldValue(Field f, Object o, String value, 422 String name) { 423 Class t = f.getType(); 424 Object arg; 425 if (t == Integer.TYPE || t == Integer .class) { 426 arg = toInteger(value, name); 427 } else if (t == Boolean.TYPE || t == Boolean .class) { 428 arg = toBoolean(value, name); 429 } else if (t == String .class) { 430 arg = value; 431 } else { 432 throw BindingSupportImpl.getInstance().illegalArgument( 433 "Unsupported field type: " + f); 434 } 435 try { 436 f.set(o, arg); 437 } catch (Throwable x) { 438 if (x instanceof InvocationTargetException ) { 439 x = ((InvocationTargetException )x).getTargetException(); 440 } 441 throw BindingSupportImpl.getInstance().illegalArgument( 442 x.getClass() + ": " + x.getMessage()); 443 } 444 } 445 446 449 public static class CmdLineResult { 450 public HashSet fieldsFilled = new HashSet(); 451 public Properties properties; 452 } 453 454 479 public static CmdLineResult processCmdLine(String [] args, ClassLoader loader, 480 Object o, String [] requiredFields, String toolName, 481 String toolDescription, boolean hasProps) { 482 try { 483 CmdLineResult res = new CmdLineResult(); 484 Properties overrides = hasProps ? new Properties() : null; 485 String propFileName = DEFAULT_PROP_FILE; 486 for (int i = 0; i < args.length; ) { 487 String arg = args[i++]; 488 if (arg.equals("-p")) { 489 if (i >= args.length) { 490 throw BindingSupportImpl.getInstance().illegalArgument( 491 "Expected file or resource name for -p"); 492 } 493 propFileName = args[i++]; 494 } else if (arg.equals("/?") || arg.equals("-help") 495 || arg.equals("--help")) { 496 throw BindingSupportImpl.getInstance().illegalArgument(""); 497 } else if (arg.startsWith("-")) { 498 String key = arg.substring(1); 499 if (key.length() == 0) { 500 throw BindingSupportImpl.getInstance().illegalArgument( 501 "Expected name of argument after '-'"); 502 } 503 try { 504 Field f = o.getClass().getField(key); 505 Class t = f.getType(); 506 int m = f.getModifiers(); 507 if (Modifier.isFinal(m) || Modifier.isStatic(m) 508 || !isSupportedFieldType(t)) { 509 throw new NoSuchFieldException (); 510 } 511 String value = i < args.length ? args[i] : null; 512 if (value.startsWith("-")) { 513 value = null; 514 } 515 if (value == null) { 516 if (t == Boolean .class || t == Boolean.TYPE) { 517 value = "true"; 518 } else { 519 throw BindingSupportImpl.getInstance().illegalArgument( 520 "Expected value for " + arg); 521 } 522 } else { 523 ++i; 524 } 525 setFieldValue(f, o, value, arg); 526 res.fieldsFilled.add(f.getName()); 527 } catch (NoSuchFieldException e) { 528 throw BindingSupportImpl.getInstance().illegalArgument( 529 "Unknown option: " + arg); 530 } 531 } else { 532 int pos = hasProps ? arg.indexOf('=') : -1; 533 if (pos <= 0) { 534 throw BindingSupportImpl.getInstance().illegalArgument( 535 "Invalid argument: " + arg); 536 } 537 String key = arg.substring(0, i); 538 String value = arg.substring(i + 1); 539 overrides.put(key, value); 540 } 541 } 542 if (hasProps) { 543 Properties p; 544 try { 545 p = PropertiesLoader.loadProperties(propFileName); 546 if (p == null) { 547 p = PropertiesLoader.loadProperties(loader, propFileName); 548 if (p == null) { 549 throw BindingSupportImpl.getInstance().illegalArgument( 550 "File or resource not found: '" + 551 propFileName + "'"); 552 } 553 } 554 } catch (IOException e) { 555 throw BindingSupportImpl.getInstance().illegalArgument( 556 "Error loading " + propFileName); 557 } 558 Properties sp = System.getProperties(); 559 for (Iterator i = sp.keySet().iterator(); i.hasNext(); ) { 560 String key = (String )i.next(); 561 if (key.startsWith("versant.") 562 || key.startsWith("javax.jdo.option.")) { 563 String value = sp.getProperty(key); 564 System.err.println("Using system property: " + 565 key + "=" + value); 566 p.put(key, value); 567 } 568 } 569 for (Iterator i = overrides.keySet().iterator(); i.hasNext(); ) { 570 String key = (String )i.next(); 571 String value = overrides.getProperty(key); 572 System.err.println("Command line override: " + key + "=" + value); 573 p.put(key, value); 574 } 575 res.properties = p; 576 } 577 return res; 578 } catch (IllegalArgumentException e) { 579 System.err.println(e.getMessage()); 580 System.err.println(); 581 printUsage(o, requiredFields, toolName, toolDescription, hasProps, 582 System.err); 583 throw e; 584 } 585 } 586 587 598 public static void printUsage(Object o, String [] requiredFields, 599 String toolName, String toolDescription, boolean hasProps, 600 PrintStream out) { 601 Field [] all = o.getClass().getFields(); 602 603 HashMap helpMap = new HashMap(); 605 for (int i = 0; i < all.length; i++) { 606 Field f = all[i]; 607 int m = f.getModifiers(); 608 if (!(Modifier.isFinal(m) && Modifier.isStatic(m)) 609 || f.getType() != String .class) { 610 continue; 611 } 612 String name = f.getName(); 613 if (name.startsWith("HELP_")) { 614 try { 615 helpMap.put(name.substring(5), f.get(null)); 616 } catch (IllegalAccessException e) { 617 throw BindingSupportImpl.getInstance().internal( 618 e.toString(), e); 619 } 620 } 621 } 622 623 HashMap defaults = new HashMap(); 625 ArrayList options = new ArrayList(); 626 HashMap fields = new HashMap(); 627 int longestOp = 0; 628 if (hasProps) { 629 String s = "-p " + DEFAULT_PROP_FILE; 630 longestOp = s.length(); 631 } 632 for (int i = 0; i < all.length; i++) { 633 Field f = all[i]; 634 int m = f.getModifiers(); 635 if (Modifier.isFinal(m) || Modifier.isStatic(m) 636 || !isSupportedFieldType(f.getType())) { 637 continue; 638 } 639 String op = f.getName(); 640 options.add(op); 641 fields.put(op, f); 642 String def; 643 try { 644 Object v = f.get(o); 645 def = v == null ? null : v.toString(); 646 } catch (IllegalAccessException e) { 647 throw BindingSupportImpl.getInstance().internal( 648 e.toString(), e); 649 } 650 String s = "-" + op; 651 if (def != null) { 652 defaults.put(op, def); 653 s = s + " " + def; 654 } 655 if (s.length() > longestOp) { 656 longestOp = s.length(); 657 } 658 } 659 660 out.println("Versant Open Access " + Debug.VERSION + " " + toolName); 662 out.println("Usage: " + toolName + 663 (hasProps ? " -p <property file or resource>" : "") + 664 " [OPTION] ... " + 665 (hasProps ? " [property=value] ..." : "")); 666 out.println(toolDescription); 667 out.println(); 668 HashSet requiredSet = new HashSet(); 669 int rfc = requiredFields == null ? 0 : requiredFields.length; 670 if (rfc > 0) { 671 requiredSet.addAll(Arrays.asList(requiredFields)); 672 out.println("Required arguements:"); 673 for (int i = 0; i < requiredFields.length; i++) { 674 printOption(requiredFields[i], fields, null, helpMap, 675 longestOp, out); 676 } 677 } 678 int n = options.size(); 679 if (n - rfc > 0 || hasProps) { 680 out.println("Optional arguements with default values:"); 681 if (hasProps) { 682 printOption("p", DEFAULT_PROP_FILE, 683 "Name of file or resource to load properties from", 684 longestOp, out); 685 } 686 for (int i = 0; i < n; i++) { 687 String op = (String )options.get(i); 688 if (!requiredSet.contains(op)) { 689 printOption(op, fields, defaults, helpMap, longestOp, out); 690 } 691 } 692 out.println(); 693 } 694 if (hasProps) { 695 out.println("Use property=value pairs to override properties " + 696 "including properties set from System properties."); 697 out.println(); 698 } 699 } 700 701 private static void printOption(String op, HashMap fields, 702 HashMap defaults, HashMap helpMap, int longestOp, PrintStream out) { 703 Field f = (Field )fields.get(op); 704 String def = defaults == null ? null : (String )defaults.get(op); 705 String help = (String )helpMap.get(op); 706 if (help == null) { 707 Class t = f.getType(); 708 if (t == Integer .class || t == Integer.TYPE) { 709 help = "int"; 710 } else if (t == Boolean .class || t == Boolean.TYPE) { 711 help = "true|false"; 712 } else if (t == String .class) { 713 help = "string"; 714 } else { 715 help = "..."; 716 } 717 } 718 printOption(op, def, help, longestOp, out); 719 } 720 721 private static void printOption(String op, String def, String help, 722 int longestOp, PrintStream out) { 723 StringBuffer b = new StringBuffer (); 724 b.append('-'); 725 b.append(op); 726 if (def != null) { 727 b.append(' '); 728 b.append(def); 729 } 730 for (int j = longestOp - b.length() + 2; j > 0; j--) { 731 b.append(' '); 732 } 733 b.append(help); 734 out.println(b.toString()); 735 } 736 737 741 private static String getClosestProperty(String s, Class cls) { 742 Method [] methods = cls.getMethods(); 743 int j = 0; 744 for (int i = 0; i < methods.length; i++) { 745 String methodName = methods[i].getName(); 746 if (methodName.startsWith("set") && methodName.length() > 3) { 747 Class params[] = methods[i].getParameterTypes(); 748 if (params.length != 0 && !params[0].isArray()) { 749 j++; 750 } 751 } 752 753 } 754 if (j == 0) { 755 return null; 756 } 757 String [] targets = new String [j]; 758 j = 0; 759 for (int i = 0; i < methods.length; i++) { 760 String methodName = methods[i].getName(); 761 if (methodName.startsWith("set") && methodName.length() > 3) { 762 Class params[] = methods[i].getParameterTypes(); 763 if (params.length != 0 && !params[0].isArray()) { 764 targets[j] = Character.toLowerCase(methodName.charAt(3)) + 765 (methodName.length() > 4 ? methodName.substring(4) : 766 ""); 767 j++; 768 } 769 } 770 } 771 772 return getClosest(s,targets,0.25f); 773 } 774 775 778 private static boolean containsProperties(Class cls, String prop){ 779 return getAllProperties(cls).contains(prop); 780 } 781 782 785 public static Set getAllProperties(Class cls) { 786 Method [] methods = cls.getMethods(); 787 Set set = new HashSet(); 788 for (int i = 0; i < methods.length; i++) { 789 String methodName = methods[i].getName(); 790 if (methodName.startsWith("set") && methodName.length() > 3) { 791 String prop = Character.toLowerCase(methodName.charAt(3)) + 792 (methodName.length() > 4 ? methodName.substring(4) : ""); 793 set.add(prop); 794 } 795 796 } 797 798 Field fields[] = cls.getFields(); 799 for (int i = 0; i < fields.length; i++) { 800 String fieldName = fields[i].getName(); 801 String prop = Character.toLowerCase(fieldName.charAt(0)) + 802 (fieldName.length() > 1 ? fieldName.substring(1) : ""); 803 804 set.add(prop); 805 } 806 return set; 807 808 } 809 810 813 private static String getAllPropsFormatted(Class cls) { 814 Set set = getAllProperties(cls); 815 if (set.isEmpty()){ 816 return null; 817 } else { 818 ArrayList list = new ArrayList(set); 819 Collections.sort(list); 820 StringBuffer buff = new StringBuffer (); 821 for (Iterator iter = list.iterator(); iter.hasNext();) { 822 String name = (String ) iter.next(); 823 824 buff.append(name); 825 buff.append(';'); 826 } 827 return buff.toString(); 828 } 829 } 830 831 835 private static String getClosest(String s, String [] targets, float diffs) { 836 if (s == null || targets == null) { 837 return null; 838 } 839 840 HashMap map = new HashMap(); 841 for (int i = 0; i < targets.length; i++) { 842 map.put(targets[i], targets[i].toUpperCase()); 843 } 844 s = s.toUpperCase(); 845 int n = s.length(); 847 float srcLenght = (float) n; 848 849 float currentWeight = 1; 850 String currentString = null; 851 Set set = map.keySet(); 852 for (Iterator iter = set.iterator(); iter.hasNext();) { 853 String origianal = (String ) iter.next(); 854 String t = (String ) map.get(origianal); 855 856 857 int m = t.length(); 859 860 int p[] = new int[n + 1]; int d[] = new int[n + 1]; int _d[]; 864 int i; int j; 868 char t_j; 870 int cost; 872 for (i = 0; i <= n; i++) { 873 p[i] = i; 874 } 875 876 for (j = 1; j <= m; j++) { 877 t_j = t.charAt(j - 1); 878 d[0] = j; 879 880 for (i = 1; i <= n; i++) { 881 cost = s.charAt(i - 1) == t_j ? 0 : 1; 882 d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost); 884 } 885 886 _d = p; 888 p = d; 889 d = _d; 890 } 891 892 float diff = ((float) p[n]) / srcLenght; 895 896 if (currentWeight > diff) { 897 currentWeight = diff; 898 currentString = origianal; 899 } 900 } 901 902 if (currentWeight <= diffs) { 903 return currentString; 904 } else { 905 return null; 906 } 907 } 908 } 909 | Popular Tags |