/* * (C) Copyright 2002 Arnaud Bailly (arnaud.oqube@gmail.com), * Yves Roos (yroos@lifl.fr) and others. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package rationals.converters.algorithms; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * A Helper class for converting string parameters to primitive * types * * @author Arnaud Bailly */ public class TypeHelper { /** hash table to store conversion constructors */ private static java.util.Map constructormap = new java.util.HashMap(); /** hash table to store conversion methods */ private static java.util.Map conversionmap = new java.util.HashMap(); /** static initilizer put constructors for base types */ static { Class cls = Integer.class; try { Class[] ctorparam = new Class[] {java.lang.String.class}; // type int cls = Integer.class; Constructor ctor = cls.getConstructor(ctorparam); constructormap.put(int.class,ctor); // type float cls = Float.class; ctor = cls.getConstructor(ctorparam); constructormap.put(float.class,ctor); // type boolean cls = Boolean.class; ctor = cls.getConstructor(ctorparam); constructormap.put(boolean.class,ctor); // type double cls = Double.class; ctor = cls.getConstructor(ctorparam); constructormap.put(double.class,ctor); // type short cls = Short.class; ctor = cls.getConstructor(ctorparam); constructormap.put(short.class,ctor); // type byte cls = Byte.class; ctor = cls.getConstructor(ctorparam); constructormap.put(byte.class,ctor); } catch(Exception ex) { System.err.println("Unable to get constructor for class "+cls.getName() +" : "+ex.getMessage()); } } /** * A method to register a factory for a type * * @param cls a class object for which we gives a factory * @param method a method object to invoke for constructing objects. This method must * be static, takes one String parameter and returns objects of class cls * @exception IllegalArgumentException if method or cls are invalid (null, not static...) */ public static void registerFactory(Class cls,Method method) { Class[] clsparms = new Class[] {java.lang.String.class}; Class retcls = method.getReturnType(); int mod = method.getModifiers(); Class[] parms = method.getParameterTypes(); if(!retcls.equals(cls) || !Modifier.isStatic(mod) || !Modifier.isPublic(mod) || Modifier.isAbstract(mod) || !java.util.Arrays.equals(parms,clsparms)) throw new IllegalArgumentException ("Invalid argument to method TypeHelper.registerFactory"); conversionmap.put(cls,method); } /** * Main method to convert from a string given a class object * * @param cls a Class object * @param str a String to parse into an object of given class */ public static Object convert(Class cls,String str) { Class[] clsparms = new Class[] {java.lang.String.class}; // first look into hashtables Constructor ctor = (Constructor)constructormap.get(cls); if(ctor != null) return invokeCtor(ctor,str); Method meth = (Method)conversionmap.get(cls); if(meth != null) return invokeMethod(meth,str); // try to find a suitable constructor try { ctor = cls.getConstructor(clsparms); // store in hashtable constructormap.put(cls,ctor); return invokeCtor(ctor,str); }catch(Exception ex) { System.err.println("No constructor with String argument for class "+cls.getName() +" : " +ex.getMessage()); } // try to find a suitable method try { Method[] methods = cls.getMethods(); // try to find a static method taking one string parameter and returning an object of class cls for(int i = 0;i<methods.length;i++) { Class retcls = methods[i].getReturnType(); int mod = methods[i].getModifiers(); Class[] parms = methods[i].getParameterTypes(); if(!retcls.equals(cls) || !Modifier.isStatic(mod) || !java.util.Arrays.equals(parms,clsparms)) continue; // found a method - hope it is OK !!! conversionmap.put(cls,methods[i]); return invokeMethod(methods[i],str); } }catch(Throwable t) { System.err.println("Error in enumerating methods for class "+cls.getName() +" : "+t.getMessage()); } // default to null System.err.println("No conversion method found for class "+cls.getName()); return null; } private static Object invokeCtor(Constructor ctor,String str) { try { return ctor.newInstance(new Object[]{str}); }catch(Throwable t) { System.err.println("Error in constructor invocation with argument "+str+" : "+t.getMessage()); return null; } } private static Object invokeMethod(Method meth,String str) { try { // assume method is static return meth.invoke(null,new Object[]{str}); }catch(Throwable t) { System.err.println("Error in method invocation with argument "+str+" : "+t.getMessage()); return null; } } }