/*
 * Copyright (C) 1999-2006 <a href="mailto:paschke@in.tum.de">Adrian Paschke</a>
 * 
 * The Utils Library is part of the Rule Based Service Level Agreement (RBSLA)
 * framework, available at 
 * <a href=" http://ibis.in.tum.de/staff/paschke/rbsla/index.htm">RBSLA</a>
 * 
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package rbsla.utils;

import java.lang.reflect.Method;

import ws.prova.RListUtils;
import org.mandarax.kernel.Term;
import org.mandarax.kernel.VariableTerm;

import java.lang.NoSuchMethodException;
import java.util.ArrayList;


public class JavaReflection 
{


	
	/**
	 * method that invokes another method given by the parameter
	 * @param query it contains the complete class path of the method
	 * @throws Exception
	 * 
	 */
	public static boolean invoke(String _query, Object[] objs)
	{
		
		
		// TODO: query with constructor parameters		
		
		try {						
			String query = _query;	
			Class clazz;
			String method;
			ArrayList params = new ArrayList();
			if (query.indexOf("[")!=-1) { // case query is RList []
				if (query.indexOf(",")!=-1) { // with parameters
					query=query.replaceAll("\\]","");
					String call = query.substring(2,query.indexOf(",")-1);					
					String className = call.substring(0,call.lastIndexOf("."));					
					if (className.indexOf("_")!=-1) clazz = objs[Integer.parseInt(className.substring(className.indexOf("_")+1))].getClass();
					else clazz = Class.forName(className);						
					method = call.substring(call.lastIndexOf(".")+1);
					String[] parameters = query.replaceAll("\\[\""+call+"\",","").split(",");
					for (int i=0;i<parameters.length;i++) {
						Object parameter = parameters[i].trim();						
						if (parameter.toString().charAt(0)=='_') {														
							parameter = (Object) objs[Integer.parseInt(parameter.toString().substring(1))];							
						} 
						params.add(parameter);							
					}					
				} else { // without parameters					
					String className = query.substring(2,query.lastIndexOf("."));					
					if (className.indexOf("_")!=-1) clazz = objs[Integer.parseInt(className.substring(className.indexOf("_")+1))].getClass();
					else clazz = Class.forName(className);					
					method = query.substring(query.lastIndexOf(".")+1,query.lastIndexOf("\""));
					
				}
			} else { // case query is String list ""
				Term term = RListUtils.rlist(query);
				clazz = term.getType(); // class name
				method = ((VariableTerm)term).getName(); 
				String[] parameters = method.substring(method.indexOf("(")+1,method.indexOf(")")).trim().split(","); // parameter names				
				method = method.substring(0,method.indexOf("(")); // method name
			}
			
			
			Class[] paramTypes = new Class[params.size()]; // types of parameters			
			for(int i=0; i<params.size();i++) // cast parameter classes
			{				
				paramTypes[i] = params.get(i).getClass();
			}
			
			try {				
				Method meth = clazz.getMethod(method,paramTypes); // method				
				if (meth.getReturnType().getName().toLowerCase().indexOf("boolean")!=-1)
				{
					
					try { // try static invocation	
						return ((Boolean)meth.invoke(null, params.toArray())).booleanValue();
					} catch (Exception inv) { // try instance invocation
						try {
							Object object = clazz.newInstance();
							return ((Boolean)meth.invoke(object, params.toArray())).booleanValue();
						} catch (Exception inv2) {
							//System.err.println("Error while calling procedural attachment "+clazz+"."+method+" - invocation failed\r\n"+inv2);
							return false;
						}
					}
				} else {
					//System.err.println("Error while calling procedural attachment "+clazz+"."+method+" - return type is not boolean");
					return false;
				}	
				
			} catch (NoSuchMethodException nsm) {				
				//System.err.println("Error while calling procedural attachment "+clazz+"."+method+" - no such method.\r\n"+nsm);
				return false;
			}

			
			
			
		} catch (Exception ge) {
			//System.err.println("Error while calling procedural attachment\r\n"+ge);
			return false;
		}

	}
}
