MapCommentGetterFactory.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 MapCommentGetter}のインスタンスを作成する。
  14.  *
  15.  * @since 2.1
  16.  * @author T.TSUCHIE
  17.  *
  18.  */
  19. public class MapCommentGetterFactory {
  20.    
  21.     private static final Logger log = LoggerFactory.getLogger(MapCommentGetterFactory.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<MapCommentGetter> create(final Class<?> beanClass, final String fieldName) {
  32.        
  33.         ArgUtils.notNull(beanClass, "beanClass");
  34.         ArgUtils.notEmpty(fieldName, "fieldName");
  35.        
  36.         // フィールド Map commentsの場合
  37.         Optional<MapCommentGetter> MapCommentGetter = createMapField(beanClass, fieldName);
  38.         if(MapCommentGetter.isPresent()) {
  39.             return MapCommentGetter;
  40.         }
  41.        
  42.         // setter メソッドの場合
  43.         MapCommentGetter = createMethod(beanClass, fieldName);
  44.         if(MapCommentGetter.isPresent()) {
  45.             return MapCommentGetter;
  46.         }
  47.        
  48.         // フィールド + commentの場合
  49.         MapCommentGetter = createField(beanClass, fieldName);
  50.         if(MapCommentGetter.isPresent()) {
  51.             return MapCommentGetter;
  52.         }
  53.        
  54.        
  55.         return Optional.empty();
  56.        
  57.        
  58.     }
  59.    
  60.     private String createMapKey(final String fieldName, final String key) {
  61.         return String.format("%s[%s]", fieldName, key);
  62.     }
  63.    
  64.     private Optional<MapCommentGetter> createMapField(final Class<?> beanClass, final String fieldName) {
  65.        
  66.         final Field commentsField;
  67.         try {
  68.             commentsField = beanClass.getDeclaredField("comments");
  69.             commentsField.setAccessible(true);
  70.            
  71.         } catch (NoSuchFieldException | SecurityException e) {
  72.             // フィールドが見つからない場合は、何もしない。
  73.             return Optional.empty();
  74.         }
  75.        
  76.         if(!Map.class.isAssignableFrom(commentsField.getType())) {
  77.             return Optional.empty();
  78.         }
  79.        
  80.         final ParameterizedType type = (ParameterizedType) commentsField.getGenericType();
  81.         final Class<?> keyType = (Class<?>) type.getActualTypeArguments()[0];
  82.         final Class<?> valueType = (Class<?>) type.getActualTypeArguments()[1];
  83.        
  84.         if(keyType.equals(String.class) && valueType.equals(String.class)) {
  85.             return Optional.of(new MapCommentGetter() {
  86.                
  87.                 @SuppressWarnings("unchecked")
  88.                 @Override
  89.                 public Optional<String> get(final Object beanObj, final String key) {
  90.                     ArgUtils.notNull(beanObj, "beanObj");
  91.                    
  92.                     try {
  93.                         Map<String, String> commentsMapObj = (Map<String, String>) commentsField.get(beanObj);
  94.                         if(commentsMapObj == null) {
  95.                             return Optional.empty();
  96.                         }
  97.                        
  98.                         final String mapKey = createMapKey(fieldName, key);
  99.                        
  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<MapCommentGetter> 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, String.class);
  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 MapCommentGetter() {
  131.                
  132.                 @Override
  133.                 public Optional<String> get(final Object beanObj, final String key) {
  134.                     ArgUtils.notNull(beanObj, "beanObj");
  135.                    
  136.                     try {
  137.                         final String address = (String)method.invoke(beanObj, key);
  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<MapCommentGetter> 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(!Map.class.isAssignableFrom(commentField.getType())) {
  167.             return Optional.empty();
  168.         }
  169.        
  170.         final ParameterizedType type = (ParameterizedType) commentField.getGenericType();
  171.         final Class<?> keyType = (Class<?>) type.getActualTypeArguments()[0];
  172.         final Class<?> valueType = (Class<?>) type.getActualTypeArguments()[1];
  173.        
  174.         if(keyType.equals(String.class) && valueType.equals(String.class)) {
  175.            
  176.             return Optional.of(new MapCommentGetter() {
  177.                
  178.                 @Override
  179.                 public Optional<String> get(final Object beanObj, final String key) {
  180.                     ArgUtils.notNull(beanObj, "beanObj");
  181.                    
  182.                     try {
  183.                         Map<String, String> commentMapObj = (Map<String, String>) commentField.get(beanObj);
  184.                         if(commentMapObj == null) {
  185.                             return Optional.empty();
  186.                         }
  187.                        
  188.                         final String comment = commentMapObj.get(key);
  189.                         return Optional.ofNullable(comment);
  190.                        
  191.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  192.                         throw new RuntimeException("fail access comment field.", e);
  193.                     }
  194.                 }
  195.             });
  196.            
  197.         }
  198.        
  199.         return Optional.empty();
  200.     }
  201.    
  202. }