Class 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$
    Author:
    Zoltan Kemenczy, Research in Motion Limited., Steve Neuendorffer, Edward Lee
    See Also:
    ASTPtFunctionApplicationNode, PtParser
    Pt.AcceptedRating:
    Yellow (neuendor)
    Pt.ProposedRating:
    Green (neuendor)
    • 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.