PositionGetterFactory.java

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

  2. import java.awt.Point;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.lang.reflect.ParameterizedType;
  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.CellPosition;
  13. import com.gh.mygreen.xlsmapper.util.Utils;

  14. /**
  15.  * {@link PositionGetter}のインスタンスを作成する
  16.  *
  17.  * @since 2.0
  18.  * @author T.TSUCHIE
  19.  *
  20.  */
  21. public class PositionGetterFactory {
  22.    
  23.     private static final Logger log = LoggerFactory.getLogger(PositionGetterFactory.class);
  24.    
  25.     /**
  26.      * フィールドの位置情報を取得するためのアクセッサを作成します。
  27.      * @param beanClass フィールドが定義されているクラス情報
  28.      * @param fieldName フィールドの名称
  29.      * @return 位置情報のgetterが存在しない場合は空を返す。
  30.      * @throws IllegalArgumentException {@literal beanClass == null or fieldName == null}
  31.      * @throws IllegalArgumentException {@literal fieldName.isEmpty() = true}
  32.      */
  33.     public Optional<PositionGetter> create(final Class<?> beanClass, final String fieldName) {
  34.        
  35.         ArgUtils.notNull(beanClass, "beanClass");
  36.         ArgUtils.notEmpty(fieldName, "fieldName");
  37.        
  38.         // フィールド Map positionsの場合
  39.         Optional<PositionGetter> positionGetter = createMapField(beanClass, fieldName);
  40.         if(positionGetter.isPresent()) {
  41.             return positionGetter;
  42.         }
  43.        
  44.         // setter メソッドの場合
  45.         positionGetter = createMethod(beanClass, fieldName);
  46.         if(positionGetter.isPresent()) {
  47.             return positionGetter;
  48.         }
  49.        
  50.         // フィールド + positionの場合
  51.         positionGetter = createField(beanClass, fieldName);
  52.         if(positionGetter.isPresent()) {
  53.             return positionGetter;
  54.         }
  55.        
  56.        
  57.         return Optional.empty();
  58.        
  59.        
  60.     }
  61.    
  62.     private Optional<PositionGetter> createMapField(final Class<?> beanClass, final String fieldName) {
  63.        
  64.         final Field positionsField;
  65.         try {
  66.             positionsField = beanClass.getDeclaredField("positions");
  67.             positionsField.setAccessible(true);
  68.            
  69.         } catch (NoSuchFieldException | SecurityException e) {
  70.             // フィールドが見つからない場合は、何もしない。
  71.             return Optional.empty();
  72.         }
  73.        
  74.         if(!Map.class.isAssignableFrom(positionsField.getType())) {
  75.             return Optional.empty();
  76.         }
  77.        
  78.         final ParameterizedType type = (ParameterizedType) positionsField.getGenericType();
  79.         final Class<?> keyType = (Class<?>) type.getActualTypeArguments()[0];
  80.         final Class<?> valueType = (Class<?>) type.getActualTypeArguments()[1];
  81.        
  82.         if(keyType.equals(String.class) && valueType.equals(CellPosition.class)) {
  83.             return Optional.of(new PositionGetter() {
  84.                
  85.                 @SuppressWarnings("unchecked")
  86.                 @Override
  87.                 public Optional<CellPosition> get(final Object beanObj) {
  88.                     ArgUtils.notNull(beanObj, "beanObj");
  89.                    
  90.                     try {
  91.                         Map<String, CellPosition> positionsMapObj = (Map<String, CellPosition>) positionsField.get(beanObj);
  92.                         if(positionsMapObj == null) {
  93.                             return Optional.empty();
  94.                         }
  95.                        
  96.                         return Optional.ofNullable(positionsMapObj.get(fieldName));
  97.                        
  98.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  99.                         throw new RuntimeException("fail access positions field.", e);
  100.                     }
  101.                 }
  102.             });
  103.            
  104.         } else if(keyType.equals(String.class) && valueType.equals(Point.class)) {
  105.            
  106.             return Optional.of(new PositionGetter() {
  107.                
  108.                 @SuppressWarnings("unchecked")
  109.                 @Override
  110.                 public Optional<CellPosition> get(final Object beanObj) {
  111.                     ArgUtils.notNull(beanObj, "beanObj");
  112.                    
  113.                     try {
  114.                         Map<String, Point> positionsMapObj = (Map<String, Point>) positionsField.get(beanObj);
  115.                         if(positionsMapObj == null) {
  116.                             return Optional.empty();
  117.                         }
  118.                        
  119.                         return Optional.ofNullable(positionsMapObj.get(fieldName))
  120.                                 .map(a -> CellPosition.of(a));
  121.                        
  122.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  123.                         throw new RuntimeException("fail access positions field.", e);
  124.                     }
  125.                 }
  126.             });
  127.            
  128.            
  129.         } else if(keyType.equals(String.class) && valueType.equals(org.apache.poi.ss.util.CellAddress.class)) {
  130.            
  131.             return Optional.of(new PositionGetter() {
  132.                
  133.                 @SuppressWarnings("unchecked")
  134.                 @Override
  135.                 public Optional<CellPosition> get(final Object beanObj) {
  136.                     ArgUtils.notNull(beanObj, "beanObj");
  137.                    
  138.                     try {
  139.                         Map<String, org.apache.poi.ss.util.CellAddress> positionsMapObj = (Map<String, org.apache.poi.ss.util.CellAddress>) positionsField.get(beanObj);
  140.                         if(positionsMapObj == null) {
  141.                             return Optional.empty();
  142.                         }
  143.                        
  144.                         return Optional.ofNullable(positionsMapObj.get(fieldName))
  145.                                 .map(a -> CellPosition.of(a));
  146.                        
  147.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  148.                         throw new RuntimeException("fail access positions field.", e);
  149.                     }
  150.                 }
  151.             });
  152.            
  153.            
  154.         } else {
  155.             // タイプが一致しない場合
  156.             log.warn("not match generics type of positions. key type:{}, value type:{}.", keyType.getName(), valueType.getName());
  157.             return Optional.empty();
  158.         }
  159.        
  160.     }
  161.    
  162.     private Optional<PositionGetter> createMethod(final Class<?> beanClass, final String fieldName) {
  163.        
  164.         final String positionMethodName = "get" + Utils.capitalize(fieldName) + "Position";
  165.        
  166.         final Method method;
  167.         try {
  168.             method = beanClass.getDeclaredMethod(positionMethodName);
  169.             method.setAccessible(true);
  170.            
  171.         } catch (NoSuchMethodException | SecurityException e) {
  172.             return Optional.empty();
  173.         }
  174.        
  175.         if(method.getReturnType().equals(CellPosition.class)) {
  176.             return Optional.of(new PositionGetter() {
  177.                
  178.                 @Override
  179.                 public Optional<CellPosition> get(final Object beanObj) {
  180.                     ArgUtils.notNull(beanObj, "beanObj");
  181.                    
  182.                     try {
  183.                         final CellPosition address = (CellPosition)method.invoke(beanObj);
  184.                         return Optional.ofNullable(address);
  185.                        
  186.                     } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
  187.                         throw new RuntimeException("fail access positions getter method.", e);
  188.                     }
  189.                    
  190.                 }
  191.             });
  192.            
  193.         } else if(method.getReturnType().equals(Point.class)) {
  194.             return Optional.of(new PositionGetter() {
  195.                
  196.                 @Override
  197.                 public Optional<CellPosition> get(final Object beanObj) {
  198.                     ArgUtils.notNull(beanObj, "beanObj");
  199.                    
  200.                     try {
  201.                         final Point point = (Point)method.invoke(beanObj);
  202.                         return Optional.ofNullable(point).map(p -> CellPosition.of(p));
  203.                        
  204.                     } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
  205.                         throw new RuntimeException("fail access positions getter method.", e);
  206.                     }
  207.                    
  208.                 }
  209.             });
  210.            
  211.         } else if(method.getReturnType().equals(org.apache.poi.ss.util.CellAddress.class)) {
  212.             return Optional.of(new PositionGetter() {
  213.                
  214.                 @Override
  215.                 public Optional<CellPosition> get(final Object beanObj) {
  216.                     ArgUtils.notNull(beanObj, "beanObj");
  217.                    
  218.                     try {
  219.                         final org.apache.poi.ss.util.CellAddress address = (org.apache.poi.ss.util.CellAddress)method.invoke(beanObj);
  220.                         return Optional.ofNullable(address).map(a -> CellPosition.of(a));
  221.                        
  222.                     } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
  223.                         throw new RuntimeException("fail access positions getter method.", e);
  224.                     }
  225.                    
  226.                 }
  227.             });
  228.         }
  229.        
  230.         return Optional.empty();
  231.        
  232.     }
  233.    
  234.     private Optional<PositionGetter> createField(final Class<?> beanClass, final String fieldName) {
  235.        
  236.         final String positionFieldName = fieldName + "Position";
  237.        
  238.         final Field positionField;
  239.         try {
  240.             positionField = beanClass.getDeclaredField(positionFieldName);
  241.             positionField.setAccessible(true);
  242.            
  243.         } catch (NoSuchFieldException | SecurityException e) {
  244.             return Optional.empty();
  245.         }
  246.        
  247.         if(positionField.getType().equals(CellPosition.class)) {
  248.            
  249.             return Optional.of(new PositionGetter() {
  250.                
  251.                 @Override
  252.                 public Optional<CellPosition> get(final Object beanObj) {
  253.                     ArgUtils.notNull(beanObj, "beanObj");
  254.                    
  255.                     try {
  256.                         final CellPosition address = (CellPosition) positionField.get(beanObj);
  257.                         return Optional.ofNullable(address);
  258.                        
  259.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  260.                         throw new RuntimeException("fail access position field.", e);
  261.                     }
  262.                 }
  263.             });
  264.            
  265.         } else if(positionField.getType().equals(Point.class)) {
  266.            
  267.             return Optional.of(new PositionGetter() {
  268.                
  269.                 @Override
  270.                 public Optional<CellPosition> get(final Object beanObj) {
  271.                     ArgUtils.notNull(beanObj, "beanObj");
  272.                    
  273.                     try {
  274.                         final Point point = (Point) positionField.get(beanObj);
  275.                         return Optional.ofNullable(point).map(p -> CellPosition.of(p));
  276.                        
  277.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  278.                         throw new RuntimeException("fail access position field.", e);
  279.                     }
  280.                 }
  281.             });
  282.            
  283.         } else if(positionField.getType().equals(org.apache.poi.ss.util.CellAddress.class)) {
  284.            
  285.             return Optional.of(new PositionGetter() {
  286.                
  287.                 @Override
  288.                 public Optional<CellPosition> get(final Object beanObj) {
  289.                     ArgUtils.notNull(beanObj, "beanObj");
  290.                    
  291.                     try {
  292.                         final org.apache.poi.ss.util.CellAddress address = (org.apache.poi.ss.util.CellAddress) positionField.get(beanObj);
  293.                         return Optional.ofNullable(address).map(a -> CellPosition.of(a));
  294.                        
  295.                     } catch (IllegalArgumentException | IllegalAccessException e) {
  296.                         throw new RuntimeException("fail access position field.", e);
  297.                     }
  298.                 }
  299.             });
  300.        
  301.         }
  302.        
  303.         return Optional.empty();
  304.     }
  305.    
  306. }