入れ子構造のBean の中の Obejct を取得する(2)

入れ子構造のBean の中の Obejct を取得する(1) - Oboe吹きプログラマの黙示録
の続き。。。

変数の宣言名でなく型を指定して、Bean の中を探索→入れ子構造も探索で指定型のインスタンスを求める。
ただし、探索に指定する型が重複して持っている場合はうまく取得できない。
List や、Map、Collection は指定して取得できない。
配列も指定して取得できない。
という限定ならば、
以下、Function<T, R> を生成するもので、目的を達成できる。

import java.lang.reflect.Field;
import java.util.function.Function;
/**
 * UniqueFieldfinder
 */
@FunctionalInterface
public interface UniqueFieldfinder<T, R>{
   R find(T u);

   @SuppressWarnings("unchecked")
   static <T, R> Function<T, R> of(Class<R> c){
      return t->(R)search(c, t);
   }

   static <T> Object search(Class<T> c, Object o){
      Field[] fs = o.getClass().getDeclaredFields();
      String cname = c.getName();
      for(Field f:fs){
         String typename = f.getType().getName();
         if (typename.startsWith("[")) continue;
         try{
            f.setAccessible(true);
            if (typename.startsWith("java.") || typename.startsWith("jdk.")
               || typename.startsWith("javax.")   || typename.startsWith("org.xml.")
               || typename.startsWith("org.w3c.")|| typename.startsWith("org.omg.")){
               if (cname.equals(f.getType().getName())){
                  return f.get(o);
               }
               continue;
            }
            if (typename.equals("double") || typename.equals("float")
               || typename.equals("long") || typename.equals("short")
               || typename.equals("int") || typename.equals("byte")
               || typename.equals("char") || typename.equals("boolean")){
               if (c.isPrimitive()){
                  return f.get(o);
               }
               continue;
            }
            if (cname.equals(f.getType().getName())){
               return f.get(o);
            }
            Object v = f.get(o);
            if (v==null) continue;
            return search(c, v);
         }catch(IllegalArgumentException e){
         }catch(IllegalAccessException e){
         }
      }
      return null;
   }
}

使用例、
入れ子構造のBean の中の Obejct を取得する(1) - Oboe吹きプログラマの黙示録
のクラスの場合、、

Aunit a = new Aunit();
Cunit c = UniqueFieldfinder.of(Cunit.class).apply(a);

とにかく、Bean や DTO の設計として、あまりにも入れ子構造が深いのは、
本当によくない。