ClassUtils.java

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

  2. import java.lang.annotation.Annotation;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Method;
  5. import java.util.Optional;

  6. import com.github.mygreen.cellformatter.lang.ArgUtils;

  7. /**
  8.  * クラスやメソッドに関するユーティリティクラス。
  9.  * また、リフレクションについても処理する。
  10.  *
  11.  * @since 2.0
  12.  * @author T.TSUCHIE
  13.  *
  14.  */
  15. public class ClassUtils {
  16.    
  17.     /**
  18.      * メソッドがアクセッサメソッド(getter/setter)か判定します。
  19.      *
  20.      * @param method メソッド情報
  21.      * @return trueの場合、アクセッサメソッド。
  22.      */
  23.     public static boolean isAccessorMethod(final Method method) {
  24.        
  25.         return isGetterMethod(method)
  26.                 || isBooleanGetterMethod(method)
  27.                 || isSetterMethod(method);
  28.        
  29.     }
  30.    
  31.     /**
  32.      * メソッドがgetterの書式かどうか判定する。
  33.      * ただし、boolean型にたいするisは{@link #isBooleanGetterMethod(Method)}で判定すること。
  34.      * <ol>
  35.      *  <li>メソッド名が'get'か始まっていること。</li>
  36.      *  <li>メソッド名が4文字以上であること。</li>
  37.      *  <li>引数がないこと。</li>
  38.      *  <li>戻り値が存在すること。</li>
  39.      * </ol>
  40.      * @param method メソッド情報
  41.      * @return trueの場合はgetterメソッドである。
  42.      */
  43.     public static boolean isGetterMethod(final Method method) {
  44.        
  45.         final String methodName = method.getName();
  46.         if(!methodName.startsWith("get")) {
  47.             return false;
  48.            
  49.         } else if(methodName.length() <= 3) {
  50.             return false;
  51.         }
  52.        
  53.         if(method.getParameterCount() > 0) {
  54.             return false;
  55.         }
  56.        
  57.         if(method.getReturnType().equals(Void.class)) {
  58.             return false;
  59.         }
  60.        
  61.         return true;
  62.        
  63.     }
  64.    
  65.     /**
  66.      * メソッドがsetterの書式かどうか判定する。
  67.      * <ol>
  68.      *  <li>メソッド名が'set'か始まっていること。</li>
  69.      *  <li>メソッド名が4文字以上であること。</li>
  70.      *  <li>引数が1つのみ存在すること</li>
  71.      *  <li>戻り値は、検証しません。</li>
  72.      * </ol>
  73.      * @param method メソッド情報
  74.      * @return trueの場合はsetterメソッドである。
  75.      */
  76.     public static boolean isSetterMethod(final Method method) {
  77.        
  78.         final String methodName = method.getName();
  79.         if(!methodName.startsWith("set")) {
  80.             return false;
  81.            
  82.         } else if(methodName.length() <= 3) {
  83.             return false;
  84.         }
  85.        
  86.         if(method.getParameterCount() != 1) {
  87.             return false;
  88.         }
  89.        
  90.         return true;
  91.        
  92.     }
  93.    
  94.     /**
  95.      * メソッドがプリミティブ型のbooleanに対するgetterの書式かどうか判定する。
  96.      * <ol>
  97.      *  <li>メソッド名が'is'か始まっていること。</li>
  98.      *  <li>メソッド名が3文字以上であること。</li>
  99.      *  <li>引数がないこと。</li>
  100.      *  <li>戻り値がプリミティブのboolean型であること。</li>
  101.      * </ol>
  102.      *
  103.      * @param method メソッド情報
  104.      * @return trueの場合はboolean型のgetterメソッドである。
  105.      */
  106.     public static boolean isBooleanGetterMethod(final Method method) {
  107.        
  108.         final String methodName = method.getName();
  109.         if(!methodName.startsWith("is")) {
  110.             return false;
  111.            
  112.         } else if(methodName.length() <= 2) {
  113.             return false;
  114.         }
  115.        
  116.         if(method.getParameterCount() > 0) {
  117.             return false;
  118.         }
  119.        
  120.         if(!isPrimitiveBoolean(method.getReturnType())) {
  121.             return false;
  122.         }
  123.        
  124.         return true;
  125.     }
  126.    
  127.     /**
  128.      * タイプがプリミティブのboolean型かどうか判定する。
  129.      * @param type 判定対象のクラスタイプ。
  130.      * @return trueの場合、プリミティブのboolean型。
  131.      * @throws IllegalArgumentException {@literal type == null.}
  132.      */
  133.     public static boolean isPrimitiveBoolean(final Class<?> type) {
  134.         ArgUtils.notNull(type, "type");
  135.        
  136.         if(type.isPrimitive() && boolean.class.isAssignableFrom(type)) {
  137.             return true;
  138.         }
  139.        
  140.         return false;
  141.     }
  142.    
  143.     /**
  144.      * クラスから、指定したフィールド情報を取得します。
  145.      * @param targetClass フィールドが定義されているクラス
  146.      * @param propertyName プロパティ名
  147.      * @param propertyType プロパティタイプ
  148.      * @return 存在しない場合、空を返します。
  149.      */
  150.     public static Optional<Field> extractField(final Class<?> targetClass, final String propertyName, final Class<?> propertyType) {
  151.        
  152.         final Field field;
  153.         try {
  154.             field = targetClass.getDeclaredField(propertyName);
  155.         } catch (NoSuchFieldException | SecurityException e) {
  156.             return Optional.empty();
  157.         }
  158.        
  159.         field.setAccessible(true);
  160.        
  161.         if(!field.getType().equals(propertyType)) {
  162.             return Optional.empty();
  163.            
  164.         }
  165.        
  166.         return Optional.of(field);
  167.        
  168.     }
  169.    
  170.     /**
  171.      * クラスから、指定したgetterメソッド情報を取得します。
  172.      * @param targetClass し抽出先のクラス
  173.      * @param propertyName プロパティ名
  174.      * @param propertyType プロパティタイプ
  175.      * @return 存在しない場合、空を返します。
  176.      */
  177.     public static Optional<Method> extractGetter(final Class<?> targetClass, final String propertyName, final Class<?> propertyType) {
  178.        
  179.         final String methodName = "get" + Utils.capitalize(propertyName);
  180.        
  181.         Method method;
  182.         try {
  183.             method = targetClass.getMethod(methodName);
  184.            
  185.         } catch (NoSuchMethodException | SecurityException e) {
  186.             return Optional.empty();
  187.         }
  188.        
  189.         method.setAccessible(true);
  190.        
  191.         if(method.getParameterCount() > 0) {
  192.             return Optional.empty();
  193.         }
  194.        
  195.         if(!method.getReturnType().equals(propertyType)) {
  196.             return Optional.empty();
  197.         }
  198.        
  199.         return Optional.of(method);
  200.     }
  201.    
  202.     /**
  203.      * クラスから、指定したboolean型のgetterメソッド情報を取得します。
  204.      * @param targetClass 抽出先のクラス
  205.      * @param propertyName プロパティ名
  206.      * @return 存在しない場合、空を返します。
  207.      */
  208.     public static Optional<Method> extractBooleanGetter(final Class<?> targetClass, final String propertyName) {
  209.        
  210.         final String methodName = "is" + Utils.capitalize(propertyName);
  211.        
  212.         Method method;
  213.         try {
  214.             method = targetClass.getMethod(methodName);
  215.            
  216.         } catch (NoSuchMethodException | SecurityException e) {
  217.             return Optional.empty();
  218.         }
  219.        
  220.         method.setAccessible(true);
  221.        
  222.         if(!method.getReturnType().equals(boolean.class)) {
  223.             return Optional.empty();
  224.         }
  225.        
  226.         return Optional.of(method);
  227.     }
  228.    
  229.     /**
  230.      * クラスから、指定したsetterメソッド情報を取得します。
  231.      * @param targetClass 抽出先のクラス
  232.      * @param propertyName プロパティ名
  233.      * @param propertyType プロパティタイプ
  234.      * @return 存在しない場合、空を返します。
  235.      */
  236.     public static Optional<Method> extractSetter(final Class<?> targetClass, final String propertyName, final Class<?> propertyType) {
  237.        
  238.         final String methodName = "set" + Utils.capitalize(propertyName);
  239.        
  240.         Method method;
  241.         try {
  242.             method = targetClass.getMethod(methodName, propertyType);
  243.         } catch (NoSuchMethodException | SecurityException e) {
  244.             return Optional.empty();
  245.         }
  246.        
  247.         method.setAccessible(true);
  248.        
  249.         return Optional.of(method);
  250.     }
  251.    
  252.     /**
  253.      * アノテーションの指定した属性値を取得する。
  254.      * <p>アノテーションの修飾子はpublicである必要があります。</p>
  255.      * @param anno アノテーションのインスタンス
  256.      * @param attrName 属性名
  257.      * @param attrType 属性のタイプ。
  258.      * @return 属性を持たない場合、空を返す。
  259.      */
  260.     @SuppressWarnings("unchecked")
  261.     public static <T> Optional<T> getAnnotationAttribute(final Annotation anno, final String attrName, final Class<T> attrType) {
  262.        
  263.         try {
  264.             final Method method = anno.annotationType().getMethod(attrName);
  265.             method.setAccessible(true);
  266.             if(!attrType.equals(method.getReturnType())) {
  267.                 return Optional.empty();
  268.             }
  269.            
  270.             final Object value = method.invoke(anno);
  271.             return Optional.of((T)value);
  272.            
  273.         } catch (Exception e) {
  274.             return Optional.empty();
  275.         }
  276.        
  277.     }
  278.    
  279.     /**
  280.      * アノテーションの指定した属性値を持つかどうか判定する。
  281.      * <p>アノテーションの修飾子はpublicである必要があります。</p>
  282.      * @param anno アノテーションのインスタンス
  283.      * @param attrName 属性名
  284.      * @param attrType 属性のタイプ。
  285.      * @return 属性を持つ場合trueを返す。
  286.      */
  287.     public static <T>  boolean hasAnnotationAttribute(final Annotation anno, final String attrName, final Class<T> attrType) {
  288.        
  289.         return getAnnotationAttribute(anno, attrName, attrType).isPresent();
  290.        
  291.     }
  292.    
  293. }