Hi Matthias, Thanks for sharing your ideas! They sound very interesting! I'll take a deeper look this weekend!
Martin Grigorov Wicket Training and Consulting https://twitter.com/mtgrigorov On Thu, Apr 21, 2016 at 10:19 PM, 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 >
