Re: Calling a function using a variable name
Martin Klang <[email protected]> Thu, 3 Feb 2005 03:44:28 +0000
| Newsgroups | gmane.text.xml.o-xml |
|---|---|
| Message-ID | <[email protected]> |
On 2 Feb 2005, at 3:09, Glen Barnes wrote:
> Is this possible in o-xml?
everything is possible!
Usually you would define a type for each different behaviour, eg
BlogModule, FooModule, BarModule.
You then still have to use conditionals to create an instance of the
right type. You can put this code in a Factory, eg in pseudo-code
ModuleFactory.createModule(String module, Node parameters){
if 'blog' return new BlogModule(parameters)
else ... etc
}
A classical, object-oriented solution would then uses polymorphism to
perform the action:
- define a shared base type Module, with a (virtual/empty) function, eg
'execute(args)'
- override this function in the derived types with the specialised
behaviour
so your code might look:
<o:set module="$factory.createModule($module-type)"/>
<o:eval select="$module.execute($parameters)"/>
The parameters may be passed either in instantiating the Module, ie in
the factory, or at point of call through the execute method - whichever
is more suitable.
There's a design-pattern called AbstractFactory which might be
interesting to look at. Possibly ott for what you need, though!
A variation is to exploit the dynamic typing of o:XML and use function
overloading instead of polymorphism:
define an execute function for each type, eg
execute(BlogModule module, Node parameters)
execute(FooModule module, Node parameters)
etc
Then call with:
<o:set module="$factory.createModule($module-type)"/>
<o:eval select="execute($module, $parameters)"/>
The right function will automatically be called, based on the runtime
type of the args.
You still have to create the type instances in the first place though.
If you absolutely need to get rid of the conditionals, you need
reflection.
Unfortunately the o:XML reflection extensions have been disabled in the
last few builds - I think 0.9.8 might have been the last one to include
them. Previously you could do:
<!-- get a function with matching name that takes exactly one parameter
-->
<o:set function="reflect:program()//function[@name = $module and
count(param) = 1]"/>
<!-- invoke it with the given argument -->
<o:eval select="$function.invoke($parameters)"/>
Reflection will make a reappearance soon, in an all-revamped MLML form
that will enable meta-programming, AOSD and much more!
Until then I'm afraid you're stuck with using the built-in Java
reflection mechanism through the o:XML Java extensions. Not very nice
at all.
hth,
/m
> I'd like to call a function based on the value of a variable:
>
> At the moment I have this:
>
> <o:choose>
> <o:when test="$module='blog'">
> <!-- Display weblog entries -->
> <o:eval select="p:blog_default($parameters)" />
> </o:when>
> .
> .
> .
> </o:choose>
>
> But what I would like to do is something like this:
>
> <o:call-function name="$module" param=,"$parameters" />
>
> Is this possible in o-xml?
>
> Thanks,
> Glen