AnnotationReader.java

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

  2. import java.lang.annotation.Annotation;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Method;
  5. import java.util.HashMap;
  6. import java.util.Map;

  7. import com.gh.mygreen.xlsmapper.xml.bind.AnnotationInfo;
  8. import com.gh.mygreen.xlsmapper.xml.bind.ClassInfo;
  9. import com.gh.mygreen.xlsmapper.xml.bind.FieldInfo;
  10. import com.gh.mygreen.xlsmapper.xml.bind.MethodInfo;
  11. import com.gh.mygreen.xlsmapper.xml.bind.AnnotationMappingInfo;


  12. /**
  13.  * フィールド、メソッドのアノテーションへアクセスするためのクラス。
  14.  * <p>Javaソースに直接アノテーションを付与する場合と、XMLで定義する方法の両方をサポートする。
  15.  *
  16.  * @version 2.0
  17.  * @author Naoki Takezoe
  18.  * @author T.TSUCHIE
  19.  *
  20.  */
  21. public class AnnotationReader {
  22.    
  23.     /**
  24.      * XMLで定義した情報。
  25.      * nullでもよい。
  26.      */
  27.     private final AnnotationMappingInfo xmlInfo;
  28.    
  29.     /**
  30.      * アノテーションを動的に組み立てるクラス。
  31.      */
  32.     private DynamicAnnotationBuilder annotationBuilder = DynamicAnnotationBuilder.getInstance();
  33.    
  34.     /**
  35.      * XMLで定義した情報を指定するコンストラクタ。
  36.      * @param xmlInfo XMLで定義したアノテーションの情報。{@link XmlIO}で読み込んで取得した値。指定しない場合はnull。
  37.      */
  38.     public AnnotationReader(final AnnotationMappingInfo xmlInfo) {
  39.         this.xmlInfo = xmlInfo;
  40.     }
  41.    
  42.     /**
  43.      * Returns all class annotations.
  44.      *
  45.      * @param clazz the target class
  46.      * @return all annotations present on target class
  47.      * @throws AnnotationReadException
  48.      */
  49.     public Annotation[] getAnnotations(final Class<?> clazz) throws AnnotationReadException {
  50.        
  51.         if(xmlInfo != null && xmlInfo.containsClassInfo(clazz.getName())) {
  52.             final ClassInfo classInfo = xmlInfo.getClassInfo(clazz.getName());
  53.             final Map<String, Annotation> map = new HashMap<>();
  54.            
  55.             if(classInfo.isOverride()) {
  56.                 for(Annotation ann : clazz.getAnnotations()) {
  57.                     map.put(ann.annotationType().getName(), ann);
  58.                 }
  59.             }
  60.            
  61.             for(AnnotationInfo annInfo: classInfo.getAnnotationInfos()) {
  62.                 try {
  63.                     map.put(annInfo.getClassName(),
  64.                             annotationBuilder.buildAnnotation(Class.forName(annInfo.getClassName()), annInfo));
  65.                 } catch (ClassNotFoundException e) {
  66.                     throw new AnnotationReadException(String.format("not found class '%s'", annInfo.getClassName()), e);
  67.                 }
  68.             }
  69.            
  70.             return map.values().toArray(new Annotation[map.size()]);
  71.         }
  72.        
  73.         return clazz.getAnnotations();
  74.     }
  75.    
  76.     /**
  77.      * Returns a class annotation for the specified type if such an annotation is present, else null.
  78.      *
  79.      * @param <A> the type of the annotation
  80.      * @param clazz the target class
  81.      * @param annClass the Class object corresponding to the annotation type
  82.      * @return the target class's annotation for the specified annotation type if present on this element, else null
  83.      * @throws AnnotationReadException
  84.      */
  85.     @SuppressWarnings("unchecked")
  86.     public <A extends Annotation> A getAnnotation(final Class<?> clazz, final Class<A> annClass) throws AnnotationReadException {
  87.         if(xmlInfo != null && xmlInfo.containsClassInfo(clazz.getName())) {
  88.             final ClassInfo classInfo = xmlInfo.getClassInfo(clazz.getName());
  89.            
  90.             if(classInfo.containsAnnotationInfo(annClass.getName())) {
  91.                 AnnotationInfo annInfo = classInfo.getAnnotationInfo(annClass.getName());
  92.                 try {
  93.                     return (A)annotationBuilder.buildAnnotation(Class.forName(annInfo.getClassName()), annInfo);
  94.                 } catch (ClassNotFoundException e) {
  95.                     throw new AnnotationReadException(String.format("not found class '%s'", annInfo.getClassName()), e);
  96.                 }
  97.             }
  98.         }
  99.        
  100.         return clazz.getAnnotation(annClass);
  101.     }
  102.    
  103.     /**
  104.      * メソッドに付与された指定したアノテーションを取得する。
  105.      *
  106.      * @param method 取得対象のメソッド。
  107.      * @param annClas 取得対象のアノテーションのタイプ。
  108.      * @return
  109.      * @throws AnnotationReadException
  110.      */
  111.     @SuppressWarnings("unchecked")
  112.     public <A extends Annotation> A getAnnotation(final Method method, final Class<A> annClas) throws AnnotationReadException {
  113.        
  114.         final Class<?> clazz = method.getDeclaringClass();
  115.        
  116.         if(xmlInfo != null && xmlInfo.containsClassInfo(clazz.getName())) {
  117.             final ClassInfo classInfo = xmlInfo.getClassInfo(clazz.getName());
  118.            
  119.             if(classInfo.containsMethodInfo(method.getName())) {
  120.                 MethodInfo methodInfo = classInfo.getMethodInfo(method.getName());
  121.                 if(methodInfo != null && methodInfo.containsAnnotationInfo(annClas.getName())) {
  122.                     AnnotationInfo annInfo = methodInfo.getAnnotationInfo(annClas.getName());
  123.                     try {
  124.                         return (A)annotationBuilder.buildAnnotation(Class.forName(annInfo.getClassName()), annInfo);
  125.                     } catch (ClassNotFoundException e) {
  126.                         throw new AnnotationReadException(String.format("not found class '%s'", annInfo.getClassName()), e);
  127.                     }
  128.                 }
  129.             }
  130.         }
  131.         return method.getAnnotation(annClas);
  132.     }
  133.    
  134.     /**
  135.      * メソッドに付与されたアノテーションを持つか判定します。
  136.      * @since 2.0
  137.      * @param method 判定対象のメソッド
  138.      * @param annClass アノテーションのタイプ
  139.      * @return trueの場合、アノテーションを持ちます。
  140.      */
  141.     public <A extends Annotation> boolean hasAnnotation(final Method method, final Class<A> annClass) {
  142.         return getAnnotation(method, annClass) != null;
  143.     }
  144.    
  145.     /**
  146.      * メソッドに付与されたアノテーションを全て取得する。
  147.      *
  148.      * @param method 取得対象のメソッド。
  149.      * @return 取得対象のアノテーションのタイプ。
  150.      * @throws AnnotationReadException
  151.      */
  152.     public Annotation[] getAnnotations(final Method method) throws AnnotationReadException {
  153.        
  154.         final Class<?> clazz = method.getDeclaringClass();
  155.        
  156.         if(xmlInfo != null && xmlInfo.containsClassInfo(clazz.getName())) {
  157.             final ClassInfo classInfo = xmlInfo.getClassInfo(clazz.getName());
  158.            
  159.             if(classInfo.containsMethodInfo(method.getName())) {
  160.                 final MethodInfo methodInfo = classInfo.getMethodInfo(method.getName());
  161.                 final Map<String, Annotation> map = new HashMap<>();
  162.                
  163.                 if(methodInfo.isOverride()) {
  164.                     for(Annotation ann : method.getAnnotations()) {
  165.                         map.put(ann.annotationType().getName(), ann);
  166.                     }
  167.                 }
  168.                
  169.                 for(AnnotationInfo annInfo: methodInfo.getAnnotationInfos()){
  170.                     try {
  171.                         map.put(annInfo.getClassName(),
  172.                                 annotationBuilder.buildAnnotation(Class.forName(annInfo.getClassName()), annInfo));
  173.                     } catch (ClassNotFoundException e) {
  174.                         throw new AnnotationReadException(String.format("not found class '%s'", annInfo.getClassName()), e);
  175.                     }
  176.                 }
  177.                
  178.                 return map.values().toArray(new Annotation[map.size()]);
  179.             }
  180.         }
  181.         return method.getAnnotations();
  182.     }
  183.    
  184.     /**
  185.      * フィールドに付与されたアノテーションを指定して取得する。
  186.      * @param field 取得対象のフィールド
  187.      * @param annClass アノテーションのタイプ
  188.      * @return
  189.      * @throws AnnotationReadException
  190.      */
  191.     @SuppressWarnings("unchecked")
  192.     public <A extends Annotation> A getAnnotation(final Field field, final Class<A> annClass) throws AnnotationReadException {
  193.        
  194.         final Class<?> clazz = field.getDeclaringClass();
  195.        
  196.         if(xmlInfo != null && xmlInfo.containsClassInfo(clazz.getName())) {
  197.             final ClassInfo classInfo = xmlInfo.getClassInfo(clazz.getName());
  198.            
  199.             if(classInfo.containsFieldInfo(field.getName())) {
  200.                 FieldInfo fieldInfo = classInfo.getFieldInfo(field.getName());
  201.                 if(fieldInfo != null && fieldInfo.containsAnnotationInfo(annClass.getName())){
  202.                     AnnotationInfo annInfo = fieldInfo.getAnnotationInfo(annClass.getName());
  203.                     try {
  204.                         return (A)annotationBuilder.buildAnnotation(Class.forName(annInfo.getClassName()), annInfo);
  205.                     } catch (ClassNotFoundException e) {
  206.                         throw new AnnotationReadException(String.format("not found class '%s'", annInfo.getClassName()), e);
  207.                     }
  208.                 }
  209.             }
  210.         }
  211.         return field.getAnnotation(annClass);
  212.     }
  213.    
  214.     /**
  215.      * フィールドに付与されたアノテーションを持つか判定します。
  216.      * @since 2.0
  217.      * @param field 判定対象のフィールド
  218.      * @param annClass アノテーションのタイプ
  219.      * @return trueの場合、アノテーションを持ちます。
  220.      */
  221.     public <A extends Annotation> boolean hasAnnotation(final Field field, final Class<A> annClass) {
  222.         return getAnnotation(field, annClass) != null;
  223.     }
  224.    
  225.     /**
  226.      * フィールドに付与されたアノテーションを全て取得する。
  227.      * @param field 取得対象のフィールド
  228.      * @return
  229.      * @throws AnnotationReadException
  230.      */
  231.     public Annotation[] getAnnotations(final Field field) throws AnnotationReadException {
  232.        
  233.         final Class<?> clazz = field.getDeclaringClass();
  234.        
  235.         if(xmlInfo != null && xmlInfo.containsClassInfo(clazz.getName())) {
  236.             final ClassInfo classInfo = xmlInfo.getClassInfo(clazz.getName());
  237.            
  238.             if(classInfo.containsFieldInfo(field.getName())) {
  239.                 final FieldInfo fieldInfo = classInfo.getFieldInfo(field.getName());
  240.                 final Map<String, Annotation> map = new HashMap<>();
  241.                
  242.                 if(fieldInfo.isOverride()) {
  243.                     for(Annotation ann : field.getAnnotations()) {
  244.                         map.put(ann.annotationType().getName(), ann);
  245.                     }
  246.                 }
  247.                
  248.                 for(AnnotationInfo annInfo: fieldInfo.getAnnotationInfos()){
  249.                     try {
  250.                         map.put(annInfo.getClassName(),
  251.                                 annotationBuilder.buildAnnotation(Class.forName(annInfo.getClassName()), annInfo));
  252.                     } catch (ClassNotFoundException e) {
  253.                         throw new AnnotationReadException(String.format("not found class '%s'", annInfo.getClassName()), e);
  254.                     }
  255.                 }
  256.                 return map.values().toArray(new Annotation[map.size()]);
  257.             }
  258.         }
  259.         return field.getAnnotations();
  260.     }
  261.    
  262.     public DynamicAnnotationBuilder getAnnotationBuilder() {
  263.         return annotationBuilder;
  264.     }
  265.    
  266.     public void setAnnotationBuilder(DynamicAnnotationBuilder annotationBuilder) {
  267.         this.annotationBuilder = annotationBuilder;
  268.     }
  269.    
  270. }