/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.xxql.columns; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import xxl.core.xxql.AdvResultSetMetaData; public abstract class ReflectionColumn extends Column { private static final long serialVersionUID = 1L; protected Class<?>[] argumentsTypes; protected Class<?> clazz; protected Column[] argumentsColumns; public ReflectionColumn(String name) { super(name); } public abstract void setMetaData(AdvResultSetMetaData metadata, String newAlias); public abstract void setMetaDatas(AdvResultSetMetaData leftMetaData, AdvResultSetMetaData rightMetaData); @SuppressWarnings("unchecked") protected Constructor getSuitableConstructor(Class<?>[] pmt) { try { Constructor ret = clazz.getConstructor(pmt); return ret; } catch (Exception e) { // don't care, if it wasn't found this way try smarter.. } for(Class cls : pmt){ System.out.println(cls); } Constructor[] constructors = clazz.getConstructors(); for(Constructor cls : constructors){ System.out.println(cls); } constrs: for (Constructor c : constructors) { Class<?>[] curPmt = c.getParameterTypes(); // if the method hasn't even got the same number of arguments we // continue if (curPmt.length != pmt.length) { continue; } // check parametertypes for compatibility for (int i = 0; i < pmt.length; i++) { if (curPmt[i].isPrimitive()) { // TODO: noch nicht ganz sauber mit zahlen, die evtl // automatisch gecasted werden... /* * fuer zahlentypen (double, float, int, long, short, char) * gilt: Methode mit ... frisst ... double : alles float : * alles ausser double int : nur char, short und int long : * alle ausser double und float short : nur short char : nur * char */ if (!getPrimitiveType(pmt[i]).equals(curPmt[i])) { continue; // type doesn't match for this parameter: try // next. } } else { Class<?> tmp = getObjectType(pmt[i]); // if expected class is superclass of given class (from pmt) // it matches if (!curPmt[i].isAssignableFrom(tmp)) { continue constrs; } } } // if Method m has passed all those checks it matches. return c; } return null; } protected Method getSuitableMethod(String methodName, Class<?>[] pmt, boolean wantStatic) { // TODO: this is far from perfect Method[] methods = clazz.getMethods(); try { Method ret = clazz.getMethod(methodName, pmt); // if either the found method is static or we're not looking for a static method anyway if(Modifier.isStatic(ret.getModifiers()) || !wantStatic) return ret; } catch (Exception e) { // don't care, if it wasn't found this way try smarter.. } mthds: for (Method m : methods) { Class<?>[] curPmt = m.getParameterTypes(); // if the method hasn't even got the same name or number of // arguments we continue if (!m.getName().equals(methodName) || curPmt.length != pmt.length) { continue; } // if the found method is *not* static, but we want a static one, try next. if(!Modifier.isStatic(m.getModifiers()) && wantStatic) continue; // void-methods are not really helpful if(m.getReturnType().equals(void.class)) continue; // check parametertypes for compatibility for (int i = 0; i < pmt.length; i++) { if (curPmt[i].isPrimitive()) { // TODO: noch nicht ganz sauber mit zahlen, die evtl // automatisch gecasted werden... /* * fuer zahlentypen (double, float, int, long, short, char) * gilt: Methode mit ... frisst ... double : alles float : * alles ausser double int : nur char, short und int long : * alle ausser double und float short : nur short char : nur * char */ if (!getPrimitiveType(pmt[i]).equals(curPmt[i])) { continue; // type doesn't match for this parameter: try // next. } } else { Class<?> tmp = getObjectType(pmt[i]); // if expected class is superclass of given class (from pmt) // it matches if (!curPmt[i].isAssignableFrom(tmp)) { continue mthds; } } } // if Method m has passed all those checks it matches. return m; } return null; } /** * Returns the Object-type for a primitive type (or just the given type if * it isn't primitive) * * @param type * a type/class, that might be primitive * @return the according non-primitive type */ @SuppressWarnings("unchecked") protected static Class getObjectType(Class<?> type) { if (!type.isPrimitive()) { return type; } if (type.equals(byte.class)) { return Byte.class; } else if (type.equals(short.class)) { return Short.class; } else if (type.equals(int.class)) { return Integer.class; } else if (type.equals(long.class)) { return Long.class; } else if (type.equals(float.class)) { return Float.class; } else if (type.equals(double.class)) { return Double.class; } else if (type.equals(boolean.class)) { return Boolean.class; } else if (type.equals(char.class)) { return Character.class; } throw new RuntimeException("Unknown primitive type " + type.getName()); } @SuppressWarnings("unchecked") protected static Class getPrimitiveType(Class<?> type) { if (type.isPrimitive()) { return type; } if (type.equals(Byte.class)) { return byte.class; } else if (type.equals(Short.class)) { return short.class; } else if (type.equals(Integer.class)) { return int.class; } else if (type.equals(Long.class)) { return long.class; } else if (type.equals(Float.class)) { return float.class; } else if (type.equals(Double.class)) { return double.class; } else if (type.equals(Boolean.class)) { return boolean.class; } else if (type.equals(Character.class)) { return char.class; } throw new RuntimeException("Unknown primitive type " + type.getName()); } }