public final void applyAnnotation(T info, MetaData retrieval, MetaDataVisitor visitor)
      throws Throwable {
    boolean trace = log.isTraceEnabled();

    if (isCleanupOnly() == false) {
      Class<C> annotationClass = getAnnotation();
      C annotation = retrieval.getAnnotation(annotationClass);
      if (annotation == null) {
        if (trace) log.trace("No annotation: " + annotationClass.getName());
        return;
      }
      if (isMetaDataAlreadyPresent(info, annotation, visitor.getControllerContext())) {
        if (trace) log.trace("MetaDataAlreadyPresent, ignoring " + annotation);
        return;
      }
      if (trace) log.trace("Applying annotation: " + annotation);
      List<? extends MetaDataVisitorNode> nodes =
          internalApplyAnnotation(info, retrieval, annotation, visitor.getControllerContext());
      if (nodes != null && nodes.isEmpty() == false) {
        for (MetaDataVisitorNode node : nodes) {
          node.initialVisit(visitor);
          node.describeVisit(visitor);
        }
      }
    } else if (trace)
      log.trace("Annotation " + getAnnotation() + " is @CleanupOnly, nothing to apply on install.");
  }
  public void cleanAnnotation(T info, MetaData retrieval, MetaDataVisitor visitor)
      throws Throwable {
    boolean trace = log.isTraceEnabled();

    if (isCleanup()) {
      Class<C> annotationClass = getAnnotation();
      C annotation = retrieval.getAnnotation(annotationClass);
      if (annotation == null) {
        if (trace) log.trace("No annotation: " + annotationClass.getName());
      } else {
        if (trace) log.trace("Cleaning annotation: " + annotation);
        internalCleanAnnotation(info, retrieval, annotation, visitor.getControllerContext());
      }
    } else if (trace) log.trace("Annotation " + getAnnotation() + " is not a @Cleanup annotation.");
  }