001    package railo.runtime.reflection;
002    
003    import java.lang.reflect.Constructor;
004    import java.lang.reflect.Field;
005    import java.lang.reflect.InvocationTargetException;
006    import java.lang.reflect.Method;
007    import java.lang.reflect.Modifier;
008    import java.util.ArrayList;
009    import java.util.Date;
010    import java.util.HashSet;
011    import java.util.Hashtable;
012    import java.util.Iterator;
013    import java.util.List;
014    import java.util.Locale;
015    import java.util.Map;
016    import java.util.Map.Entry;
017    import java.util.Set;
018    import java.util.TimeZone;
019    import java.util.Vector;
020    
021    import railo.commons.io.res.Resource;
022    import railo.commons.lang.StringUtil;
023    import railo.commons.lang.types.RefInteger;
024    import railo.commons.lang.types.RefIntegerImpl;
025    import railo.runtime.engine.ThreadLocalPageContext;
026    import railo.runtime.exp.ApplicationException;
027    import railo.runtime.exp.ExpressionException;
028    import railo.runtime.exp.NativeException;
029    import railo.runtime.exp.PageException;
030    import railo.runtime.java.JavaObject;
031    import railo.runtime.op.Caster;
032    import railo.runtime.op.Decision;
033    import railo.runtime.op.Duplicator;
034    import railo.runtime.op.Operator;
035    import railo.runtime.reflection.pairs.ConstructorInstance;
036    import railo.runtime.reflection.pairs.MethodInstance;
037    import railo.runtime.reflection.storage.WeakConstructorStorage;
038    import railo.runtime.reflection.storage.WeakFieldStorage;
039    import railo.runtime.reflection.storage.WeakMethodStorage;
040    import railo.runtime.type.Array;
041    import railo.runtime.type.Collection;
042    import railo.runtime.type.Collection.Key;
043    import railo.runtime.type.KeyImpl;
044    import railo.runtime.type.ObjectWrap;
045    import railo.runtime.type.Query;
046    import railo.runtime.type.Struct;
047    import railo.runtime.type.util.ArrayUtil;
048    import railo.runtime.type.util.Type;
049    
050    /**
051     * Class to reflect on Objects and classes 
052     */
053    public final class Reflector {
054    
055            
056        private static final Object NULL = new Object();
057        
058        
059            private static WeakConstructorStorage cStorage=new WeakConstructorStorage();
060        private static WeakFieldStorage fStorage=new WeakFieldStorage();
061        private static WeakMethodStorage mStorage=new WeakMethodStorage();
062    
063        /**
064         * check if Class is instanceof a a other Class
065         * @param srcClassName Class name to check
066         * @param trg is Class of?
067         * @return is Class Class of...
068         */
069        public static boolean isInstaneOf(String srcClassName,Class trg) {
070            try {
071                return isInstaneOf(Class.forName(srcClassName),trg);
072            } 
073            catch (ClassNotFoundException e) {
074                return false;
075            }
076        }
077        
078        /**
079         * check if Class is instanceof a a other Class
080         * @param srcClassName Class name to check
081         * @param trgClassName is Class of?
082         * @return is Class Class of...
083         */
084        public static boolean isInstaneOf(String srcClassName,String trgClassName) {
085            try {
086                return isInstaneOf(Class.forName(srcClassName),trgClassName);
087            } 
088            catch (ClassNotFoundException e) {
089                return false;
090            }
091        }
092        
093        /**
094         * check if Class is instanceof a a other Class
095         * @param src is Class of?
096         * @param trgClassName Class name to check
097         * @return is Class Class of...
098         */
099        public static boolean isInstaneOf(Class src, String trgClassName) {
100            try {
101                return isInstaneOf(src,Class.forName(trgClassName));
102            } 
103            catch (ClassNotFoundException e) {
104                return false;
105            }
106        }
107            
108        
109        public static boolean isInstaneOfIgnoreCase(Class src ,String trg) {
110            if(src.isArray()) {
111                return isInstaneOfIgnoreCase(src.getComponentType() ,trg);
112            }
113            
114            if(src.getName().equalsIgnoreCase(trg))return true;
115            
116            // Interface
117            if(_checkInterfaces(src,trg)) {
118                return true;
119            }
120            // Extends 
121            src=src.getSuperclass();
122            if(src!=null) return isInstaneOfIgnoreCase(src, trg);
123            return false;
124        }
125        
126        
127            /**
128             * check if Class is instanceof a a other Class
129             * @param src Class to check
130             * @param trg is Class of?
131             * @return is Class Class of...
132             */
133        public static boolean isInstaneOf(Class src ,Class trg) {
134            if(src.isArray() && trg.isArray()) {
135                return isInstaneOf(src.getComponentType() ,trg.getComponentType());
136            }
137            
138            if(src==trg)return true;
139            
140            // Interface
141            if(trg.isInterface()) {
142                return _checkInterfaces(src,trg);
143            }
144            // Extends 
145            
146            while(src!=null) {
147                if(src==trg) return true;
148                src=src.getSuperclass();
149            }
150            return trg==Object.class;
151        }
152        
153        private static boolean _checkInterfaces(Class src, String trg) {
154            Class[] interfaces = src.getInterfaces();
155            if(interfaces==null) return false;
156            for(int i=0;i<interfaces.length;i++) {
157                if(interfaces[i].getName().equalsIgnoreCase(trg))return true;
158                if(_checkInterfaces(interfaces[i],trg)) return true;
159            }
160            return false;
161        }
162        
163        private static boolean _checkInterfaces(Class src, Class trg) {
164            Class[] interfaces = src.getInterfaces();
165            if(interfaces==null) return false;
166            for(int i=0;i<interfaces.length;i++) {
167                if(interfaces[i]==trg)return true;
168                if(_checkInterfaces(interfaces[i],trg)) return true;
169            }
170            src=src.getSuperclass();
171            if(src!=null) return _checkInterfaces(src,trg);
172            return false;
173        }
174            
175            /**
176             * get all Classes from a Object Array
177             * @param objs Objects to get
178             * @return classes from Objects
179             */
180            public static Class[] getClasses(Object[] objs) {
181                    Class[] cls=new Class[objs.length];
182                    for(int i=0;i<objs.length;i++) {
183                            if(objs[i]==null)cls[i]=Object.class;
184                            else cls[i]=objs[i].getClass();
185                    }
186                    return cls;
187            }
188            
189            /**
190             * convert a primitive class Type to a Reference Type (Example: int -> java.lang.Integer)
191             * @param c Class to convert
192             * @return converted Class (if primitive)
193             */
194            public static Class toReferenceClass(Class c) {
195                    if(c.isPrimitive()) {
196                            if(c==boolean.class)  return Boolean.class;
197                            if(c==byte.class)  return Byte.class;
198                            if(c==short.class)  return Short.class;
199                            if(c==char.class)  return Character.class;
200                            if(c==int.class)  return Integer.class;
201                            if(c==long.class)  return Long.class;
202                            if(c==float.class)  return Float.class;
203                            if(c==double.class)  return Double.class;
204                    }
205                    return c;               
206            }
207    
208            /**
209             * creates a string list with class arguments in a displable form
210             * @param clazzArgs arguments to display
211             * @return list
212             */
213            public static String getDspMethods(Class... clazzArgs) {
214                    StringBuffer sb=new StringBuffer();
215                    for(int i=0;i<clazzArgs.length;i++) {
216                            if(i>0)sb.append(", ");
217                            sb.append(Caster.toTypeName(clazzArgs[i]));
218                    }
219                    return sb.toString();
220            }
221            
222            /**
223             * checks if src Class is "like" trg class
224             * @param src Source Class
225             * @param trg Target Class
226             * @return is similar
227             */
228            public static boolean like(Class src, Class trg) {
229                    if(src==trg) return true;
230                    return isInstaneOf(src,trg);
231            }
232            
233            /**
234             * convert Object from src to trg Type, if possible
235             * @param src Object to convert
236             * @param srcClass Source Class
237             * @param trgClass Target Class
238             * @return converted Object
239             * @throws PageException 
240             */
241            public static Object convert(Object src, Class trgClass, RefInteger rating) throws PageException {
242                    if(rating!=null) {
243                            Object trg = _convert(src, trgClass);
244                            if(src==trg) {
245                                    rating.plus(10);
246                                    return trg;
247                            }
248                            if(src==null || trg==null) {
249                                    rating.plus(0);
250                                    return trg;
251                            }
252                            if(isInstaneOf(src.getClass(), trg.getClass())) {
253                                    rating.plus(9);
254                                    return trg;
255                            }
256                            if(src.equals(trg)) {
257                                    rating.plus(8);
258                                    return trg;
259                            }
260                            
261                            // different number
262                            boolean bothNumbers=src instanceof Number && trg instanceof Number;
263                            if(bothNumbers && ((Number)src).doubleValue()==((Number)trg).doubleValue()) {
264                                    rating.plus(7);
265                                    return trg;
266                            }
267                            
268                            
269                            
270                            String sSrc=Caster.toString(src,null);
271                            String sTrg=Caster.toString(trg,null);
272                            if(sSrc!=null && sTrg!=null) {
273                                    
274                                    // different number types
275                                    if(src instanceof Number && trg instanceof Number && sSrc.equals(sTrg)) {
276                                            rating.plus(6);
277                                            return trg;
278                                    }
279                                    
280                                    // looks the same
281                                    if(sSrc.equals(sTrg)) {
282                                            rating.plus(5);
283                                            return trg;
284                                    }
285                                    if(sSrc.equalsIgnoreCase(sTrg)) {
286                                            rating.plus(4);
287                                            return trg;
288                                    }
289                            }
290                            
291                            // CF Equal
292                            try {
293                                    if(Operator.equals(src, trg, false, true)) {
294                                            rating.plus(3);
295                                            return trg;
296                                    }
297                            } catch (Throwable t) {}
298                            
299                            
300                            return trg;
301                    }
302                    return _convert(src, trgClass);
303            }
304    
305            public static Object _convert(Object src, Class trgClass) throws PageException {
306                    if(src==null) {
307                            if(trgClass.isPrimitive())
308                                    throw new ApplicationException("can't convert [null] to ["+trgClass.getName()+"]");
309                            return null;
310                    }
311                    if(like(src.getClass(), trgClass)) return src;
312                    String className=trgClass.getName();
313                    
314    
315                    if(src instanceof ObjectWrap) {
316                            src = ((ObjectWrap) src).getEmbededObject();
317                            return _convert(src, trgClass);
318                    }
319                    if(className.startsWith("java.lang.")){
320                            if(trgClass==Boolean.class)             return Caster.toBoolean(src);
321                            if(trgClass==Integer.class)             return Caster.toInteger(src);
322                            if(trgClass==String.class)                      return Caster.toString(src);
323                            if(trgClass==Byte.class)                        return Caster.toByte(src);
324                            if(trgClass==Short.class)                       return Caster.toShort(src);
325                            if(trgClass==Long.class)                        return Caster.toLong(src);
326                            if(trgClass==Float.class)                       return Caster.toFloat(src);
327                            if(trgClass==Double.class)                      return Caster.toDouble(src);
328                            if(trgClass==Character.class) {
329                                    String str=Caster.toString(src,null);
330                                    if(str!=null && str.length()==1) return new Character(str.charAt(0));
331                            }
332                    }
333                    
334                    if(Decision.isArray(src)) {
335                            if(trgClass.isArray()) {
336                                    return toNativeArray(trgClass,src);
337                            }
338                            else if(isInstaneOf(trgClass, List.class)) {
339                                    return Caster.toList(src);
340                            }
341                            else if(isInstaneOf(trgClass, Array.class)) {
342                                    return Caster.toArray(src);
343                            }
344                    }
345                    
346                    if(trgClass==Date.class) return Caster.toDate(src,true,null);
347                    else if(trgClass==Query.class) return Caster.toQuery(src);
348                    else if(trgClass==Map.class) return Caster.toMap(src);
349                    else if(trgClass==Struct.class) return Caster.toStruct(src);
350                    else if(trgClass==Resource.class) return Caster.toResource(ThreadLocalPageContext.get(),src,false);
351                    // this 2 method are used to support conversion that match neo src types
352                    else if(trgClass==Hashtable.class) return Caster.toHashtable(src);
353                    else if(trgClass==Vector.class) return Caster.toVetor(src);
354                    else if(trgClass==java.util.Collection.class) return Caster.toJavaCollection(src);
355                    else if(trgClass==TimeZone.class && Decision.isString(src)) return Caster.toTimeZone(Caster.toString(src));
356                    else if(trgClass==Collection.Key.class) return KeyImpl.toKey(src);
357                    else if(trgClass==Locale.class && Decision.isString(src)) return Caster.toLocale(Caster.toString(src));
358                    if(trgClass.isPrimitive()) {
359                            //return convert(src,srcClass,toReferenceClass(trgClass));
360                            return _convert(src,toReferenceClass(trgClass));
361                    }
362                    throw new ApplicationException("can't convert ["+Caster.toClassName(src)+"] to ["+Caster.toClassName(trgClass)+"]");
363            }
364    
365            /**
366             * gets Constructor Instance matching given parameter
367             * @param clazz Clazz to Invoke
368             * @param args Matching args
369             * @return Matching ConstructorInstance
370             * @throws NoSuchMethodException
371             * @throws PageException
372             */
373    
374            public static ConstructorInstance getConstructorInstance(Class clazz, Object[] args) throws NoSuchMethodException {
375                    ConstructorInstance ci=getConstructorInstance(clazz, args,null);
376                if(ci!=null) return ci;
377                throw new NoSuchMethodException("No matching Constructor for "+clazz.getName()+"("+getDspMethods(getClasses(args))+") found");
378            }
379            
380            public static ConstructorInstance getConstructorInstance(Class clazz, Object[] args, ConstructorInstance defaultValue) {
381                    args=cleanArgs(args);
382                    Constructor[] constructors=cStorage.getConstructors(clazz,args.length);//getConstructors(clazz);
383                    if(constructors!=null) {
384                        Class[] clazzArgs = getClasses(args);
385                            // exact comparsion
386                            outer:for(int i=0;i<constructors.length;i++) {
387                                    if(constructors[i]!=null) {
388                                            
389                                            Class[] parameterTypes = constructors[i].getParameterTypes();
390                                            for(int y=0;y<parameterTypes.length;y++) {
391                                                    if(toReferenceClass(parameterTypes[y])!=clazzArgs[y]) continue outer;
392                                            }
393                                            return new ConstructorInstance(constructors[i],args);
394                                    }
395                            }
396                            // like comparsion
397                            outer:for(int i=0;i<constructors.length;i++) {
398                                    if(constructors[i]!=null) {
399                                            Class[] parameterTypes = constructors[i].getParameterTypes();
400                                            for(int y=0;y<parameterTypes.length;y++) {
401                                                    if(!like(clazzArgs[y],toReferenceClass(parameterTypes[y]))) continue outer;
402                                            }
403                                            return new ConstructorInstance(constructors[i],args);
404                                    }
405                            }       
406                            // convert comparsion
407                            ConstructorInstance ci=null;
408                        int _rating=0;
409                            outer:for(int i=0;i<constructors.length;i++) {
410                                    if(constructors[i]!=null) {
411                                            RefInteger rating=(constructors.length>1)?new RefIntegerImpl(0):null;
412                                            Class[] parameterTypes = constructors[i].getParameterTypes();
413                                            Object[] newArgs = new Object[args.length];
414                                            for(int y=0;y<parameterTypes.length;y++) {
415                                                    try {
416                                                            newArgs[y]=convert(args[y],toReferenceClass(parameterTypes[y]),rating);
417                                                    } catch (PageException e) {
418                                                            continue outer;
419                                                    }
420                                            }
421                                            if(ci==null || rating.toInt()>_rating) {
422                                                    if(rating!=null)_rating=rating.toInt();
423                                                    ci=new ConstructorInstance(constructors[i],newArgs);
424                                            }
425                                            //return new ConstructorInstance(constructors[i],newArgs);
426                                    }
427                            }
428                        return ci;
429                    }
430                    return defaultValue;
431                    //throw new NoSuchMethodException("No matching Constructor for "+clazz.getName()+"("+getDspMethods(getClasses(args))+") found");
432            }
433    
434            /**
435             * gets the MethodInstance matching given Parameter
436             * @param clazz Class Of the Method to get
437             * @param methodName Name of the Method to get
438             * @param args Arguments of the Method to get
439             * @return return Matching Method
440         * @throws  
441             */
442            public static MethodInstance getMethodInstanceEL(Class clazz, Collection.Key methodName, Object[] args) {
443                args=cleanArgs(args);
444                    
445                    Method[] methods = mStorage.getMethods(clazz,methodName,args.length);//getDeclaredMethods(clazz);
446                    
447                    if(methods!=null) {
448                        Class[] clazzArgs = getClasses(args);
449                            // exact comparsion
450                        //print.e("exact:"+methodName);
451                        outer:for(int i=0;i<methods.length;i++) {
452                                    if(methods[i]!=null) {
453                                            Class[] parameterTypes = methods[i].getParameterTypes();
454                                            for(int y=0;y<parameterTypes.length;y++) {
455                                                    if(toReferenceClass(parameterTypes[y])!=clazzArgs[y]) continue outer;
456                                            }
457                                            return new MethodInstance(methods[i],args);
458                                    }
459                            }
460                            // like comparsion
461                        //MethodInstance mi=null;
462                        // print.e("like:"+methodName);
463                        outer:for(int i=0;i<methods.length;i++) {
464                                    if(methods[i]!=null) {
465                                            Class[] parameterTypes = methods[i].getParameterTypes();
466                                            for(int y=0;y<parameterTypes.length;y++) {
467                                                    if(!like(clazzArgs[y],toReferenceClass(parameterTypes[y]))) continue outer;
468                                            }
469                                            return new MethodInstance(methods[i],args);
470                                    }
471                            }
472                        
473                        
474                            // convert comparsion
475                        // print.e("convert:"+methodName);
476                        MethodInstance mi=null;
477                        int _rating=0;
478                            outer:for(int i=0;i<methods.length;i++) {
479                                    if(methods[i]!=null) {
480                                            RefInteger rating=(methods.length>1)?new RefIntegerImpl(0):null;
481                                            Class[] parameterTypes = methods[i].getParameterTypes();
482                                            Object[] newArgs = new Object[args.length];
483                                            for(int y=0;y<parameterTypes.length;y++) {
484                                                    try {
485                                                            newArgs[y]=convert(args[y],toReferenceClass(parameterTypes[y]),rating);
486                                                    } catch (PageException e) {
487                                                            continue outer;
488                                                    }
489                                            }
490                                            if(mi==null || rating.toInt()>_rating) {
491                                                    if(rating!=null)_rating=rating.toInt();
492                                                    mi=new MethodInstance(methods[i],newArgs);
493                                            }
494                                            //return new MethodInstance(methods[i],newArgs);
495                                    }
496                            }return mi;
497                    }
498                    return null;
499            }
500    
501    
502        private static Object[] cleanArgs(Object[] args) {
503            if(args==null) return args;
504            
505            for(int i=0;i<args.length;i++){
506                    args[i]=_clean(args[i]);
507            }
508            return args;
509        }
510            
511            
512        private static Object _clean(Object obj)  {
513                    if(obj instanceof ObjectWrap) {
514                            try {
515                                    return ((ObjectWrap)obj).getEmbededObject();
516                            } catch (PageException e) {
517                                    return obj;
518                            }
519                    }
520                    if(obj instanceof Collection) return  _clean((Collection)obj);
521                    if(obj instanceof Map) return  _clean((Map)obj);
522                    if(obj instanceof List) return  _clean((List)obj);
523                    if(obj instanceof Object[]) return  _clean((Object[])obj);
524                    return obj;
525            }
526        
527        private static Object _clean(Collection coll) {
528            Iterator<Object> vit = coll.valueIterator();
529            Object v;
530            boolean change=false;
531            while(vit.hasNext()){
532                    v=vit.next();
533                    if(v!=_clean(v)) {
534                            change=true;
535                            break;
536                    }
537            }
538            if(!change) return coll;
539            
540            coll=coll.duplicate(false);
541            Iterator<Entry<Key, Object>> eit = coll.entryIterator();
542            Entry<Key, Object> e;
543            while(eit.hasNext()){
544                    e=eit.next();
545                    coll.setEL(e.getKey(), _clean(e.getValue()));
546            }
547            
548            return coll;
549        }
550        
551        private static Object _clean(Map map) {
552            Iterator vit = map.values().iterator();
553            Object v;
554            boolean change=false;
555            while(vit.hasNext()){
556                    v=vit.next();
557                    if(v!=_clean(v)) {
558                            change=true;
559                            break;
560                    }
561            }
562            if(!change) return map;
563            
564            map=Duplicator.duplicateMap(map, false);
565            Iterator<Entry> eit = map.entrySet().iterator();
566            Entry e;
567            while(eit.hasNext()){
568                    e=eit.next();
569                    map.put(e.getKey(), _clean(e.getValue()));
570            }
571            
572            return map;
573        }
574        
575        private static Object _clean(List list) {
576            Iterator it = list.iterator();
577            Object v;
578            boolean change=false;
579            while(it.hasNext()){
580                    v=it.next();
581                    if(v!=_clean(v)) {
582                            change=true;
583                            break;
584                    }
585            }
586            if(!change) return list;
587            
588            list=Duplicator.duplicateList(list, false);
589            it = list.iterator();
590            while(it.hasNext()){
591                    list.add(_clean(it.next()));
592            }
593            
594            return list;
595        }
596        
597        private static Object _clean(Object[] src) {
598            boolean change=false;
599            for(int i=0;i<src.length;i++){
600                    if(src[i]!=_clean(src[i])) {
601                            change=true;
602                            break;
603                    }
604            }
605            if(!change) return src;
606            
607            Object[] trg=new Object[src.length];
608                    for(int i=0;i<trg.length;i++) {
609                            trg[i]=_clean(src[i]);
610                    }
611            
612            return trg;
613        }
614    
615            /**
616         * gets the MethodInstance matching given Parameter
617         * @param clazz Class Of the Method to get
618         * @param methodName Name of the Method to get
619         * @param args Arguments of the Method to get
620         * @return return Matching Method
621         * @throws NoSuchMethodException
622         * @throws PageException
623         */
624        public static MethodInstance getMethodInstance(Class clazz, String methodName, Object[] args) 
625            throws NoSuchMethodException {
626            MethodInstance mi=getMethodInstanceEL(clazz, KeyImpl.getInstance(methodName), args);
627            if(mi!=null) return mi;
628            
629            Class[] classes = getClasses(args);
630            //StringBuilder sb=null;
631            JavaObject jo;
632            Class c;
633            ConstructorInstance ci;
634            for(int i=0;i<classes.length;i++){
635                    if(args[i] instanceof JavaObject) {
636                            jo=(JavaObject) args[i];
637                            c=jo.getClazz();
638                            ci = Reflector.getConstructorInstance(c, new Object[0], null);
639                            if(ci==null) {
640                                    
641                            throw new NoSuchMethodException("The "+pos(i+1)+" parameter of "+methodName+"("+getDspMethods(classes)+") ia a object created " +
642                                            "by the createObject function (JavaObject/JavaProxy). This object has not been instantiated because it does not have a constructor " +
643                                            "that takes zero arguments. Railo cannot instantiate it for you, please use the .init(...) method to instantiate it with the correct parameters first");
644                                    
645                                    
646                            }
647                    }
648            }
649            /*
650            the argument list contains objects created by createObject, 
651            that are no instantiated (first,third,10th) and because this object have no constructor taking no arguments, Railo cannot instantiate them.
652            you need first to instantiate this objects. 
653            */
654            throw new NoSuchMethodException("No matching Method for "+methodName+"("+getDspMethods(classes)+") found for "+
655                            Caster.toTypeName(clazz));
656        }
657            
658            private static String pos(int index) {
659                    if(index==1) return "first";
660                    if(index==2) return "second";
661                    if(index==3) return "third";
662                    
663                    return index+"th";
664            }
665    
666            /**
667             * same like method getField from Class but ignore case from field name
668             * @param clazz class to search the field
669             * @param name name to search
670             * @return Matching Field
671             * @throws NoSuchFieldException
672             
673             */
674        public static Field[] getFieldsIgnoreCase(Class clazz, String name) throws NoSuchFieldException  {
675            Field[] fields=fStorage.getFields(clazz,name);
676            if(fields!=null) return fields;
677            throw new NoSuchFieldException("there is no field with name "+name+" in object ["+Type.getName(clazz)+"]");
678        }
679        
680        public static Field[] getFieldsIgnoreCase(Class clazz, String name, Field[] defaultValue)  {
681            Field[] fields=fStorage.getFields(clazz,name);
682            if(fields!=null) return fields;
683            return defaultValue;
684            
685            
686        }
687    
688        public static String[] getPropertyKeys(Class clazz)  {
689            Set keys=new HashSet();
690            Field[] fields = clazz.getFields();
691            Field field;
692            Method[] methods = clazz.getMethods();
693            Method method;
694            String name;
695            
696            for(int i=0;i<fields.length;i++) {
697                    field=fields[i];
698                    if(Modifier.isPublic(field.getModifiers()) )keys.add(field.getName());
699            }
700            
701            for(int i=0;i<methods.length;i++) {
702                    method=methods[i];
703                    if(Modifier.isPublic(method.getModifiers()) ) {
704                            if(isGetter(method)) {
705                                    name=method.getName();
706                                    if(name.startsWith("get"))keys.add(method.getName().substring(3));
707                                    else keys.add(method.getName().substring(2));
708                            }
709                            else if(isSetter(method)) keys.add(method.getName().substring(3));
710                    }
711            }
712            
713            return (String[]) keys.toArray(new String[keys.size()]);
714        }
715    
716        public static boolean hasPropertyIgnoreCase(Class clazz, String name)  {
717            if(hasFieldIgnoreCase(clazz, name)) return true;
718            
719            Method[] methods = clazz.getMethods();
720            Method method;
721            String n;
722            for(int i=0;i<methods.length;i++) {
723                    method=methods[i];
724                    if(Modifier.isPublic(method.getModifiers()) && StringUtil.endsWithIgnoreCase(method.getName(),name)) {
725                            n=null;
726                            if(isGetter(method)) {
727                                    n=method.getName();
728                                    if(n.startsWith("get"))n=method.getName().substring(3);
729                                    else n=method.getName().substring(2);
730                            }
731                            else if(isSetter(method)) n=method.getName().substring(3);
732                            if(n!=null && n.equalsIgnoreCase(name)) return true;
733                    }
734            }
735            return false;
736        }
737        
738        
739        public static boolean hasFieldIgnoreCase(Class clazz, String name)  {
740            return !ArrayUtil.isEmpty(getFieldsIgnoreCase(clazz, name, null));
741            //getFieldIgnoreCaseEL(clazz, name)!=null;
742        }
743        
744    
745            /**
746             * call constructor of a class with matching arguments
747             * @param clazz Class to get Instance
748             * @param args Arguments for the Class
749             * @return invoked Instance
750             * @throws PageException
751             */
752            public static Object callConstructor(Class clazz, Object[] args) throws PageException {
753                args=cleanArgs(args);
754                try {
755                return getConstructorInstance(clazz,args).invoke();
756            } 
757                    catch (InvocationTargetException e) {
758                            Throwable target = e.getTargetException();
759                            if(target instanceof PageException) throw (PageException)target;
760                            throw Caster.toPageException(e.getTargetException());
761                    } 
762                    catch (Exception e) {
763                        throw Caster.toPageException(e);
764                    }
765            }
766            
767            public static Object callConstructor(Class clazz, Object[] args, Object defaultValue) {
768                args=cleanArgs(args);
769                try {
770                ConstructorInstance ci = getConstructorInstance(clazz,args,null);
771                if(ci==null) return defaultValue;
772                return ci.invoke();
773            }
774                    catch (Throwable t) {
775                        return defaultValue;
776                    }
777            }
778    
779            /**
780             * calls a Method of a Objct
781             * @param obj Object to call Method on it
782             * @param methodName Name of the Method to get
783             * @param args Arguments of the Method to get
784             * @return return return value of the called Method
785             * @throws PageException
786             */
787            public static Object callMethod(Object obj, String methodName, Object[] args) throws PageException {
788                    return callMethod(obj, KeyImpl.getInstance(methodName), args);
789            }
790            
791            public static Object callMethod(Object obj, Collection.Key methodName, Object[] args) throws PageException {
792                    if(obj==null) {
793                            throw new ExpressionException("can't call method ["+methodName+"] on object, object is null");
794                    }
795            
796                    MethodInstance mi=getMethodInstanceEL(obj.getClass(), methodName, args);
797                    if(mi==null)
798                        throw throwCall(obj,methodName,args);
799                try {
800                    return mi.invoke(obj);
801            }
802                    catch (InvocationTargetException e) {
803                            Throwable target = e.getTargetException();
804                            if(target instanceof PageException) throw (PageException)target;
805                            throw new NativeException(e.getTargetException());
806                    } 
807                    catch (Exception e) {
808                            throw new NativeException(e);
809                    }
810            }
811            
812    
813            public static Object callMethod(Object obj, Collection.Key methodName, Object[] args, Object defaultValue) {
814                    if(obj==null) {
815                            return defaultValue;
816                    }
817                    MethodInstance mi=getMethodInstanceEL(obj.getClass(), methodName, args);
818                    if(mi==null)
819                        return defaultValue;
820                try {
821                    return mi.invoke(obj);
822            }
823                    catch (Throwable t) {
824                            return defaultValue;
825                    }
826            }
827    
828            public static ExpressionException throwCall(Object obj,String methodName, Object[] args) {
829                    return new ExpressionException("No matching Method/Function for "+Type.getName(obj)+"."+methodName+"("+getDspMethods(getClasses(args))+") found");
830            }
831            public static ExpressionException throwCall(Object obj,Collection.Key methodName, Object[] args) {
832                    return new ExpressionException("No matching Method/Function for "+Type.getName(obj)+"."+methodName+"("+getDspMethods(getClasses(args))+") found");
833            }
834    
835            /**
836             * calls a Static Method on the given CLass
837             * @param clazz Class to call Method on it
838             * @param methodName Name of the Method to get
839             * @param args Arguments of the Method to get
840             * @return return return value of the called Method
841             * @throws PageException
842             */
843            public static Object callStaticMethod(Class clazz, String methodName, Object[] args) throws PageException {
844                    try {
845                return getMethodInstance(clazz,methodName,args).invoke(null);
846            }
847                    catch (InvocationTargetException e) {
848                            Throwable target = e.getTargetException();
849                            if(target instanceof PageException) throw (PageException)target;
850                            throw Caster.toPageException(e.getTargetException());
851                    } 
852                    catch (Exception e) {
853                            throw Caster.toPageException(e);
854                    }
855            }
856        
857        /**
858         * to get a Getter Method of a Object
859         * @param clazz Class to invoke method from
860         * @param prop Name of the Method without get
861         * @return return Value of the getter Method
862         * @throws NoSuchMethodException
863         * @throws PageException
864         */
865        public static MethodInstance getGetter(Class clazz, String prop) throws PageException, NoSuchMethodException {
866            String getterName = "get"+StringUtil.ucFirst(prop);
867            MethodInstance mi = getMethodInstanceEL(clazz,KeyImpl.getInstance(getterName),ArrayUtil.OBJECT_EMPTY);
868            
869            if(mi==null){
870                    String isName = "is"+StringUtil.ucFirst(prop);
871                mi = getMethodInstanceEL(clazz,KeyImpl.getInstance(isName),ArrayUtil.OBJECT_EMPTY);
872                if(mi!=null){
873                    Method m = mi.getMethod();
874                    Class rtn = m.getReturnType();
875                    if(rtn!=Boolean.class && rtn!=boolean.class) mi=null;
876                }
877            }
878                
879            
880            if(mi==null)
881                    throw new ExpressionException("No matching property ["+prop+"] found in ["+Caster.toTypeName(clazz)+"]");
882            Method m=mi.getMethod();
883            
884            if(m.getReturnType()==void.class) 
885                throw new NoSuchMethodException("invalid return Type, method ["+m.getName()+"] for Property ["+getterName+"] must have return type not void");
886            
887            return mi;
888        }
889        
890        /**
891         * to get a Getter Method of a Object
892         * @param clazz Class to invoke method from
893         * @param prop Name of the Method without get
894         * @return return Value of the getter Method
895         */
896        public static MethodInstance getGetterEL(Class clazz, String prop) {
897            prop="get"+StringUtil.ucFirst(prop);
898            MethodInstance mi = getMethodInstanceEL(clazz,KeyImpl.getInstance(prop),ArrayUtil.OBJECT_EMPTY);
899            if(mi==null) return null;
900            if(mi.getMethod().getReturnType()==void.class) return null;
901            return mi;
902        }
903            
904            /**
905             * to invoke a getter Method of a Object
906             * @param obj Object to invoke method from
907             * @param prop Name of the Method without get
908             * @return return Value of the getter Method
909             * @throws PageException
910             */
911            public static Object callGetter(Object obj, String prop) throws PageException {
912                try {
913                        return getGetter(obj.getClass(), prop).invoke(obj);
914                    }
915                    catch (InvocationTargetException e) {
916                            Throwable target = e.getTargetException();
917                            if(target instanceof PageException) throw (PageException)target;
918                            throw Caster.toPageException(e.getTargetException());
919                    } 
920                    catch (Exception e) {
921                            throw Caster.toPageException(e);
922                    }
923            }
924        
925        /**
926         * to invoke a setter Method of a Object
927         * @param obj Object to invoke method from
928         * @param prop Name of the Method without get
929         * @param value Value to set to the Method
930         * @return MethodInstance
931         * @throws NoSuchMethodException
932         * @throws PageException
933         */
934        public static MethodInstance getSetter(Object obj, String prop,Object value) throws NoSuchMethodException {
935                prop="set"+StringUtil.ucFirst(prop);
936                MethodInstance mi = getMethodInstance(obj.getClass(),prop,new Object[]{value});
937                Method m=mi.getMethod();
938                
939                if(m.getReturnType()!=void.class)
940                    throw new NoSuchMethodException("invalid return Type, method ["+m.getName()+"] must have return type void, now ["+m.getReturnType().getName()+"]");
941                return mi;
942        }
943        
944        
945        
946        
947        /*
948         * to invoke a setter Method of a Object
949         * @param obj Object to invoke method from
950         * @param prop Name of the Method without get
951         * @param value Value to set to the Method
952         * @return MethodInstance
953         * @deprecated use instead <code>getSetter(Object obj, String prop,Object value, MethodInstance defaultValue)</code>
954         
955        public static MethodInstance getSetterEL(Object obj, String prop,Object value)  {
956            prop="set"+StringUtil.ucFirst(prop);
957            MethodInstance mi = getMethodInstanceEL(obj.getClass(),KeyImpl.getInstance(prop),new Object[]{value});
958            if(mi==null) return null;
959            Method m=mi.getMethod();
960            
961            if(m.getReturnType()!=void.class) return null;
962            return mi;
963        }*/
964        
965        /**
966         * to invoke a setter Method of a Object
967         * @param obj Object to invoke method from
968         * @param prop Name of the Method without get
969         * @param value Value to set to the Method
970         * @return MethodInstance
971         */
972        public static MethodInstance getSetter(Object obj, String prop,Object value, MethodInstance defaultValue)  {
973            prop="set"+StringUtil.ucFirst(prop);
974            MethodInstance mi = getMethodInstanceEL(obj.getClass(),KeyImpl.getInstance(prop),new Object[]{value});
975            if(mi==null) return defaultValue;
976            Method m=mi.getMethod();
977            
978            if(m.getReturnType()!=void.class) return defaultValue;
979            return mi;
980        }
981            
982            /**
983             * to invoke a setter Method of a Object
984             * @param obj Object to invoke method from
985             * @param prop Name of the Method without get
986             * @param value Value to set to the Method
987             * @throws PageException
988             */
989            public static void callSetter(Object obj, String prop,Object value) throws PageException {
990                try {
991                        getSetter(obj, prop, value).invoke(obj);
992                    }
993                    catch (InvocationTargetException e) {
994                            Throwable target = e.getTargetException();
995                            if(target instanceof PageException) throw (PageException)target;
996                            throw Caster.toPageException(e.getTargetException());
997                    } 
998                    catch (Exception e) {
999                            throw Caster.toPageException(e);
1000                    }
1001            }
1002            
1003            /**
1004             * do nothing when not exist
1005             * @param obj
1006             * @param prop
1007             * @param value
1008             * @throws PageException
1009             */
1010            public static void callSetterEL(Object obj, String prop,Object value) throws PageException {
1011                try {
1012                        MethodInstance setter = getSetter(obj, prop, value,null);
1013                        if(setter!=null)setter.invoke(obj);
1014                    }
1015                    catch (InvocationTargetException e) {
1016                            Throwable target = e.getTargetException();
1017                            if(target instanceof PageException) throw (PageException)target;
1018                            throw Caster.toPageException(e.getTargetException());
1019                    } 
1020                    catch (Exception e) {
1021                            throw Caster.toPageException(e);
1022                    }
1023            }
1024    
1025            /**
1026             * to get a visible Field of a object
1027             * @param obj Object to invoke
1028             * @param prop property to call
1029             * @return property value
1030             * @throws PageException
1031             */
1032            public static Object getField(Object obj, String prop) throws PageException  {
1033                try {
1034                    return getFieldsIgnoreCase(obj.getClass(),prop)[0].get(obj);
1035            }
1036                    catch (Throwable e) {
1037                throw Caster.toPageException(e);
1038                    }
1039            }
1040            
1041            public static Object getField(Object obj, String prop, Object defaultValue) {
1042                if(obj==null) return defaultValue;
1043                    Field[] fields = getFieldsIgnoreCase(obj.getClass(),prop,null);
1044                    if(ArrayUtil.isEmpty(fields)) return defaultValue;
1045                    
1046                    try {
1047                            return fields[0].get(obj);
1048                    } catch (Throwable t) {
1049                            return defaultValue;
1050                    }
1051            }
1052            
1053            /**
1054             * assign a value to a visible Field of a object
1055             * @param obj Object to assign value to his property
1056             * @param prop name of property
1057             * @param value Value to assign
1058             * @throws PageException
1059             */
1060            public static boolean setField(Object obj, String prop,Object value) throws PageException {
1061                Class clazz=value.getClass();
1062                    try {
1063                    Field[] fields = getFieldsIgnoreCase(obj.getClass(),prop);
1064                    // exact comparsion
1065                            for(int i=0;i<fields.length;i++) {
1066                                    if(toReferenceClass(fields[i].getType())==clazz){
1067                                            fields[i].set(obj,value);
1068                                            return true;
1069                                    }
1070                            }
1071                            // like comparsion
1072                            for(int i=0;i<fields.length;i++) {
1073                                    if(like(fields[i].getType(),clazz)) {
1074                                            fields[i].set(obj,value);
1075                                            return true;
1076                                    }
1077                            }       
1078                            // convert comparsion
1079                            for(int i=0;i<fields.length;i++) {   
1080                                    try {
1081                                            fields[i].set(obj,convert(value,toReferenceClass(fields[i].getType()),null));
1082                                            return true;
1083                                    } catch (PageException e) {}
1084                            }
1085            }
1086                    catch (Exception e) {
1087                            throw Caster.toPageException(e);
1088                    }
1089                    return false;
1090            }
1091    
1092            /**
1093             * to get a visible Propety (Field or Getter) of a object
1094             * @param obj Object to invoke
1095             * @param prop property to call
1096             * @return property value
1097             * @throws PageException
1098             */
1099            public static Object getProperty(Object obj, String prop) throws PageException  {
1100                Object rtn=getField(obj,prop,NULL);// NULL is used because the field can contain null as well
1101                    if(rtn!=NULL) return rtn;
1102                    
1103                    char first=prop.charAt(0);
1104            if(first>='0' && first<='9') throw new ApplicationException("there is no property with name ["+prop+"]");
1105            return callGetter(obj,prop);
1106            
1107            }
1108    
1109            /**
1110             * to get a visible Propety (Field or Getter) of a object
1111             * @param obj Object to invoke
1112             * @param prop property to call
1113             * @return property value
1114             */
1115            public static Object getProperty(Object obj, String prop, Object defaultValue)  {
1116                    
1117                    // first try field
1118                    Field[] fields = getFieldsIgnoreCase(obj.getClass(),prop,null);
1119                    if(!ArrayUtil.isEmpty(fields)) {
1120                            try {
1121                                    return fields[0].get(obj);
1122                            } catch (Throwable t) {}
1123                    }
1124                    
1125                    // then getter
1126            try {
1127                char first=prop.charAt(0);
1128                if(first>='0' && first<='9') return defaultValue;
1129                return getGetter(obj.getClass(), prop).invoke(obj);
1130            } catch (Throwable e1) {
1131                return defaultValue;
1132            } 
1133            }
1134            
1135            /**
1136             * assign a value to a visible Property (Field or Setter) of a object
1137             * @param obj Object to assign value to his property
1138             * @param prop name of property
1139             * @param value Value to assign
1140             * @throws PageException
1141             */
1142            public static void setProperty(Object obj, String prop,Object value) throws PageException{
1143                boolean done=false;
1144                    try {
1145                    if(setField(obj,prop,value))done=true;
1146                } 
1147                    catch (Throwable t) {
1148                            
1149            }
1150                if(!done)callSetter(obj,prop,value);
1151            }
1152            
1153            /**
1154             * assign a value to a visible Property (Field or Setter) of a object
1155             * @param obj Object to assign value to his property
1156             * @param prop name of property
1157             * @param value Value to assign
1158             */
1159            public static void setPropertyEL(Object obj, String prop,Object value) {
1160                    
1161                    // first check for field
1162                    Field[] fields = getFieldsIgnoreCase(obj.getClass(),prop,null);
1163                    if(!ArrayUtil.isEmpty(fields)){
1164                            try {
1165                                    fields[0].set(obj,value);
1166                                    return;
1167                            } catch (Throwable t) {}
1168                    }
1169                    
1170                    // then check for setter
1171            try {
1172                getSetter(obj, prop, value).invoke(obj);
1173            } 
1174            catch (Throwable t) {} 
1175            
1176            }
1177            
1178        
1179    
1180        private static Object toNativeArray(Class clazz, Object obj) throws PageException {
1181            //if(obj.getClass()==clazz) return obj;
1182                    Object[] objs=null;
1183                    if(obj instanceof Array)                                                objs=toRefArray((Array)obj);
1184                    else if(obj instanceof List)                                    objs=toRefArray((List)obj);
1185                    else if(Decision.isNativeArray(obj)) {
1186                            if(obj.getClass()==boolean[].class)                     objs=toRefArray((boolean[])obj);
1187                            else if(obj.getClass()==byte[].class)           objs=toRefArray((byte[])obj);
1188                            else if(obj.getClass()==char[].class)           objs=toRefArray((char[])obj);
1189                            else if(obj.getClass()==short[].class)          objs=toRefArray((short[])obj);
1190                            else if(obj.getClass()==int[].class)            objs=toRefArray((int[])obj);
1191                            else if(obj.getClass()==long[].class)           objs=toRefArray((long[])obj);
1192                            else if(obj.getClass()==float[].class)          objs=toRefArray((float[])obj);
1193                            else if(obj.getClass()==double[].class)         objs=toRefArray((double[])obj);
1194                            else                                                                            objs=(Object[])obj;//toRefArray((Object[])obj);
1195                            
1196                    }
1197                    if(clazz==objs.getClass()) return objs;
1198                    
1199                    //if(objs==null) return defaultValue;
1200                    //Class srcClass = objs.getClass().getComponentType();
1201                    Class trgClass = clazz.getComponentType();
1202                    Object rtn = java.lang.reflect.Array.newInstance(trgClass, objs.length);
1203                    for(int i=0;i<objs.length;i++) {
1204                            //java.lang.reflect.Array.set(rtn, i, convert(objs[i], srcClass, trgClass));
1205                            java.lang.reflect.Array.set(rtn, i, convert(objs[i], trgClass,null));
1206                    }
1207                    return rtn;
1208            }
1209            
1210    
1211            private static Object[] toRefArray(boolean[] src) {
1212                    Boolean[] trg=new Boolean[src.length];
1213                    for(int i=0;i<trg.length;i++) {
1214                            trg[i]=src[i]?Boolean.TRUE:Boolean.FALSE;
1215                    }
1216                    return trg;
1217            }
1218    
1219            private static Byte[] toRefArray(byte[] src) {
1220                    Byte[] trg=new Byte[src.length];
1221                    for(int i=0;i<trg.length;i++) {
1222                            trg[i]=new Byte(src[i]);
1223                    }
1224                    return trg;
1225            }
1226    
1227            private static Character[] toRefArray(char[] src) {
1228                    Character[] trg=new Character[src.length];
1229                    for(int i=0;i<trg.length;i++) {
1230                            trg[i]=new Character(src[i]);
1231                    }
1232                    return trg;
1233            }
1234    
1235            private static Short[] toRefArray(short[] src) {
1236                    Short[] trg=new Short[src.length];
1237                    for(int i=0;i<trg.length;i++) {
1238                            trg[i]=Short.valueOf(src[i]);
1239                    }
1240                    return trg;
1241            }
1242    
1243            private static Integer[] toRefArray(int[] src) {
1244                    Integer[] trg=new Integer[src.length];
1245                    for(int i=0;i<trg.length;i++) {
1246                            trg[i]=Integer.valueOf(src[i]);
1247                    }
1248                    return trg;
1249            }
1250    
1251            private static Long[] toRefArray(long[] src) {
1252                    Long[] trg=new Long[src.length];
1253                    for(int i=0;i<trg.length;i++) {
1254                            trg[i]=Long.valueOf(src[i]);
1255                    }
1256                    return trg;
1257            }
1258    
1259            private static Float[] toRefArray(float[] src) {
1260                    Float[] trg=new Float[src.length];
1261                    for(int i=0;i<trg.length;i++) {
1262                            trg[i]=new Float(src[i]);
1263                    }
1264                    return trg;
1265            }
1266    
1267            private static Double[] toRefArray(double[] src) {
1268                    Double[] trg=new Double[src.length];
1269                    for(int i=0;i<trg.length;i++) {
1270                            trg[i]=new Double(src[i]);
1271                    }
1272                    return trg;
1273            }
1274            
1275            private static Object[] toRefArray(Array array) throws PageException {
1276                    Object[] objs=new Object[array.size()];
1277                    for(int i=0;i<objs.length;i++) {
1278                            objs[i]=array.getE(i+1);
1279                    }
1280                    return objs;
1281            }
1282            
1283            private static Object[] toRefArray(List list) {
1284                    Object[] objs=new Object[list.size()];
1285                    for(int i=0;i<objs.length;i++) {
1286                            objs[i]=list.get(i);
1287                    }
1288                    return objs;
1289            }
1290    
1291            public static boolean isGetter(Method method) {
1292                    if(method.getParameterTypes().length>0) return false;
1293                    if(method.getReturnType()==void.class) return false;
1294                    if(!method.getName().startsWith("get") && !method.getName().startsWith("is")) return false;
1295                    if(method.getDeclaringClass()==Object.class) return false;
1296                    return true;
1297            }
1298    
1299            public static boolean isSetter(Method method) {
1300                    if(method.getParameterTypes().length!=1) return false;
1301                    if(method.getReturnType()!=void.class) return false;
1302                    if(!method.getName().startsWith("set")) return false;
1303                    if(method.getDeclaringClass()==Object.class) return false;
1304                    return true;
1305            }
1306    
1307            /**
1308             * return all methods that are defined by the class itself (not extended)
1309             * @param clazz
1310             * @return
1311             */
1312            public static Method[] getDeclaredMethods(Class clazz) {
1313                    Method[] methods = clazz.getMethods();
1314                    ArrayList list=new ArrayList();
1315                    for(int i=0;i<methods.length;i++) {
1316                            if(methods[i].getDeclaringClass()==clazz) list.add(methods[i]);
1317                    }
1318                    if(list.size()==0) return new Method[0];
1319                    return (Method[]) list.toArray(new Method[list.size()]);
1320            }
1321    
1322            public static Method[] getSetters(Class clazz) {
1323                    Method[] methods = clazz.getMethods();
1324                    ArrayList list=new ArrayList();
1325                    for(int i=0;i<methods.length;i++) {
1326                            if(isSetter(methods[i])) list.add(methods[i]);
1327                    }
1328                    if(list.size()==0) return new Method[0];
1329                    return (Method[]) list.toArray(new Method[list.size()]);
1330            }
1331            
1332            public static Method[] getGetters(Class clazz) {
1333                    Method[] methods = clazz.getMethods();
1334                    ArrayList list=new ArrayList();
1335                    for(int i=0;i<methods.length;i++) {
1336                            if(isGetter(methods[i])) list.add(methods[i]);
1337                    }
1338                    if(list.size()==0) return new Method[0];
1339                    return (Method[]) list.toArray(new Method[list.size()]);
1340            }
1341    
1342            /**
1343             * check if given class "from" can be converted to class "to" without explicit casting
1344             * @param from source class
1345             * @param to target class
1346             * @return is it possible to convert from "from" to "to"
1347             */
1348            public static boolean canConvert(Class from, Class to) {
1349                    // Identity Conversions
1350                    if(from==to) return true;
1351                    
1352                    // Widening Primitive Conversion
1353                    if(from==byte.class) {
1354                            return to==short.class || to==int.class || to==long.class || to==float.class || to==double.class ;
1355                    }
1356                    if(from==short.class) {
1357                            return to==int.class || to==long.class || to==float.class || to==double.class ;
1358                    }
1359                    if(from==char.class) {
1360                            return to==int.class || to==long.class || to==float.class || to==double.class ;
1361                    }
1362                    if(from==int.class) {
1363                            return to==long.class || to==float.class || to==double.class ;
1364                    }
1365                    if(from==long.class) {
1366                            return to==float.class || to==double.class ;
1367                    }
1368                    if(from==float.class) {
1369                            return to==double.class ;
1370                    }
1371                    return false;
1372            }
1373    
1374            public static String removeGetterPrefix(String name) {
1375                    if(name.startsWith("get")) return name.substring(3);
1376                    if(name.startsWith("is")) return name.substring(2);
1377                    return name;
1378            }
1379    
1380            
1381    
1382             
1383    }