You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Drew Davidson <dr...@ognl.org> on 2004/08/26 02:21:51 UTC

New OGNL list operators: sorting

I have been refactoring the OGNL parser for 2.7.0 (so that OGNL 3 will 
share the same parser with OGNL 2) and I added a sorting operator to the 
list operators.  I've been wanting to scratch this itch for some time.  
Many is the time when I wanted a sorted list and had to delegate to some 
Java method to do it; usually it was a simple sort that didn't deserve 
the infrastructure of a complicated Java method.

Here are a few examples of how it can be used

    someList.{< #this }
           Sort ascending the list of objects by comparing them against 
each other (i.e. list of Integers, Dates, etc. - anything that 
implements Comparable).

    someList.{< name }     
            Sort ascending by comparing "name" properties of both 
objects in the list.

    someList.{> name }     
            Sort descending by comparing "name" properties of both 
objects in the list.

    someList.{> orderDate, name }     
            Sort descending by comparing "orderDate" property; if 
orderDate is equal in both objects then sub-sort the elements by "name" 
property.  Both are descending order.

    someList.{< name, :[ [0].orderDate.compareTo([1].orderDate) ] }
          Sort ascending by name, then by the expression given 
(ascending sense selected so compareTo() will work exactly as specified).

    someList.{< name, :[ -[0].orderDate.compareTo([1].orderDate) ] }
          Sort ascending by name, then by the expression given 
(ascending sense selected so the compareTo() result will be negated, 
thus making the secondary sort effectively descending).

The simple case of sorting a list by some expression both have in common 
looks simple; you can specify ascending or descending and the expression 
that retreives an object from each that implements Comparable (if they 
are not Comparable then an exception is thrown).

The more complicated case is for those who want to monkey with the sort 
order or do more complicated sorts, like reversing the sense of the 
ascending/descending by returning a different value from the 
expression.  The last example above, for example, performs a compareTo() 
and negates the result. This effectively changes the sense of the sort 
operation from ascending to descending only for the subsort comparison.  
The complicated case specifies a lambda expression; the sort node will 
pass both comparison objects to this expression as an array of 2 
elements.  From there you can do anything you wish that returns an 
integer (or anything that can be converted to an integer), the result 
being used in the same fashion as the integer Comparable.compareTo() 
result (i.e. 0 is equal, 1 is left is greater than right, -1 is left is 
less than right).

This is useful when you want to use comparators that are external to the 
objects themselves; a common case is Collator for doing string comparison:

    #collator = @java.text.Collator@getInstance(),
    #collator.strength = @java.text.Collator@PRIMARY,
    sortedByName = objects.{< :[ #collator.compare([0].name, [1].name) ] }

The key here is that the simple case stays simple and understandable and 
the syntax is available to let you do more complicated, dynamic stuff 
(like, for example, if you want to present search panel in an 
application and let the user choose the sort order and fields to sort on 
- you can encapsulate the sort in the OGNL expression and leave the 
comparison up to another object).

What does everyone think?  Is this too complicated or bizarre?  Is it 
worth adding to the OGNL language?

- Drew

-- 
+---------------------------------+
< Drew Davidson | OGNL Technology >
+---------------------------------+
|  Email: drew@ognl.org          /
|    Web: http://www.ognl.org   /
|    Vox: (520) 531-1966       <
|    Fax: (520) 531-1965        \
| Mobile: (520) 405-2967         \
+---------------------------------+


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: New OGNL list operators: sorting

Posted by Jamie Orchard-Hays <ja...@dang.com>.
That's definitely useful. The complex sort does look a bit arcane, but it's
understandable.

Jamie
----- Original Message ----- 
From: "Drew Davidson" <dr...@ognl.org>
To: <og...@lists.ognl.org>; <og...@lists.ognl.org>;
"Tapestry users" <ta...@jakarta.apache.org>
Sent: Wednesday, August 25, 2004 8:21 PM
Subject: New OGNL list operators: sorting


> I have been refactoring the OGNL parser for 2.7.0 (so that OGNL 3 will
> share the same parser with OGNL 2) and I added a sorting operator to the
> list operators.  I've been wanting to scratch this itch for some time.
> Many is the time when I wanted a sorted list and had to delegate to some
> Java method to do it; usually it was a simple sort that didn't deserve
> the infrastructure of a complicated Java method.
>
> Here are a few examples of how it can be used
>
>     someList.{< #this }
>            Sort ascending the list of objects by comparing them against
> each other (i.e. list of Integers, Dates, etc. - anything that
> implements Comparable).
>
>     someList.{< name }
>             Sort ascending by comparing "name" properties of both
> objects in the list.
>
>     someList.{> name }
>             Sort descending by comparing "name" properties of both
> objects in the list.
>
>     someList.{> orderDate, name }
>             Sort descending by comparing "orderDate" property; if
> orderDate is equal in both objects then sub-sort the elements by "name"
> property.  Both are descending order.
>
>     someList.{< name, :[ [0].orderDate.compareTo([1].orderDate) ] }
>           Sort ascending by name, then by the expression given
> (ascending sense selected so compareTo() will work exactly as specified).
>
>     someList.{< name, :[ -[0].orderDate.compareTo([1].orderDate) ] }
>           Sort ascending by name, then by the expression given
> (ascending sense selected so the compareTo() result will be negated,
> thus making the secondary sort effectively descending).
>
> The simple case of sorting a list by some expression both have in common
> looks simple; you can specify ascending or descending and the expression
> that retreives an object from each that implements Comparable (if they
> are not Comparable then an exception is thrown).
>
> The more complicated case is for those who want to monkey with the sort
> order or do more complicated sorts, like reversing the sense of the
> ascending/descending by returning a different value from the
> expression.  The last example above, for example, performs a compareTo()
> and negates the result. This effectively changes the sense of the sort
> operation from ascending to descending only for the subsort comparison.
> The complicated case specifies a lambda expression; the sort node will
> pass both comparison objects to this expression as an array of 2
> elements.  From there you can do anything you wish that returns an
> integer (or anything that can be converted to an integer), the result
> being used in the same fashion as the integer Comparable.compareTo()
> result (i.e. 0 is equal, 1 is left is greater than right, -1 is left is
> less than right).
>
> This is useful when you want to use comparators that are external to the
> objects themselves; a common case is Collator for doing string comparison:
>
>     #collator = @java.text.Collator@getInstance(),
>     #collator.strength = @java.text.Collator@PRIMARY,
>     sortedByName = objects.{< :[ #collator.compare([0].name, [1].name) ] }
>
> The key here is that the simple case stays simple and understandable and
> the syntax is available to let you do more complicated, dynamic stuff
> (like, for example, if you want to present search panel in an
> application and let the user choose the sort order and fields to sort on
> - you can encapsulate the sort in the OGNL expression and leave the
> comparison up to another object).
>
> What does everyone think?  Is this too complicated or bizarre?  Is it
> worth adding to the OGNL language?
>
> - Drew
>
> --
> +---------------------------------+
> < Drew Davidson | OGNL Technology >
> +---------------------------------+
> |  Email: drew@ognl.org          /
> |    Web: http://www.ognl.org   /
> |    Vox: (520) 531-1966       <
> |    Fax: (520) 531-1965        \
> | Mobile: (520) 405-2967         \
> +---------------------------------+
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


RE: New OGNL list operators: sorting

Posted by Nicholas Lesiecki <nl...@vmsinfo.com>.
I think it's a great idea. Bring it on.

--nick

-----Original Message-----
From: Drew Davidson [mailto:drew@ognl.org] 
Sent: Wednesday, August 25, 2004 5:22 PM
To: ognl-interest@lists.ognl.org; ognl-developer@lists.ognl.org; Tapestry
users
Subject: New OGNL list operators: sorting

I have been refactoring the OGNL parser for 2.7.0 (so that OGNL 3 will 
share the same parser with OGNL 2) and I added a sorting operator to the 
list operators.  I've been wanting to scratch this itch for some time.  
Many is the time when I wanted a sorted list and had to delegate to some 
Java method to do it; usually it was a simple sort that didn't deserve 
the infrastructure of a complicated Java method.

Here are a few examples of how it can be used

    someList.{< #this }
           Sort ascending the list of objects by comparing them against 
each other (i.e. list of Integers, Dates, etc. - anything that 
implements Comparable).

    someList.{< name }     
            Sort ascending by comparing "name" properties of both 
objects in the list.

    someList.{> name }     
            Sort descending by comparing "name" properties of both 
objects in the list.

    someList.{> orderDate, name }     
            Sort descending by comparing "orderDate" property; if 
orderDate is equal in both objects then sub-sort the elements by "name" 
property.  Both are descending order.

    someList.{< name, :[ [0].orderDate.compareTo([1].orderDate) ] }
          Sort ascending by name, then by the expression given 
(ascending sense selected so compareTo() will work exactly as specified).

    someList.{< name, :[ -[0].orderDate.compareTo([1].orderDate) ] }
          Sort ascending by name, then by the expression given 
(ascending sense selected so the compareTo() result will be negated, 
thus making the secondary sort effectively descending).

The simple case of sorting a list by some expression both have in common 
looks simple; you can specify ascending or descending and the expression 
that retreives an object from each that implements Comparable (if they 
are not Comparable then an exception is thrown).

The more complicated case is for those who want to monkey with the sort 
order or do more complicated sorts, like reversing the sense of the 
ascending/descending by returning a different value from the 
expression.  The last example above, for example, performs a compareTo() 
and negates the result. This effectively changes the sense of the sort 
operation from ascending to descending only for the subsort comparison.  
The complicated case specifies a lambda expression; the sort node will 
pass both comparison objects to this expression as an array of 2 
elements.  From there you can do anything you wish that returns an 
integer (or anything that can be converted to an integer), the result 
being used in the same fashion as the integer Comparable.compareTo() 
result (i.e. 0 is equal, 1 is left is greater than right, -1 is left is 
less than right).

This is useful when you want to use comparators that are external to the 
objects themselves; a common case is Collator for doing string comparison:

    #collator = @java.text.Collator@getInstance(),
    #collator.strength = @java.text.Collator@PRIMARY,
    sortedByName = objects.{< :[ #collator.compare([0].name, [1].name) ] }

The key here is that the simple case stays simple and understandable and 
the syntax is available to let you do more complicated, dynamic stuff 
(like, for example, if you want to present search panel in an 
application and let the user choose the sort order and fields to sort on 
- you can encapsulate the sort in the OGNL expression and leave the 
comparison up to another object).

What does everyone think?  Is this too complicated or bizarre?  Is it 
worth adding to the OGNL language?

- Drew

-- 
+---------------------------------+
< Drew Davidson | OGNL Technology >
+---------------------------------+
|  Email: drew@ognl.org          /
|    Web: http://www.ognl.org   /
|    Vox: (520) 531-1966       <
|    Fax: (520) 531-1965        \
| Mobile: (520) 405-2967         \
+---------------------------------+


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


RE: New OGNL list operators: sorting

Posted by Patrick Lightbody <pl...@yahoo.com>.
I think sorting would be a good thing, but I do admit I'm getting very
confused about the various collection notations that would now be
available. Can you detail projection, sorting, etc?

> -----Original Message-----
> From: Drew Davidson [mailto:drew@ognl.org]
> Sent: Wednesday, August 25, 2004 5:22 PM
> To: ognl-interest@lists.ognl.org; ognl-developer@lists.ognl.org;
Tapestry
> users
> Subject: New OGNL list operators: sorting
> 
> I have been refactoring the OGNL parser for 2.7.0 (so that OGNL 3 will
> share the same parser with OGNL 2) and I added a sorting operator to
the
> list operators.  I've been wanting to scratch this itch for some time.
> Many is the time when I wanted a sorted list and had to delegate to
some
> Java method to do it; usually it was a simple sort that didn't deserve
> the infrastructure of a complicated Java method.
> 
> Here are a few examples of how it can be used
> 
>     someList.{< #this }
>            Sort ascending the list of objects by comparing them
against
> each other (i.e. list of Integers, Dates, etc. - anything that
> implements Comparable).
> 
>     someList.{< name }
>             Sort ascending by comparing "name" properties of both
> objects in the list.
> 
>     someList.{> name }
>             Sort descending by comparing "name" properties of both
> objects in the list.
> 
>     someList.{> orderDate, name }
>             Sort descending by comparing "orderDate" property; if
> orderDate is equal in both objects then sub-sort the elements by
"name"
> property.  Both are descending order.
> 
>     someList.{< name, :[ [0].orderDate.compareTo([1].orderDate) ] }
>           Sort ascending by name, then by the expression given
> (ascending sense selected so compareTo() will work exactly as
specified).
> 
>     someList.{< name, :[ -[0].orderDate.compareTo([1].orderDate) ] }
>           Sort ascending by name, then by the expression given
> (ascending sense selected so the compareTo() result will be negated,
> thus making the secondary sort effectively descending).
> 
> The simple case of sorting a list by some expression both have in
common
> looks simple; you can specify ascending or descending and the
expression
> that retreives an object from each that implements Comparable (if they
> are not Comparable then an exception is thrown).
> 
> The more complicated case is for those who want to monkey with the
sort
> order or do more complicated sorts, like reversing the sense of the
> ascending/descending by returning a different value from the
> expression.  The last example above, for example, performs a
compareTo()
> and negates the result. This effectively changes the sense of the sort
> operation from ascending to descending only for the subsort
comparison.
> The complicated case specifies a lambda expression; the sort node will
> pass both comparison objects to this expression as an array of 2
> elements.  From there you can do anything you wish that returns an
> integer (or anything that can be converted to an integer), the result
> being used in the same fashion as the integer Comparable.compareTo()
> result (i.e. 0 is equal, 1 is left is greater than right, -1 is left
is
> less than right).
> 
> This is useful when you want to use comparators that are external to
the
> objects themselves; a common case is Collator for doing string
comparison:
> 
>     #collator = @java.text.Collator@getInstance(),
>     #collator.strength = @java.text.Collator@PRIMARY,
>     sortedByName = objects.{< :[ #collator.compare([0].name, [1].name)
] }
> 
> The key here is that the simple case stays simple and understandable
and
> the syntax is available to let you do more complicated, dynamic stuff
> (like, for example, if you want to present search panel in an
> application and let the user choose the sort order and fields to sort
on
> - you can encapsulate the sort in the OGNL expression and leave the
> comparison up to another object).
> 
> What does everyone think?  Is this too complicated or bizarre?  Is it
> worth adding to the OGNL language?
> 
> - Drew
> 
> --
> +---------------------------------+
> < Drew Davidson | OGNL Technology >
> +---------------------------------+
> |  Email: drew@ognl.org          /
> |    Web: http://www.ognl.org   /
> |    Vox: (520) 531-1966       <
> |    Fax: (520) 531-1965        \
> | Mobile: (520) 405-2967         \
> +---------------------------------+
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ognl-developer-unsubscribe@lists.ognl.org
> For additional commands, e-mail: ognl-developer-help@lists.ognl.org


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org