ArrayCommentGetterFactory.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.List;
  7. import java.util.Map;
  8. import java.util.Optional;

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

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

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