/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ package org.opensourcephysics.ejs.control; import java.lang.reflect.Method; import org.opensourcephysics.ejs.control.value.BooleanValue; import org.opensourcephysics.ejs.control.value.DoubleValue; import org.opensourcephysics.ejs.control.value.IntegerValue; import org.opensourcephysics.ejs.control.value.StringValue; import org.opensourcephysics.ejs.control.value.Value; /** * A class to store and invoke methods using reflection. */ public class MethodWithOneParameter { private String methodName; private int methodType; private Object targetObject = null; private Object[] parameterList = {}; private Method methodToCall; private MethodWithOneParameter secondMethod = null; private Value returnValue = null; // AMAVP (See Note in ControlElement) /** * Equivalent to MethodWithOneParameter (_type, _target, _name, null); */ // MethodWithOneParameter (int _type, Object _target, String _name) { // this(_type, _target, _name, null); // } /** * Creates a new method from the input parameters. * @param int _type An integer type to help create families of actions * @param Object _target The object that implements the method * @param String _name The description of the method. * 1.- If the method's parameter list is void, then you can specify either * 'method()' or just 'method' * 2.- If the method accepts a boolean, you can specify either 'method(true)' * or 'method(false)' * 3.- If the method accepts a double, you can specify something like 'method(1.0)' * 4.- If the method accepts an integer, you can specify something like 'method(1)' * 5.- If the method accepts a String, you can specify something like 'method("my string")' * In all cases, the first version is the recommended one. * @param MethodWithOneParameter _secondMethod A second action that will be invoked * following this one. This is useful when you want to call more than one methods at once * @param _anObject and object for the very special case of method("#CONTROL#"); //Added on Jan 31st 2004 */ MethodWithOneParameter(int _type, Object _target, String _name, String _returnType, MethodWithOneParameter _secondMethod, Object _anObject) { Class<?>[] classList = {}; Object parameter = null; Class<?> parameterClass = null; methodName = _name; methodType = _type; targetObject = _target; secondMethod = _secondMethod; String parts[] = splitMethodName(_name.trim()); if(parts[2].equals("#CONTROL#")&&(_anObject!=null)) { //$NON-NLS-1$ parameter = _anObject; parameterClass = _anObject.getClass(); // System.out.println ("Class of OBJECT is "+parameterClass); } else { Value value = Value.parseConstant(parts[2], false); // NO silent mode if(value instanceof StringValue) { // method ("String") parameter = value.getString(); parameterClass = _name.getClass(); // String } else if(value instanceof BooleanValue) { // method (boolean) parameter = new Boolean(value.getBoolean()); parameterClass = Boolean.TYPE; } else if(value instanceof DoubleValue) { // method (double) parameter = new Double(value.getDouble()); parameterClass = Double.TYPE; } else if(value instanceof IntegerValue) { // method (int) parameter = new Integer(value.getInteger()); parameterClass = Integer.TYPE; } } if(parameter!=null) { // method(parameter); classList = new Class[1]; classList[0] = parameterClass; // parameter parameterList = new Object[1]; parameterList[0] = parameter; } methodToCall = resolveMethod(targetObject, parts[1], classList); if(methodToCall==null) { System.err.println(getClass().getName()+" : Error! Unable to find a suitable method "+methodName+" in class "+targetObject.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$ } if(_returnType==null) { returnValue = null; // AMAVP } else { _returnType = _returnType.trim().toLowerCase(); if(_returnType.equals("double")) { //$NON-NLS-1$ returnValue = new DoubleValue(0.0); // else if (_returnType.equals("byte")) returnValue = new IntegerValue(0); } else if(_returnType.equals("int")) { //$NON-NLS-1$ returnValue = new IntegerValue(0); } else if(_returnType.equals("string")) { //$NON-NLS-1$ returnValue = new StringValue(""); //$NON-NLS-1$ } else if(_returnType.equals("boolean")) { //$NON-NLS-1$ returnValue = new BooleanValue(false); } else { returnValue = null; // return type is void } } } public Value invoke(int _type, Object _callingObject) { // Modified for AMAVP if(methodType!=_type) { return null; } // System.out.println ("Invoking method "+this.methodName+" with Value "+parameterList); try { if(returnValue==null) { // void return type methodToCall.invoke(targetObject, parameterList); } else if(returnValue instanceof DoubleValue) { ((DoubleValue) returnValue).value = ((Double) methodToCall.invoke(targetObject, parameterList)).doubleValue(); } else if(returnValue instanceof IntegerValue) { ((IntegerValue) returnValue).value = ((Integer) methodToCall.invoke(targetObject, parameterList)).intValue(); } else if(returnValue instanceof BooleanValue) { ((BooleanValue) returnValue).value = ((Boolean) methodToCall.invoke(targetObject, parameterList)).booleanValue(); } else if(returnValue instanceof StringValue) { ((StringValue) returnValue).value = methodToCall.invoke(targetObject, parameterList).toString(); } if(secondMethod!=null) { secondMethod.invoke(_type, _callingObject); } } catch(Exception exc) { exc.printStackTrace(System.err); return null; } return returnValue; } public boolean equals(int _type, Object _target, String _name) { if(methodType!=_type) { return false; } if(targetObject!=_target) { return false; } return methodName.equals(_name); } public String toString() { return methodName; } static public Method resolveMethod(Object _target, String _name, Class<?>[] _classList) { java.lang.reflect.Method[] allMethods = _target.getClass().getMethods(); for(int i = 0; i<allMethods.length; i++) { if(!allMethods[i].getName().equals(_name)) { continue; } Class<?>[] parameters = allMethods[i].getParameterTypes(); if(parameters.length!=_classList.length) { continue; } boolean fits = true; for(int j = 0; j<parameters.length; j++) { if(!parameters[j].isAssignableFrom(_classList[j])) { fits = false; break; } } if(fits) { return allMethods[i]; } } return null; } static public String[] splitMethodName(String _inputName) { String part[] = new String[3]; String restOfIt = _inputName; int index1 = _inputName.indexOf('.'); int index2 = _inputName.indexOf('('); if((index1>0)&&((index2<0)||(index2>index1))) { part[0] = _inputName.substring(0, index1); // target restOfIt = _inputName.substring(index1+1); // rest of it } else { part[0] = null; // No target } index1 = restOfIt.indexOf("("); //$NON-NLS-1$ if(index1<=0) { // format 'method' part[1] = restOfIt; part[2] = null; } else { // format 'method()' or 'method(parameter)' part[1] = restOfIt.substring(0, index1).trim(); restOfIt = restOfIt.substring(index1); index2 = restOfIt.lastIndexOf(')'); if(index2<0) { System.err.println(" : Error! Incorrect method description "+_inputName); //$NON-NLS-1$ return null; } part[2] = restOfIt.substring(1, index2).trim(); } // for (int i=0; i<part.length; i++) System.out.println ("Part["+i+"] = "+part[i]); return part; } } // End of class /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */