Throwable な Function から、Optional<LocalDate>を生成することでコードを短く

先日、Optional の filter を連結して使う - Oboe吹きプログラマの黙示録 で書いた例は、
DateFormat の日付の妥当性チェック setLenient(true=厳しくない)を行い、これが返却値なしの void メソッドであることから
どうしてもあのようになってしまっていた。

日付入力文字列→チェックを行って日付型への変換は、今まで嫌というほど書いてきたが、
oboe2uran.hatenablog.com

これを使って以下のように書いて少しは短くなる。。。

final TextField<String> dateField = new TextField<>("date", new Model<String>());
queue(dateText);

queue(new Button("submit").add(AjaxFormSubmitBehavior.onSubmit("click", SerialThrowableConsumer.of(t->{
   LocalDate date = Optional.ofNullable(dateField.getModelObject())
   .map(ThrowableFunction.of(s->{
      DateFormat f = new SimpleDateFormat("yyyy/MM/dd");
      f.setLenient(false);
      f.parse(s);
      return s;}))
   .map(e->LocalDate.parse(e, DateTimeFormatter.ofPattern("yyyy/MM/dd")))
   .orElseThrow(()->new RuntimeException("is null Error!!"));
   
   // TODO t=AjaxRequestTarget  
}, (t, x)->{
   // TODO t=AjaxRequestTarget  x=Exception
}))));

RuntimeException であれ java.text.ParseException: Unparseable date: を捕捉できてればいいのである。
これでも、沢山の日付入力があるとやはり書くのがたいへん。。

それで以前、日付のユーティリティクラスを作ったことがあり、そこに static メソッドで Optional
返すメソッドを用意する。

public final class DateUtil{
     private DateUtil(){}
     public static Optional<LocalDate> optionalDate(String string, String pattern){
      return Optional.ofNullable(string)
      .map(ThrowableFunction.of(e->{
         DateFormat f = new SimpleDateFormat(pattern);
         f.setLenient(false);
         f.parse(e);
         return e;}))
      .map(e->LocalDate.parse(e, DateTimeFormatter.ofPattern(pattern)));
   }
}

これで、dateField.getModelObject() での入力した日付文字列の処理は、以下のように書ける。

queue(new Button("submit").add(AjaxFormSubmitBehavior.onSubmit("click", SerialThrowableConsumer.of(t->{
   LocalDate date = DateUtil.optionalDate(dateText.getModelObject(), "yyyy/MM/dd")
   .orElseThrow(()->new RuntimeException("is null Error!!"));
   
   // TODO t=AjaxRequestTarget  
}, (t, x)->{
   // TODO t=AjaxRequestTarget  x=Exception
}))));