BeanUtils の copyProperties に喧嘩を売るつもりはないけど。。。

Apache の commons-beanutils
今更、BeanUtils の copyProperties と張りあうつもりもないし、Entity DTO Form などで属性値渡すような
アーキテクチャ(アプリ構成)には、とっくに興味がないのだが、、、
原始的には、面白いところなので、書いてみた。

公開している GitHub - yipuran/yipuran-core: Java application framework から、
Fieldsetter. リフレクションでフィールドに値をセット
Throwable な、関数型インターフェース
とにかく便利な、GenericBuilder を使って以下のように書ける。

同一の属性名、同じ型をコピー先に持つことを前提とした厳格なコピーで
誤りがあれば例外をスロー

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 copy(T t, Supplier<R> s){
   GenericBuilder<R> builder = Arrays.stream(t.getClass().getDeclaredFields())
   .collect(ThrowableSupplier.to(()->GenericBuilder.of(s)), ThrowableBiConsumer.of((r, f)->{
      f.setAccessible(true);
      r.with(Fieldsetter.of((p, u)->f.getName()), f.get(t));
   }), (r, u)->{});
   return builder.build();
}

コピー先に同一の属性が宣言されていなくても、存在するものだけはコピーして
そうでないものは無視する寛大なコピー

public static <R, T> R copylenient(T t, Supplier<R> s){
   GenericBuilder<R> builder = Arrays.stream(t.getClass().getDeclaredFields())
   .collect(ThrowableSupplier.to(()->GenericBuilder.of(s)), ThrowableBiConsumer.of((g, f)->{
      f.setAccessible(true);
      g.with((v, u)->{
         try{
            Field d = v.getClass().getField(f.getName());
            d.setAccessible(true);
            d.set(v, u);
         }catch(Throwable x){
         }
      }, f.get(t));
   }, (a, b)->{})
   ,(v, u)->{});
   return builder.build();
}

これは、yipuran-core に入れておいた。