Java Bean のコピー(1)、 Snake case ⇔ Camel case

Field 属性が、Snake case で記述された Java のオブジェクト(Bean)と
Camel case で記述された Java のオブジェクト(Bean)
相互に値をコピー生成する方法、
つまり、Snake case で記述されたフィールド属性値を対応する Camel case で記述されたフィールド属性値にセットして
オブジェクトを生成する。また、その逆である。
昨日の投稿、
Java で、Snake case ⇔ Camel case - Oboe吹きプログラマの黙示録
から、思いつくコードである。

フィールド属性値 Get / Set や、Throwable な関数型インターフェースを使用、
GitHub - yipuran/yipuran-core: Java application framework
を利用する。

Snake case → Camel case

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;
import org.yipuran.function.ThrowableBiConsumer;
import org.yipuran.function.ThrowableConsumer;
import org.yipuran.function.ThrowableSupplier;
import org.yipuran.util.Fieldsetter;
import org.yipuran.util.GenericBuilder;
public static <R, T> R copySnakeToCamel(T t, Class<R> cls){
   Map<String, String> fmap = Arrays.stream(cls.getDeclaredFields())
   .map(e->e.getName())
   .collect(()->new HashMap<String, String>(), (r, s)->r.put(s, s), (r, s)->{});
   GenericBuilder<R> builder = Arrays.stream(t.getClass().getDeclaredFields())
   .collect(ThrowableSupplier.to(()->GenericBuilder.of(ThrowableSupplier.to(()->cls.newInstance())))
      , ThrowableBiConsumer.of((r, f)->{
         f.setAccessible(true);
         String camel = Optional.of(Pattern.compile("_")
         .splitAsStream(f.getName().toLowerCase()).filter(e->e.length() > 0)
         .collect(StringBuilder::new
               , (rr, tt)->rr.append(tt.substring(0, 1).toUpperCase()).append(tt.substring(1))
         , (v, w)->{}).toString()).filter(e->e.length() > 1)
         .map(e->e.substring(0, 1).toLowerCase() + e.substring(1)).get();
      if (fmap.containsKey(camel)){
         r.with(Fieldsetter.of((p, u)->camel), f.get(t));
      }
   }), (r, s)->{});
   return builder.build();
}

Camel case → Snake case

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.yipuran.function.ThrowableBiConsumer;
import org.yipuran.function.ThrowableSupplier;
import org.yipuran.util.Fieldsetter;
import org.yipuran.util.GenericBuilder;
public static <R, T> R copyCamelToSnake(T t, Class<R> cls){
   Map<String, String> fmap = Arrays.stream(cls.getDeclaredFields())
   .map(e->e.getName())
   .collect(()->new HashMap<String, String>(), (r, s)->r.put(s.toLowerCase(), s), (r, s)->{});
   GenericBuilder<R> builder = Arrays.stream(t.getClass().getDeclaredFields())
   .collect(ThrowableSupplier.to(()->GenericBuilder.of(ThrowableSupplier.to(()->cls.newInstance())))
      , ThrowableBiConsumer.of((r, f)->{
         f.setAccessible(true);
         String snake = f.getName().replaceAll("([a-z0-9]+)([A-Z]+)", "$1_$2").toLowerCase();
      if (fmap.containsKey(snake)){
         r.with(Fieldsetter.of((p, u)->snake), f.get(t));
      }
   }), (r, s)->{});
   return builder.build();
}