|
Table of Contents
Call Descriptor & ParametersThe importance of call descriptor and paramters is that they allow to specify the exact metaobject protocol (MOP) we want to use. Using these elements we can see the metaobject programming as a task of connecting objects (as we did in the tracing example). In this section we will review the API of the ClassDescriptor| class and the Parameter interface. CallDescriptor class
The The important part of the CallDescriptor API is its contructor, that takes all the necessary information to make the call: public CallDescriptor(String aType, String aMethod, Parameter... aParameters){...} This call descriptor will produce code like this: ((aType) metaobject).aMethod(aParameters) The last argument is a list of Parameter intances (as it is a varargs constructor) that describes the parameters that will be used in the call. For example, if we want to invoke println over System.out without arguments, the call descriptor should be like: new CallDescriptor("java.io.PrintStream", "println"); Next we will review the interface Parameter in detail. Parameter interface
The The parameter interface defines three methods that have to be implemented: public String evaluate(Operation aOperation); This method must return the code of the parameter, for the given operation. The code can include Javassist syntax. public String getType(Operation aOperation);
This method must return the fully qualified type of the parameter's evaluation. If the parameter represents an int it should return public boolean shouldBeEvaluatedAtHook(Operation aOperation); This method is here for optimization only. It must return true if the parameter should be evaluated at the hook (because it uses contextual information). Sometimes, certain parameters are evaluated but never used (because they are used to invoke a method in a metaobejct that is nested and the first metaobject in the chain does not call proceed, then, it would be perfect if their evaluation could be delayed until it is really necessary. This is the purpose of this method, to give a hint to the Reflex code generation engine. An example parameter that records the time when the hook was reached is: public class TimeParameter implements Parameter{ public String evaluate(Operation aOperation){ return "System.currentTimeMillis()"; } public String getType(Operation aOperation){ return "long"; } public boolean shouldBeEvaluatedAtHook(Operation aOperation){ return true; } }
The Another parameter (a bit more complex) is one that makes use of the operation specified. In this case to determine if the read/write operation thas is being done is read: public class IsRead implements Parameter{ public String evaluate(Operation aOperation){ return String.valueOf(((Operation.ReadWrite) aOperation).isRead()); } public String getType(Operation aOperation){ return "boolean"; } public boolean shouldBeEvaluatedAtHook(Operation aOperation){ return false; } }
The evaluate method returns Next we will see some of the ready-to-use parameters provided by Reflex. Utility Parameters
This parameter evaluates to the context object: the current class if the operation is in static context and this if it is not.
This parameter evaluates to the result of the operation (the value about to be returned by a method invocation, the resulting value of the field access if the expression is read access, the resulting value of the object creation, etc). This parameter is the same as the
This parameter evaluates to the closure object used to invoke the next step in the chain of metoabjects.
This method evaluates to an array of objects, objects that are the parameters of the operation: new Object[]{ parameter1, parameter2, ..., parameterN}
This method evaluates to the name of the operation: the method name if it is a method receive or a method invocation, the field name if it is a field access, etc.
This parameter evaluates to the type of the object receiving the operation: the type of an object subject of a message send, the type of a field being accessed, etc.
This parameter evaluates to the declaring class of the operation: the class declaring a method or constructor that is being invoked or a field that is being accessed.
This parameter evaluates to the line number of the operation if available. |