DropDownChoice の IChoiceRenderer

2年近く前、Wicket6 → 7 になった時、DropDownChoice の為の IChoiceRenderer が、
 public T getObject(String id, IModel> choices)
が増えて、choices のgetModelObject() で取ってくるものをこのメソッドで返さなくてはならなくなり、
当時、以下のように、optionタグの value属性値を返せるようにするインターフェースを用意して
更に、IChoiceRenderer継承と、DropDownChoice がそれを使うように継承したものを作った。。
IChoiceRenderer ラムダ化 - Oboe吹きプログラマの黙示録

でも、やはりDropDownChoice の継承と、選択要素にoptionタグの value属性値を返せるようにするインターフェース
を付けるなんて方法は、選択要素の構造に手を加えるので良くない。
かと言って、IChoiceRenderer の無名インナークラスのコーディングは、長くなって嫌だ。

option タグの value を返すもの。bodyを返すもの。選択されたものを判断して返すもの。
これらの処理関数を埋め込めるラムダ式になっていれば良い。

import java.util.List;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;
import org.danekja.java.util.function.serializable.SerializableBiPredicate;
import org.danekja.java.util.function.serializable.SerializableFunction;
/**
 * IChoiceRenderer を提供
 */
public class ChoiceRender{
   private ChoiceRender(){}

   public static <T> IChoiceRenderer<T> of(SerializableFunction<T, String> idfunction
         , SerializableFunction<T, String> displayfunction
         , SerializableBiPredicate<T, String> bipredicate
   ){
      return new IChoiceRenderer<T>(){
         @Override
         public Object getDisplayValue(T t){
            return displayfunction.apply(t);
         }
         @Override
         public String getIdValue(T t, int index){
            return idfunction.apply(t);
         }
         @Override
         public T getObject(String id, IModel<? extends List<? extends T>> choices){
            return choices.getObject().stream().filter(e->bipredicate.test(e, id)).findFirst().orElse(null);
         }
      };
   }
}


例)
以下のような対象クラスがあったとする。

public class Foo implements Serializable{
   public int val;
   public String name;
   public Foo(int val, String name){
      this.val = val;
      this.name = name;
   }
}
final DropDownChoice<Foo> selectFoo =
new DropDownChoice<Foo>("select1", new Model<>(), Arrays.asList(new Foo(1,"A"), new Foo(2,"B"), new Foo(3,"C") )
      , ChoiceRender.of(t->Integer.toString(t.val), t->t.name, (t,u)->Integer.toString(t.val).equals(u)) ) ;
queue(selectFoo);

そして、optionタグの value も body も同じものとして生成することも簡単に書ける。

例えば、"a","b","c"

final DropDownChoice<String> selectChar =
new DropDownChoice<String>("select2", new Model<>(), Arrays.asList("a","b","c")
   , ChoiceRender.of(t->t, t->t, (t,u)->t.equals(u)) ) ;
queue(selectChar);

フォーム送信されて受け取るところ。。

Optional.ofNullable(selectChar.getModelObject()).ifPresent(s->{
  // 
});