Hi Matthias, interesting ideas, thank you for sharing! I'm going to have a closer look either this weekend or next (a bit busy right now). Currently I'm working on some Java 8 helpers for Wicket 7, similar to the LambdaModel thing currently in WicketStuff. I'm doing that mostly to just play around with some ideas but also because I'm not entirely happy with the WicketStuff LambdaModel - basically I'm exploring to see whether I can come up with something I like better.
Carl-Eric On Thu, 21 Apr 2016 20:19:52 +0000 (UTC) Matthias Metzger <[email protected]> wrote: > Hello everyone, > I just saw yesterday, that the IModel became/will become a > @FunctionalInterface in Wicket 8 and was very happy about it. I am > also very happy about the ongoing implementations and discussions > around lambda usage in Wicket, because it simplifies a lot of code. > Now, one thing I have been working on, is implementing some of the > now known methods of Stream<T> for a AbstractReadOnlyModel and also > for other things - like columns. I have not seen such discussions on > here, please forgive me if I missed that. If it has indeed not been > discussed and you find the idea useful, you can take a look at an > implementation in the following repository: > https://github.com/noobymatze/lambdawicket-model/blob/master/src/main/java/com/github/noobymatze/lambdawicket/model/ReadOnlyModel.java > > What might we be able to do with that? > Consider a Person containing an Address, containing a Street with a > name. Now I want to display the name of the street. How would I go > about that?new Label("streetName", () -> > person.getAddress().getStreet().getName()); This is one approach, but > it completely ignores the possibility of null values and a default > value for such cases. I could wrap the above in an Optional or create > a method in the Person class like 'Optional<String> getStreetName() > {...}'. > > With the proposed ReadOnlyModel I could also do it in the following > way: new Label("streetName", ReadOnlyModel.of(person). > map(Person::getAddress). map(Address::getStreet). > map(Street::getName). orElse("n/a")); But that's not all. Imagine we > would need to dynamically truncate the streetName based on user > input: IModel<WicketFunction<String, String>> truncate = () -> str -> > str.length() > 10 ? str.substring(0, 10) + "..." : str; > IModel<String> truncatedStreetName = ReadOnlyModel.of(person). > map(Person::getAddress). map(Address::getStreet). > map(Street::getName). apply(truncate). orElse("n/a"); Now we > could switch the truncate Model using a > DropDownChoice<WicketFunction<String, String>> or by just setting the > contained function somewhere.truncate.setObject(str -> > str.substring(0, 20)); > > The whole approach is - if I am not mistaken - heavier on memory, > because instead of one IModel<String> we now have 5 or 6 Models, that > cannot be garbage collected, because they are all needed to perform > the computation. > > This doesn't apply for mapping over an IColumn though, because it > doesn't need to rely on the laziness, like the ReadOnlyModel does > (otherwise a change in truncate wouldn't mean a change in the final > value), so:new LambdaColumn(of("Name"), Person::getAddress). > map(Address::getStreet). map(Street::getName). orElse("n/a")); > would create 4 new instances of the LambdaColumn, but 3 of them could > be gc'd more or less the second they were created - like I said, if I > am not mistaken. If this is at all an approach you think might be > useful, I would be happy to provide the implementation of the > LambdaColumn. Otherwise just ignore my message. :) Have a nice > day,Matthias
