/* (non-Javadoc)
   * @see edu.umd.cs.findbugs.ba.INullnessAnnotationDatabase#getResolvedAnnotation(java.lang.Object, boolean)
   */
  public NullnessAnnotation getResolvedAnnotation(Object o, boolean getMinimal) {
    Profiler profiler = Global.getAnalysisCache().getProfiler();
    profiler.start(this.getClass());
    try {

      if (DEBUG) {
        System.out.println("getResolvedAnnotation: o=" + o + "...");
      }

      TypeQualifierAnnotation tqa = null;

      if (o instanceof XMethodParameter) {
        XMethodParameter param = (XMethodParameter) o;

        tqa =
            TypeQualifierApplications.getEffectiveTypeQualifierAnnotation(
                param.getMethod(), param.getParameterNumber(), nonnullTypeQualifierValue);
      } else if (o instanceof XMethod || o instanceof XField) {
        tqa =
            TypeQualifierApplications.getEffectiveTypeQualifierAnnotation(
                (AnnotatedObject) o, nonnullTypeQualifierValue);
      }

      NullnessAnnotation result = toNullnessAnnotation(tqa);
      if (DEBUG) {
        System.out.println("   ==> " + (result != null ? result.toString() : "not found"));
      }
      return result;
    } finally {
      profiler.end(this.getClass());
    }
  }
  @CheckForNull
  @Override
  public NullnessAnnotation getResolvedAnnotation(final Object o, boolean getMinimal) {

    Profiler profiler = Global.getAnalysisCache().getProfiler();
    profiler.start(this.getClass());
    try {
      if (o instanceof XMethodParameter) {
        XMethodParameter mp = (XMethodParameter) o;
        XMethod m = mp.getMethod();
        // TODO: Handle argument to equals specially: generate special
        // bug code for it
        int parameterNumber = mp.getParameterNumber();
        if (parameterNumber == 0) {
          if (m.getName().equals("equals")
              && m.getSignature().equals("(Ljava/lang/Object;)Z")
              && !m.isStatic()) return NullnessAnnotation.CHECK_FOR_NULL;
          else if (m.getName().equals("main")
              && m.getSignature().equals("([Ljava/lang/String;)V")
              && m.isStatic()
              && m.isPublic()) return NullnessAnnotation.NONNULL;
          else if (assertsFirstParameterIsNonnull(m)) return NullnessAnnotation.NONNULL;
          else if (m.getName().equals("compareTo")
              && m.getSignature().endsWith(";)Z")
              && !m.isStatic()) return NullnessAnnotation.NONNULL;
        }
      } else if (o instanceof XMethod) {
        XMethod m = (XMethod) o;
        String name = m.getName();
        String signature = m.getSignature();
        if (!m.isStatic()
            && (name.equals("clone") && signature.equals("()Ljava/lang/Object;")
                || name.equals("toString") && signature.equals("()Ljava/lang/String;")
                || m.isPrivate()
                    && name.equals("readResolve")
                    && signature.equals("()Ljava/lang/Object;"))) {
          NullnessAnnotation result = super.getDirectAnnotation(m);
          if (result != null) return result;
          return NullnessAnnotation.NONNULL;
        }

      } else if (o instanceof XField) {
        XField f = (XField) o;
        if (f.getName().startsWith("this$")) return NullnessAnnotation.NONNULL;
      }
      NullnessAnnotation result = super.getResolvedAnnotation(o, getMinimal);
      return result;
    } finally {
      profiler.end(this.getClass());
    }
  }
  public When validate(Object constantValue) {
    if (validator == null) throw new IllegalStateException("No validator");
    IAnalysisCache analysisCache = Global.getAnalysisCache();
    Profiler profiler = analysisCache.getProfiler();
    profiler.start(validator.getClass());
    AtomicBoolean performing = performingValidation.get();
    try {
      if (!performing.compareAndSet(false, true)) {
        throw new IllegalStateException("recursive validation");
      }

      return validator.forConstantValue(proxy, constantValue);
    } catch (Exception e) {
      AnalysisContext.logError(
          "Error executing custom validator for " + typeQualifier + " " + constantValue, e);
      return When.UNKNOWN;
    } finally {
      if (!performing.compareAndSet(true, false)) {
        throw new IllegalStateException("performingValidation not set when validation completes");
      }
      profiler.end(validator.getClass());
    }
  }