You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by Supun Kamburugamuva <su...@gmail.com> on 2007/08/23 08:13:15 UTC

VELOCITY-362 and VELOCITY-529 Solved

Hi list,

I'm really glad that I could solve both VELOCITY-362 and VELOCITY-529.
Here is a general description about how I solved the two problems.

These two problems are interrelated and solving one gives the chance
to solve the other as well. For example if we can specify that a set
of macro files must be used for a particular rendering of a template
(VELOCITY-529) that same underlying mechanism can be used for
specifying that #parse files must be used for the rendering of a
template.

As I have mentioned previously in a mail, the problem with the #parse
and macros was that parse files are built (building AST) and rendered
at the render time of the template.  Macro call is considered valid if
it already has an implementation (it has to be registered). So the
problem was that macros are defined in #parse files which are built
after the files which contain the macro calls were built. So the macro
calls got invalidated and considered as text.

In my approach I don't invalidate macros at the parsing time and let
that happen at the render time.  So a macro call without a macro
implementation won't get invalidated. I have done few changes to the
parser to support this.

When we see a macro call instead of requesting for a VelocimacroProxy
object I'm creating a RuntimeMacro object. I have added few methods to
the InternalHouseKeepingContext to hold the macro libraries associated
with a particular merge. When a template.merge happens with a macro
libraries list the macro libraries (names) are added to the context.
When the RuntimeMacro is rendered it checks for a Macro implementation
in the Macrolibraries specified in the context. If it can find a
VelocimacroProxy it initializes it and then renders it.

VELOCITY-529
Template.merge(context, writer, Macro Library List);

VELOCITY-529
#parse(macroLibrary.vm)
##use macros from the library
#foo()

I think this mail is getting too long. I have added couple of test
cases as well.

Regards,
Supun.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
For additional commands, e-mail: dev-help@velocity.apache.org


Re: VELOCITY-362 and VELOCITY-529 Solved

Posted by Will Glass-Husain <wg...@gmail.com>.
Hello colleagues,

I want to add a note about this.  To me, this is a significant upgrade in
our macro capability.  Previously developers had only two choices.  They
could put individual macros in a template or create a global library of
macros available to all templates.  Now, developers can create libraries
that are selected on a per template basis.

Why is this useful?

Well, before if you had users uploading templates into a pre-existing system
(for example, Roller) they were out of luck unless they could get an admin
to add new macros to the global library.  Now, each user can specify a macro
library that only applies to the templates in their account.

Another benefit is you can create alternative macro libraries with the same
name but different definition.  The macro libraries can be swapped at run
time.  For example, you might choose different macro libraries based on a
user's locale or browser type.

There are two ways of doing this.

(1) By including a macro library (really, just another template file) at the
top of a template with #parse.
    #parse("my_macros.vm")

This was possible before, but never worked right.  (and was warned against
in the docs).  Now it works great.

(2) By specifying a list of macros when merging the the template
    Template.merge(Context, Writer, List)

where the third argument is a list of template names containing macros.

The technical means to make this work was to move macro parsing from
initialization time to render time (same as #parse).  Templates are cached,
so performance should remain about the same as before.

I'm sure we'll see more benefits once Velocity 1.6 is released.  In the
meantime, let me say "Well done!" to our Google Summer of Code contributor,
Supun Kamburugamuva.

Supun has told me that he plans to continue working on Velocity; I
personally welcome his further ideas and contributions.

Best, Will

On 8/22/07, Supun Kamburugamuva <su...@gmail.com> wrote:
>
> Hi list,
>
> I'm really glad that I could solve both VELOCITY-362 and VELOCITY-529.
> Here is a general description about how I solved the two problems.
>
> These two problems are interrelated and solving one gives the chance
> to solve the other as well. For example if we can specify that a set
> of macro files must be used for a particular rendering of a template
> (VELOCITY-529) that same underlying mechanism can be used for
> specifying that #parse files must be used for the rendering of a
> template.
>
> As I have mentioned previously in a mail, the problem with the #parse
> and macros was that parse files are built (building AST) and rendered
> at the render time of the template.  Macro call is considered valid if
> it already has an implementation (it has to be registered). So the
> problem was that macros are defined in #parse files which are built
> after the files which contain the macro calls were built. So the macro
> calls got invalidated and considered as text.
>
> In my approach I don't invalidate macros at the parsing time and let
> that happen at the render time.  So a macro call without a macro
> implementation won't get invalidated. I have done few changes to the
> parser to support this.
>
> When we see a macro call instead of requesting for a VelocimacroProxy
> object I'm creating a RuntimeMacro object. I have added few methods to
> the InternalHouseKeepingContext to hold the macro libraries associated
> with a particular merge. When a template.merge happens with a macro
> libraries list the macro libraries (names) are added to the context.
> When the RuntimeMacro is rendered it checks for a Macro implementation
> in the Macrolibraries specified in the context. If it can find a
> VelocimacroProxy it initializes it and then renders it.
>
> VELOCITY-529
> Template.merge(context, writer, Macro Library List);
>
> VELOCITY-529
> #parse(macroLibrary.vm)
> ##use macros from the library
> #foo()
>
> I think this mail is getting too long. I have added couple of test
> cases as well.
>
> Regards,
> Supun.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
> For additional commands, e-mail: dev-help@velocity.apache.org
>
>


-- 
Forio Business Simulations

Will Glass-Husain
wglass@forio.com
www.forio.com

Re: VELOCITY-362 and VELOCITY-529 Solved

Posted by Nathan Bubna <nb...@gmail.com>.
Great work, Supun!  The code and tests look great.  I look forward to
trying this out myself.

On 8/22/07, Supun Kamburugamuva <su...@gmail.com> wrote:
> Hi list,
>
> I'm really glad that I could solve both VELOCITY-362 and VELOCITY-529.
> Here is a general description about how I solved the two problems.
>
> These two problems are interrelated and solving one gives the chance
> to solve the other as well. For example if we can specify that a set
> of macro files must be used for a particular rendering of a template
> (VELOCITY-529) that same underlying mechanism can be used for
> specifying that #parse files must be used for the rendering of a
> template.
>
> As I have mentioned previously in a mail, the problem with the #parse
> and macros was that parse files are built (building AST) and rendered
> at the render time of the template.  Macro call is considered valid if
> it already has an implementation (it has to be registered). So the
> problem was that macros are defined in #parse files which are built
> after the files which contain the macro calls were built. So the macro
> calls got invalidated and considered as text.
>
> In my approach I don't invalidate macros at the parsing time and let
> that happen at the render time.  So a macro call without a macro
> implementation won't get invalidated. I have done few changes to the
> parser to support this.
>
> When we see a macro call instead of requesting for a VelocimacroProxy
> object I'm creating a RuntimeMacro object. I have added few methods to
> the InternalHouseKeepingContext to hold the macro libraries associated
> with a particular merge. When a template.merge happens with a macro
> libraries list the macro libraries (names) are added to the context.
> When the RuntimeMacro is rendered it checks for a Macro implementation
> in the Macrolibraries specified in the context. If it can find a
> VelocimacroProxy it initializes it and then renders it.
>
> VELOCITY-529
> Template.merge(context, writer, Macro Library List);
>
> VELOCITY-529
> #parse(macroLibrary.vm)
> ##use macros from the library
> #foo()
>
> I think this mail is getting too long. I have added couple of test
> cases as well.
>
> Regards,
> Supun.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
> For additional commands, e-mail: dev-help@velocity.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@velocity.apache.org
For additional commands, e-mail: dev-help@velocity.apache.org