freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Daniel Dekany (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (FREEMARKER-61) ?sort_using with a Comparator parameter
Date Wed, 12 Jul 2017 07:27:00 GMT

    [ https://issues.apache.org/jira/browse/FREEMARKER-61?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16083565#comment-16083565
] 

Daniel Dekany edited comment on FREEMARKER-61 at 7/12/17 7:26 AM:
------------------------------------------------------------------

{{sort}} is currently parameterless, so adding parameters would mean that the return value
of {{foo?sort}} will have to change from purely sequence to sequence plus method, which is
not 100% backward compatible. But I think {{sort_using}} (or rather, {{sort_with}}?) is not
worse than {{sort}} anyway, because it expresses clearly what the argument does. (Adding one
more built-in name is not really new syntax, I'm not afraid of it... there are hundreds of
it already.)

Using {{ObjectConstructor}} is highly discouraged because of security concerns. It can't be
removed due to backward compatibility unfortunately, but some use {{freemarker.core.TemplateClassResolver.SAFER_RESOLVER}}
to fix this issue. We can't build a core feature on its existence. But, if {{MyComparator}}
implements {{TemplateModel}} (which is an empty interface), then you can use {{?new}}.

Why do you want unwrapping per item to be the default? Also, why do you want it to a be an
option exposed to the caller? When would you use {{true}} or {{false}}, as a template author?
(Most users have no idea what object wrapping is, so the parameter doesn't make sense for
them. Also, as FM2 doesn't support named parameters in function calls, it can't be guessed
what that {{true}}/{{false}} means there. My first bet would be that its increasing vs descending
order, but I would be wrong.)

Edit: OK, I just realize you don't want unwrapping per item, you want the models to be passed
to the {{Comparator}}. Makes sense, though yet again it's not very performant. Instead of
{{String stringToCompare = user.getName()}} you would have {{if (\!(user instanceof TemplateHashModel))
die(); TemplateModel value = ((TemplateHashModel) user).get("name"); if (\!(value instanceof
TemplateScalarModel)) die(); String stringToCompare = ((TemplateScalarModel) value).getAsString()}}.
Models just aren't for data grinding.

Another thing... as you subclass {{Comparator}}, we can actually check with reflection if
it expect {{TemplateModel}}-s or not (as the generic type parameters are accessible due to
subclassing). If it expect two {{TemplateModel}}-s, we don't unwrap as you have suggested,
otherwise we unwrap (the while {{List}}, I guess).


was (Author: ddekany):
{{sort}} is currently parameterless, so adding parameters would mean that the return value
of {{foo?sort}} will have to change from purely sequence to sequence plus method, which is
not 100% backward compatible. But I think {{sort_using}} (or rather, {{sort_with}}?) is not
worse than {{sort}} anyway, because it expresses clearly what the argument does. (Adding one
more built-in name is not really new syntax, I'm not afraid of it... there are hundreds of
it already.)

Using {{ObjectConstructor}} is highly discouraged because of security concerns. It can't be
removed due to backward compatibility unfortunately, but some use {{freemarker.core.TemplateClassResolver.SAFER_RESOLVER}}
to fix this issue. We can't build a core feature on its existence. But, if {{MyComparator}}
implements {{TemplateModel}} (which is an empty interface), then you can use {{?new}}.

Why do you want unwrapping per item to be the default? Also, why do you want it to a be an
option exposed to the caller? When would you use {{true}} or {{false}}, as a template author?
(Most users have no idea what object wrapping is, so the parameter doesn't make sense for
them. Also, as FM2 doesn't support named parameters in function calls, it can't be guessed
what that {{true}}/{{false}} means there. My first bet would be that its increasing vs descending
order, but I would be wrong.)

Edit: OK, I just realize you don't want unwrapping per item, you want the models to be passed
to the {{Comparator}}. Makes sense, though yet again it's not very performant. Instead of
{{String compareThis = user.getName()}} you would have {{if (\!(user instanceof TemplateHashModel))
die(); TemplateModel value = ((TemplateHashModel) user).get("name"); if (\!(value instanceof
TemplateScalarModel)) die(); String stringToCompare = ((TemplateScalarModel) value).getAsString()}}.
Models just aren't for data grinding.

> ?sort_using with a Comparator parameter
> ---------------------------------------
>
>                 Key: FREEMARKER-61
>                 URL: https://issues.apache.org/jira/browse/FREEMARKER-61
>             Project: Apache Freemarker
>          Issue Type: New Feature
>          Components: engine
>    Affects Versions: 2.3.26-incubating
>            Reporter: Ondra Žižka
>
> Hi Daniel :)
> I know that lists should be sorted before passing them to the template in general.
> In our case, the template is backed by a generic API for graph database which gives an
{{Iterable}} for any 1:N relation. So sorting needs to happen in the template.
> Now I'd like to sort that, for which the {{?sort_by(["...", "..."])}} is good enough,
except when it gets a bit more complicated - e.g. sometimes the values are missing in which
case it should sort by something else...
> Doing that in a template is not a good idea, so I suggest this, elegant in my opinion,
solution:
> First you'd have a Comparator in Java, and perhaps register it like you do with {{FreemarkerMethod}}.
> Then you could pass this as a parameter to {{?sort_using.}}
> {code}
> public class SortByName implements Comparator { ... }
> myData.persons?sort_using("SortByName")
> {code}
> This would be even better if it could pass parameters to the constructor:
> {code}
> public class SortByName implements Comparator {
>     public SortByName(boolean ladiesFirst) { ... }
> }
> myData.persons?sort_using("SortByName", [true])
> {code}
> This would greatly leverage sorting in templates while not complicating the template
syntax or cluttering {{?sort_by}}.
> Thanks for considering.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message