ptolemy.data.expr
Class CachedMethod

java.lang.Object
  extended by ptolemy.data.expr.CachedMethod
Direct Known Subclasses:
CachedMethod.ArrayMapCachedMethod, CachedMethod.BaseConvertCachedMethod, CachedMethod.MatrixMapCachedMethod

public class CachedMethod
extends java.lang.Object

An instance of this class represents a method or function that is invoked by the Ptolemy II expression evaluator. Instances of this class are returned by the static findMethod() method, and can be invoked by the apply() method. This class is used by the expression language to find Java methods that are bound in expressions that use function application, i.e. an ASTPtFunctionApplicationNode, and in method invocation, i.e. an ASTPtMethodNode.

This class is used to represent two distinct types of Java methods that can be invoked. The METHOD type corresponds to an instance method of a java class, invoked on an object of an appropriate class (the base class). The FUNCTION type corresponds to a static method of a java class. These types corresponds to the two distinct expression constructs that can be used to invoke Java methods. The type of construct reflected can be queried using the getCachedMethodType() method, which returns either FUNCTION or METHOD. Additionally, this class can be used to represent Java methods that were not found. If the CachedMethod corresponds to an invokeable Java method, then the isValid() method will return true. CachedMethods that are not valid cannot be invoked by the invoke() method.

This class provides several services that distinguish it from Java's built-in reflection mechanism:

  1. Methods are found based on name and the types of ptolemy token arguments, represented by instances of the ptolemy.data.type.Type base class.
  2. FUNCTIONS are searched for in a set of classes registered with the parser.
  3. METHODS are searched for a base class, and in all superclasses of the base class.
  4. Found methods, represented by instances of this class, are cached and indexed to improve the speed of method lookup. The cache is synchronized so that it can be safely accessed from multiple threads.
  5. Allows for the possibility of several automatic conversions that increase the applicability of single methods

The automatic conversions that are allowed on the arguments of reflected Java methods can be particularly tricky to understand. The findMethod() method is fairly aggressive about finding valid methods to invoke. In particular, given a set of arguments with token types, the findMethod() method might return a cached method that:

  1. Accepts token arguments of exactly the same type.
  2. Accepts token arguments that are of a type that the given types can be automatically converted to, as determined by the Ptolemy type lattice.
  3. Accepts the corresponding Java native type of either of the first two cases, i.e. an IntToken argument may reflect a method that accepts a Java int.
  4. Accepts a corresponding Java array type, if the argument type is an ArrayType.
  5. Accepts a corresponding Java array of array type, if the argument type is a MatrixType.
The underlying conversions are implemented by the ConversionUtilities class, which has more specific documentation the underlying conversions. The inverse of the same conversions are performed on the results of a Java method invocation, in order to convert the result back into a Ptolemy token.

Since there may be many methods that match a particular function application or method invocation, under the above conversions, the findMethod() method attempts to return the most specific Java method that can be called. Generally speaking, conversions are preferred in the above order. If one Java method is not clearly preferable to all others, then the findMethod() method will throw an exception. This may happen if there are multiple functions defined with varying argument types.

Additionally, the findMethod() method may return a CachedMethod that automatically "maps" arrays and matrices over a scalar function. The result of invoking the CachedMethod is an array or matrix of whatever type is returned by the original function.

As an example of how this works, evaluation of the expression "fix([0.5, 0.1; 0.4, 0.3], 16, 1)" performs results in the invocation of the method named "fix" in the ptolemy.data.expr.FixPointFunctions that takes a Java double and two Java ints and returns an instance of ptolemy.math.FixPoint. This function is invoked once for each element of the matrix (converting each DoubleToken into the corresponding double, and each IntToken into the corresponding int), and the results are packaged back into a 2x2 FixMatrixToken.

Additional classes to be searched for static methods can be added through the method registerFunctionClass() in PtParser. This class assumes that new classes are added to the search path before models are constructed, and simply clears the internal cache and index when new classes are registered.

Since:
Ptolemy II 2.0
Version:
$Id: CachedMethod.java 57040 2010-01-27 20:52:32Z cxh $
Author:
Zoltan Kemenczy, Research in Motion Limited., Steve Neuendorffer, Edward Lee
See Also:
ASTPtFunctionApplicationNode, PtParser
Accepted Rating:
Yellow (neuendor)
Proposed Rating:
Green (neuendor)

Nested Class Summary
static class CachedMethod.ArgumentConversion
          Class representing an argument conversion.
static class CachedMethod.ArrayMapCachedMethod
          A class representing the invocation of a scalar method on an array of elements.
static class CachedMethod.BaseConvertCachedMethod
          A cached method that converts the object on which the method is invoked as well as the arguments.
static class CachedMethod.MatrixMapCachedMethod
          A class representing the invocation of a scalar method on a matrix of elements.
static class CachedMethod.TypeArgumentConversion
          A class representing an argument conversion to another ptolemy type, followed by the given conversion.
 
Field Summary
private  Type[] _argumentTypes
           
private static java.util.Hashtable _cachedMethods
           
private  CachedMethod.ArgumentConversion[] _conversions
           
private  int _hashcode
           
private  java.lang.reflect.Method _method
           
private  java.lang.String _methodName
           
private  Type _returnType
           
private  int _type
           
static CachedMethod.ArgumentConversion ARRAYTOKEN_CONVERSION
          Conversion from an ArrayToken to a Token array (Token[]).
static int FUNCTION
          Indicator of a function (vs. method).
static CachedMethod.ArgumentConversion IDENTITY_CONVERSION
          Identity conversion.
static CachedMethod.ArgumentConversion IMPOSSIBLE_CONVERSION
          Impossible argument conversion.
static int METHOD
          Indicator of a method (vs. function).
static CachedMethod.ArgumentConversion NATIVE_CONVERSION
          Conversion from tokens to Java native types.
 
Constructor Summary
protected CachedMethod(java.lang.String methodName, Type[] argumentTypes, java.lang.reflect.Method method, CachedMethod.ArgumentConversion[] conversions, int type)
          Construct a new CachedMethod.
 
Method Summary
private static void _addCachedMethod(CachedMethod cachedMethod)
          Add the specified instance of this class to the cache.
protected static boolean _areConversionsPreferable(CachedMethod.ArgumentConversion[] conversions1, java.lang.Class[] arguments1, CachedMethod.ArgumentConversion[] conversions2, java.lang.Class[] arguments2)
          Return true if the conversions in the first argument are preferable to the conversions in the third argument, for methods with argument types given by the second and fourth arguments.
private static CachedMethod _findFUNCTION(java.lang.String methodName, Type[] argumentTypes)
           
private static CachedMethod _findMETHOD(java.lang.String methodName, Type[] argumentTypes)
           
private static CachedMethod _getCachedMethod(java.lang.String methodName, Type[] argumentTypes, int type)
          Return the CachedMethod that corresponds to methodName and argumentTypes if it had been cached previously.
protected static CachedMethod.ArgumentConversion _getConversion(java.lang.Class formal, Type actual)
          Return a conversion to convert the second argument into the class given by the first argument.
protected static java.lang.reflect.Method _polymorphicGetMethod(java.lang.Class library, java.lang.String methodName, Type[] argumentTypes, CachedMethod.ArgumentConversion[] conversions)
          Return the first method in the specified class that has the specified name and can be invoked with the specified argument types.
static void clear()
          Clear the cache.
 boolean equals(java.lang.Object object)
          Return true if the argument is an instance of CachedMethod that represents the same method or function as this instance.
static CachedMethod findMethod(java.lang.String methodName, Type[] argumentTypes, int type)
          Find a method or function with the specified name and argument types.
 int getCachedMethodType()
          Return the type of this class, which is one of METHOD or FUNCTION.
 CachedMethod.ArgumentConversion[] getConversions()
          Return the conversions the are applied to the arguments of this function or method.
 java.lang.reflect.Method getMethod()
          Return the method giving the operation associated with this object, or null if none was found.
 Type getReturnType()
          Return the type of the token that results from an invocation of this method.
 int hashCode()
          Return the hash code.
 Token invoke(java.lang.Object[] argValues)
          Apply the operation represented by this object to the specified arguments.
 boolean isFunction()
          Return true if this instance represents a function (vs. a method).
 boolean isMethod()
          Return true if this instance represents a method (vs. a function).
 boolean isValid()
          Return true if the search for the method or function represented by this object found an invokeable method.
 java.lang.String methodDescription()
          Return a verbose description of the cached method being invoked.
 java.lang.String toString()
          Return a string representation.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

FUNCTION

public static final int FUNCTION
Indicator of a function (vs. method).

See Also:
Constant Field Values

METHOD

public static final int METHOD
Indicator of a method (vs. function).

See Also:
Constant Field Values

IMPOSSIBLE_CONVERSION

public static final CachedMethod.ArgumentConversion IMPOSSIBLE_CONVERSION
Impossible argument conversion.


ARRAYTOKEN_CONVERSION

public static final CachedMethod.ArgumentConversion ARRAYTOKEN_CONVERSION
Conversion from an ArrayToken to a Token array (Token[]).


NATIVE_CONVERSION

public static final CachedMethod.ArgumentConversion NATIVE_CONVERSION
Conversion from tokens to Java native types.


IDENTITY_CONVERSION

public static final CachedMethod.ArgumentConversion IDENTITY_CONVERSION
Identity conversion. Does nothing.


_methodName

private java.lang.String _methodName

_argumentTypes

private Type[] _argumentTypes

_method

private java.lang.reflect.Method _method

_conversions

private CachedMethod.ArgumentConversion[] _conversions

_hashcode

private int _hashcode

_returnType

private Type _returnType

_type

private int _type

_cachedMethods

private static java.util.Hashtable _cachedMethods
Constructor Detail

CachedMethod

protected CachedMethod(java.lang.String methodName,
                       Type[] argumentTypes,
                       java.lang.reflect.Method method,
                       CachedMethod.ArgumentConversion[] conversions,
                       int type)
                throws IllegalActionException
Construct a new CachedMethod. Generally speaking, it is not necessary for any users of this class to invoke this method. The static findMethod() method finds the appropriate method for a given set of argument types and invokes this constructor to create a cached method.

Parameters:
methodName - The name of the encapsulated method.
argumentTypes - An array of token types that can be passed to the method, subject to the given set of conversions. For a FUNCTION, the number of argument types must be the same as the number of arguments to the given method. For a METHOD, there is an additional type in the array (the first) corresponding to the type of object the method is getting invoked on.
method - The Java method that will be invoked by the invoke() method. If this parameter is null, then the method is not valid and cannot be invoked.
conversions - An array of conversions that will convert arguments of the corresponding argument types to arguments that the method will accept. If the method accepts Token arguments, then this array will contain IDENTITY_CONVERSION conversions. This array must be the same size as the number of arguments to the method.
type - The type of the method.
Throws:
IllegalActionException - If the return type of the cached method cannot be determined.
Method Detail

clear

public static void clear()
Clear the cache. This is generally called by the PtParser class when new classes are registered to be searched.


equals

public boolean equals(java.lang.Object object)
Return true if the argument is an instance of CachedMethod that represents the same method or function as this instance. Note that if this returns true, then both this instance and the argument will have the same hashcode, as required by the Object base class.

Overrides:
equals in class java.lang.Object
Parameters:
object - The object to compare to.
Returns:
True if the argument represents the same method or function.

findMethod

public static CachedMethod findMethod(java.lang.String methodName,
                                      Type[] argumentTypes,
                                      int type)
                               throws IllegalActionException
Find a method or function with the specified name and argument types. The last argument is either METHOD or FUNCTION to distinguish the two cases. For the METHOD case, the first argument type is the class on which the method is to be invoked. For the FUNCTION case, the function is a static method of a registered class. This method attempts to find the specified function in the cache, and searches the registered classes only if the function is not in the cache.

This method first attempts to resolve the function in the registered function classes by finding a method and a set of argument conversions that allow the method to be invoked on the given types. If the above fails and at least one argument is an array type or matrix type, a map is attempted over those argument types and the registered function classes are searched again. This process is repeated until all arguments are scalars or a function signature match is found.

Parameters:
methodName - The method or function name.
argumentTypes - The argument types, including as the first element the type of object on which the method is invoked, if this is a method invocation.
type - FUNCTION or METHOD.
Returns:
A cached method that is valid if a matching method was found.
Throws:
IllegalActionException - If the method cannot be found.

getCachedMethodType

public int getCachedMethodType()
Return the type of this class, which is one of METHOD or FUNCTION.

Returns:
The type of this class.

getConversions

public CachedMethod.ArgumentConversion[] getConversions()
Return the conversions the are applied to the arguments of this function or method. Note that in most cases, it is not necessary to call this method, as the invoke() method provides all the necessary information. It is provided for code, such as the code generator that need more than the usual amount of information about methods that have been found.

Returns:
The conversions applied to the arguments.

getMethod

public java.lang.reflect.Method getMethod()
                                   throws IllegalActionException
Return the method giving the operation associated with this object, or null if none was found. Note that in most cases, it is not necessary to call this method, as the invoke() method provides all the necessary information. It is provided for code, such as the code generator that need more than the usual amount of information about methods that have been found.

Returns:
The method associated with this instance.
Throws:
IllegalActionException - If the method was not found, or this class represents a method mapped over an array or matrix.

getReturnType

public Type getReturnType()
                   throws IllegalActionException
Return the type of the token that results from an invocation of this method. Note that in most cases, it is not necessary to call this method, as the invoke() method provides all the necessary information. It is provided for code, such as the code generator that need more than the usual amount of information about methods that have been found.

Returns:
The type of the token that results from an invocation of this method.
Throws:
IllegalActionException - If a method or function with the correct argument types was not found.

hashCode

public int hashCode()
Return the hash code. This method is overridden to be consistent with the overridden equals method.

Overrides:
hashCode in class java.lang.Object
Returns:
A hash code.

invoke

public Token invoke(java.lang.Object[] argValues)
             throws IllegalActionException
Apply the operation represented by this object to the specified arguments. This method performs any necessary conversions on token arguments, and, if necessary, converts the returned value into a token. This method may be overridden by derived classes to implement non-standard conversions.

Parameters:
argValues - An array of Token objects that will be used as the arguments.
Returns:
The result of the method invocation, as a Token.
Throws:
IllegalActionException - If this cached method is not valid, or the invoked method throws it.

isFunction

public boolean isFunction()
Return true if this instance represents a function (vs. a method).

Returns:
True if this instance represents a function.

isMethod

public boolean isMethod()
Return true if this instance represents a method (vs. a function).

Returns:
True if this instance represents a method.

isValid

public boolean isValid()
Return true if the search for the method or function represented by this object found an invokeable method.

Returns:
True if a method was found.

methodDescription

public java.lang.String methodDescription()
Return a verbose description of the cached method being invoked.

Returns:
A verbose description of the cached method being invoked.

toString

public java.lang.String toString()
Return a string representation.

Overrides:
toString in class java.lang.Object
Returns:
A string representation.

_areConversionsPreferable

protected static boolean _areConversionsPreferable(CachedMethod.ArgumentConversion[] conversions1,
                                                   java.lang.Class[] arguments1,
                                                   CachedMethod.ArgumentConversion[] conversions2,
                                                   java.lang.Class[] arguments2)
Return true if the conversions in the first argument are preferable to the conversions in the third argument, for methods with argument types given by the second and fourth arguments. To return true, every conversion in the first method must be preferable or equal to conversions in the second. The two arguments are required to have the same length, or else an InternalErrorException will be thrown.

Parameters:
conversions1 - The first set of conversions.
arguments1 - The arguments of the first method.
conversions2 - The second set of conversions.
arguments2 - The arguments of the second method.
Returns:
True if the first set of conversions is preferable to the second.

_getConversion

protected static CachedMethod.ArgumentConversion _getConversion(java.lang.Class formal,
                                                                Type actual)
Return a conversion to convert the second argument into the class given by the first argument.

Parameters:
formal - The class to which the type shall be converted.
actual - The type to be converted.
Returns:
The best correct conversion, or IMPOSSIBLE_CONVERSION if no such conversion exists.

_polymorphicGetMethod

protected static java.lang.reflect.Method _polymorphicGetMethod(java.lang.Class library,
                                                                java.lang.String methodName,
                                                                Type[] argumentTypes,
                                                                CachedMethod.ArgumentConversion[] conversions)
Return the first method in the specified class that has the specified name and can be invoked with the specified argument types. The last argument is an array that is populated with the conversions that will be required to invoke this method. This method walks through all the superclasses of the given class, and returns the best match (resulting in the most preferable set of argument conversions) to the given argument types. It returns null if there is no match.

Parameters:
library - A class to be searched.
methodName - The name of the method.
argumentTypes - The types of the arguments.
conversions - An array of the same length as argumentTypes that will be populated by this method with the conversions to use for the arguments.
Returns:
the first method in the specified class that has the specified name and can be invoked with the specified argument types.

_addCachedMethod

private static void _addCachedMethod(CachedMethod cachedMethod)
Add the specified instance of this class to the cache.

Parameters:
cachedMethod - The instance to add to the cache.

_findFUNCTION

private static CachedMethod _findFUNCTION(java.lang.String methodName,
                                          Type[] argumentTypes)
                                   throws IllegalActionException
Throws:
IllegalActionException

_findMETHOD

private static CachedMethod _findMETHOD(java.lang.String methodName,
                                        Type[] argumentTypes)
                                 throws IllegalActionException
Throws:
IllegalActionException

_getCachedMethod

private static CachedMethod _getCachedMethod(java.lang.String methodName,
                                             Type[] argumentTypes,
                                             int type)
                                      throws IllegalActionException
Return the CachedMethod that corresponds to methodName and argumentTypes if it had been cached previously.

Throws:
IllegalActionException