public static boolean checkIfAnnotationValueAttributeIsEntity(
      AnnotationMirror mirror, String attributeName, EclipseMessager messager) {
    Map<AnnotationTypeElementDeclaration, AnnotationValue> valueMap = mirror.getElementValues();
    Set<Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue>> valueSet =
        valueMap.entrySet();

    for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> annoKeyValue : valueSet) {
      if (annoKeyValue.getKey().getSimpleName().equals(attributeName)) {
        ClassDeclaration annoValue = (ClassDeclaration) annoKeyValue.getValue().getValue();
        Entity entityAnnotation = annoValue.getAnnotation(Entity.class);
        if (entityAnnotation == null) {
          SourcePosition pos = annoKeyValue.getValue().getPosition();
          messager.printError(
              pos,
              "'"
                  + attributeName
                  + "' attribute value class should be annotated with 'javax.persistence.Entity'");
          return false;
        }
      }
    }
    return true;
  }
  private void processSuperclass(Thing data, Map<String, AnnotationValue> beanValues) {
    AnnotationValue value = beanValues.get("superclass");
    data.put("superclass", null);
    data.put("genericDecls", "");
    data.put("classModifiers", "");
    data.put("propertyNameConstantsInherited", false);
    data.put("getPropertyChangeSupportInherited", false);
    data.put("getPropertyChangeSupportModifiers", "protected");
    data.put("paramStringInherited", false);
    data.put("paramStringModifiers", "protected");
    data.put("createPropertyMapInherited", false);
    data.put("createPropertyMapModifiers", "public");
    data.put("atLeastOneDouble", false);
    data.put("atLeastOneBound", false);
    data.put("atLeastOneObject", false);
    data.put("atLeastOneDefault", false);

    if (value == null) {
      data.setEmpty("superclassConstructors");
    } else {
      if (!(value.getValue() instanceof ClassDeclaration)) {
        error(value, "superclass must be a class");
        return;
      }
      ClassDeclaration superclass = (ClassDeclaration) value.getValue();
      data.put("superclass", superclass.getQualifiedName());
      boolean hasProperties = !l(beanValues, "properties").isEmpty();
      // check if getPropertyChangeSupport or some superclass defines bound properties in @Bean
      checkInheritedMethod(
          data,
          "getPropertyChangeSupport",
          "java.beans.PropertyChangeSupport",
          superclass,
          true,
          new InheritCheck() {
            @Override
            public boolean isInherited(Thing d, ClassDeclaration classDeclaration) {
              Bean beanAnn = classDeclaration.getAnnotation(Bean.class);
              if (beanAnn != null) {
                Property[] properties = beanAnn.properties();
                for (Property property : properties) {
                  if (property.bound()) {
                    d.put("getPropertyChangeSupportInherited", true);
                    d.put("getPropertyChangeSupportModifiers", "protected");
                    return true;
                  }
                }
              }
              return false;
            }
          });
      // check if paramString inherited or some superclass has @Bean
      checkInheritedMethod(
          data,
          "paramString",
          "java.lang.String",
          superclass,
          !hasProperties,
          new InheritCheck() {
            @Override
            public boolean isInherited(Thing d, ClassDeclaration classDeclaration) {
              if (classDeclaration.getAnnotation(Bean.class) != null) {
                d.put("paramStringInherited", true);
                d.put("paramStringModifiers", "protected");
                return true;
              }
              return false;
            }
          });
      // check if createPropertyMap inherited or some superclass has @Bean with
      // defineCreatePropertyMap
      checkInheritedMethod(
          data,
          "createPropertyMap",
          "java.lang.String",
          superclass,
          !hasProperties,
          new InheritCheck() {
            @Override
            public boolean isInherited(Thing d, ClassDeclaration classDeclaration) {
              Bean beanAnn = classDeclaration.getAnnotation(Bean.class);
              if (beanAnn != null && beanAnn.defineCreatePropertyMap()) {
                d.put("createPropertyMapInherited", true);
                d.put("createPropertyMapModifiers", "public");
                return true;
              }
              return false;
            }
          });

      String genericDecls = null;
      Collection<TypeParameterDeclaration> formalTypeParameters2 =
          superclass.getFormalTypeParameters();
      for (TypeParameterDeclaration typeParameterDeclaration : formalTypeParameters2) {
        genericDecls = addWithCommasBetween(genericDecls, typeParameterDeclaration);
      }
      if (genericDecls == null) {
        genericDecls = "";
      } else {
        genericDecls = '<' + genericDecls + '>';
      }
      data.put("genericDecls", genericDecls);

      String classModifiers = "";
      for (Modifier modifier : superclass.getModifiers()) {
        if (!"abstract".equals(modifier.toString())) {
          classModifiers += modifier.toString() + ' ';
        }
      }
      data.put("classModifiers", classModifiers);

      Collection<ConstructorDeclaration> constructors = superclass.getConstructors();
      if (constructors.isEmpty()) {
        data.setEmpty("superclassConstructors");
      } else {
        for (ConstructorDeclaration constructorDeclaration : constructors) {
          data.add("superclassConstructors", setupMethod(constructorDeclaration, false));
        }
      }

      boolean extendPropertyNameConstants = false;
      if (b(beanValues, "definePropertyNameConstants")) {
        // if superclass has a PropertyNameConstants interface or a Bean annotation with
        //     definePropertyNameConstants=true, we need to have our PropertyNameConstants
        //     extend it
        Collection<TypeDeclaration> nestedTypes = superclass.getNestedTypes();
        for (TypeDeclaration typeDeclaration : nestedTypes) {
          if ("PropertyNames".equals(typeDeclaration.getSimpleName())
              && (typeDeclaration instanceof InterfaceDeclaration)) {
            extendPropertyNameConstants = true;
          }
        }
        if (!extendPropertyNameConstants) {
          // check if the superclass is annotated with Bean
          Bean annotation = superclass.getAnnotation(Bean.class);
          if (annotation != null) {
            extendPropertyNameConstants = annotation.definePropertyNameConstants();
          }
        }
      }
      data.put("propertyNameConstantsInherited", extendPropertyNameConstants);
    }
  }