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