private boolean b(Map<String, AnnotationValue> values, String name) {
   AnnotationValue annotationValue = values.get(name);
   if (annotationValue == null) {
     return false;
   }
   return ((Boolean) annotationValue.getValue()).booleanValue();
 }
 //	private String s(Map<String, AnnotationValue> values, String name, String def) {
 //		AnnotationValue annotationValue = values.get(name);
 //		if (annotationValue == null) {
 //			return def;
 //		}
 //		return (String) annotationValue.getValue();
 //	}
 private int i(Map<String, AnnotationValue> values, String name, int def) {
   AnnotationValue annotationValue = values.get(name);
   if (annotationValue == null) {
     return def;
   }
   return ((Integer) annotationValue.getValue()).intValue();
 }
 private List<AnnotationValue> l(Map<String, AnnotationValue> values, String name) {
   AnnotationValue annotationValue = values.get(name);
   if (annotationValue == null) {
     return Collections.emptyList();
   }
   @SuppressWarnings("unchecked")
   List<AnnotationValue> value = (List<AnnotationValue>) annotationValue.getValue();
   return value;
 }
 private void setValue(Thing data, Map<String, AnnotationValue> values, String name, Object def) {
   AnnotationValue annotationValue = values.get(name);
   if (annotationValue == null) {
     if (def != null) {
       data.put(name, def);
     }
   } else {
     data.put(name, annotationValue.getValue());
   }
 }
  private static boolean checkTransferInfoType(
      AnnotationValue annotationValue, EclipseMessager messager) {
    AnnotationMirror mirror = (AnnotationMirror) annotationValue.getValue();
    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("type")) {
        String annoValue = (String) annoKeyValue.getValue().getValue();
        if (annoValue != null && annoValue.trim().length() == 0) {
          SourcePosition pos = annoKeyValue.getValue().getPosition();
          messager.printError(pos, TYPE_ATTRIBUTE_SHOULD_BE_NOT_EMPTY);
        }
        return false;
      }
    }
    return true;
  }
  //	private AnnotationValue get(Map<String, AnnotationValue> values, String name, AnnotationValue
  // def) {
  //		AnnotationValue value = values.get(name);
  //		if (value != null)
  //			return value;
  //		return def;
  //	}
  private void processProperties(Thing data, Map<String, AnnotationValue> beanValues) {
    boolean atLeastOneBound = false;
    boolean atLeastOneDouble = false;
    boolean atLeastOneObject = false;
    String firstPropertyName = null;
    AnnotationValue propertiesValue = beanValues.get("properties");
    if (propertiesValue == null) {
      data.setEmpty("properties");
    } else {
      Set<String> propertyNames = new HashSet<String>();
      AnnotationValue defaultType = null;
      AnnotationValue defaultTypeString = null;
      AnnotationValue defaultKeyType = null;
      AnnotationValue defaultKeyTypeString = null;
      AnnotationValue defaultReader = null;
      AnnotationValue defaultWriter = null;
      AnnotationValue defaultBound = null;
      AnnotationValue defaultKind = null;
      AnnotationValue defaultOmitFromToString = null;
      AnnotationValue defaultNotNull = null;
      AnnotationValue defaultIsStatic = null;
      AnnotationValue defaultIsSynchronized = null;

      @SuppressWarnings("unchecked")
      List<AnnotationValue> properties = (List<AnnotationValue>) propertiesValue.getValue();
      for (AnnotationValue annotationValue : properties) {
        AnnotationMirror propertyMirror = (AnnotationMirror) annotationValue.getValue();
        Map<String, AnnotationValue> propertyValues = getAnnotationValues(propertyMirror);
        AnnotationValue name = propertyValues.get("name");
        AnnotationValue plural = propertyValues.get("plural");
        AnnotationValue type = propertyValues.get("type");
        AnnotationValue typeString = propertyValues.get("typeString");
        AnnotationValue keyType = propertyValues.get("keyType");
        AnnotationValue keyTypeString = propertyValues.get("keyTypeString");
        AnnotationValue reader = propertyValues.get("reader");
        AnnotationValue writer = propertyValues.get("writer");
        AnnotationValue bound = propertyValues.get("bound");
        AnnotationValue kind = propertyValues.get("kind");
        AnnotationValue omitFromToString = propertyValues.get("omitFromToString");
        AnnotationValue notNull = propertyValues.get("notNull");
        AnnotationValue isStatic = propertyValues.get("isStatic");
        AnnotationValue isSynchronized = propertyValues.get("isSynchronized");

        if (Property.DEFAULTS.equals(name.getValue())) {
          defaultType = type;
          defaultTypeString = typeString;
          defaultKeyType = keyType;
          defaultKeyTypeString = keyTypeString;
          defaultReader = reader;
          defaultWriter = writer;
          defaultBound = bound;
          defaultKind = kind;
          defaultOmitFromToString = omitFromToString;
          defaultNotNull = notNull;
          defaultIsStatic = isStatic;
          defaultIsSynchronized = isSynchronized;
          continue;
        }

        // plugin the default values
        if (type == null && typeString == null) {
          type = defaultType;
          typeString = defaultTypeString;
        }
        if (keyType == null && keyTypeString == null) {
          keyType = defaultKeyType;
          keyTypeString = defaultKeyTypeString;
        }
        if (reader == null) {
          reader = defaultReader;
        }
        if (writer == null) {
          writer = defaultWriter;
        }
        if (bound == null) {
          bound = defaultBound;
        }
        if (kind == null) {
          kind = defaultKind;
        }
        if (omitFromToString == null) {
          omitFromToString = defaultOmitFromToString;
        }
        if (notNull == null) {
          notNull = defaultNotNull;
        }
        if (isStatic == null) {
          isStatic = defaultIsStatic;
        }
        if (isSynchronized == null) {
          isSynchronized = defaultIsSynchronized;
        }

        Thing property = new Thing("property");
        property.put("name", name.getValue());

        if (typeString == null) {
          if (type == null) {
            property.put("type", "java.lang.String");
          } else {
            if (type.getValue() instanceof TypeDeclaration) {
              property.put("type", ((TypeDeclaration) type.getValue()).getQualifiedName());
            } else {
              property.put("type", ((PrimitiveType) type.getValue()).toString());
            }
          }
        } else {
          if (type != null) {
            String message = "@Property cannot have both type and typeString attributes specified";
            error(typeString, message);
            error(type, message);
            property.put("type", "<ERROR>");
          } else {
            property.put("type", typeString.getValue());
          }
        }

        PropertyKind propertyKind = PropertyKind.SIMPLE;
        if (kind != null) {
          propertyKind = PropertyKind.valueOf(kind.getValue().toString());
        }

        // check for duplicate keytype specifications
        if (propertyKind.isMap()) {
          if (keyTypeString == null) {
            if (keyType == null) {
              property.put("keyType", "java.lang.String");
            } else {
              property.put("keyType", ((TypeDeclaration) keyType.getValue()).getQualifiedName());
            }
          } else if (keyType != null) {
            String message =
                "@Property cannot have both keyType and keyTypeString attributes specified";
            error(keyType, message);
            error(keyTypeString, message);
            property.put("keyType", "<ERROR>");
          }
        } else {
          if (keyTypeString != null) {
            error(
                keyTypeString,
                "@Property can only have a keyTypeString attribute if kind is MAP or UNMODIFIABLE_MAP");
          }
          if (keyType != null) {
            error(
                keyType,
                "@Property can only have a keyType attribute if kind is MAP or UNMODIFIABLE_MAP");
          }
          property.put("keyType", "<ERROR>");
        }

        // check for plural names
        if (propertyKind.isSimple()) {
          if (plural != null) {
            error(plural, "@Property cannot have plural specified if kind is SIMPLE");
          }
          property.put("pluralName", null);
        } else {
          if (plural == null) {
            property.put("pluralName", name.getValue() + "s");
          } else {
            property.put("pluralName", plural.getValue());
          }
        }

        property.put("simple", propertyKind.isSimple());
        property.put("list", propertyKind.isList());
        property.put("map", propertyKind.isMap());
        property.put("set", propertyKind.isSet());
        String typeName = (String) property.get("type");

        property.put("float", "float".equals(typeName));
        property.put("double", "double".equals(typeName));
        property.put("boolean", "boolean".equals(typeName));
        property.put("char", "char".equals(typeName));
        property.put("byte", "byte".equals(typeName));
        property.put("long", "long".equals(typeName));
        property.put("int", "int".equals(typeName));
        property.put("short", "short".equals(typeName));

        if (property.containsKey("firstPropertyName")) {
          property.put("firstPropertyName", name.getValue());
        }
        if (propertyNames.contains(name.getValue())) {
          error(
              name,
              "Duplicate property name '" + name + "' specified for @Bean properties definition");
        } else {
          propertyNames.add((String) name.getValue());
        }

        if (bound != null) {
          if (isStatic != null) {
            error(bound, "Static properties cannot be declared bound");
            error(isStatic, "Static properties cannot be declared bound");
          } else {
            atLeastOneBound = true;
          }
        }

        if ("double".equals(property.get("type"))) {
          data.put("atLeastOneDouble", true);
        }
        property.put("kind", propertyKind);
        property.put("omitFromToString", b(omitFromToString));
        data.add("properties", property);

        // evil hack to get the type, which is a Class

        boolean isPrimitive =
            BeanAnnotationProcessor.PRIMITIVE_TYPES.contains(property.get("type"));
        property.put("primitive", isPrimitive);

        if (!isPrimitive) {
          data.put("atLeastOneObject", true);
        }

        property.put("bound", b(bound));
        if (writer == null) {
          property.put("writerAccess", Access.PUBLIC.getModifier());
          property.put("writeable", true);
        } else {
          EnumConstantDeclaration writerValue = (EnumConstantDeclaration) writer.getValue();
          Access writerAccess = Access.valueOf(writerValue.toString());
          property.put("writerAccess", writerAccess.getModifier());
          property.put("writeable", writerAccess != Access.NONE);
        }
        if (reader == null) {
          property.put("readerAccess", Access.PUBLIC.getModifier());
          property.put("readable", true);
        } else {
          EnumConstantDeclaration readerValue = (EnumConstantDeclaration) reader.getValue();
          Access readerAccess = Access.valueOf(readerValue.toString());
          property.put("readerAccess", readerAccess.getModifier());
          property.put("readable", readerAccess != Access.NONE);
        }

        boolean bNotNull = b(notNull);
        boolean bIsStatic = b(isStatic);
        boolean bIsSynchronized = b(isSynchronized);
        property.put("notNull", bNotNull);

        if (bNotNull && isPrimitive) {
          error(
              notNull,
              "Cannot specify notNull for primitive-typed property "
                  + name.getValue()
                  + " in @Property");
        }
        String extraFieldKeywords = "";
        String extraMethodKeywords = "";
        if (bIsStatic) {
          extraFieldKeywords = "static ";
          extraMethodKeywords = "static ";
        }
        if (bIsSynchronized) {
          if (bIsStatic) {
            extraMethodKeywords += "synchronized ";
          } else {
            extraMethodKeywords = "synchronized ";
          }
        }
        property.put("extraFieldKeywords", extraFieldKeywords);
        property.put("extraMethodKeywords", extraMethodKeywords);
        property.checkAllValuesSet(propertiesValue, this);
      }
    }
    data.put(
        "definePropertyChangeSupport",
        !((Boolean) data.get("getPropertyChangeSupportInherited")) && atLeastOneBound);
    data.put("atLeastOneDouble", atLeastOneDouble);
    data.put("atLeastOneObject", atLeastOneObject);
    data.put("firstPropertyName", firstPropertyName);
  }
  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);
    }
  }
 private boolean b(AnnotationValue value) {
   if (value == null) {
     return false;
   }
   return ((Boolean) value.getValue()).booleanValue();
 }