You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Daniel Dekany <dd...@freemail.hu> on 2002/04/12 17:02:59 UTC

Pluggable Preprocessor proposal

I started this thread to separate the preprocessor thing from the
whitespace thread. Also I would like to introduce a more concrete idea
about pluggable preprocessors:

package org.apache.velocity.app;

import java.io.*;

public interface Preprocessor
{
    void init(VelocityEngine ve);
    Reader getReader(InputStream is, String encoding, String name);
}

getReader returns a reader which makes some transformations (i.e.
preprocessing) on the original stream. name is passed so that the
Preprocessor can decide how to preprocess based on the file extension.

When a new VelocityEngine instance created, it should create a
Preprocessor instance using the parameterless constructor of class
specified in preprocessor.class runtime configuration value. If
preprocessor.class is missing then it defaults to a built-in class,
which basically does nothing. Then it calls init method with the
VelocityEngine instance as a parameter, so Preprocessor instance can
call methods like getPropery, warn, etc.

In the org.apache.valocity.Template this line:

  BufferedReader br =
      new BufferedReader( new InputStreamReader( is, encoding ) );

should be replaced by this:

  BufferedReader br =
      new BufferedReader(
          rsvc.getPreprocessor().getReader( is, encoding, name )
      );

Note the new method in RunntimeServices interface.

That's all.

About whitespace gobbling and preprocessors:
If we want to solve whitespace handling with preprocessors (the
problem was that Velocity tries to be application independent tool,
while the practical method of whitespace gobbling is application
dependent), then core Velocity should not gobble whitespace at all.
But since the typical usage of Velocity is HTML/XML template writing,
that already proposed white space gobbling should be implemented with
a Preprocessor class that comes with the standard Velocity
distribution. Then user can specify that preprocessor in the config
file, or (s)he can reuse that class in his/her custom Preprocessor
(it's obvious how to chain preprocessors).


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Pluggable Preprocessor proposal

Posted by Jim Rudnicki <jd...@pacbell.net>.
> ... the
> problem was that Velocity tries to be application independent tool,
> while the practical method of whitespace gobbling is application
> dependent ...

Yes.  I'm glad you put this into words.  This is why I keep thinking there
is no _one_ solution to the problem.

Jim




--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Re[2]: Pluggable Preprocessor proposal

Posted by Daniel Dekany <dd...@freemail.hu>.
On Monday, April 15, 2002 2:26 PM "Geir Magnusson Jr." <ge...@optonline.net>
writen:

[snip]
> This problem is to some degree the exact same problem as our 'loader
> decorator' problem, so I wonder if we can combine the two into one
solution.

>
> The 'loader decorator' problem is one where you want to ask for one thing
> like 'templates/foo/bar.vm' and have it resolve to something else.
>
> So in each case, a subcomponent of the resource manager is returning
> something different than casual inspection would suggest.

[snip]

I would like to stress again that resource loaders deal with byte streams,
while template preprocessors deal with text streams. (Currently the
byte-stream -> text-stream transformation hapens inside Template class.)
Also, in the original proposal we want to preprocess templates only.


[snip]
> 3) a 'dynamic preprocessor' that xforms the 'pretty-to-look-at' stream to
a
> stream that does the right output.

[snip]

Another important motivation is that one (me :)) may want to extend VTL
syntax with application specific features. For example I need JSP-tag like
syntax (will be xformed to tool calls).


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Re[2]: Pluggable Preprocessor proposal

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
Sorry about the delay.  Racing good on Saturday, and then basically took a
day off yesterday...

On 4/12/02 6:45 PM, "Daniel Dekany" <dd...@freemail.hu> wrote:

> Friday, April 12, 2002, 10:17:50 PM, Geir Magnusson Jr. wrote:
> 
> [snip]
>> It's not clear why this should be where you put it - why there should be one
>> global preprocessor per instance of VE.
> 
> The idea was that I don't want to bloat Velocity core with the issues
> of multiple preprocessors (which preprocessor to use, how to configure
> them, etc).

I can guarantee the core isn't going to get bloated :)

> Instead, you allow application developer to develop
> his/her own Preprocessor, which is *maybe* a dispatcher to other
> preprocessors. E.g. it chooses a preprocessor instance depending on
> the file extension. So that global preprocessor is in fact a
> "preprocessor manager". But this will not be the problem of velocity
> and this is the point.

If you put it in 'Template.java', that's core Velocity.  To me, that seems
like the wrong place.

This problem is to some degree the exact same problem as our 'loader
decorator' problem, so I wonder if we can combine the two into one solution.

The 'loader decorator' problem is one where you want to ask for one thing
like 'templates/foo/bar.vm' and have it resolve to something else.

So in each case, a subcomponent of the resource manager is returning
something different than casual inspection would suggest.

 
>> I also have questions about if you want this xformation cached (which it
>> will be) or not, or the choice.
> 
> Yes, this is a problem. Fortunately in practice one may want to cache
> them, since the preprocessing is independent of merge(...) context.
> But read on...
> 
>> For example, you might want parameterized xformations...
> 
> Currently Resource.data is depends on the state (maybe lastModified)
> of source. If we want to deal with the problem above, then
> Resource.data has to depend on the state of the global preprocessor
> instance too. So Resource.isSourceModified will not enough since we
> need a Resource.isPreprocessorModified too... and then Preprocessor
> need new methods too... etc. Ugly and complicated. Independently of
> the preprocessor problem: the current dependency management is not
> general enough. It should be redesigned. As I see it when looking into
> the code, it's design already caused problems. But this would be
> totally different thread what I want not start now. So as long as we
> don't have a adequate dependency management IMO we can survive with
> always-cached preprocessed templates. When we have an adequate one,
> the problem of caching of preprocessed templates will be trivial.

I dunno.  I think this should be in the regular resource management area - I
haven't had enough time to think about it.  But is seems from the app point
of view that it doesn't matter if the template is pre-processed or was that
way originally.

One motivation for this solution is that people want both pretty-to-look-at
templates in their editors at the same time that output is a 'certain way'.
This relationship is not general, so the notion of pre-processing comes into
play.

Now, working backwards from the end result, a template stream that produces
the right output, it's really irrelevant how that got there  :

1) do it 'right' in the editor
2) have a magic editor that shows the author one thing and writes another
thing to disk (call that a 'static preprocessor')
3) a 'dynamic preprocessor' that xforms the 'pretty-to-look-at' stream to a
stream that does the right output.

Clearly 1) is not popular :), 2) isn't a good solution so 3) is where we
have to focus.  But the fact that all 3 are equivalent might help convince
that it can be thought of as a resource management problem....

The cool think about this is that the done this way, the solution can be
mocked up outside of Velocity - you can take an existing template, xform it,
and render that...


-- 
Geir Magnusson Jr.                                     geirm@optonline.net
System and Software Consulting

The cost of synchronization is much less that the cost of stupidity.


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re[2]: Pluggable Preprocessor proposal

Posted by Daniel Dekany <dd...@freemail.hu>.
Friday, April 12, 2002, 10:17:50 PM, Geir Magnusson Jr. wrote:

[snip]
> It's not clear why this should be where you put it - why there should be one
> global preprocessor per instance of VE.

The idea was that I don't want to bloat Velocity core with the issues
of multiple preprocessors (which preprocessor to use, how to configure
them, etc). Instead, you allow application developer to develop
his/her own Preprocessor, which is *maybe* a dispatcher to other
preprocessors. E.g. it chooses a preprocessor instance depending on
the file extension. So that global preprocessor is in fact a
"preprocessor manager". But this will not be the problem of velocity
and this is the point.

> I also have questions about if you want this xformation cached (which it
> will be) or not, or the choice.

Yes, this is a problem. Fortunately in practice one may want to cache
them, since the preprocessing is independent of merge(...) context.
But read on...

> For example, you might want parameterized xformations...

Currently Resource.data is depends on the state (maybe lastModified)
of source. If we want to deal with the problem above, then
Resource.data has to depend on the state of the global preprocessor
instance too. So Resource.isSourceModified will not enough since we
need a Resource.isPreprocessorModified too... and then Preprocessor
need new methods too... etc. Ugly and complicated. Independently of
the preprocessor problem: the current dependency management is not
general enough. It should be redesigned. As I see it when looking into
the code, it's design already caused problems. But this would be
totally different thread what I want not start now. So as long as we
don't have a adequate dependency management IMO we can survive with
always-cached preprocessed templates. When we have an adequate one,
the problem of caching of preprocessed templates will be trivial.


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Pluggable Preprocessor proposal

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
I have to get back on the road (going to Boston...) but here's a quick POV
on this.

On 4/12/02 11:02 AM, "Daniel Dekany" <dd...@freemail.hu> wrote:

> I started this thread to separate the preprocessor thing from the
> whitespace thread. Also I would like to introduce a more concrete idea
> about pluggable preprocessors:
> 
> package org.apache.velocity.app;
> 
> import java.io.*;
> 
> public interface Preprocessor
> {
>   void init(VelocityEngine ve);
>   Reader getReader(InputStream is, String encoding, String name);
> }
> 
> getReader returns a reader which makes some transformations (i.e.
> preprocessing) on the original stream. name is passed so that the
> Preprocessor can decide how to preprocess based on the file extension.
> 
> When a new VelocityEngine instance created, it should create a
> Preprocessor instance using the parameterless constructor of class
> specified in preprocessor.class runtime configuration value. If
> preprocessor.class is missing then it defaults to a built-in class,
> which basically does nothing. Then it calls init method with the
> VelocityEngine instance as a parameter, so Preprocessor instance can
> call methods like getPropery, warn, etc.
> 
> In the org.apache.valocity.Template this line:
> 
> BufferedReader br =
>     new BufferedReader( new InputStreamReader( is, encoding ) );
> 
> should be replaced by this:
> 
> BufferedReader br =
>     new BufferedReader(
>         rsvc.getPreprocessor().getReader( is, encoding, name )
>     );
> 
> Note the new method in RunntimeServices interface.
> 
> That's all.

It's not clear why this should be where you put it - why there should be one
global preprocessor per instance of VE.

I would think that we could combine this with some of the planned resource
manager work, and combine it there as a general input filter.

I also have questions about if you want this xformation cached (which it
will be) or not, or the choice.

For example, you might want parameterized xformations...

Will have hours in the car to think about it...

> About whitespace gobbling and preprocessors:
> If we want to solve whitespace handling with preprocessors (the
> problem was that Velocity tries to be application independent tool,
> while the practical method of whitespace gobbling is application
> dependent), then core Velocity should not gobble whitespace at all.
> But since the typical usage of Velocity is HTML/XML template writing,
> that already proposed white space gobbling should be implemented with
> a Preprocessor class that comes with the standard Velocity
> distribution. Then user can specify that preprocessor in the config
> file, or (s)he can reuse that class in his/her custom Preprocessor
> (it's obvious how to chain preprocessors).
> 
> 
> --
> To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> For additional commands, e-mail:
> <ma...@jakarta.apache.org>
> 

-- 
Geir Magnusson Jr.                                     geirm@optonline.net
System and Software Consulting
"They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety." - Benjamin Franklin



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>