I will try to expain consicely and clearly what the proposal is again.
Current situation:
'Extra' functionality can be called in several ways:
- implemenated in 'executeFunction' of an MMObjectBuilder extension
e.g. <mm:field name="gui(title)" />
<mm:ffield name="cache(s(100x100))" />
Such function are characterized by a name and a list of arguments.
If called by getValue(String) then all arguments must be String, because a
StringTokenizer it uses.
You can also give a List of parameters if String are to limiting:
MMObejctBuilder#executeFunction(String, List)
Node#getFunctionValue(String, List)
- Functionality can be on NodeManager and Module:
NodeManager:
public String getInfo(String command);
public String getInfo(String command, ServletRequest req, ServletResponse resp);
public NodeList getList(String command, Map parameters);
public NodeList getList(String command, Map parameters, ServletRequest req,
ServletResponse resp);
Module:
public String getInfo(String command);
public String getInfo(String command, ServletRequest req, ServletResponse resp);
public NodeList getList(String command, Map parameters);
public NodeList getList(String command, Map parameters, ServletRequest req,
ServletResponse resp);
The generalisation which can be made from this is that a piece of 'extra'
functionality is defined by:
- An object where it works on (node, nodeManager, module)
- A String identifying it ('command')
- A List or a Map with auxiliary parameters
- 'standard' parameters like a ServletRequest and ServletResponse object
Daniel came up with an implementation with the following properties:
- Piece of functionality is not connected to a specific object, but to a
'set'. This look a bit like a namespace of static functions.
This hack now proposes a generic way to deal with 'extra' functionality, and
solves a few problems which you can have with it.
- First of all, we see a descrepancy in the way to handle the parameters:
Sometimes a 'List' is to be given and sometimes a 'Map'.
- There is no way to define how big the list must be, or which keys
the map must have. Nor of which type the values must be.
For these two problems I already provided an 'Arguments' object in
org.mmbase.util. In this hack it appears as 'Parameters' (Arguments will
then be removed)
The Parameters object works like this:
Every possible parameter is defined by a "Parameter" object which is a
simply container with the following entries:
String key;
Class type;
and also (these two are less essential):
String description = "";
Object defaultValue = null
The Parameters object contains an array of such Parameter objects, and
should actually be instantiated with such an Array.
This Parameter[] is the definition of the arguments of the function.
Parameters is not a definition but contains actual parameter values. It uses
the Parameter[] to check these.
Parameters itself implements List, so it can directly be fed to
executeFunction of MMObjectBuilder.
Because it knows the complete definition of the function it is for, it can
be filled as a Map, because every Parameter is assosciated with a key.
So, it is also easy to make a Map of a Parameters object (with the 'toMap'
method).
In less words: A Parameters object implements List, has fixed size, and
defines the type of every element. It can easily be tranformed to a Map.
To use it you need a Parameter[] which you could e.g. define as a Constant
on the spot where you also implement the actual function.
Parameters is hardly more then a utitily class to help you filling a list
in the way it has to be for the specific function.
This hack proposes now that this should be the general way, and adds for
this the extra class 'Function'. The function object specifies the function
completely. Therefore it contains these members:
protected String name;
protected ReturnType returnType;
private Parameter[] parameterDefinition
Because a function has a name, a return type and a certain number of
specified parameters.
The 'ReturnType' class is actually simply a wrapper around 'Class' (but
contains e.g. also descripton)
Function furtermore contains the methods to execute the functionality, but
abstract because it is not yet known where that would eacutally be
implemented.
So
abstract public class Function {
protected Function(String name, Parameter[] def, ReturnType returnType);
: all function implementation need this info, so this protecte constructor
must be called by extensions
/**
* Creates an empty 'Parameters' object for you, which you have to fill and feed
back to getFunctionValue
* @see #getFunctionValue
*/
public Parameters getNewParameters() {
/**
* Executes the defined function supplying the given arguments.
* @see #getNewParameters
*/
abstract public Object getFunctionValue(Parameters arguments);
}
When you have a function object you can call the functionality which it
describes:
Function function = <some way to get the Function object>: will need at
least a 'name' argument;
Parameter params = function.getNewParameters();
params.set("bla", value); // will lead to errors if parameters 'bla' is not
// defined for this function, or 'value' is of the wrong
type.
// 'standard' parameters can go like this:
if (params.hasParameter(Param.REQUEST))) {
params.set("request", request);
}
params.set(..)..
Object result = function.getFunctionValue(params);
Of course you can now implement different actions with the reuslt depending
e.g. on its type. You can use things like 'result instanceof' of ask the
function object what the return type is supposed to be (it that is correct
depends only on the impleentor of the functionality)
The hack is about this way to generalize the already existing way to deal
with extra functionality. For example in taglib implemenation to this
generic functions as soon as I have the 'Function' boejct is does not matter
any more, and everything became uniform, besides a selector implementation
for the isntantion of the function object.
The way to get the function object is not complety included in this hack.
The existing ways (on Node, NodeManager and Module) can easily be
implemented, and in speeltuin I put some proposals for these.
For functions on Node I'd propose to add an extra method on MMObjectBuilder:
Param[] getFunctionParameterDefinition(String name);
which can be implemenated simply.
I'm not sure how it should go for Modules, NodeManager and 'Sets' but I'd go for
anything. And would be ready to leave that unimplemented in 1.7. In taglib I
would only anticipate the possibliity.
I could also imaging a private taglib implementation of Function to speak to
java functions generally (e.g. in a <%! %> block on the same jsp). But such
an implemenation would then be part of the taglib project and no need to
included that in this hack.
I hope this clears up things a bit.
Michiel
--
Michiel Meeuwissen
Mediapark C101 Hilversum
+31 (0)35 6772979
nl_NL eo_XX en_US
mihxil'
[] ()