Open Source Repository

Home /jodd/jodd-3.3.2 | Repository Home



jodd/util/AnnotationDataReader.java
// Copyright (c) 2003-2012, Jodd Team (jodd.org). All Rights Reserved.

package jodd.util;

import jodd.typeconverter.Convert;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;

/**
 * Annotation reader that reads an annotation and returns annotation data object filled
 * with annotation element values. May be used when having two or more annotations with
 * same elements - since java doesn't support annotation inheritance.
 */
public abstract class AnnotationDataReader<A extends Annotation, D extends AnnotationDataReader.AnnotationData<A>> {

  protected final Class<A> annotationClass;

  // ---------------------------------------------------------------- ctor

  /**
   * Creates new annotation data reader using annotation definition
   * from class generics.
   */
  @SuppressWarnings( {"unchecked"})
  protected AnnotationDataReader() {
    annotationClass = ReflectUtil.getGenericSupertype(this.getClass());
    if (annotationClass == null) {
      throw new IllegalArgumentException("Unable to resolve annotation from generic supertype.");
    }
  }

  /**
   * Creates new annotation data reader using provided annotation class.
   */
  protected AnnotationDataReader(Class<A> annotationClass) {
    this.annotationClass = annotationClass;
  }


  // ---------------------------------------------------------------- methods

  /**
   * Returns annotation class.
   */
  public Class<A> getAnnotationClass() {
    return annotationClass;
  }

  /**
   * Returns <code>true</code> if annotation is present on
   * given accessible object.
   */
  public boolean hasAnnotation(AccessibleObject accessibleObject) {
    return accessibleObject.isAnnotationPresent(annotationClass);
  }

  /**
   * Reads {@link AnnotationData annotation data} on provided accessible object.
   * If annotation is not presented, <code>null</code> is returned.
   */
  public D readAnnotationData(AccessibleObject accessibleObject) {

    A annotation = accessibleObject.getAnnotation(annotationClass);
    if (annotation == null) {
      return null;
    }

    return createAnnotationData(annotation);
  }

  /**
   * Creates annotation data from given annotation.
   */
  protected abstract D createAnnotationData(A annotation);

  // ---------------------------------------------------------------- read

  /**
   * Reads non-empty, trimmed, annotation element value. If annotation value is
   * an empty string, returns <code>null</code>.
   */
  protected String readStringElement(A annotation, String name) {
    String value = Convert.toString(ReflectUtil.readAnnotationValue(annotation, name));
    if (value != null) {
      value = value.trim();
      if (value.length() == 0) {
        value = null;
      }
    }
    return value;
  }

  /**
   * Reads annotation element as an object.
   */
  protected Object readElement(A annotation, String name) {
    return ReflectUtil.readAnnotationValue(annotation, name);
  }


  // ---------------------------------------------------------------- annotation data

  /**
   * Base class for annotation data, for holding annotation elements values.
   */
  public abstract static class AnnotationData<N extends Annotation> {

    protected final N annotation;

    protected AnnotationData(N annotation) {
      this.annotation = annotation;
    }

    /**
     * Returns annotation.
     */
    public N getAnnotation() {
      return annotation;
    }
  }
}