Re: Extending the foreach directive

2008-03-11 Thread Jonathan Revusky

Gary Bentley wrote:

Hi Jonathan,

The original aim of the request was to allow a JoSQL statement to be 
used directly within Velocity.  More specifically it would be that the 
WHERE clause, ORDER BY clause and potentially the GROUP BY clause (and 
as a further extension the LIMIT and GROUP BY ORDER clauses) could be used.


Well, okay, but then, frankly, you didn't formulate your original 
question very well. What you're wanting above is something very general, 
and I answered the question as specifically how do you do the specific 
example you gave in FreeMarker.


The thing is that it so happened that the specific example you used 
could be written directly using FreeMarker without exposing anything 
extra from the java side -- or interacting with josql, and of course, 
your whole motive is to interact with josql, but that was not at all 
clear from the question. Never mind, nobody's perfect. :-)


The freemarker code I gave simply used ?sort_by which is a freemarker 
built-in See: 
http://freemarker.org/docs/ref_builtins_sequence.html#ref_builtin_sort_by


FreeMarker currently doesn't have built-ins that replicate all of an SQL 
SELECT statement, like GROUP BY and HAVING and so on. (Of course, as a 
practical matter, a lot of SELECT queries are just about like that one, 
with a sort key and a condition.)


But okay, what you want to do is expose josql functionality to FreeMarker...




To do this in Velocity I was going to do (I've written, the code but due 
to personal reasons not had chance to go further with it yet):


#foreach ($v in $josql.filter ("name LIKE '/opt/%' order by dir, name", 
$files))


This isn't as elegant as I'd like but it will work.  I had looked at 
modifying the Velocity grammar to support N arguments to a tool but I 
ran into a number of problems with it. 
Unfortunately, from what I've 
seen, the Velocity grammar has hard coded support for the "foreach" 
statement.  Personally I'd like to see the grammar in the form:


[args]


Well, the basic way you could have that syntax in FreeMarker is along 
the lines of the example I gave in the last message. Here is an 
approximate possibility:


<#macro josqlIterator
sequence
where=[]
order_by=[]
group_by=[]
having=[]
descending=false
>
 <#local results=josql.filter(where, order_by, group_by, having, 
descending)>

 <#list results as result>
<#nested result result_index+1 result_count>
 


I guess it is assumed that you receive a sequence as a required 
parameter and the other named parameters are optional and default to the 
empty sequence, except for descending which defaults to false.


So here would be a possible invocation of the above macro.

<@josqlIterator sequence=files
where=["LIKE '/opt/%'"]
order_by=["dir", "name"] ; row, index
>
 

   ${index}. ${flogger.getPromo(row)}

  


Note that in the above example, unlike the one I gave in the last 
messsage, I had the invocation of the loop pass in three loop variables, 
the row and its 1-based index, and the total row count.  This, besides 
being a fairly realistic scenario that you'd need something like that, 
gives you an idea of the flexibility of the macro system.




And then have the tool invoked with the arguments passed to it.  But 
that's not for me to decide.


What do you mean, it's not for you to decide? If you mean that it's not 
technically feasible with Velocity, well, use a tool that has the 
flexibility to do it how you want to.




As for it's implementation in FreeMarker, I would like to do that in 
time (I wasn't aware of FreeMarker before), but again having a "native" 
implementation for the statement would be preferable to the special 
macro you defined.  When I get around to a FreeMarker implementation 
I'll let you know and you can tell me the possibilities!


Well, I've given you a flavor of it here. Obviously you have a lot more 
possibilities than you do with Velocity. Frankly, I think it's like 
night and day...


But let me say, that if you get into doing this with FreeMarker, in this 
case, I really think you'd be better off using the code from the SVN 
HEAD. You can get the latest greatest here:


http://freemarker.org:8085/browse/FM-TRUNK

And then you click on the "COMPLETED BUILDS" tab and choose the latest 
one. (At the moment that is:)


http://freemarker.org:8085/browse/FM-TRUNK-153

and then you click on the Artifacts tab and pick up the freemarker.jar.

The reason to use the 2.4 codebase (the stable release is 2.3.x) is that 
there are specifically some very nice new features for exposing java 
methods to the template layer. It's annotation based, so that, even 
though java doesn't support optional and default parameters, or invoking 
parameters by name,you can add  an annotation on the java side so that 
it effectively has optional and default parameters and invocation by 
name when you call it from the template layer.


Lik

Re: Extending the foreach directive

2008-03-11 Thread Gary Bentley

Hi Jonathan,

The original aim of the request was to allow a JoSQL statement to be 
used directly within Velocity.  More specifically it would be that the 
WHERE clause, ORDER BY clause and potentially the GROUP BY clause (and 
as a further extension the LIMIT and GROUP BY ORDER clauses) could be used.


To do this in Velocity I was going to do (I've written the code but due 
to personal reasons not had chance to go further with it yet):


#foreach ($v in $josql.filter ("name LIKE '/opt/%' order by dir, name", 
$files))


This isn't as elegant as I'd like but it will work.  I had looked at 
modifying the Velocity grammar to support N arguments to a tool but I 
ran into a number of problems with it.  Unfortunately, from what I've 
seen, the Velocity grammar has hard coded support for the "foreach" 
statement.  Personally I'd like to see the grammar in the form:


[args]

And then have the tool invoked with the arguments passed to it.  But 
that's not for me to decide.


As for it's implementation in FreeMarker, I would like to do that in 
time (I wasn't aware of FreeMarker before), but again having a "native" 
implementation for the statement would be preferable to the special 
macro you defined.  When I get around to a FreeMarker implementation 
I'll let you know and you can tell me the possibilities!


Gary


Jonathan Revusky wrote:

Gary Bentley wrote:

Hi,

I'm the developer of JoSQL (http://josql.sf.net) and I've had a 
request from a user to extend the foreach directive to include JoSQL 
processing facilities.


Along the lines of:

#foreach( $mud in $mudsOnSpecial where $customer.hasPurchased($mud) 
order by $mud.price)


 
   
 $flogger.getPromo( $mud )
   
 


Hi, Gary, since you wrote me that note about trying to get in with ASF 
(thanks but no thanks) I looked back on your participation in this 
list. I see you posed the above question.


Here's how you do the above in FreeMarker:


<#--
 Special foreach replacement macro that
 sorts the sequence by a fieldname (the orderByField parameter)
 and executes the associated nested block if
 the condition is satisfied, where the condition parameter
 is a function or method that operates on the item in
 the sequence and returns a boolean
-->

<#macro specialForeach sequence condition orderByField>
<#list sequence?sort_by(orderByField) as item>
<#if condition(item)>
<#nested item>




Example usage:

<@specialForeach sequence=mud condition=customer.hasPurchased 
orderByField="price" ; item>

   
  
${flogger.getPromo(item)}
  
   


Now, I didn't have time to look into how you do this in Velocity. 
There's a fairly long discussion after this. Could you summarize it? 
How do you do the above in Velocity? You can answer in private or on 
the list, but really, it should be the latter, since other people 
might want to know, and after all, that's what these lists are for, 
right?


Cheers,

Jonathan Revusky


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-03-11 Thread Jonathan Revusky

Gary Bentley wrote:

Hi,

I'm the developer of JoSQL (http://josql.sf.net) and I've had a request 
from a user to extend the foreach directive to include JoSQL processing 
facilities.


Along the lines of:

#foreach( $mud in $mudsOnSpecial where $customer.hasPurchased($mud) 
order by $mud.price)


 
   
 $flogger.getPromo( $mud )
   
 


Hi, Gary, since you wrote me that note about trying to get in with ASF 
(thanks but no thanks) I looked back on your participation in this list. 
I see you posed the above question.


Here's how you do the above in FreeMarker:


<#--
 Special foreach replacement macro that
 sorts the sequence by a fieldname (the orderByField parameter)
 and executes the associated nested block if
 the condition is satisfied, where the condition parameter
 is a function or method that operates on the item in
 the sequence and returns a boolean
-->

<#macro specialForeach sequence condition orderByField>
<#list sequence?sort_by(orderByField) as item>
<#if condition(item)>
<#nested item>




Example usage:

<@specialForeach sequence=mud condition=customer.hasPurchased 
orderByField="price" ; item>

   
  
${flogger.getPromo(item)}
  
   


Now, I didn't have time to look into how you do this in Velocity. 
There's a fairly long discussion after this. Could you summarize it? How 
do you do the above in Velocity? You can answer in private or on the 
list, but really, it should be the latter, since other people might want 
to know, and after all, that's what these lists are for, right?


Cheers,

Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/

Velocity or FreeMarker: Looking at 5 Years of Practical Experience
http://freemarker.blogspot.com/2007/12/velocity-of-freemarker-looking-at-5.html 





In essence to allow the collection to be filtered and ordered prior to 
being processed by the foreach directive.  Alternatively it may be that 
I would add it via a custom directive.


To make this work though I have a couple of questions:

1. How do I make a new directive available to velocity?  I am currently, 
for testing purposes, using the "ant docs" command to process a file 
that has the extended syntax in it.  I have modified the 
"directive.properties" file to add my new
class, it is loaded and I've modified the value returned by the 
"getName" method of my class however when I then use the

directive in my test file it isn't being used.

2. How do I get the arguments for the directive from the Node?  When I 
modify the Foreach class directly I find that only 4 child nodes are 
added to the Node, basically no more children are available after the 
"where" keyword.  (To make argument
processing work I've modified the Parser.jjt file to allow for more args 
for the foreach directive).  How can I find
out what the arguments are and how can I get the parser to make them 
available?  They are available if I iterate through

the tokens associated with the Node.

Many thanks,

Gary



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-17 Thread Nathan Bubna
On Jan 17, 2008 7:34 AM, Christopher Schultz
<[EMAIL PROTECTED]> wrote:
> Gary,
>
> Gary Bentley wrote:
> > Actually, just so I know could you let me know what the life-cycle is
> >  for tool objects?  Is a new tool object created per request and
> > hence discarded after the request has been made.  Or is a pool of
> > objects created and then an object assigned from the pool to each
> > request?
>
> No pools AFAIK: you get a new object per-[scope]. If it's application
> scope, then the object gets created at webapp startup and lives for the
> life of the app. Same for session or request. Actually, I think VelTools
> 2.0 does lazy loading so you won't get a JoSQL object for a particular
> request if none is ever requested.

Just to clear up a little grammatical ambiguity above, the request or
session tools do not live for the life of the app (as could be read
above), but rather for the life of the request or session,
respectively.  And yes, VelocityTools doesn't pool, it's just not
worth the overhead for most tools.  And yes, VelTools 2 only loads
tools when they're used.

> > I am trying to avoid the relatively costly statement parse, but I
> > think it may be unavoidable anyway since to identify the relevant
> > Query object (that will do the actual work) I would have to parse and
> > then normalize the query string anyway.
>
> I think what you want to do is parse the query string on demand, and let
> the template author figure out the rest.
>
> Finally, don't forget that a tool instance does not equal one of your
> query instances. You could write a tool that creates a new query for
> every single "request" made to the tool. In that case, you don't have a
> threading issue (but may have a performance issue). If you wanted to be
> really anal about it, you could keep a cache of query string -> query
> objects in your tool, though i doubt very much it would be really worth
> it. Parsing those queries shouldn't take /that/ long.
>
> Honestly, I think the explosion of "tools" for velocity is starting to
> look like ColdFusion where everything is a view tag instead of being put
> into the controller like it really should be. :(

we've never claimed to be an MVC purists. :)  MVC is just another
pattern that is ideal sometimes, ok sometimes, and just unnecessary
sometimes.  it's not hard to ignore any tools you don't like.

> I realize that you are simply trying to cater to your users, but I'm not
> sure if this tool is really in their best interest.

nor could you be sure. ;)  there are many different apps and needs out
there.  and many perfectly reasonable and helpful ways of developing
them.

>
> -chris
>
>
>

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-17 Thread Nathan Bubna
Cool.  If it doesn't do what you need (like access the velocity
context or velocity engine), you can bet one of the other tools
probably does.

On Jan 16, 2008 10:03 PM, Gary Bentley <[EMAIL PROTECTED]> wrote:
> Thanks for that Nathan, I'll probably use the LoopTool as a template, it
> appears to have the items you are talking about.
>
> Gary
>
>
>
> Nathan Bubna wrote:
> > On Jan 16, 2008 2:27 PM, Christopher Schultz
> > <[EMAIL PROTECTED]> wrote:
> >
> >> Gary,
> >>
> >> Gary Bentley wrote:
> >>
> >>> For the class name, it's needed because during the parse it uses the
> >>> class name to resolve method/field accesses.  Without it resolution
> >>> would be needed at execution time.  In theory it's not needed but it
> >>> also allows the query to be parsed into the relevant tree of objects so
> >>> that it can be reused for execution.
> >>>
> >> Gotcha.
> >>
> >>
> >>> It also has the benefit of making
> >>> the query more readable to humans, so if you pass the query around
> >>> others can tell what class it is operating on.
> >>>
> >> When I was reading the "quick description" on the website, I was
> >> confused at first because it wasn't clear that a collection of existing
> >> objects were being passed-in as a context to evaluate the query (until I
> >> kept reading, of course). At first, I thought that "SELECT * FROM
> >> java.io.File" would magically read from the filesystem. Silly me!
> >>
> >>
> >>> There is one issue, you
> >>> said that the tool is put into the application scope, however JoSQL
> >>> isn't thread safe, is it possible to get the tool to be created per
> >>> thread?  (I could however use a query pool and normalize the query
> >>> string if not)
> >>>
> >> That's really up to you. Velocity Tools itself will not create a new
> >> tool per thread, but you can specify that a tool should be
> >> request-scoped (that is, a new one is created for each request). Since
> >> Velocity Tools was really created for webapp-use, and webapps should
> >> only use a single thread for each request, this works out just fine.
> >>
> >> If the JoSQL processors are not thread safe, you can simply direct your
> >> users to specify "request" scope when configuring the tool in the
> >> Velocity Tools toolbox.
> >>
> >
> > Definitely use request scope if there's any thread safety concerns.
> > With VelocityTools 2.0 (still in beta, but final release is largely
> > waiting on feedback and finishing docs), you can even add a
> > ValidScope(Scope.REQUEST) annotation to your tool class, to prevent
> > users from using the tool in any other scope.  Also, if your tool will
> > be needing access to the current context (in VelocityTools 2, just add
> > a setVelocityContext(Context ctx) method and it will automatically be
> > given to the tool each request), then be sure to use request scope.
> >
> > (Apologies for all my not-so-subtle plugs for VelocityTools 2; i want
> > to be sure people are motivated to upgrade from 1.4 soon :)
> >
> >
> >>> I do have plans for a future enhancement to allow a bind variable to be
> >>> used of a class name instead so that it can be more dynamic.
> >>>
> >> Speaking of bind variables, I found myself a little thrown by their
> >> syntax for the simple reason that it differs from JDBC. Perhaps you
> >> could offer separate parsers at runtime for those who prefer the
> >> JDBC-style syntax.
> >>
> >> Good luck,
> >> -chris
> >>
> >>
> >>
> >
>
> > -
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
>

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-17 Thread Christopher Schultz

Gary,

Gary Bentley wrote:

Actually, just so I know could you let me know what the life-cycle is
 for tool objects?  Is a new tool object created per request and
hence discarded after the request has been made.  Or is a pool of
objects created and then an object assigned from the pool to each
request?


No pools AFAIK: you get a new object per-[scope]. If it's application
scope, then the object gets created at webapp startup and lives for the
life of the app. Same for session or request. Actually, I think VelTools
2.0 does lazy loading so you won't get a JoSQL object for a particular
request if none is ever requested.


I am trying to avoid the relatively costly statement parse, but I
think it may be unavoidable anyway since to identify the relevant
Query object (that will do the actual work) I would have to parse and
then normalize the query string anyway.


I think what you want to do is parse the query string on demand, and let
the template author figure out the rest.

Finally, don't forget that a tool instance does not equal one of your
query instances. You could write a tool that creates a new query for
every single "request" made to the tool. In that case, you don't have a
threading issue (but may have a performance issue). If you wanted to be
really anal about it, you could keep a cache of query string -> query
objects in your tool, though i doubt very much it would be really worth
it. Parsing those queries shouldn't take /that/ long.

Honestly, I think the explosion of "tools" for velocity is starting to
look like ColdFusion where everything is a view tag instead of being put
into the controller like it really should be. :(

I realize that you are simply trying to cater to your users, but I'm not
sure if this tool is really in their best interest.

-chris




signature.asc
Description: OpenPGP digital signature


Re: Extending the foreach directive

2008-01-17 Thread Christopher Schultz

Gary,

Gary Bentley wrote:
For the bind variables is it possible to use "?" as the placeholder like 
you can for JDBC.  Is that what you meant?


Yeah, that's what I meant.

-chris




signature.asc
Description: OpenPGP digital signature


Re: Extending the foreach directive

2008-01-16 Thread Claude Brisson
Le jeudi 17 janvier 2008 à 17:01 +1000, Gary Bentley a écrit :
> Hi Nathan,
> 
> Just on the annotation, if I set it as request will that mean that there 
> is 1 JoSQL object per request?

Yes.

> For example if a template is processed in a single request that has 2 
> josql.execute calls (say) will it be the same JoSQL object that is used 
> for both?

Yes, but the two josql.execute calls will be called sequentially by the
same thread.

> I just need to know since it is the query that isn't thread safe but if 
> the same object is used for both then I need to create 2 query objects.

You should not need two different objects in this particular case.


  Claude

> Thanks,
> 
> Gary
> 
> 
> Gary Bentley wrote:
> > Thanks for that Nathan, I'll probably use the LoopTool as a template, 
> > it appears to have the items you are talking about.
> >
> > Gary
> >
> >
> > Nathan Bubna wrote:
> >> On Jan 16, 2008 2:27 PM, Christopher Schultz
> >> <[EMAIL PROTECTED]> wrote:
> >>  
> >>> Gary,
> >>>
> >>> Gary Bentley wrote:
> >>>
>  For the class name, it's needed because during the parse it uses the
>  class name to resolve method/field accesses.  Without it resolution
>  would be needed at execution time.  In theory it's not needed but it
>  also allows the query to be parsed into the relevant tree of 
>  objects so
>  that it can be reused for execution.
>    
> >>> Gotcha.
> >>>
> >>>
>  It also has the benefit of making
>  the query more readable to humans, so if you pass the query around
>  others can tell what class it is operating on.
>    
> >>> When I was reading the "quick description" on the website, I was
> >>> confused at first because it wasn't clear that a collection of existing
> >>> objects were being passed-in as a context to evaluate the query 
> >>> (until I
> >>> kept reading, of course). At first, I thought that "SELECT * FROM
> >>> java.io.File" would magically read from the filesystem. Silly me!
> >>>
> >>>
>  There is one issue, you
>  said that the tool is put into the application scope, however JoSQL
>  isn't thread safe, is it possible to get the tool to be created per
>  thread?  (I could however use a query pool and normalize the query
>  string if not)
>    
> >>> That's really up to you. Velocity Tools itself will not create a new
> >>> tool per thread, but you can specify that a tool should be
> >>> request-scoped (that is, a new one is created for each request). Since
> >>> Velocity Tools was really created for webapp-use, and webapps should
> >>> only use a single thread for each request, this works out just fine.
> >>>
> >>> If the JoSQL processors are not thread safe, you can simply direct your
> >>> users to specify "request" scope when configuring the tool in the
> >>> Velocity Tools toolbox.
> >>> 
> >>
> >> Definitely use request scope if there's any thread safety concerns.
> >> With VelocityTools 2.0 (still in beta, but final release is largely
> >> waiting on feedback and finishing docs), you can even add a
> >> ValidScope(Scope.REQUEST) annotation to your tool class, to prevent
> >> users from using the tool in any other scope.  Also, if your tool will
> >> be needing access to the current context (in VelocityTools 2, just add
> >> a setVelocityContext(Context ctx) method and it will automatically be
> >> given to the tool each request), then be sure to use request scope.
> >>
> >> (Apologies for all my not-so-subtle plugs for VelocityTools 2; i want
> >> to be sure people are motivated to upgrade from 1.4 soon :)
> >>
> >>  
>  I do have plans for a future enhancement to allow a bind variable 
>  to be
>  used of a class name instead so that it can be more dynamic.
>    
> >>> Speaking of bind variables, I found myself a little thrown by their
> >>> syntax for the simple reason that it differs from JDBC. Perhaps you
> >>> could offer separate parsers at runtime for those who prefer the
> >>> JDBC-style syntax.
> >>>
> >>> Good luck,
> >>> -chris
> >>>
> >>>
> >>> 
> >>
> >> -
> >> To unsubscribe, e-mail: [EMAIL PROTECTED]
> >> For additional commands, e-mail: [EMAIL PROTECTED]
> >>
> >>   
> >
> 
> -
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-16 Thread Gary Bentley
Actually, just so I know could you let me know what the life-cycle is 
for tool objects?  Is a new tool object created per request and hence 
discarded after the request has been made.  Or is a pool of objects 
created and then an object assigned from the pool to each request?  I am 
trying to avoid the relatively costly statement parse, but I think it 
may be unavoidable anyway since to identify the relevant Query object 
(that will do the actual work) I would have to parse and then normalize 
the query string anyway.


Thanks,

Gary


Gary Bentley wrote:
Thanks for that Nathan, I'll probably use the LoopTool as a template, 
it appears to have the items you are talking about.


Gary


Nathan Bubna wrote:

On Jan 16, 2008 2:27 PM, Christopher Schultz
<[EMAIL PROTECTED]> wrote:
 

Gary,

Gary Bentley wrote:
   

For the class name, it's needed because during the parse it uses the
class name to resolve method/field accesses.  Without it resolution
would be needed at execution time.  In theory it's not needed but it
also allows the query to be parsed into the relevant tree of 
objects so

that it can be reused for execution.
  

Gotcha.

   

It also has the benefit of making
the query more readable to humans, so if you pass the query around
others can tell what class it is operating on.
  

When I was reading the "quick description" on the website, I was
confused at first because it wasn't clear that a collection of existing
objects were being passed-in as a context to evaluate the query 
(until I

kept reading, of course). At first, I thought that "SELECT * FROM
java.io.File" would magically read from the filesystem. Silly me!

   

There is one issue, you
said that the tool is put into the application scope, however JoSQL
isn't thread safe, is it possible to get the tool to be created per
thread?  (I could however use a query pool and normalize the query
string if not)
  

That's really up to you. Velocity Tools itself will not create a new
tool per thread, but you can specify that a tool should be
request-scoped (that is, a new one is created for each request). Since
Velocity Tools was really created for webapp-use, and webapps should
only use a single thread for each request, this works out just fine.

If the JoSQL processors are not thread safe, you can simply direct your
users to specify "request" scope when configuring the tool in the
Velocity Tools toolbox.



Definitely use request scope if there's any thread safety concerns.
With VelocityTools 2.0 (still in beta, but final release is largely
waiting on feedback and finishing docs), you can even add a
ValidScope(Scope.REQUEST) annotation to your tool class, to prevent
users from using the tool in any other scope.  Also, if your tool will
be needing access to the current context (in VelocityTools 2, just add
a setVelocityContext(Context ctx) method and it will automatically be
given to the tool each request), then be sure to use request scope.

(Apologies for all my not-so-subtle plugs for VelocityTools 2; i want
to be sure people are motivated to upgrade from 1.4 soon :)

 
I do have plans for a future enhancement to allow a bind variable 
to be

used of a class name instead so that it can be more dynamic.
  

Speaking of bind variables, I found myself a little thrown by their
syntax for the simple reason that it differs from JDBC. Perhaps you
could offer separate parsers at runtime for those who prefer the
JDBC-style syntax.

Good luck,
-chris





-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

  




-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-16 Thread Gary Bentley

Hi Nathan,

Just on the annotation, if I set it as request will that mean that there 
is 1 JoSQL object per request?


For example if a template is processed in a single request that has 2 
josql.execute calls (say) will it be the same JoSQL object that is used 
for both?


I just need to know since it is the query that isn't thread safe but if 
the same object is used for both then I need to create 2 query objects.


Thanks,

Gary


Gary Bentley wrote:
Thanks for that Nathan, I'll probably use the LoopTool as a template, 
it appears to have the items you are talking about.


Gary


Nathan Bubna wrote:

On Jan 16, 2008 2:27 PM, Christopher Schultz
<[EMAIL PROTECTED]> wrote:
 

Gary,

Gary Bentley wrote:
   

For the class name, it's needed because during the parse it uses the
class name to resolve method/field accesses.  Without it resolution
would be needed at execution time.  In theory it's not needed but it
also allows the query to be parsed into the relevant tree of 
objects so

that it can be reused for execution.
  

Gotcha.

   

It also has the benefit of making
the query more readable to humans, so if you pass the query around
others can tell what class it is operating on.
  

When I was reading the "quick description" on the website, I was
confused at first because it wasn't clear that a collection of existing
objects were being passed-in as a context to evaluate the query 
(until I

kept reading, of course). At first, I thought that "SELECT * FROM
java.io.File" would magically read from the filesystem. Silly me!

   

There is one issue, you
said that the tool is put into the application scope, however JoSQL
isn't thread safe, is it possible to get the tool to be created per
thread?  (I could however use a query pool and normalize the query
string if not)
  

That's really up to you. Velocity Tools itself will not create a new
tool per thread, but you can specify that a tool should be
request-scoped (that is, a new one is created for each request). Since
Velocity Tools was really created for webapp-use, and webapps should
only use a single thread for each request, this works out just fine.

If the JoSQL processors are not thread safe, you can simply direct your
users to specify "request" scope when configuring the tool in the
Velocity Tools toolbox.



Definitely use request scope if there's any thread safety concerns.
With VelocityTools 2.0 (still in beta, but final release is largely
waiting on feedback and finishing docs), you can even add a
ValidScope(Scope.REQUEST) annotation to your tool class, to prevent
users from using the tool in any other scope.  Also, if your tool will
be needing access to the current context (in VelocityTools 2, just add
a setVelocityContext(Context ctx) method and it will automatically be
given to the tool each request), then be sure to use request scope.

(Apologies for all my not-so-subtle plugs for VelocityTools 2; i want
to be sure people are motivated to upgrade from 1.4 soon :)

 
I do have plans for a future enhancement to allow a bind variable 
to be

used of a class name instead so that it can be more dynamic.
  

Speaking of bind variables, I found myself a little thrown by their
syntax for the simple reason that it differs from JDBC. Perhaps you
could offer separate parsers at runtime for those who prefer the
JDBC-style syntax.

Good luck,
-chris





-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

  




-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-16 Thread Gary Bentley
Thanks for that Nathan, I'll probably use the LoopTool as a template, it 
appears to have the items you are talking about.


Gary


Nathan Bubna wrote:

On Jan 16, 2008 2:27 PM, Christopher Schultz
<[EMAIL PROTECTED]> wrote:
  

Gary,

Gary Bentley wrote:


For the class name, it's needed because during the parse it uses the
class name to resolve method/field accesses.  Without it resolution
would be needed at execution time.  In theory it's not needed but it
also allows the query to be parsed into the relevant tree of objects so
that it can be reused for execution.
  

Gotcha.



It also has the benefit of making
the query more readable to humans, so if you pass the query around
others can tell what class it is operating on.
  

When I was reading the "quick description" on the website, I was
confused at first because it wasn't clear that a collection of existing
objects were being passed-in as a context to evaluate the query (until I
kept reading, of course). At first, I thought that "SELECT * FROM
java.io.File" would magically read from the filesystem. Silly me!



There is one issue, you
said that the tool is put into the application scope, however JoSQL
isn't thread safe, is it possible to get the tool to be created per
thread?  (I could however use a query pool and normalize the query
string if not)
  

That's really up to you. Velocity Tools itself will not create a new
tool per thread, but you can specify that a tool should be
request-scoped (that is, a new one is created for each request). Since
Velocity Tools was really created for webapp-use, and webapps should
only use a single thread for each request, this works out just fine.

If the JoSQL processors are not thread safe, you can simply direct your
users to specify "request" scope when configuring the tool in the
Velocity Tools toolbox.



Definitely use request scope if there's any thread safety concerns.
With VelocityTools 2.0 (still in beta, but final release is largely
waiting on feedback and finishing docs), you can even add a
ValidScope(Scope.REQUEST) annotation to your tool class, to prevent
users from using the tool in any other scope.  Also, if your tool will
be needing access to the current context (in VelocityTools 2, just add
a setVelocityContext(Context ctx) method and it will automatically be
given to the tool each request), then be sure to use request scope.

(Apologies for all my not-so-subtle plugs for VelocityTools 2; i want
to be sure people are motivated to upgrade from 1.4 soon :)

  

I do have plans for a future enhancement to allow a bind variable to be
used of a class name instead so that it can be more dynamic.
  

Speaking of bind variables, I found myself a little thrown by their
syntax for the simple reason that it differs from JDBC. Perhaps you
could offer separate parsers at runtime for those who prefer the
JDBC-style syntax.

Good luck,
-chris





-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

  


Re: Extending the foreach directive

2008-01-16 Thread Gary Bentley

Hi Chris,

Thanks for the info.

For the bind variables is it possible to use "?" as the placeholder like 
you can for JDBC.  Is that what you meant?


Gary


Christopher Schultz wrote:

Gary,

Gary Bentley wrote:
For the class name, it's needed because during the parse it uses the 
class name to resolve method/field accesses.  Without it resolution 
would be needed at execution time.  In theory it's not needed but it 
also allows the query to be parsed into the relevant tree of objects 
so that it can be reused for execution.


Gotcha.

It also has the benefit of making the query more readable to humans, 
so if you pass the query around others can tell what class it is 
operating on.


When I was reading the "quick description" on the website, I was 
confused at first because it wasn't clear that a collection of 
existing objects were being passed-in as a context to evaluate the 
query (until I kept reading, of course). At first, I thought that 
"SELECT * FROM java.io.File" would magically read from the filesystem. 
Silly me!


There is one issue, you said that the tool is put into the 
application scope, however JoSQL isn't thread safe, is it possible to 
get the tool to be created per thread?  (I could however use a query 
pool and normalize the query string if not)


That's really up to you. Velocity Tools itself will not create a new 
tool per thread, but you can specify that a tool should be 
request-scoped (that is, a new one is created for each request). Since 
Velocity Tools was really created for webapp-use, and webapps should 
only use a single thread for each request, this works out just fine.


If the JoSQL processors are not thread safe, you can simply direct 
your users to specify "request" scope when configuring the tool in the 
Velocity Tools toolbox.


I do have plans for a future enhancement to allow a bind variable to 
be used of a class name instead so that it can be more dynamic.


Speaking of bind variables, I found myself a little thrown by their 
syntax for the simple reason that it differs from JDBC. Perhaps you 
could offer separate parsers at runtime for those who prefer the 
JDBC-style syntax.


Good luck,
-chris



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-16 Thread Nathan Bubna
On Jan 16, 2008 2:27 PM, Christopher Schultz
<[EMAIL PROTECTED]> wrote:
> Gary,
>
> Gary Bentley wrote:
> > For the class name, it's needed because during the parse it uses the
> > class name to resolve method/field accesses.  Without it resolution
> > would be needed at execution time.  In theory it's not needed but it
> > also allows the query to be parsed into the relevant tree of objects so
> > that it can be reused for execution.
>
> Gotcha.
>
> > It also has the benefit of making
> > the query more readable to humans, so if you pass the query around
> > others can tell what class it is operating on.
>
> When I was reading the "quick description" on the website, I was
> confused at first because it wasn't clear that a collection of existing
> objects were being passed-in as a context to evaluate the query (until I
> kept reading, of course). At first, I thought that "SELECT * FROM
> java.io.File" would magically read from the filesystem. Silly me!
>
> > There is one issue, you
> > said that the tool is put into the application scope, however JoSQL
> > isn't thread safe, is it possible to get the tool to be created per
> > thread?  (I could however use a query pool and normalize the query
> > string if not)
>
> That's really up to you. Velocity Tools itself will not create a new
> tool per thread, but you can specify that a tool should be
> request-scoped (that is, a new one is created for each request). Since
> Velocity Tools was really created for webapp-use, and webapps should
> only use a single thread for each request, this works out just fine.
>
> If the JoSQL processors are not thread safe, you can simply direct your
> users to specify "request" scope when configuring the tool in the
> Velocity Tools toolbox.

Definitely use request scope if there's any thread safety concerns.
With VelocityTools 2.0 (still in beta, but final release is largely
waiting on feedback and finishing docs), you can even add a
ValidScope(Scope.REQUEST) annotation to your tool class, to prevent
users from using the tool in any other scope.  Also, if your tool will
be needing access to the current context (in VelocityTools 2, just add
a setVelocityContext(Context ctx) method and it will automatically be
given to the tool each request), then be sure to use request scope.

(Apologies for all my not-so-subtle plugs for VelocityTools 2; i want
to be sure people are motivated to upgrade from 1.4 soon :)

> > I do have plans for a future enhancement to allow a bind variable to be
> > used of a class name instead so that it can be more dynamic.
>
> Speaking of bind variables, I found myself a little thrown by their
> syntax for the simple reason that it differs from JDBC. Perhaps you
> could offer separate parsers at runtime for those who prefer the
> JDBC-style syntax.
>
> Good luck,
> -chris
>
>

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-16 Thread Christopher Schultz

Gary,

Gary Bentley wrote:
For the class name, it's needed because during the parse it uses the 
class name to resolve method/field accesses.  Without it resolution 
would be needed at execution time.  In theory it's not needed but it 
also allows the query to be parsed into the relevant tree of objects so 
that it can be reused for execution.


Gotcha.

It also has the benefit of making 
the query more readable to humans, so if you pass the query around 
others can tell what class it is operating on.


When I was reading the "quick description" on the website, I was 
confused at first because it wasn't clear that a collection of existing 
objects were being passed-in as a context to evaluate the query (until I 
kept reading, of course). At first, I thought that "SELECT * FROM 
java.io.File" would magically read from the filesystem. Silly me!


There is one issue, you 
said that the tool is put into the application scope, however JoSQL 
isn't thread safe, is it possible to get the tool to be created per 
thread?  (I could however use a query pool and normalize the query 
string if not)


That's really up to you. Velocity Tools itself will not create a new 
tool per thread, but you can specify that a tool should be 
request-scoped (that is, a new one is created for each request). Since 
Velocity Tools was really created for webapp-use, and webapps should 
only use a single thread for each request, this works out just fine.


If the JoSQL processors are not thread safe, you can simply direct your 
users to specify "request" scope when configuring the tool in the 
Velocity Tools toolbox.


I do have plans for a future enhancement to allow a bind variable to be 
used of a class name instead so that it can be more dynamic.


Speaking of bind variables, I found myself a little thrown by their 
syntax for the simple reason that it differs from JDBC. Perhaps you 
could offer separate parsers at runtime for those who prefer the 
JDBC-style syntax.


Good luck,
-chris



signature.asc
Description: OpenPGP digital signature


Re: Extending the foreach directive

2008-01-16 Thread Gary Bentley

Hi Chris,

For the class name, it's needed because during the parse it uses the 
class name to resolve method/field accesses.  Without it resolution 
would be needed at execution time.  In theory it's not needed but it 
also allows the query to be parsed into the relevant tree of objects so 
that it can be reused for execution.  It also has the benefit of making 
the query more readable to humans, so if you pass the query around 
others can tell what class it is operating on.  There is one issue, you 
said that the tool is put into the application scope, however JoSQL 
isn't thread safe, is it possible to get the tool to be created per 
thread?  (I could however use a query pool and normalize the query 
string if not)


I do have plans for a future enhancement to allow a bind variable to be 
used of a class name instead so that it can be more dynamic.


Thanks again for all the advice, I'll let you know when the tool is 
available.


Gary


Christopher Schultz wrote:

Gary,

Gary Bentley wrote:
Many thanks for the responses.  They are both very helpful.  I think 
at this point I'll go for Chris's suggestion since that will be 
easier to implement.  There are some differences between the way that 
JoSQL and Velocity works so there will be limitations but overall I 
think it will be easier this way.


I think they can complement each other very well: JoSQL seems very 
self-contained, so you can easily create a re-usable "tool" that is 
shareable across Context instances (Velocity Tools will put a tool 
like this into "application" scope for a webapp), and Velocity 
operates on any collection/iterator/array of objects generically.


So, you can simply write a method that takes one collection of objects 
and emits another one (or an iterator) and use it directly.


Show us what you've got when you've got it. Your tool definitely looks 
very interesting (though I'm not sure why you have to SELECT * FROM 
[class name]... I suppose you needed something in there!).


Good luck,
-chris



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-16 Thread Christopher Schultz

Gary,

Gary Bentley wrote:
Many thanks for the responses.  They are both very helpful.  I think at 
this point I'll go for Chris's suggestion since that will be easier to 
implement.  There are some differences between the way that JoSQL and 
Velocity works so there will be limitations but overall I think it will 
be easier this way.


I think they can complement each other very well: JoSQL seems very 
self-contained, so you can easily create a re-usable "tool" that is 
shareable across Context instances (Velocity Tools will put a tool like 
this into "application" scope for a webapp), and Velocity operates on 
any collection/iterator/array of objects generically.


So, you can simply write a method that takes one collection of objects 
and emits another one (or an iterator) and use it directly.


Show us what you've got when you've got it. Your tool definitely looks 
very interesting (though I'm not sure why you have to SELECT * FROM 
[class name]... I suppose you needed something in there!).


Good luck,
-chris



signature.asc
Description: OpenPGP digital signature


Re: Extending the foreach directive

2008-01-15 Thread Gary Bentley

Nathan/Chris,

Many thanks for the responses.  They are both very helpful.  I think at 
this point I'll go for Chris's suggestion since that will be easier to 
implement.  There are some differences between the way that JoSQL and 
Velocity works so there will be limitations but overall I think it will 
be easier this way.


Thanks,

Gary


Christopher Schultz wrote:

Gary,

Gary Bentley wrote:

Along the lines of:

#foreach( $mud in $mudsOnSpecial where $customer.hasPurchased($mud) 
order by $mud.price)


This looks like mixing SQL-ish syntax with Java collections, which is 
precisely what JoSQL was designed to do. Why extend Velocity when you 
can simply use JoSQL as it was intended:


#foreach($mud in $josql.execute("SELECT [whatever] FROM mud.Type WHERE 
$customer.hasPurchased($mud)", $mudsOnSpecial))


... with with your muds

#end

then you just have to implement a JoSQL tool and shove it into the 
velocity context. You tool can do something like this:


public Iterator execute(String query, Object (or List?) source)
{
Query q = new Query();
q.parse(query);

QueryResults qr = q.execute(source);


List res = qr.getResults();

return res.iterator();
}

I think this would be a whole lot easier than re-writing Velocity.

Since this capability is orthogonal to Velocity's, it seems to be a 
better choice for architecture, too.


-chris



-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Re: Extending the foreach directive

2008-01-15 Thread Christopher Schultz

Gary,

Gary Bentley wrote:

Along the lines of:

#foreach( $mud in $mudsOnSpecial where $customer.hasPurchased($mud) 
order by $mud.price)


This looks like mixing SQL-ish syntax with Java collections, which is 
precisely what JoSQL was designed to do. Why extend Velocity when you 
can simply use JoSQL as it was intended:


#foreach($mud in $josql.execute("SELECT [whatever] FROM mud.Type WHERE 
$customer.hasPurchased($mud)", $mudsOnSpecial))


... with with your muds

#end

then you just have to implement a JoSQL tool and shove it into the 
velocity context. You tool can do something like this:


public Iterator execute(String query, Object (or List?) source)
{
Query q = new Query();
q.parse(query);

QueryResults qr = q.execute(source);


List res = qr.getResults();

return res.iterator();
}

I think this would be a whole lot easier than re-writing Velocity.

Since this capability is orthogonal to Velocity's, it seems to be a 
better choice for architecture, too.


-chris



signature.asc
Description: OpenPGP digital signature


Re: Extending the foreach directive

2008-01-15 Thread Nathan Bubna
Hi Gary,

So far as i know, you are in fairly unique territory.  The #if and
#foreach directives were never really meant to be extended or
replaced, so far as i know.  Their roots go deep into the parser and
will almost certainly require a custom build of Velocity, not just
some configuration and extensions.  You may be the first to try
something much like this.  But brave experiments usually teach a lot,
so i'm certainly curious to see how it works out and hear if there are
ways we can make things easier for such efforts down the road.

In the meantime, i do have a somewhat lateral suggestion: have you
considered using a "Tool" type of syntax instead?  I know it probably
wouldn't be as clean, but it might be a  lot easier to implement.
I've actually been heading down a parallel road myself lately with the
work i've been doing on the LoopTool
(http://svn.apache.org/viewvc/velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java?view=markup)

Rather than mess with the parser and core directives, i've made it
relatively simple to have a #foreach watched by the LoopTool to
automatically skip or stop before specific elements.  The syntax is
currently:

#foreach( $foo in $loop.watch($myFoos).skip('badfoo').stop('prematureEndFoo') )
Here's a $foo
#end

The above would skip any $foo that equals 'badfoo' and stop iteration
when the next foo equals 'prematureEndFoo'.  Pretty rudimentary, but
not too far from your example, particularly if combined with the
SortTool.

The tricky part of making a $josql tool to do

#foreach( $mud in
$josql.filter($mudsOnSpecial).where('$customer.hasPurchased($mud)').orderBy('price')
)

would be working out the $customer.hasPurchased($mud) part.  Though i
think that is feasible if you give the tool access to the current
context and VelocityEngine so you can evaluate the condition.  Then
the orderBy can be implemented to sort on $mud properties, just like
SortTool can.

Anyway, if you're curious about taking the tool route, i'm much more
capable of helping out than with modifying the #foreach directive,
which would be totally new to me. :)  Others here would be of more
help with that, if they're not too busy at the moment.

On Jan 15, 2008 4:45 AM, Gary Bentley <[EMAIL PROTECTED]> wrote:
> Hi,
>
> I'm the developer of JoSQL (http://josql.sf.net) and I've had a request
> from a user to extend the foreach directive to include JoSQL processing
> facilities.
>
> Along the lines of:
>
> #foreach( $mud in $mudsOnSpecial where $customer.hasPurchased($mud) order by 
> $mud.price)
>
>   
> 
>   $flogger.getPromo( $mud )
> 
>   
>
> In essence to allow the collection to be filtered and ordered prior to being 
> processed by the foreach directive.
> Alternatively it may be that I would add it via a custom directive.
>
> To make this work though I have a couple of questions:
>
> 1. How do I make a new directive available to velocity?  I am currently, for 
> testing purposes, using the "ant docs" command
> to process a file that has the extended syntax in it.  I have modified the 
> "directive.properties" file to add my new
> class, it is loaded and I've modified the value returned by the "getName" 
> method of my class however when I then use the
> directive in my test file it isn't being used.
>
> 2. How do I get the arguments for the directive from the Node?  When I modify 
> the Foreach class directly I find that only 4
> child nodes are added to the Node, basically no more children are available 
> after the "where" keyword.  (To make argument
> processing work I've modified the Parser.jjt file to allow for more args for 
> the foreach directive).  How can I find
> out what the arguments are and how can I get the parser to make them 
> available?  They are available if I iterate through
> the tokens associated with the Node.
>
> Many thanks,
>
> Gary
>
>
>
>
> -
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Extending the foreach directive

2008-01-15 Thread Gary Bentley

Hi,

I'm the developer of JoSQL (http://josql.sf.net) and I've had a request 
from a user to extend the foreach directive to include JoSQL processing 
facilities.


Along the lines of:

#foreach( $mud in $mudsOnSpecial where $customer.hasPurchased($mud) order by 
$mud.price)

 
   
 $flogger.getPromo( $mud )
   
 

In essence to allow the collection to be filtered and ordered prior to being processed by the foreach directive.  
Alternatively it may be that I would add it via a custom directive.


To make this work though I have a couple of questions:

1. How do I make a new directive available to velocity?  I am currently, for testing purposes, using the "ant docs" command 
to process a file that has the extended syntax in it.  I have modified the "directive.properties" file to add my new

class, it is loaded and I've modified the value returned by the "getName" 
method of my class however when I then use the
directive in my test file it isn't being used.

2. How do I get the arguments for the directive from the Node?  When I modify the Foreach class directly I find that only 4 
child nodes are added to the Node, basically no more children are available after the "where" keyword.  (To make argument

processing work I've modified the Parser.jjt file to allow for more args for 
the foreach directive).  How can I find
out what the arguments are and how can I get the parser to make them available? 
 They are available if I iterate through
the tokens associated with the Node.

Many thanks,

Gary




-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]