:: 1) the decoupling of AndroMDA from any particular scripting :: engine (i.e.
:: Velocity)
:: 2) the addition of FreeMarker as a supported scripting :: engine alternative
:: :: So here is my opinion on the topic. Point (1) just seems :: like a good thing to do from an architectural point of view. :: I cannot see any strong reasons for why we'd want AndroMDA :: to continue to be so tightly coupled to Velocity. Just :: because we decouple AndroMDA from Velocity does not mean we :: must provide an alternative scripting engine. It just means :: that we can.
:: :: Point (2) is not so clear to me. I believe Jonathan has :: stated the case very clearly. Would AndroMDA be served well :: by the "friendly fascism" of not providing alternative :: scripting engines? Or would AndroMDA be better served by :: providing alternatives? Jonathan thinks yes. I honestly do :: not know, but I don't think more choices is clearly better. :: I actually see it as a really hard call to know what is the :: right thing to do. Honestly I would be ok with it going either way.
i'm the www.beanshell.org supporting guy who popped in the middle of the discussion with my first post.
i've got a point to support choice... if you look at the way andromda can be used by _developers_ you realize that it's never going to be that simple as drawing uml and typing ant. you always need to change things here and there, understand the way andromda works, or even more create your own cartridge for a single project. so having choice helps here.
and on the other hand if we have choice then we will have cartridges written in various script languages that hurts uniformity, etc... but it's not a problem for those drawing kind of users, who will only type ant and don't know what's happening inside. and if the cartridge architecture is flexible enough then we could have 3 ejb cartridge and let the insiders choose. if you document only one, set the default configuration to use the velocity based one, then who's not digging deep will not see anything about the "mess".
and as of beanshell, i think it's great to use the same language on the macro level as on the execution level. if you can use java to generate java you can have a lot of fun, with multi level macros, etc... it's power (, that must not be abused of course).
and as of quote, back quote context switches... imho it's much cleaner to have a switching syntax other then # on each line. and with a proper syntax highlighting it's much easier to read.
FreeMarker has the ability to define something called transforms, which run the things in between two tags through a transform or filter. Some such transforms could be as simple as just making everything upper case, but they can be arbitrarily copmlex. We actually have one in our distro for jython, though we could support beanshell quite well, and then you just go:
<@jython>
for i in range(10) :
....
print x, y # and the print result goes to the template output
</@jython>It's extra powerful, because the stuff inside the jython tags has substitutions applied to it, so it could be:
<@jython>
for i in range(${num_items}) : # num_items from the template context
...
...
env[x] = foo # we put the foo variable in the template's context
</@jython>It's insanely powerful. We have a jython runtime you can embed out-of-the-box, but we could provide beanshell quite easily. So, basically, the FreeMarker support could basically subsume jython or beanshell support, since transform facilities in FreeMarker could allow you to embed a scripting language in a FreeMarker template. Also, FreeMarker can use any 3rd party JSP taglibs.
And in terms of things like recursion and closures and so on, you could look at:
http://freemarker.org/docs/dgui_misc_userdefdir.html
Look in particular at the Nested Content and Loop Variables subsections in the above-linked page.
I think that, from the above, you can imagine all kinds of powerful things you can do in FreeMarker that are next-to-impossible in Velocity and require you to jump through all kinds of hoops.
But, in general, you can't anticipate all the things that users want to do. It's better to provide more options.
Oh, and by the way, do you know that FreeMarker is at least partly a Hungarian project? My two co-admins on the project are both Hungarian -- Attila Szegedi and Daniel Dekany. (Another reason to have a look. ;-))
Regards,
Jonathan Revusky -- lead developer, FreeMarker project, http://freemarker.org/
example with beanshell: generate a method for each entry in methods array, and as their body call each other method. (syntax is just a quick idea)
see also attached file without wrapped.
// start in execution context for(int i = 0; i < methods.size(); ++i) { // no cast needed here, beanshell typesystem can be relaxed (most probably) Method thisMethod = methods.get(i);
// switch to quoted context <+ public void ${thisMethod}(String calledBy) // assumes thisMethod.toString() returns it's name (it goes into the generated file) { ${ // go back here to beanshell execution context // log we were called and call all other methods
generateLog(thisMethod, calledBy); // put logging here with a "macro call"
for (int j = 0; j < methods.size(); ++j) { Method otherMethod = methods.get(j);
if (thisMethod != otherMethod) // skip ourselves to avoid infinite reqursion { <+ // calling method ${otherMethod} from ${thisMethod} ${otherMethod}("${thisMethod}"); +> } } } } +>
}
// this is effectively a macro void generateLog(String thisMethod, String calledBy) { <+ log.info("method ${thisMethod} called by ${calledBy}"); +> }
(this example is probably buggy as writing stuff at the macro level requres heavy testing :)
by a preparser written by us, it would be turned into a beanshell script with full of stream.write's (similar to how JSP's work). there's a possibility of easily supporting multiple output streams from one template for example by giving the stream id after '<+', sometimes it can be a big help!
anyways i think choice is better, and can be controlled with documentation and defaults. and if there were a clean interface in andromda i would implement the above.
what do you think?
yours,
- 101
------------------------------------------------------------------------
// start in execution context for(int i = 0; i < methods.size(); ++i) { // no cast needed here, beanshell typesystem can be relaxed (most probably) Method thisMethod = methods.get(i);
// switch to quoted context <+ public void ${thisMethod}(String calledBy) // assumes thisMethod.toString() returns it's name (it goes into the generated file) { ${ // go back here to beanshell execution context // log we were called and call all other methods
generateLog(thisMethod, calledBy); // put logging here with a "macro call"
for (int j = 0; j < methods.size(); ++j) { Method otherMethod = methods.get(j);
if (thisMethod != otherMethod) // skip ourselves to avoid infinite reqursion { <+ // calling method ${otherMethod} from ${thisMethod} ${otherMethod}("${thisMethod}"); +> } } } } +>
}
// this is effectively a macro void generateLog(String thisMethod, String calledBy) { <+ log.info("method ${thisMethod} called by ${calledBy}"); +> }
------------------------------------------------------- This SF.Net email sponsored by: Free pre-built ASP.NET sites including Data Reports, E-commerce, Portals, and Forums are available now. Download today and enter to win an XBOX or Visual Studio .NET. http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 _______________________________________________ Andromda-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/andromda-devel
