LabelGetterFactory.java

  1. package com.gh.mygreen.xlsmapper.fieldaccessor;

  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5. import java.lang.reflect.ParameterizedType;
  6. import java.util.Map;
  7. import java.util.Optional;

  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;

  10. import com.gh.mygreen.xlsmapper.util.ArgUtils;
  11. import com.gh.mygreen.xlsmapper.util.Utils;

  12. /**
  13.  * {@link LabelGetter}のインスタンスを作成する。
  14.  *
  15.  * @since 2.0
  16.  * @author T.TSUCHIE
  17.  *
  18.  */
  19. public class LabelGetterFactory {
  20.    
  21.     private static final Logger log = LoggerFactory.getLogger(LabelGetterFactory.class);
  22.    
  23.     /**
  24.      * フィールドのラベル情報を取得するためのアクセッサを作成します。
  25.      * @param beanClass フィールドが定義されているクラス情報
  26.      * @param fieldName フィールドの名称
  27.      * @return ラベル情報のgetterが存在しない場合は空を返す。
  28.      * @throws IllegalArgumentException {@literal beanClass == null or fieldName == null}
  29.      * @throws IllegalArgumentException {@literal fieldName.isEmpty() = true}
  30.      */
  31.     public Optional<LabelGetter> create(final Class<?> beanClass, final String fieldName) {
  32.        
  33.         ArgUtils.notNull(beanClass, "beanClass");
  34.         ArgUtils.notEmpty(fieldName, "fieldName");
  35.        
  36.         // フィールド Map labelsの場合
  37.         Optional<LabelGetter> LabelGetter = createMapField(beanClass, fieldName);
  38.         if(LabelGetter.isPresent()) {
  39.             return LabelGetter;
  40.         }
  41.        
  42.         // setter メソッドの場合
  43.         LabelGetter = createMethod(beanClass, fieldName);
  44.         if(LabelGetter.isPresent()) {
  45.             return LabelGetter;
  46.         }
  47.        
  48.         // フィールド + labelの場合
  49.         LabelGetter = createField(beanClass, fieldName);
  50.         if(LabelGetter.isPresent()) {
  51.             return LabelGetter;
  52.         }
  53.        
  54.        
  55.         return Optional.empty();
  56.        
  57.        
  58.     }
  59.    
  60.     private Optional<LabelGetter> createMapField(final Class<?> beanClass, final String fieldName) {
  61.        
  62.         final Field labelsField;
  63.         try {
  64.             labelsField = beanClass.getDeclaredField("labels");
  65.             labelsField.setAccessible(true);
  66.            
  67.         } catch (NoSuchFieldException | SecurityException e) {
  68.             // フィールドが見つからない場合は、何もしない。
  69.             return Optional.empty();
  70.         }
  71.        
  72.         if(!Map.class.isAssignableFrom(labelsField.getType())) {
  73.             return Optional.empty();
  74.         }
  75.        
  76.         final ParameterizedType type = (ParameterizedType) labelsField.getGenericType();
  77.         final Class<?> keyType = (Class<?>) type.getActualTypeArguments()[0];
  78.         final Class<?> valueType = (Class<?>) type.getActualTypeArguments()[1];
  79.        
  80.         if(keyType.equals(String.class) && valueType.equals(String.class)) {
  81.             return Optional.of(new LabelGetter() {
  82.                
  83.                 @SuppressWarnings("unchecked")
  84.                 @Override
  85.                 public Optional<String> get(final Object beanObj) {
  86.                     ArgUtils.notNull(beanObj, "beanObj");
  87.                    
  88.                     try {
  89.                         Map<String, String> labelsMapObj = (Map<String, String>) labelsField.get(beanObj);
  90.                         if(labelsMapObj == null) {
  91.                             return Optional.empty();
  92.                         }
  93.                        
  94.                         return Optional.ofNullable(labelsMapObj.get(fieldName));
  95.                        
  96.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  97.                         throw new RuntimeException("fail access labels field.", e);
  98.                     }
  99.                 }
  100.             });
  101.            
  102.         } else {
  103.             // タイプが一致しない場合
  104.             log.warn("not match generics type of labels. key type:{}, value type:{}.", keyType.getName(), valueType.getName());
  105.             return Optional.empty();
  106.         }
  107.        
  108.     }
  109.    
  110.     private Optional<LabelGetter> createMethod(final Class<?> beanClass, final String fieldName) {
  111.        
  112.         final String labelMethodName = "get" + Utils.capitalize(fieldName) + "Label";
  113.        
  114.         final Method method;
  115.         try {
  116.             method = beanClass.getDeclaredMethod(labelMethodName);
  117.             method.setAccessible(true);
  118.            
  119.         } catch (NoSuchMethodException | SecurityException e) {
  120.             return Optional.empty();
  121.         }
  122.        
  123.         if(method.getReturnType().equals(String.class)) {
  124.             return Optional.of(new LabelGetter() {
  125.                
  126.                 @Override
  127.                 public Optional<String> get(final Object beanObj) {
  128.                     ArgUtils.notNull(beanObj, "beanObj");
  129.                    
  130.                     try {
  131.                         final String address = (String)method.invoke(beanObj);
  132.                         return Optional.ofNullable(address);
  133.                        
  134.                     } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
  135.                         throw new RuntimeException("fail access labels getter method.", e);
  136.                     }
  137.                    
  138.                 }
  139.             });
  140.            
  141.         }
  142.        
  143.         return Optional.empty();
  144.        
  145.     }
  146.    
  147.     private Optional<LabelGetter> createField(final Class<?> beanClass, final String fieldName) {
  148.        
  149.         final String labelFieldName = fieldName + "Label";
  150.        
  151.         final Field labelField;
  152.         try {
  153.             labelField = beanClass.getDeclaredField(labelFieldName);
  154.             labelField.setAccessible(true);
  155.            
  156.         } catch (NoSuchFieldException | SecurityException e) {
  157.             return Optional.empty();
  158.         }
  159.        
  160.         if(labelField.getType().equals(String.class)) {
  161.            
  162.             return Optional.of(new LabelGetter() {
  163.                
  164.                 @Override
  165.                 public Optional<String> get(final Object beanObj) {
  166.                     ArgUtils.notNull(beanObj, "beanObj");
  167.                    
  168.                     try {
  169.                         final String address = (String) labelField.get(beanObj);
  170.                         return Optional.ofNullable(address);
  171.                        
  172.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  173.                         throw new RuntimeException("fail access label field.", e);
  174.                     }
  175.                 }
  176.             });
  177.            
  178.         }
  179.        
  180.         return Optional.empty();
  181.     }
  182.    
  183. }