Source Code Cross Referenced for Classes.java in  » Ajax » zk » org » zkoss » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » zk » org.zkoss.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Classes.java
0002:
0003:        {{IS_NOTE
0004:
0005:        	Purpose: Utilities to handle Class
0006:        	Description:
0007:        	History:
0008:        	 2001/4/19, Tom M. Yeh: Created.
0009:
0010:        }}IS_NOTE
0011:
0012:        Copyright (C) 2001 Potix Corporation. All Rights Reserved.
0013:
0014:        {{IS_RIGHT
0015:        	This program is distributed under GPL Version 2.0 in the hope that
0016:        	it will be useful, but WITHOUT ANY WARRANTY.
0017:        }}IS_RIGHT
0018:         */
0019:        package org.zkoss.lang;
0020:
0021:        import java.util.Map;
0022:        import java.util.HashMap;
0023:        import java.util.List;
0024:        import java.util.LinkedList;
0025:        import java.util.Collection;
0026:        import java.util.Arrays;
0027:        import java.util.Date;
0028:        import java.lang.reflect.Constructor;
0029:        import java.lang.reflect.AccessibleObject;
0030:        import java.lang.reflect.Method;
0031:        import java.lang.reflect.Field;
0032:        import java.lang.reflect.InvocationTargetException;
0033:        import java.lang.reflect.Modifier;
0034:        import java.math.BigDecimal;
0035:        import java.math.BigInteger;
0036:
0037:        import org.zkoss.mesg.MCommon;
0038:        import org.zkoss.mesg.Messages;
0039:        import org.zkoss.lang.Strings;
0040:        import org.zkoss.lang.Objects;
0041:        import org.zkoss.math.BigDecimals;
0042:        import org.zkoss.math.BigIntegers;
0043:        import org.zkoss.util.MultiCache;
0044:        import org.zkoss.util.Cache;
0045:        import org.zkoss.util.IllegalSyntaxException;
0046:        import org.zkoss.util.logging.Log;
0047:
0048:        /**
0049:         * Utilities to handle java.lang.Class
0050:         *
0051:         * @author tomyeh
0052:         */
0053:        public class Classes {
0054:            private static final Log log = Log.lookup(Classes.class);
0055:
0056:            /**
0057:             * Instantiates a new instance of the specified class with
0058:             * the specified arguments and argument types.
0059:             *
0060:             * <p>Note only public constructors are searched.
0061:             *
0062:             * @param cls the class of the instance to create
0063:             * @param argTypes the argument types of the constructor to inovke
0064:             * @param args the arguments to initialize the instance
0065:             * @return the new instance
0066:             *
0067:             * @exception NoSuchMethodException if a matching method is not found
0068:             * @exception InstantiationException if the class that declares the
0069:             * underlying constructor represents an abstract class
0070:             * @exception InvocationTargetException if the underlying constructor
0071:             * throws an exception
0072:             * @see #newInstance(String, Class[], Object[])
0073:             */
0074:            public static final Object newInstance(Class cls, Class[] argTypes,
0075:                    Object[] args) throws NoSuchMethodException,
0076:                    InstantiationException, InvocationTargetException,
0077:                    IllegalAccessException {
0078:                return cls.getConstructor(argTypes).newInstance(args);
0079:            }
0080:
0081:            /**
0082:             * Instantiates a new instance of the specified class with the
0083:             * specified argument.
0084:             *
0085:             * <p>It searches all contructor for the first one that matches
0086:             * the specified arguments.
0087:             * @since 3.0.1
0088:             */
0089:            public static final Object newInstance(Class cls, Object[] args)
0090:                    throws NoSuchMethodException, InstantiationException,
0091:                    InvocationTargetException, IllegalAccessException {
0092:                if (args == null || args.length == 0)
0093:                    return cls.newInstance();
0094:
0095:                final Constructor[] cs = cls.getConstructors();
0096:                for (int j = 0; j < cs.length; ++j) {
0097:                    final Class[] types = cs[j].getParameterTypes();
0098:                    if (types.length == args.length) {
0099:                        for (int k = args.length;;) {
0100:                            if (--k < 0)
0101:                                return cs[j].newInstance(args);
0102:
0103:                            final Object arg = args[k];
0104:                            final Class type = types[k];
0105:                            if (arg == null)
0106:                                if (type.isPrimitive())
0107:                                    break; //mismatch
0108:                                else
0109:                                    continue; //match
0110:
0111:                            if (type.isInstance(arg))
0112:                                continue; //match
0113:                            if (!type.isPrimitive()
0114:                                    || !Primitives.toWrapper(type).isInstance(
0115:                                            arg))
0116:                                break; //mismatch
0117:                        }
0118:                    }
0119:                }
0120:
0121:                final StringBuffer sb = new StringBuffer(80)
0122:                        .append("No contructor compatible with ");
0123:                for (int j = 0; j < args.length; ++j)
0124:                    sb.append(j != 0 ? ", " : "[").append(
0125:                            args[j] != null ? args[j].getClass().getName()
0126:                                    : null);
0127:                throw new NoSuchMethodException(sb.append("] in ").append(
0128:                        cls.getName()).toString());
0129:            }
0130:
0131:            /**
0132:             * Instantiates a new instance of the specified class name
0133:             * with the specified arguments.
0134:             *
0135:             * <p>It uses Class.forName to get the class.
0136:             *
0137:             * @param clsName the class name of the instance to create
0138:             * @param argTypes the argument types of the constructor to inovke
0139:             * @param args the arguments to initialize the instance
0140:             * @return the new instance
0141:             *
0142:             * @exception NoSuchMethodException if a matching method is not found
0143:             * @exception InstantiationException if the class that declares the
0144:             * underlying constructor represents an abstract class
0145:             * @exception InvocationTargetException if the underlying constructor
0146:             * throws an exception
0147:             * @exception ClassNotFoundException if the specified class name is not a class
0148:             * @see #newInstance(Class, Class[], Object[])
0149:             */
0150:            public static final Object newInstance(String clsName,
0151:                    Class[] argTypes, Object[] args)
0152:                    throws NoSuchMethodException, InstantiationException,
0153:                    InvocationTargetException, ClassNotFoundException,
0154:                    IllegalAccessException {
0155:                return newInstance(Class.forName(clsName), argTypes, args);
0156:            }
0157:
0158:            /**
0159:             * Creates and initializes a new instance of the specified class name
0160:             * with the specified arguments, by use of {@link #forNameByThread}.
0161:             *
0162:             * <p>It uses {@link #forNameByThread} to get the class.
0163:             *
0164:             * @param clsName the class name of the instance to create
0165:             * @param argTypes the argument types of the constructor to inovke
0166:             * @param args the arguments to initialize the instance
0167:             * @return the new instance
0168:             *
0169:             * @exception NoSuchMethodException if a matching method is not found
0170:             * @exception InstantiationException if the class that declares the
0171:             * underlying constructor represents an abstract class
0172:             * @exception InvocationTargetException if the underlying constructor
0173:             * throws an exception
0174:             * @exception ClassNotFoundException if the specified class name is not a class
0175:             * @see #newInstance(Class, Class[], Object[])
0176:             */
0177:            public static final Object newInstanceByThread(String clsName,
0178:                    Class[] argTypes, Object[] args)
0179:                    throws NoSuchMethodException, InstantiationException,
0180:                    InvocationTargetException, ClassNotFoundException,
0181:                    IllegalAccessException {
0182:                return newInstance(forNameByThread(clsName), argTypes, args);
0183:            }
0184:
0185:            /**
0186:             * Creates and initializes a new instance of the specified class name
0187:             * with default constructor, by use of {@link #forNameByThread}.
0188:             */
0189:            public static final Object newInstanceByThread(String clsName)
0190:                    throws NoSuchMethodException, InstantiationException,
0191:                    InvocationTargetException, ClassNotFoundException,
0192:                    IllegalAccessException {
0193:                return newInstance(forNameByThread(clsName), null, null);
0194:            }
0195:
0196:            /**
0197:             * Returns the Class object of the specified class name, using
0198:             * the current thread's context class loader.
0199:             *
0200:             * <p>In additions, it handles the primitive types, such as int and double.
0201:             *
0202:             * @param clsName fully qualified name of the desired class
0203:             * @return the Class object representing the desired class
0204:             * @exception ClassNotFoundException if the class cannot be located by the specified class loader
0205:             */
0206:            public static final Class forNameByThread(String clsName)
0207:                    throws ClassNotFoundException {
0208:                clsName = toInternalForm(clsName);
0209:                final Class cls = Primitives.toClass(clsName);
0210:                return cls != null ? cls : Class.forName(clsName, true, Thread
0211:                        .currentThread().getContextClassLoader());
0212:            }
0213:
0214:            /**
0215:             * Change class name to internal form (e.g. byte[] -> [B). If already in
0216:             * internal form, then just return it.
0217:             */
0218:            public static final String toInternalForm(String clsName) {
0219:                final int k = clsName.indexOf('[');
0220:                if (k <= 0) { //not an array, or already in internal form
0221:                    return clsName; //just return
0222:                }
0223:
0224:                //component class
0225:                final String elm = clsName.substring(0, k).trim();
0226:                if (elm.length() == 0)
0227:                    throw new IllegalArgumentException(
0228:                            "Not a legal class name: \"" + clsName + '"');
0229:
0230:                //array depth
0231:                boolean leftb = false;
0232:                final String stub = clsName.substring(k);
0233:                final StringBuffer sb = new StringBuffer(128);
0234:                for (int j = 0; j < stub.length(); j++) {
0235:                    final char ch = stub.charAt(j);
0236:                    if (ch == '[') {
0237:                        if (leftb)
0238:                            throw new IllegalArgumentException(
0239:                                    "Not a legal class name: \"" + clsName
0240:                                            + '"');
0241:                        leftb = true;
0242:                        sb.append('[');
0243:                    } else if (ch == ']') {
0244:                        if (!leftb)
0245:                            throw new IllegalArgumentException(
0246:                                    "Not a legal class name: \"" + clsName
0247:                                            + '"');
0248:                        leftb = false;
0249:                    }
0250:                }
0251:                if (leftb)
0252:                    throw new IllegalArgumentException(
0253:                            "Not a legal class name: \"" + clsName + '"');
0254:
0255:                final char code = Primitives.getNotation(elm);
0256:                if (code != (char) 0) {//primitive array
0257:                    sb.append(code);
0258:                } else {//object array
0259:                    sb.append('L').append(elm).append(';');
0260:                }
0261:                return sb.toString();
0262:            }
0263:
0264:            /**
0265:             * Gets the topmost interface of the specified class or interface that
0266:             * implements or extends the specified interface.
0267:             * For example, if A extends B, and C implements A,
0268:             * then getTopInterface(C, B) returns A.
0269:             *
0270:             * <p>The interfaces implemented by the specified class is checked first,
0271:             * and then the subclass.
0272:             *
0273:             * @param cls the class or interface
0274:             * @param subIF the sub-interface
0275:             * @return the topmost interface extending subIF, or null if subIF
0276:             * is not implemented by cls
0277:             */
0278:            public static Class getTopmostInterface(Class cls, Class subIF) {
0279:                if (cls.isInterface())
0280:                    return subIF.isAssignableFrom(cls) ? cls : null;
0281:
0282:                while (cls != null) {
0283:                    final Class[] ifs = cls.getInterfaces();
0284:                    for (int j = 0; j < ifs.length; ++j)
0285:                        if (subIF.isAssignableFrom(ifs[j]))
0286:                            return ifs[j];
0287:
0288:                    cls = cls.getSuperclass();
0289:                }
0290:                return null;
0291:            }
0292:
0293:            /** Returns all interfaces that are implemented by the specified class.
0294:             * <p>Unlike {@link Class#getInterfaces}, it recursively searches
0295:             * for all derived classes.
0296:             */
0297:            public static Class[] getAllInterfaces(Class cls) {
0298:                final List l = new LinkedList();
0299:                while (cls != null) {
0300:                    final Class[] ifs = cls.getInterfaces();
0301:                    for (int j = 0; j < ifs.length; ++j)
0302:                        l.add(ifs[j]);
0303:
0304:                    cls = cls.getSuperclass();
0305:                }
0306:                final int sz = l.size();
0307:                return (Class[]) l.toArray(new Class[sz]);
0308:            }
0309:
0310:            /**
0311:             * Tests whether a class contains the specified method.
0312:             * Only public methods are tested.
0313:             *
0314:             * @param cls the class to test
0315:             * @param name the method name
0316:             * @param paramTypes the list of parameter types
0317:             * @return true if it contains the method
0318:             */
0319:            public static final boolean containsMethod(Class cls, String name,
0320:                    Class[] paramTypes) {
0321:                try {
0322:                    cls.getMethod(name, paramTypes);
0323:                    return true;
0324:                } catch (NoSuchMethodException ex) {//no found
0325:                    return false;
0326:                }
0327:            }
0328:
0329:            /** Corrects a string to a valid Java name.
0330:             * Currently, it only removes '-' and capitalizes the succeeding
0331:             * character. Example, 'field-name' becomes 'fieldName'.
0332:             */
0333:            public final static String correctFieldName(String name) {
0334:                int j = name.indexOf('-');
0335:                if (j < 0)
0336:                    return name; //nothing to change
0337:
0338:                for (final StringBuffer sb = new StringBuffer(name);;) {
0339:                    sb.deleteCharAt(j);
0340:                    if (sb.length() == j)
0341:                        return sb.toString();
0342:
0343:                    sb.setCharAt(j, Character.toUpperCase(sb.charAt(j)));
0344:
0345:                    j = sb.indexOf("-", j);
0346:                    if (j < 0)
0347:                        return sb.toString();
0348:                }
0349:            }
0350:
0351:            /**
0352:             * Convert an attribute name, returned by toAttributeName, to
0353:             * a method name.
0354:             *
0355:             * <p>toMethodName("true", "is") => "isTrue"<br>
0356:             * toMethodName("true", "") => "true"
0357:             *
0358:             * @param attrName the attribute name
0359:             * @param prefix the prefix; one of is, get and set
0360:             * @return the method name
0361:             * @see #toAttributeName
0362:             */
0363:            public static final String toMethodName(String attrName,
0364:                    String prefix) {
0365:                if (prefix.length() == 0)
0366:                    return attrName;
0367:
0368:                StringBuffer sb = new StringBuffer(prefix);
0369:                char[] buf = attrName.toCharArray();
0370:                buf[0] = Character.toUpperCase(buf[0]);
0371:                return sb.append(buf).toString();
0372:            }
0373:
0374:            /**
0375:             * Tests if a method name is an attribute, i.e., prefixing with is,
0376:             * get or set. Caller could then test if it is a setter or getter
0377:             * by charAt(0)=='s'.
0378:             *
0379:             * <p>Note 'set' is considered as an attribute, whose name is an
0380:             * empty string.
0381:             *
0382:             * @param methodName the method name to test
0383:             * @return true if it is setter or getter
0384:             */
0385:            public static final boolean isAttribute(String methodName) {
0386:                int len = methodName.length();
0387:                if (len < 2)
0388:                    return false;
0389:
0390:                int j;
0391:                switch (methodName.charAt(0)) {
0392:                case 's':
0393:                case 'g':
0394:                    if (len < 3 || methodName.charAt(1) != 'e'
0395:                            || methodName.charAt(2) != 't')
0396:                        return false;
0397:                    j = 3;
0398:                    break;
0399:                case 'i':
0400:                    if (methodName.charAt(1) != 's')
0401:                        return false;
0402:                    j = 2;
0403:                    break;
0404:                default:
0405:                    return false;
0406:                }
0407:                return j == len || Character.isUpperCase(methodName.charAt(j));
0408:            }
0409:
0410:            /**
0411:             * Converts a method name to an attribute name by removing the prefix
0412:             * is, get or set, or null if it doesn't start with is, get or set.
0413:             *
0414:             * <p>The code is optimized for better performance.
0415:             *
0416:             * @param methodName the method name
0417:             * @return the attribute name; null if it is not an attribute name
0418:             * @see #toMethodName
0419:             */
0420:            public static final String toAttributeName(String methodName) {
0421:                int len = methodName.length();
0422:                if (len < 2)
0423:                    return null;
0424:
0425:                int j;
0426:                switch (methodName.charAt(0)) {
0427:                case 's':
0428:                case 'g':
0429:                    if (len < 3 || methodName.charAt(1) != 'e'
0430:                            || methodName.charAt(2) != 't')
0431:                        return null;
0432:                    j = 3;
0433:                    break;
0434:                case 'i':
0435:                    if (methodName.charAt(1) != 's')
0436:                        return null;
0437:                    j = 2;
0438:                    break;
0439:                default:
0440:                    return null;
0441:                }
0442:                if (j == len || Character.isUpperCase(methodName.charAt(j))) {
0443:                    char[] buf = new char[len - j];
0444:                    if (buf.length > 0) {
0445:                        methodName.getChars(j, len, buf, 0);
0446:                        buf[0] = Character.toLowerCase(buf[0]);
0447:                    }
0448:                    return new String(buf);
0449:                }
0450:                return null;
0451:            }
0452:
0453:            //--Support Class--
0454:            /**The method info class used for {@link #parseMethod(String signature)}.
0455:             * This info describe the method return type, method name and two collections for
0456:             * arguments type and arguments name;
0457:             */
0458:            public static class MethodInfo {
0459:                /** The return type (class name), or null if no specified. */
0460:                public String returnType;
0461:                public String method;
0462:                public String[] argTypes;
0463:                public String[] argNames;
0464:                public String throwsEx;
0465:
0466:                //constructor
0467:                protected MethodInfo(String r, String m, String[] argTs,
0468:                        String[] argNs, String tEx) {
0469:                    returnType = r;
0470:                    method = m;
0471:                    argTypes = argTs;
0472:                    argNames = argNs;
0473:                    throwsEx = tEx;
0474:                }
0475:            }
0476:
0477:            /**
0478:             * Gets the method information from a signature. 
0479:             * It returns a method info with the return type, method name and two collections 
0480:             * of arguments type and arguments name.
0481:             *
0482:             * @param signature the method signature.
0483:             * @return MethodInfo The method information including return type, method name
0484:             *			and two collections for argument type annd arguments name.
0485:             */
0486:            public static final MethodInfo parseMethod(String signature)
0487:                    throws IllegalSyntaxException {
0488:                int len = signature.length();
0489:                int j = Strings.skipWhitespaces(signature, 0);
0490:                int k = Strings.anyOf(signature, "( \t\n\r", j);
0491:                k = Strings.skipWhitespaces(signature, k);
0492:                if (k >= len)
0493:                    throw new IllegalSyntaxException(signature);
0494:
0495:                String returnType = null;
0496:                char cc = signature.charAt(k);
0497:                if (cc != '(') {
0498:                    //skip the return type
0499:                    returnType = signature.substring(j, k).trim();
0500:                    //
0501:                    j = k;
0502:                    k = signature.indexOf('(', j + 1);
0503:                    if (k < 0)
0504:                        throw new IllegalSyntaxException(signature);
0505:                }
0506:                String method = signature.substring(j, k).trim();
0507:
0508:                Collection argTypes = new LinkedList();
0509:                Collection argNames = new LinkedList();
0510:                do {
0511:                    j = Strings.skipWhitespaces(signature, k + 1);
0512:                    if (signature.charAt(j) == ')')
0513:                        break;
0514:                    k = Strings.anyOf(signature, ",) \t\n\r", j);
0515:                    k = Strings.skipWhitespaces(signature, k);
0516:                    if (k >= len)
0517:                        throw new IllegalSyntaxException(signature);
0518:                    argTypes.add(signature.substring(j, k).trim());
0519:
0520:                    cc = signature.charAt(k);
0521:                    if (cc != ',' && cc != ')') { //parameter name found
0522:                        k = Strings.anyOf(signature, ",) \t\n\r", j = k);
0523:                        k = Strings.skipWhitespaces(signature, k);
0524:                        argNames.add(signature.substring(j, k).trim());
0525:
0526:                        k = Strings.anyOf(signature, ",)", k);
0527:                        if (k >= len)
0528:                            throw new IllegalSyntaxException(signature);
0529:                    } else {
0530:                        argNames.add(""); //no name specified
0531:                    }
0532:                } while (signature.charAt(k) == ',');
0533:
0534:                assert argTypes.size() == argNames.size();
0535:
0536:                //process throws ...
0537:                String strThrows = "throws";
0538:                String tEx = null;
0539:                j = signature.indexOf(strThrows, k);
0540:                if (j >= k && j < len) { //got throws
0541:                    k = signature.indexOf(';', j);
0542:                    if (k >= 0)
0543:                        tEx = signature.substring(j + strThrows.length(), k)
0544:                                .trim();
0545:                    else
0546:                        tEx = signature.substring(j + strThrows.length(), len)
0547:                                .trim();
0548:                }
0549:
0550:                return new MethodInfo(returnType, method, (String[]) argTypes
0551:                        .toArray(new String[argTypes.size()]),
0552:                        (String[]) argNames
0553:                                .toArray(new String[argNames.size()]), tEx);
0554:            }
0555:
0556:            /**
0557:             * Gets the method based on the signature. It also returns the parameter
0558:             * names to the params list.
0559:             *
0560:             * <p>Like {@link #getMethodInPublic(Class, String, Class[])}, it returns
0561:             * only public method in a public class/interface.
0562:             *
0563:             * <p>For example, "find(java.lang.String name)" will return
0564:             * the method with one String-typed argument and params will hold "name".
0565:             * The return type is optional (actualy ignored).
0566:             *
0567:             * <p>If params is null, the parameter names are not returned and
0568:             * the signature could be simplified as "find(java.lang.String)".
0569:             *
0570:             * <p>A cache mechanism is implemented, so you don't need to cache it
0571:             * again in the caller.
0572:             *
0573:             * @param cls the class to look
0574:             * @param signature the method signature; the return type is optional
0575:             * @param params the collection to hold the parameter names returned;
0576:             * null means no parameter names to return
0577:             */
0578:            public static final Method getMethodBySignature(Class cls,
0579:                    String signature, Collection params)
0580:                    throws NoSuchMethodException, ClassNotFoundException {
0581:                MethodInfo mi = parseMethod(signature);
0582:
0583:                LinkedList argTypes = new LinkedList();
0584:                for (int i = 0; i < mi.argTypes.length; i++) {
0585:                    argTypes.add(forNameByThread(mi.argTypes[i]));
0586:                    if (params != null)
0587:                        params.add(mi.argNames[i]); //param name found
0588:                }
0589:
0590:                return getMethodInPublic(cls, mi.method, (Class[]) argTypes
0591:                        .toArray(new Class[argTypes.size()]));
0592:            }
0593:
0594:            /**
0595:             * Gets the method that is declared in a public class/interface.
0596:             *
0597:             * <p>Class.getMethod returns a public method but the class itself
0598:             * might not be public. However, in many cases, that class
0599:             * also implements a public interface or class.
0600:             *
0601:             * <p>This method will search all its public classes to look for
0602:             * the method that is 'real' public.
0603:             *
0604:             * <p>NoSuchMethodException is thrown if no public 
0605:             * class/interface is found to have the method.
0606:             */
0607:            public static final Method getMethodInPublic(Class cls,
0608:                    String name, Class[] argTypes) throws NoSuchMethodException {
0609:                final Method m = cls.getMethod(name, argTypes);
0610:                if (Modifier.isPublic(m.getDeclaringClass().getModifiers()))
0611:                    return m;
0612:
0613:                final Class[] clses = cls.getInterfaces();
0614:                for (int j = 0; j < clses.length; ++j)
0615:                    try {
0616:                        return getMethodInPublic(clses[j], name, argTypes);
0617:                    } catch (NoSuchMethodException ex) { //ignore it
0618:                    }
0619:
0620:                final Class basecls = cls.getSuperclass();
0621:                if (basecls != null)
0622:                    try {
0623:                        return getMethodInPublic(basecls, name, argTypes);
0624:                    } catch (NoSuchMethodException ex) { //ignore it
0625:                    }
0626:
0627:                throw new NoSuchMethodException(cls + ": " + name + " "
0628:                        + Objects.toString(argTypes));
0629:            }
0630:
0631:            /** Gets one of the close method by specifying the arguments, rather
0632:             * than the argument types. It actually calls {@link #getCloseMethod}.
0633:             */
0634:            public static final Method getMethodByObject(Class cls,
0635:                    String name, Object[] args) throws NoSuchMethodException {
0636:                if (args == null)
0637:                    return getMethodInPublic(cls, name, null);
0638:
0639:                final Class[] argTypes = new Class[args.length];
0640:                for (int j = 0; j < args.length; ++j)
0641:                    argTypes[j] = args[j] != null ? args[j].getClass() : null;
0642:                return getCloseMethod(cls, name, argTypes);
0643:            }
0644:
0645:            /**
0646:             * Gets one of the close methods -- a close method is a method
0647:             * with the same name and the compatible argument type.
0648:             * By compatiable we mean the real method's argument type is
0649:             * the same as or a superclass of the specified one.
0650:             *
0651:             * <p>It might not be the best fit one, unless there is a method
0652:             * whose argument types are exactly argTypes.
0653:             *
0654:             * <p>You might specify the exact number in argTypes. If any of them is
0655:             * unknwon, use null. Example, in the following, the first argument could
0656:             * be anything and the second is anything deriving from MyClass:<br>
0657:             * <code>new Class[] {null, MyClass.class}</code>
0658:             *
0659:             * <p>Note: if an argument accepts int, then Integer is considered
0660:             * as compatible (unlike Class.getMethod). So are long, byte...
0661:             *
0662:             * <p>A cache mechanism is implemented, so you don't need to cache it
0663:             * again in the caller.
0664:             *
0665:             * @param cls the class to locate the method
0666:             * @param name the method name
0667:             * @param argTypes an array of the argument classes;
0668:             * null to denote no argument at all (i.e., exact match).
0669:             * Any argTypes[i] could be null to denote any class.
0670:             * @return the method
0671:             * @exception NoSuchMethodException if the method is not found
0672:             */
0673:            public static final Method getCloseMethod(Class cls, String name,
0674:                    Class[] argTypes) throws NoSuchMethodException {
0675:                if (argTypes == null || argTypes.length == 0)
0676:                    return getMethodInPublic(cls, name, null);
0677:
0678:                final AOInfo aoi = new AOInfo(cls, name, argTypes, 0);
0679:                Method m = (Method) _closms.get(aoi);
0680:                if (m != null)
0681:                    return m;
0682:
0683:                m = myGetCloseMethod(cls, name, argTypes, false);
0684:                _closms.put(aoi, m);
0685:                return m;
0686:            }
0687:
0688:            /**
0689:             * Like {@link #getCloseMethod} to get a 'close' method, but
0690:             * it look for subclass of the arguement (instead of superclass).
0691:             * In other words, it looks for the method whose argument type is
0692:             * the same as or a subclass of the specified one.
0693:             */
0694:            public static final Method getCloseMethodBySubclass(Class cls,
0695:                    String name, Class[] argTypes) throws NoSuchMethodException {
0696:                if (argTypes == null || argTypes.length == 0)
0697:                    return getMethodInPublic(cls, name, null);
0698:
0699:                final AOInfo aoi = new AOInfo(cls, name, argTypes,
0700:                        B_BY_SUBCLASS);
0701:                Method m = (Method) _closms.get(aoi);
0702:                if (m != null)
0703:                    return m;
0704:
0705:                m = myGetCloseMethod(cls, name, argTypes, true);
0706:                _closms.put(aoi, m);
0707:                return m;
0708:            }
0709:
0710:            private static Cache _closms = new MultiCache(20, 1024,
0711:                    4 * 60 * 60 * 1000);
0712:
0713:            private static final Method myGetCloseMethod(final Class cls,
0714:                    final String name, final Class[] argTypes,
0715:                    final boolean bySubclass) throws NoSuchMethodException {
0716:                assert D.OFF || argTypes != null : "Caller shall handle null";
0717:                for (int j = 0;; ++j) {
0718:                    if (j == argTypes.length) {//all argTypes[j] non-null
0719:                        try {
0720:                            return getMethodInPublic(cls, name, argTypes);
0721:                        } catch (NoSuchMethodException ex) { //ignore it
0722:                            break;
0723:                        }
0724:                    }
0725:                    if (argTypes[j] == null) //specil handling required
0726:                        break;
0727:                }
0728:
0729:                final Method[] ms = cls.getMethods();
0730:                for (int j = 0; j < ms.length; ++j) {
0731:                    if (!ms[j].getName().equals(name))
0732:                        continue;
0733:
0734:                    final Class[] mTypes = ms[j].getParameterTypes();
0735:                    if (mTypes.length != argTypes.length)
0736:                        continue; //not matched
0737:
0738:                    final boolean bPublic = Modifier.isPublic(ms[j]
0739:                            .getDeclaringClass().getModifiers());
0740:                    for (int k = 0;; ++k) {
0741:                        if (k == argTypes.length) { //all matched
0742:                            if (bPublic)
0743:                                return ms[j];
0744:                            try {
0745:                                return getMethodInPublic(cls, ms[j].getName(),
0746:                                        ms[j].getParameterTypes());
0747:                            } catch (NoSuchMethodException ex) {
0748:                            }
0749:                            break;//not match; look for next
0750:                        }
0751:
0752:                        final Class argType = argTypes[k], mType = mTypes[k];
0753:                        if (argType == null
0754:                                || (!bySubclass && mType
0755:                                        .isAssignableFrom(argType))
0756:                                || (bySubclass && argType
0757:                                        .isAssignableFrom(mType)))
0758:                            continue; //match
0759:
0760:                        final Class c = Primitives.toPrimitive(argType);
0761:                        if (c == null || !c.equals(mType))
0762:                            break; //not match
0763:                    }
0764:                }
0765:                throw new NoSuchMethodException(cls + ": " + name
0766:                        + " argTypes: " + Objects.toString(argTypes));
0767:            }
0768:
0769:            /** Returns all close methods that match the specified condition, or
0770:             * a zero-length array if none is found.
0771:             * <p>Unlike {@link #getCloseMethod}, we don't cache the searched result,
0772:             * and it won't throw any exception.
0773:             */
0774:            public static final Method[] getCloseMethods(Class cls,
0775:                    String name, Class[] argTypes) {
0776:                if (argTypes == null || argTypes.length == 0) {
0777:                    try {
0778:                        return new Method[] { getMethodInPublic(cls, name, null) };
0779:                    } catch (NoSuchMethodException ex) {
0780:                        return new Method[0];
0781:                    }
0782:                }
0783:                return myGetCloseMethods(cls, name, argTypes, false);
0784:            }
0785:
0786:            /**
0787:             * Like {@link #getCloseMethods} to get all 'close' methods, but
0788:             * it look for subclass of the arguement (instead of superclass).
0789:             * In other words, it looks for the method whose argument type is
0790:             * the same as or a subclass of the specified one.
0791:             */
0792:            public static final Method[] getCloseMethodsBySubclass(Class cls,
0793:                    String name, Class[] argTypes) {
0794:                if (argTypes == null || argTypes.length == 0)
0795:                    return getCloseMethods(cls, name, null);
0796:                return myGetCloseMethods(cls, name, argTypes, true);
0797:            }
0798:
0799:            private static final Method[] myGetCloseMethods(final Class cls,
0800:                    final String name, final Class[] argTypes,
0801:                    final boolean bySubclass) {
0802:                assert D.OFF || argTypes != null : "Caller shall handle null";
0803:                final List mtds = new LinkedList();
0804:                final Method[] ms = cls.getMethods();
0805:                for (int j = 0; j < ms.length; ++j) {
0806:                    if (!ms[j].getName().equals(name))
0807:                        continue;
0808:
0809:                    final Class[] mTypes = ms[j].getParameterTypes();
0810:                    if (mTypes.length != argTypes.length)
0811:                        continue; //not matched
0812:
0813:                    final boolean bPublic = Modifier.isPublic(ms[j]
0814:                            .getDeclaringClass().getModifiers());
0815:                    for (int k = 0;; ++k) {
0816:                        if (k == argTypes.length) { //all matched
0817:                            if (bPublic) {
0818:                                mtds.add(ms[j]);
0819:                            } else {
0820:                                try {
0821:                                    mtds.add(getMethodInPublic(cls, ms[j]
0822:                                            .getName(), ms[j]
0823:                                            .getParameterTypes()));
0824:                                } catch (NoSuchMethodException ex) { //ignore; not add
0825:                                }
0826:                            }
0827:                            break; //found; next method
0828:                        }
0829:
0830:                        final Class argType = argTypes[k], mType = mTypes[k];
0831:                        if (argType == null
0832:                                || (!bySubclass && mType
0833:                                        .isAssignableFrom(argType))
0834:                                || (bySubclass && argType
0835:                                        .isAssignableFrom(mType)))
0836:                            continue; //match one argument
0837:
0838:                        final Class c = Primitives.toPrimitive(argType);
0839:                        if (c == null || !c.equals(mType))
0840:                            break; //not match; next method
0841:                    }
0842:                }
0843:                return (Method[]) mtds.toArray(new Method[mtds.size()]);
0844:            }
0845:
0846:            /**
0847:             * Search the get method; not imply B_METHODONLY.
0848:             */
0849:            public static final int B_GET = 0; //must be 0
0850:            /**
0851:             * Search the set method; not imply B_METHODONLY.
0852:             */
0853:            public static final int B_SET = 1; //must be 1
0854:            /**
0855:             * Only search for public methods or fields.
0856:             */
0857:            public static final int B_PUBLIC_ONLY = 0x0002;
0858:            /**
0859:             * Only search for methods; excluding fields.
0860:             */
0861:            public static final int B_METHOD_ONLY = 0x0004;
0862:
0863:            /** Used by {@link #getCloseMethodBySubclass} to distiquish
0864:             * {@link #getCloseMethod}.
0865:             */
0866:            private static final int B_BY_SUBCLASS = 0x1000;
0867:
0868:            /**
0869:             * Gets the specified accessible object, either a method or a field, by
0870:             * searching the specified name.
0871:             *
0872:             * <p>The search sequence is: (assume field name is body)><br>
0873:             * getBody(...)<br>
0874:             * isBody(...)<br>
0875:             * body(...)<br>
0876:             * body
0877:             *
0878:             * <p>If B_SET is specified, setBody(...) is searched instead of
0879:             * getBody(...) and isBody(...). The field is searched only if
0880:             * argsType.length is 0 or 1.
0881:             *
0882:             * <p>Note: it uses {@link #getCloseMethod} to get the method.
0883:             *
0884:             * <p>A cache mechanism is implemented, so you don't need to cache it
0885:             * again in the caller.
0886:             *
0887:             * @param cls the class to find
0888:             * @param name the name of the accessible object
0889:             * @param argTypes the parameter type of the method to find
0890:             * @param flags a combination of B_xxx or zero
0891:             * @return the accessible object; either Field or Method
0892:             * @exception NoSuchMethodException if neither the set method of
0893:             *   specified field nor the field itself not found
0894:             * @exception SecurityException if access to the information is denied
0895:             */
0896:            public static final AccessibleObject getAccessibleObject(Class cls,
0897:                    String name, Class[] argTypes, int flags)
0898:                    throws NoSuchMethodException {
0899:                final AOInfo aoi = new AOInfo(cls, name, argTypes, flags);
0900:                AccessibleObject ao = (AccessibleObject) _acsos.get(aoi);
0901:                if (ao != null)
0902:                    return ao;
0903:
0904:                ao = myGetAcsObj(cls, name, argTypes, flags);
0905:                _acsos.put(aoi, ao);
0906:                return ao;
0907:            }
0908:
0909:            private static Cache _acsos = new MultiCache(20, 600,
0910:                    4 * 60 * 60 * 1000);
0911:
0912:            private static final AccessibleObject myGetAcsObj(Class cls,
0913:                    String name, Class[] argTypes, int flags)
0914:                    throws NoSuchMethodException {
0915:                //try public set/get
0916:                final String decoratedName = toMethodName(name,
0917:                        (flags & B_SET) != 0 ? "set" : "get");
0918:                try {
0919:                    return getCloseMethod(cls, decoratedName, argTypes);
0920:                } catch (NoSuchMethodException ex) { //ignore
0921:                }
0922:
0923:                //try public is
0924:                String isMethodName = null;
0925:                if ((flags & B_SET) == 0)
0926:                    try {
0927:                        isMethodName = toMethodName(name, "is");
0928:                        return getCloseMethod(cls, isMethodName, argTypes);
0929:                    } catch (NoSuchMethodException ex) { //ignore
0930:                    }
0931:
0932:                //try public same
0933:                try {
0934:                    return getCloseMethod(cls, name, argTypes);
0935:                } catch (NoSuchMethodException ex) {
0936:                    if ((flags & (B_PUBLIC_ONLY | B_METHOD_ONLY)) == (B_PUBLIC_ONLY | B_METHOD_ONLY))
0937:                        throw ex;
0938:                }
0939:
0940:                if ((flags & B_PUBLIC_ONLY) == 0) {
0941:                    //try any set/get
0942:                    try {
0943:                        return getAnyMethod(cls, decoratedName, argTypes);
0944:                    } catch (NoSuchMethodException ex) { //ignore
0945:                    }
0946:
0947:                    //try any is
0948:                    if ((flags & B_SET) == 0)
0949:                        try {
0950:                            return getAnyMethod(cls, isMethodName, argTypes);
0951:                        } catch (NoSuchMethodException ex) { //ignore
0952:                        }
0953:
0954:                    //try any same
0955:                    try {
0956:                        return getAnyMethod(cls, name, argTypes);
0957:                    } catch (NoSuchMethodException ex) {
0958:                        if ((flags & B_METHOD_ONLY) != 0)
0959:                            throw ex;
0960:                    }
0961:                }
0962:
0963:                if (argTypes != null && argTypes.length > 1)
0964:                    throw new NoSuchMethodException(cls + ": " + name + " "
0965:                            + Objects.toString(argTypes));
0966:
0967:                try {
0968:                    //try public field
0969:                    try {
0970:                        return cls.getField(name);
0971:                    } catch (NoSuchFieldException ex) { //ignore
0972:                        if ((flags & B_PUBLIC_ONLY) != 0)
0973:                            throw ex;
0974:                    }
0975:
0976:                    //try any field
0977:                    return getAnyField(cls, name);
0978:                } catch (NoSuchFieldException ex) { //ignore
0979:                    throw new NoSuchMethodException(cls + ": name=" + name
0980:                            + " args=" + Objects.toString(argTypes));
0981:                }
0982:            }
0983:
0984:            /** The infomation of the access object. */
0985:            private static class AOInfo {
0986:                private Class cls;
0987:                private String name;
0988:                private Class[] argTypes;
0989:                private int flags;
0990:
0991:                private AOInfo(Class cls, String name, Class[] argTypes,
0992:                        int flags) {
0993:                    this .cls = cls;
0994:                    this .name = name;
0995:                    this .argTypes = argTypes;
0996:                    this .flags = flags;
0997:                }
0998:
0999:                public int hashCode() {
1000:                    return cls.hashCode() + name.hashCode() + flags;
1001:                }
1002:
1003:                public boolean equals(Object o) {
1004:                    if (!(o instanceof  AOInfo))
1005:                        return false;
1006:
1007:                    AOInfo aoi = (AOInfo) o;
1008:                    int len = argTypes != null ? argTypes.length : 0;
1009:                    int len2 = aoi.argTypes != null ? aoi.argTypes.length : 0;
1010:                    if (len != len2)
1011:                        return false;
1012:
1013:                    if (flags != aoi.flags || !cls.equals(aoi.cls)
1014:                            || !name.equals(aoi.name))
1015:                        return false;
1016:
1017:                    for (int j = 0; j < len; ++j)
1018:                        if (!Objects.equals(argTypes[j], aoi.argTypes[j]))
1019:                            return false;
1020:                    return true;
1021:                }
1022:            }
1023:
1024:            /**
1025:             * Gets the specified method by searching all methods including
1026:             * <i>any</i> access control and any base class.
1027:             * Note: you rarely need to call this metod. In most cases,
1028:             * Class.getMethod, {@link #getCloseMethod}, and
1029:             * {@link #getMethodInPublic} are what you need.
1030:             *
1031:             * <p>The search sequence is: this class's methods, and then
1032:             * the superclass's methods.
1033:             *
1034:             * <p>Note: public methods don't be treated different. If the caller
1035:             * wants to search public methods first, it has to call Class.getMethod
1036:             * first.
1037:             *
1038:             * @param cls the class to search
1039:             * @param name the method name
1040:             * @param argTypes the parameter array of types
1041:             * @return the Method object
1042:             * @exception NoSuchMethodException if a matching method is not found.
1043:             * @exception SecurityException if access to the information is denied.
1044:             * @see #getAccessibleObject(Class, String, Class[], int)
1045:             * @see #getAnyField(Class, String)
1046:             */
1047:            public static final Method getAnyMethod(Class cls, String name,
1048:                    Class[] argTypes) throws NoSuchMethodException {
1049:                try {
1050:                    return cls.getDeclaredMethod(name, argTypes);
1051:                } catch (NoSuchMethodException ex) {
1052:                    final Class[] clses = cls.getInterfaces();
1053:                    for (int j = 0; j < clses.length; ++j)
1054:                        try {
1055:                            return getAnyMethod(clses[j], name, argTypes);
1056:                        } catch (NoSuchMethodException e2) { //ignore it
1057:                        }
1058:
1059:                    cls = cls.getSuperclass();
1060:                    if (cls == null)
1061:                        throw ex;
1062:                    return getAnyMethod(cls, name, argTypes);
1063:                }
1064:            }
1065:
1066:            /**
1067:             * Gets the specified field by searching all fields including
1068:             * any access control and any base class.
1069:             * The search sequence is: this class's fields, and then
1070:             * the superclass's fields.
1071:             *
1072:             * <p>Note: public fields don't be treated different. If the caller
1073:             * wants to search public fields first, it has to call Class.getField
1074:             * first.
1075:             *
1076:             * @param cls the class to search
1077:             * @param name the field name
1078:             * @return the Field object
1079:             * @exception NoSuchFieldException if a matching field is not found.
1080:             * @exception SecurityException if access to the information is denied.
1081:             * @see #getAccessibleObject(Class, String, Class[], int)
1082:             * @see #getAnyMethod(Class, String, Class[])
1083:             */
1084:            public static final Field getAnyField(Class cls, String name)
1085:                    throws NoSuchFieldException {
1086:                for (;;) {
1087:                    try {
1088:                        return cls.getDeclaredField(name);
1089:                    } catch (NoSuchFieldException ex) {
1090:                        cls = cls.getSuperclass();
1091:                        if (cls == null)
1092:                            throw ex;
1093:                    }
1094:                }
1095:            }
1096:
1097:            /**
1098:             * Searches thru each element of the specified array of classes, and
1099:             * returns classes that are super-classes (or equal) of
1100:             * the sepcified class.
1101:             *
1102:             * @param cls the specified class; null is not allowed
1103:             * @param clsToCheck the class array to check; null is acceptable
1104:             * @return a subset of clsToCheck that are super-class of cls;
1105:             * null if no one qualified
1106:             */
1107:            public static final Class[] getSuperClasses(Class cls,
1108:                    Class[] clsToCheck) {
1109:                if (clsToCheck != null) {
1110:                    int[] hits = new int[clsToCheck.length];
1111:                    int no = 0;
1112:                    for (int j = 0; j < clsToCheck.length; ++j)
1113:                        if (clsToCheck[j].isAssignableFrom(cls))
1114:                            hits[no++] = j;
1115:
1116:                    if (no != clsToCheck.length) {
1117:                        if (no == 0)
1118:                            return null;
1119:                        Class[] exc = new Class[no];
1120:                        for (int j = 0; j < no; ++j)
1121:                            exc[j] = clsToCheck[hits[j]];
1122:                        return exc;
1123:                    }
1124:                }
1125:                return clsToCheck;
1126:            }
1127:
1128:            /**
1129:             * Check whether the specified class is a primitive or a primitive wrapper.
1130:             */
1131:            public static final boolean isPrimitiveWrapper(Class cls) {
1132:                return Objects.equals(cls.getPackage(), Boolean.class
1133:                        .getPackage())
1134:                        && (cls.equals(Boolean.class) || cls.equals(Byte.class)
1135:                                || cls.equals(Character.class)
1136:                                || cls.equals(Double.class)
1137:                                || cls.equals(Float.class)
1138:                                || cls.equals(Integer.class)
1139:                                || cls.equals(Long.class) || cls
1140:                                .equals(Short.class));
1141:            }
1142:
1143:            /** Checks whether the specified class is a numeric class.
1144:             *
1145:             * @param extend whether to consider Date, char, boolean, Character
1146:             * and Boolean as a numeric object.
1147:             */
1148:            public static final boolean isNumeric(Class cls, boolean extend) {
1149:                if (cls.isPrimitive())
1150:                    return extend
1151:                            || (!cls.equals(char.class) && !cls
1152:                                    .equals(boolean.class));
1153:
1154:                if (Number.class.isAssignableFrom(cls))
1155:                    return true;
1156:
1157:                return extend
1158:                        && (cls.equals(Date.class) || cls.equals(Boolean.class) || cls
1159:                                .equals(Character.class));
1160:            }
1161:
1162:            /** Converts an object to the specified class.
1163:             * It is the same as coerce(cls, val, true).
1164:             *
1165:             * <p>Future: use org.apache.commons.el.Coercions
1166:             *
1167:             * @param val the value.
1168:             * @exception ClassCastException if failed to convert
1169:             * @see #coerce(Class, Object, boolean)
1170:             */
1171:            public static Object coerce(Class cls, Object val)
1172:                    throws ClassCastException {
1173:                if (cls.isInstance(val))
1174:                    return val;
1175:
1176:                if (String.class == cls) {
1177:                    return Objects.toString(val);
1178:                } else if (BigDecimal.class == cls) {
1179:                    if (val == null) {
1180:                        return null;
1181:                    } else if (val instanceof  Double) {
1182:                        return new BigDecimal(((Double) val).doubleValue());
1183:                    } else if (val instanceof  Float) {
1184:                        return new BigDecimal(((Float) val).doubleValue());
1185:                    } else if (val instanceof  BigInteger) {
1186:                        return new BigDecimal((BigInteger) val);
1187:                    } else if (val instanceof  Number) {
1188:                        return BigDecimals.toBigDecimal(((Number) val)
1189:                                .intValue());
1190:                    } else if (val instanceof  String) {
1191:                        return new BigDecimal((String) val);
1192:                    } else if (val instanceof  Date) {
1193:                        return new BigDecimal(((Date) val).getTime());
1194:                    }
1195:                } else if (Integer.class == cls || int.class == cls) {
1196:                    if (val == null) {
1197:                        return Integer.class == cls ? null
1198:                                : Objects.ZERO_INTEGER;
1199:                    } else if (val instanceof  Integer) { //int.class
1200:                        return val;
1201:                    } else if (val instanceof  Number) {
1202:                        return new Integer(((Number) val).intValue());
1203:                    } else if (val instanceof  String) {
1204:                        return new Integer((String) val);
1205:                    }
1206:                } else if (Boolean.class == cls || boolean.class == cls) {
1207:                    if (val == null) {
1208:                        return Boolean.class == cls ? null : Boolean.FALSE;
1209:                    } else if (val instanceof  Boolean) { //boolean.class
1210:                        return val;
1211:                    } else if (val instanceof  String) {
1212:                        return Boolean.valueOf((String) val);
1213:                    } else if (val instanceof  BigDecimal) {
1214:                        return Boolean
1215:                                .valueOf(((BigDecimal) val).signum() != 0);
1216:                    } else if (val instanceof  BigInteger) {
1217:                        return Boolean
1218:                                .valueOf(((BigInteger) val).signum() != 0);
1219:                    } else if (val instanceof  Number) {
1220:                        return Boolean.valueOf(((Number) val).intValue() != 0);
1221:                    } else {
1222:                        return Boolean.TRUE; //non-null is true
1223:                    }
1224:                } else if (Short.class == cls || short.class == cls) {
1225:                    if (val == null) {
1226:                        return Short.class == cls ? null : Objects.ZERO_SHORT;
1227:                    } else if (val instanceof  Short) { //short.class
1228:                        return val;
1229:                    } else if (val instanceof  Number) {
1230:                        return new Short(((Number) val).shortValue());
1231:                    } else if (val instanceof  String) {
1232:                        return new Short((String) val);
1233:                    }
1234:                } else if (Long.class == cls || long.class == cls) {
1235:                    if (val == null) {
1236:                        return Long.class == cls ? null : Objects.ZERO_LONG;
1237:                    } else if (val instanceof  Long) { //long.class
1238:                        return val;
1239:                    } else if (val instanceof  Number) {
1240:                        return new Long(((Number) val).longValue());
1241:                    } else if (val instanceof  String) {
1242:                        return new Long((String) val);
1243:                    } else if (val instanceof  Date) {
1244:                        return new Long(((Date) val).getTime());
1245:                    }
1246:                } else if (Double.class == cls || double.class == cls) {
1247:                    if (val == null) {
1248:                        return Double.class == cls ? null : Objects.ZERO_DOUBLE;
1249:                    } else if (val instanceof  Double) { //double.class
1250:                        return val;
1251:                    } else if (val instanceof  Number) {
1252:                        return new Double(((Number) val).doubleValue());
1253:                    } else if (val instanceof  String) {
1254:                        return new Double((String) val);
1255:                    } else if (val instanceof  Date) {
1256:                        return new Double(((Date) val).getTime());
1257:                    }
1258:                } else if (BigInteger.class == cls) {
1259:                    if (val == null) {
1260:                        return null;
1261:                    } else if (val instanceof  Integer) {
1262:                        return BigIntegers.toBigInteger((Integer) val);
1263:                    } else if (val instanceof  Short) {
1264:                        return BigIntegers.toBigInteger((Short) val);
1265:                    } else if (val instanceof  Byte) {
1266:                        return BigIntegers.toBigInteger((Byte) val);
1267:                    } else if (val instanceof  Number) {
1268:                        return BigIntegers.toBigInteger(((Number) val)
1269:                                .longValue());
1270:                    } else if (val instanceof  String) {
1271:                        return new BigInteger((String) val);
1272:                    } else if (val instanceof  Date) {
1273:                        return BigIntegers.toBigInteger(((Date) val).getTime());
1274:                    }
1275:                } else if (Float.class == cls || float.class == cls) {
1276:                    if (val == null) {
1277:                        return Float.class == cls ? null : Objects.ZERO_FLOAT;
1278:                    } else if (val instanceof  Float) { //float.class
1279:                        return val;
1280:                    } else if (val instanceof  Number) {
1281:                        return new Float(((Number) val).floatValue());
1282:                    } else if (val instanceof  String) {
1283:                        return new Float((String) val);
1284:                    } else if (val instanceof  Date) {
1285:                        return new Float(((Date) val).getTime());
1286:                    }
1287:                } else if (Byte.class == cls || byte.class == cls) {
1288:                    if (val == null) {
1289:                        return Byte.class == cls ? null : Objects.ZERO_BYTE;
1290:                    } else if (val instanceof  Byte) { //byte.class
1291:                        return val;
1292:                    } else if (val instanceof  Number) {
1293:                        return new Byte(((Number) val).byteValue());
1294:                    } else if (val instanceof  String) {
1295:                        return new Byte((String) val);
1296:                    }
1297:                } else if (Character.class == cls || char.class == cls) {
1298:                    if (val == null) {
1299:                        return Character.class == cls ? null
1300:                                : Objects.NULL_CHARACTER;
1301:                    } else if (val instanceof  Character) { //character.class
1302:                        return val;
1303:                    } else if (val instanceof  Number) {
1304:                        return new Character((char) ((Number) val).shortValue());
1305:                    } else if (val instanceof  String) {
1306:                        final String s = (String) val;
1307:                        return s.length() > 0 ? new Character(s.charAt(0))
1308:                                : Objects.NULL_CHARACTER;
1309:                    }
1310:                } else if (Date.class == cls) {
1311:                    if (val == null) {
1312:                        return null;
1313:                    } else if (val instanceof  Number) {
1314:                        return new Date(((Number) val).longValue());
1315:                    }
1316:                } else if (Number.class == cls) {
1317:                    if (val == null) {
1318:                        return null;
1319:                    } else if (val instanceof  String) {
1320:                        return new BigDecimal((String) val);
1321:                    } else if (val instanceof  Date) {
1322:                        return new BigDecimal(((Date) val).getTime());
1323:                    }
1324:                } else {
1325:                    if (val == null) {
1326:                        return null;
1327:                    } else {
1328:                        try {
1329:                            return cls.newInstance();
1330:                        } catch (Exception ex) {
1331:                            final ClassCastException t = new ClassCastException(
1332:                                    Messages
1333:                                            .get(
1334:                                                    MCommon.CLASS_NOT_COMPATIABLE,
1335:                                                    new Object[] {
1336:                                                            val.getClass(), cls }));
1337:                            t.initCause(ex);
1338:                            throw t;
1339:                        }
1340:                    }
1341:                }
1342:
1343:                throw new ClassCastException(Messages.get(
1344:                        MCommon.CLASS_NOT_COMPATIABLE, new Object[] {
1345:                                val != null ? val + "("
1346:                                        + val.getClass().getName() + ")"
1347:                                        : "null", cls }));
1348:            }
1349:
1350:            /** Converts to the specified type.
1351:             *
1352:             * @param nullable whether the result could be null.
1353:             * If false, 0 is used for number, the default constructor is used
1354:             * for others. {@link #coerce(Class, Object)} is a special case that
1355:             * is equivalent to nullable=true.
1356:             * @exception ClassCastException if failed to convert
1357:             */
1358:            public static Object coerce(Class cls, Object val, boolean nullable)
1359:                    throws ClassCastException {
1360:                if (nullable || val != null)
1361:                    return coerce(cls, val);
1362:
1363:                if (BigDecimal.class == cls) {
1364:                    return Objects.ZERO_BIG_DECIMAL;
1365:                } else if (Integer.class == cls || int.class == cls) {
1366:                    return Objects.ZERO_INTEGER;
1367:                } else if (Boolean.class == cls || boolean.class == cls) {
1368:                    return Boolean.FALSE;
1369:                } else if (Short.class == cls || short.class == cls) {
1370:                    return Objects.ZERO_SHORT;
1371:                } else if (Long.class == cls || long.class == cls) {
1372:                    return Objects.ZERO_LONG;
1373:                } else if (Double.class == cls || double.class == cls) {
1374:                    return Objects.ZERO_DOUBLE;
1375:                } else if (Byte.class == cls || byte.class == cls) {
1376:                    return Objects.ZERO_BYTE;
1377:                } else if (BigInteger.class == cls) {
1378:                    return Objects.ZERO_BIG_INTEGER;
1379:                } else if (Float.class == cls || float.class == cls) {
1380:                    return Objects.ZERO_FLOAT;
1381:                } else if (Character.class == cls || char.class == cls) {
1382:                    return Objects.NULL_CHARACTER;
1383:                } else {
1384:                    try {
1385:                        return cls.newInstance();
1386:                    } catch (Exception ex) {
1387:                        final ClassCastException t = new ClassCastException(
1388:                                Messages.get(MCommon.CLASS_NOT_COMPATIABLE,
1389:                                        new Object[] { "null", cls }));
1390:                        t.initCause(ex);
1391:                        throw t;
1392:                    }
1393:                }
1394:            }
1395:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.