001 /* 002 * hammurapi-rules @mesopotamia.version@ 003 * Hammurapi rules engine. 004 * Copyright (C) 2005 Hammurapi Group 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 019 * 020 * URL: http://http://www.hammurapi.biz 021 * e-Mail: support@hammurapi.biz 022 */ 023 package biz.hammurapi.dispatch; 024 025 import java.lang.reflect.Method; 026 import java.util.ArrayList; 027 import java.util.Collection; 028 import java.util.Collections; 029 import java.util.List; 030 031 /** 032 * This class introspects an object passed to the constructor and creates 033 * invocation handlers for methods with one argument and the name provided in 034 * the constructor. 035 * Invocation handler would not invoke target method with incompatible argument. 036 * @author Pavel Vlasov 037 * @revision $Revision$ 038 */ 039 public class IntrospectingInvocationTarget implements InvocationTarget { 040 041 List handlers=new ArrayList(); 042 043 /** 044 * Introspects the target and creates an array of invocation handlers. 045 * Invocation handlers created by introspection report their return types as 046 * fact types. getFactTypes() returns empty array if return type is void. 047 * @param targetInstance Target instance 048 * @param methodName Method name 049 * @param parameterType Invocation handlers shall accept arguments of this type. Can be null. 050 */ 051 public IntrospectingInvocationTarget(final Object targetInstance, final String methodName, Class parameterType) { 052 super(); 053 054 055 Method[] methods=targetInstance.getClass().getMethods(); 056 for (int i=0; i<methods.length; i++) { 057 if (methods[i].getParameterTypes().length == 1) { 058 if (methodName.equals(methods[i].getName())) { 059 final Method method=methods[i]; 060 final Class actualParameterType = method.getParameterTypes()[0]; 061 062 // Make sure that target method will accept parameterType arguments 063 if ((parameterType==null || actualParameterType.isAssignableFrom(parameterType))) { 064 handlers.add( 065 new InvocationHandler() { 066 067 public void invoke(Object arg, ResultConsumer resultConsumer) throws Throwable { 068 // Invoke only with compatible parameters. 069 if (actualParameterType.isInstance(arg)) { 070 Object ret=method.invoke(targetInstance, new Object[] {arg}); 071 if (ret!=null && resultConsumer!=null) { 072 resultConsumer.consume(ret); 073 } 074 } 075 } 076 077 public Class getParameterType() { 078 return actualParameterType; 079 } 080 081 public String toString() { 082 return "["+methodName+" handler] Target method: "+method; 083 } 084 085 public Class[] getFactTypes() { 086 Class ret = method.getReturnType(); 087 return void.class.equals(ret) ? new Class[] {} : new Class[] {ret}; 088 } 089 090 }); 091 } 092 } 093 } 094 } 095 096 } 097 098 public Collection getInvocationHandlers() { 099 return Collections.unmodifiableCollection(handlers); 100 } 101 102 }