KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > util > BeanUtils


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

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 JavaDoc;
18 import java.lang.reflect.InvocationTargetException JavaDoc;
19 import java.lang.reflect.Field JavaDoc;
20 import java.lang.reflect.Modifier JavaDoc;
21 import java.io.PrintStream JavaDoc;
22 import java.io.IOException JavaDoc;
23
24 import com.versant.core.common.BindingSupportImpl;
25 import com.versant.core.common.Debug;
26
27 /**
28  * Static utility methods for working with java beans.
29  */

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 JavaDoc[].class);
49         PRIMITIVE_NAME_MAP.put(Integer.TYPE.getName() + "[]", Integer JavaDoc[].class);
50         PRIMITIVE_NAME_MAP.put(Short.TYPE.getName() + "[]", Short JavaDoc[].class);
51         PRIMITIVE_NAME_MAP.put(Byte.TYPE.getName() + "[]", Byte JavaDoc[].class);
52         PRIMITIVE_NAME_MAP.put(Boolean.TYPE.getName() + "[]", Boolean JavaDoc[].class);
53         PRIMITIVE_NAME_MAP.put(Character.TYPE.getName() + "[]", Character JavaDoc[].class);
54         PRIMITIVE_NAME_MAP.put(Float.TYPE.getName() + "[]", Float JavaDoc[].class);
55         PRIMITIVE_NAME_MAP.put(Double.TYPE.getName() + "[]", Double JavaDoc[].class);
56
57     }
58
59     private static final Class JavaDoc[] STRING_ARGS = new Class JavaDoc[]{String JavaDoc.class};
60     private static final Class JavaDoc[] INT_ARGS = new Class JavaDoc[]{Integer.TYPE};
61     private static final Class JavaDoc[] BOOLEAN_ARGS = new Class JavaDoc[]{Boolean.TYPE};
62
63     private static final String JavaDoc DEFAULT_PROP_FILE = "versant.properties";
64
65     /**
66      * Find and set all properties or public fields on bean from key/value
67      * pairs in props. Only int, String and boolean properties and fields may
68      * be set. This is a NOP if props or bean is null.
69      *
70      * @exception IllegalArgumentException if any are invalid
71      */

72     public static void setProperties(Object JavaDoc bean, Map props)
73             throws IllegalArgumentException JavaDoc {
74         if (props == null || bean == null) return;
75         Class JavaDoc cls = bean.getClass();
76         Object JavaDoc[] args = new Object JavaDoc[1];
77         for (Iterator i = props.entrySet().iterator(); i.hasNext(); ) {
78             Map.Entry e = (Map.Entry)i.next();
79             String JavaDoc prop = (String JavaDoc)e.getKey();
80             String JavaDoc value = (String JavaDoc)e.getValue();
81             Field JavaDoc f = findField(prop, cls, value, args);
82             if (f != null) {
83                 try {
84                     f.set(bean, args);
85                 } catch (Throwable JavaDoc x) {
86                     if (x instanceof InvocationTargetException JavaDoc) {
87                         x = ((InvocationTargetException JavaDoc)x).getTargetException();
88                     }
89                     throw BindingSupportImpl.getInstance().illegalArgument(
90                             x.getClass() + ": " + x.getMessage());
91                 }
92             }
93             Method JavaDoc m = findSetMethod(prop, cls, value, args);
94             try {
95                 m.invoke(bean, args);
96             } catch (IllegalArgumentException JavaDoc x) {
97                 throw x;
98             } catch (Throwable JavaDoc x) {
99                 if (x instanceof InvocationTargetException JavaDoc) {
100                     x = ((InvocationTargetException JavaDoc)x).getTargetException();
101                 }
102                 throw BindingSupportImpl.getInstance().illegalArgument(
103                         x.getClass() + ": " + x.getMessage());
104             }
105         }
106     }
107
108     /**
109      * Set a property on bean. Only int, String and boolean properties may be
110      * set.
111      * @exception IllegalArgumentException if invalid
112      */

113     public static void setProperty(Object JavaDoc bean, String JavaDoc prop, String JavaDoc value)
114             throws IllegalArgumentException JavaDoc {
115         Class JavaDoc cls = bean.getClass();
116         Object JavaDoc[] args = new Object JavaDoc[1];
117         Method JavaDoc m = findSetMethod(prop, cls, value, args);
118         try {
119             m.invoke(bean, args);
120         } catch (IllegalArgumentException JavaDoc x) {
121             throw x;
122         } catch (Throwable JavaDoc x) {
123             if (x instanceof InvocationTargetException JavaDoc) {
124                 x = ((InvocationTargetException JavaDoc)x).getTargetException();
125             }
126             throw BindingSupportImpl.getInstance().illegalArgument(
127                     x.getClass() + ": " + x.getMessage());
128         }
129     }
130
131     private static Field JavaDoc findField(String JavaDoc prop, Class JavaDoc cls, String JavaDoc value,
132             Object JavaDoc[] args) {
133         try {
134             Field JavaDoc f = cls.getField(prop);
135             Class JavaDoc t = f.getType();
136             if (t == Integer.TYPE || t == Integer JavaDoc.class) {
137                 args[0] = toInteger(value, prop);
138             } else if (t == Boolean.TYPE || t == Boolean JavaDoc.class) {
139                 args[0] = toBoolean(value, prop);
140             } else if (t == String JavaDoc.class) {
141                 args[0] = value;
142             } else {
143                 throw BindingSupportImpl.getInstance().internal(
144                         "Unsupported field type: " + f);
145             }
146             return f;
147         } catch (NoSuchFieldException JavaDoc e) {
148             return null;
149         }
150     }
151
152     private static Method JavaDoc findSetMethod(String JavaDoc prop, Class JavaDoc cls, String JavaDoc value,
153             Object JavaDoc[] args) {
154         String JavaDoc name = "set" + Character.toUpperCase(prop.charAt(0)) +
155             prop.substring(1);
156         Method JavaDoc m;
157         try {
158             try {
159                 m = cls.getMethod(name, STRING_ARGS);
160                 args[0] = value;
161             } catch (NoSuchMethodException JavaDoc x) {
162                 try {
163                     m = cls.getMethod(name, INT_ARGS);
164                     args[0] = toInteger(value, prop);
165                 } catch (NoSuchMethodException JavaDoc xx) {
166                     m = cls.getMethod(name, BOOLEAN_ARGS);
167                     args[0] = toBoolean(value, prop);
168                 }
169             }
170         } catch (NoSuchMethodException JavaDoc x) {
171             String JavaDoc pos = getClosestProperty(prop,cls);
172             String JavaDoc 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 JavaDoc toBoolean(String JavaDoc value, String JavaDoc 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 JavaDoc toInteger(String JavaDoc value, String JavaDoc prop) {
197         try {
198             return new Integer JavaDoc(value);
199         } catch (NumberFormatException JavaDoc xx) {
200             throw BindingSupportImpl.getInstance().illegalArgument(
201                 "Expected int value for '" + prop + "' got '" + value + "'");
202         }
203     }
204
205     /**
206      * Process a list of command line arguments in [-propertyname value]+
207      * format setting each on the bean.
208      * @param args Command line arguments as passed to a main method
209      * @param expected Names of allowed properties
210      * @exception IllegalArgumentException if args are invalid
211      */

212     public static void setCommandLineArgs(Object JavaDoc bean, String JavaDoc[] args,
213             String JavaDoc[] expected) throws IllegalArgumentException JavaDoc {
214
215         int n = args.length;
216         Object JavaDoc[] v = new Object JavaDoc[1];
217         for (int i = 0; i < n; i++) {
218             String JavaDoc s = args[i];
219             if (!s.startsWith("-")) {
220                 throw BindingSupportImpl.getInstance().illegalArgument(
221                         "Invalid argument: " + s);
222             }
223             String JavaDoc 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 JavaDoc value = args[i];
237             Method JavaDoc m = findSetMethod(prop, bean.getClass(), value, v);
238             try {
239                 m.invoke(bean, v);
240             } catch (IllegalArgumentException JavaDoc x) {
241                 throw x;
242             } catch (Throwable JavaDoc x) {
243                 if (x instanceof InvocationTargetException JavaDoc) {
244                     x = ((InvocationTargetException JavaDoc)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     /**
255      * Add any properties from a semicolon delimited String ps to props.
256      */

257     public static void parseProperties(String JavaDoc ps, Properties props) {
258         StringTokenizer t = new StringTokenizer(ps, "=", false);
259         for (;;) {
260             String JavaDoc 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 JavaDoc 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     /**
279      * Parse semicolon delimited properties from props and set them on bean.
280      * This can handle String, int and boolean properties.
281      * @exception IllegalArgumentException on errors
282      */

283     public static void parseProperties(String JavaDoc props, Object JavaDoc bean) {
284         if (props == null || props.length() == 0) return;
285         Class JavaDoc cls = bean.getClass();
286         Object JavaDoc[] args = new Object JavaDoc[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 JavaDoc key = props.substring(last, i);
295             int j = props.indexOf(';', ++i);
296             String JavaDoc value;
297             if (j < 0) value = props.substring(i);
298             else value = props.substring(i, j);
299             Method JavaDoc m = findSetMethod(key, cls, value, args);
300             try {
301                 m.invoke(bean, args);
302             } catch (Exception JavaDoc e) {
303                 Throwable JavaDoc t;
304                 if (e instanceof InvocationTargetException JavaDoc) {
305                     t = ((InvocationTargetException JavaDoc)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     /**
319      * Convert a primitive name (int, byte etc.) to a class or null if the
320      * name is not a primitive.
321      */

322     public static Class JavaDoc toClass(String JavaDoc primitiveName) {
323         return (Class JavaDoc)PRIMITIVE_NAME_MAP.get(primitiveName);
324     }
325
326     /**
327      * Load the class with name using loaded. The name may be a primitive
328      * (int, byte etc) or a single dimensional array (e.g. int[]).
329      */

330     public static Class JavaDoc loadClass(String JavaDoc name, boolean initialize,
331             ClassLoader JavaDoc loader) throws ClassNotFoundException JavaDoc {
332         Class JavaDoc 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     /**
344      * Create a new instance of cname using loader. It must be an instance of
345      * mustBe.
346      */

347     public static Object JavaDoc newInstance(String JavaDoc cname, ClassLoader JavaDoc loader, Class JavaDoc mustBe) {
348         try {
349             Class JavaDoc 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 JavaDoc e) {
356             if( BindingSupportImpl.getInstance().isOwnException(e) )
357             {
358                 throw (RuntimeException JavaDoc)e;
359             }
360             throw BindingSupportImpl.getInstance().runtime(
361                     "Unable to create instance of " + cname + ": " +
362                     e.getMessage(), e);
363         }
364     }
365
366     /**
367      * Get the value of a property of bean.
368      */

369     public static Object JavaDoc getPropertyValue(Object JavaDoc bean, String JavaDoc property)
370             throws Exception JavaDoc {
371         Class JavaDoc cls = bean.getClass();
372         property = Character.toUpperCase(property.charAt(0)) +
373                 property.substring(1);
374         Method JavaDoc m;
375         try {
376             m = cls.getMethod("get" + property, null);
377         } catch (NoSuchMethodException JavaDoc e) {
378             m = cls.getMethod("is" + property, null);
379         }
380         return m.invoke(bean, null);
381     }
382
383     /**
384      * Fill o by introspecting all of its public non-static, non-final fields
385      * that are int, Integer, boolean, Boolean or String and looking for
386      * properties named prefix + fieldname to populate them.
387      */

388     public static void fillFields(Object JavaDoc o, String JavaDoc prefix, Map props,
389             Set fieldsToIgnore) {
390         Field JavaDoc[] a = o.getClass().getFields();
391         for (int i = 0; i < a.length; i++) {
392             Field JavaDoc 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 JavaDoc name = f.getName();
399             if (fieldsToIgnore != null && fieldsToIgnore.contains(name)) {
400                 continue;
401             }
402             String JavaDoc prop = prefix + name;
403             String JavaDoc value = (String JavaDoc)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 JavaDoc t) {
412         return t == Integer.TYPE || t == Integer JavaDoc.class
413             || t == Boolean.TYPE || t == Boolean JavaDoc.class
414             || t == String JavaDoc.class;
415     }
416
417     /**
418      * Set field f on o converting value to the correct type for the field.
419      * Fields of int, Integer, boolean, Boolean and String are suppported.
420      */

421     private static void setFieldValue(Field JavaDoc f, Object JavaDoc o, String JavaDoc value,
422             String JavaDoc name) {
423         Class JavaDoc t = f.getType();
424         Object JavaDoc arg;
425         if (t == Integer.TYPE || t == Integer JavaDoc.class) {
426             arg = toInteger(value, name);
427         } else if (t == Boolean.TYPE || t == Boolean JavaDoc.class) {
428             arg = toBoolean(value, name);
429         } else if (t == String JavaDoc.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 JavaDoc x) {
438             if (x instanceof InvocationTargetException JavaDoc) {
439                 x = ((InvocationTargetException JavaDoc)x).getTargetException();
440             }
441             throw BindingSupportImpl.getInstance().illegalArgument(
442                     x.getClass() + ": " + x.getMessage());
443         }
444     }
445
446     /**
447      * The result of a call to processCmdline.
448      */

449     public static class CmdLineResult {
450         public HashSet fieldsFilled = new HashSet();
451         public Properties properties;
452     }
453
454     /**
455      * <p>Process command line arguments. Arguments starting with a dash are
456      * expected to match the names of public fields in o (like
457      * {@link #fillFields}) with non-boolean fields requiring an argument.
458      * If a boolean field does not have an argument then it is set to true.</p>
459      *
460      * <p>If hasProps is true then there is an implicit -p arguement to
461      * specify the resource name or filename of a properties file to load and
462      * return. The default name is versant.properties. The argument is first
463      * treated as a file and if this fails then as a resource. System
464      * properties starting with "versant." or "javax.jdo.option." are added
465      * after the properties are loaded. Finally command line arguments of the
466      * form key=value are added i.e. they override any previous value.</p>
467      *
468      * <p>Errors are printed to System.err followed by usage information and
469      * an IllegalArgumentException is thrown.</p>
470      *
471      * <p>If one of the args is /? or -help or --help then the usage is printed
472      * and an IllegalArgumentException is thrown.</p>
473      *
474      * @return The fieldsFilled set contains the names of all fields that were
475      * set from the command line. If hasProps is true then the properties field
476      * on the result holds all properties with overrides already applied
477      * otherwise it is null.
478      */

479     public static CmdLineResult processCmdLine(String JavaDoc[] args, ClassLoader JavaDoc loader,
480             Object JavaDoc o, String JavaDoc[] requiredFields, String JavaDoc toolName,
481             String JavaDoc toolDescription, boolean hasProps) {
482         try {
483             CmdLineResult res = new CmdLineResult();
484             Properties overrides = hasProps ? new Properties() : null;
485             String JavaDoc propFileName = DEFAULT_PROP_FILE;
486             for (int i = 0; i < args.length; ) {
487                 String JavaDoc 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 JavaDoc 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 JavaDoc f = o.getClass().getField(key);
505                         Class JavaDoc t = f.getType();
506                         int m = f.getModifiers();
507                         if (Modifier.isFinal(m) || Modifier.isStatic(m)
508                                 || !isSupportedFieldType(t)) {
509                             throw new NoSuchFieldException JavaDoc();
510                         }
511                         String JavaDoc value = i < args.length ? args[i] : null;
512                         if (value.startsWith("-")) {
513                             value = null;
514                         }
515                         if (value == null) {
516                             if (t == Boolean JavaDoc.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 JavaDoc 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 JavaDoc key = arg.substring(0, i);
538                     String JavaDoc 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 JavaDoc 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 JavaDoc key = (String JavaDoc)i.next();
561                     if (key.startsWith("versant.")
562                             || key.startsWith("javax.jdo.option.")) {
563                         String JavaDoc 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 JavaDoc key = (String JavaDoc)i.next();
571                     String JavaDoc 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 JavaDoc 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     /**
588      * <p>Print command line usage information by introspecting o to find all
589      * of its public non-static, non-final fields that are int, Integer,
590      * boolean, Boolean or String. For each field a public static final
591      * String field named HELP_fieldname is used to provided a description
592      * of the field if present. The values of the fields in o are assumed
593      * to be the defaults.</p>
594      *
595      * <p>If hasProps is true the information on how to specify key=value
596      * properties is also printed.</p>
597      */

598     public static void printUsage(Object JavaDoc o, String JavaDoc[] requiredFields,
599             String JavaDoc toolName, String JavaDoc toolDescription, boolean hasProps,
600             PrintStream JavaDoc out) {
601         Field JavaDoc[] all = o.getClass().getFields();
602
603         // find all of the help text
604
HashMap helpMap = new HashMap();
605         for (int i = 0; i < all.length; i++) {
606             Field JavaDoc f = all[i];
607             int m = f.getModifiers();
608             if (!(Modifier.isFinal(m) && Modifier.isStatic(m))
609                     || f.getType() != String JavaDoc.class) {
610                 continue;
611             }
612             String JavaDoc name = f.getName();
613             if (name.startsWith("HELP_")) {
614                 try {
615                     helpMap.put(name.substring(5), f.get(null));
616                 } catch (IllegalAccessException JavaDoc e) {
617                     throw BindingSupportImpl.getInstance().internal(
618                             e.toString(), e);
619                 }
620             }
621         }
622
623         // map all the options to their default values
624
HashMap defaults = new HashMap();
625         ArrayList options = new ArrayList();
626         HashMap fields = new HashMap();
627         int longestOp = 0;
628         if (hasProps) {
629             String JavaDoc s = "-p " + DEFAULT_PROP_FILE;
630             longestOp = s.length();
631         }
632         for (int i = 0; i < all.length; i++) {
633             Field JavaDoc 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 JavaDoc op = f.getName();
640             options.add(op);
641             fields.put(op, f);
642             String JavaDoc def;
643             try {
644                 Object JavaDoc v = f.get(o);
645                 def = v == null ? null : v.toString();
646             } catch (IllegalAccessException JavaDoc e) {
647                 throw BindingSupportImpl.getInstance().internal(
648                         e.toString(), e);
649             }
650             String JavaDoc 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         // now print everything
661
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 JavaDoc op = (String JavaDoc)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 JavaDoc op, HashMap fields,
702             HashMap defaults, HashMap helpMap, int longestOp, PrintStream JavaDoc out) {
703         Field JavaDoc f = (Field JavaDoc)fields.get(op);
704         String JavaDoc def = defaults == null ? null : (String JavaDoc)defaults.get(op);
705         String JavaDoc help = (String JavaDoc)helpMap.get(op);
706         if (help == null) {
707             Class JavaDoc t = f.getType();
708             if (t == Integer JavaDoc.class || t == Integer.TYPE) {
709                 help = "int";
710             } else if (t == Boolean JavaDoc.class || t == Boolean.TYPE) {
711                 help = "true|false";
712             } else if (t == String JavaDoc.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 JavaDoc op, String JavaDoc def, String JavaDoc help,
722             int longestOp, PrintStream JavaDoc out) {
723         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
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     /**
738      * Get the closest property that can be set to this s, or return null, if
739      * they are too diffrent.
740      */

741     private static String JavaDoc getClosestProperty(String JavaDoc s, Class JavaDoc cls) {
742         Method JavaDoc[] methods = cls.getMethods();
743         int j = 0;
744         for (int i = 0; i < methods.length; i++) {
745             String JavaDoc methodName = methods[i].getName();
746             if (methodName.startsWith("set") && methodName.length() > 3) {
747                 Class JavaDoc 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 JavaDoc[] targets = new String JavaDoc[j];
758         j = 0;
759         for (int i = 0; i < methods.length; i++) {
760             String JavaDoc methodName = methods[i].getName();
761             if (methodName.startsWith("set") && methodName.length() > 3) {
762                 Class JavaDoc 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     /**
776      * Does this class contain this property
777      */

778     private static boolean containsProperties(Class JavaDoc cls, String JavaDoc prop){
779         return getAllProperties(cls).contains(prop);
780     }
781
782     /**
783      * Get all the valid properties for this class.
784      */

785     public static Set getAllProperties(Class JavaDoc cls) {
786         Method JavaDoc[] methods = cls.getMethods();
787         Set set = new HashSet();
788         for (int i = 0; i < methods.length; i++) {
789             String JavaDoc methodName = methods[i].getName();
790             if (methodName.startsWith("set") && methodName.length() > 3) {
791                 String JavaDoc prop = Character.toLowerCase(methodName.charAt(3)) +
792                         (methodName.length() > 4 ? methodName.substring(4) : "");
793                 set.add(prop);
794             }
795
796         }
797
798         Field JavaDoc fields[] = cls.getFields();
799         for (int i = 0; i < fields.length; i++) {
800             String JavaDoc fieldName = fields[i].getName();
801             String JavaDoc 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     /**
811      * format the properties.
812      */

813     private static String JavaDoc getAllPropsFormatted(Class JavaDoc 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 JavaDoc buff = new StringBuffer JavaDoc();
821             for (Iterator iter = list.iterator(); iter.hasNext();) {
822                 String JavaDoc name = (String JavaDoc) iter.next();
823
824                 buff.append(name);
825                 buff.append(';');
826             }
827             return buff.toString();
828         }
829     }
830
831     /**
832      * This method uses a Levenshtein Distance algorithm to find the closest
833      * match.
834      */

835     private static String JavaDoc getClosest(String JavaDoc s, String JavaDoc[] 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(); // length of s
846

847         float srcLenght = (float) n;
848
849         float currentWeight = 1;
850         String JavaDoc currentString = null;
851         Set set = map.keySet();
852         for (Iterator iter = set.iterator(); iter.hasNext();) {
853             String JavaDoc origianal = (String JavaDoc) iter.next();
854             String JavaDoc t = (String JavaDoc) map.get(origianal);
855
856
857             int m = t.length(); // length of t
858

859
860             int p[] = new int[n + 1]; //'previous' cost array, horizontally
861
int d[] = new int[n + 1]; // cost array, horizontally
862
int _d[]; //placeholder to assist in swapping p and d
863

864             // indexes into strings s and t
865
int i; // iterates through s
866
int j; // iterates through t
867

868             char t_j; // jth character of t
869

870             int cost; // cost
871

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                     // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
883
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
884                 }
885
886                 // copy current distance counts to 'previous row' distance counts
887
_d = p;
888                 p = d;
889                 d = _d;
890             }
891
892             // our last action in the above loop was to switch d and p, so p now
893
// actually has the most recent cost counts
894
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