JsonElement genJsonElement(TypeMirror t, Element el, Kind kind) {
      if (kind == null) {
        Log.e("invalid state. this is APT bugs.");
        encountError = true;
        return defaultAction(t, el);
      }

      JsonElement jsonElement = new JsonElement();
      jsonElement.setKey(getElementKeyString(el));

      JsonKey key = el.getAnnotation(JsonKey.class);

      String setter = getElementSetter(el);
      if (key.in() && setter == null) {
        Log.e("can't find setter method", el);
        encountError = true;
        return defaultAction(t, el);
      }

      String getter = getElementGetter(el);
      if (key.out() && getter == null) {
        Log.e("can't find getter method", el);
        encountError = true;
        return defaultAction(t, el);
      }

      String converterClassName = getConverterClassName(el);
      if (converterClassName != null) {
        TypeElement element = processingEnv.getElementUtils().getTypeElement(converterClassName);
        Log.d(element != null ? element.asType().toString() : null);
        if (element == null
            || !isMethodExists(element, "getInstance", Modifier.PUBLIC, Modifier.STATIC)) {
          Log.e("converter needs [public static getInstance()].", element);
        }
        kind = Kind.CONVERTER;
      }

      jsonElement.setIn(key.in());
      jsonElement.setSetter(setter);
      jsonElement.setOut(key.out());
      jsonElement.setGetter(getter);
      jsonElement.setModelName(t.toString());
      jsonElement.setKind(kind);
      jsonElement.setConverter(converterClassName);

      return jsonElement;
    }
 String getElementKeyString(Element element) {
   JsonKey key = element.getAnnotation(JsonKey.class);
   JsonModel model = element.getEnclosingElement().getAnnotation(JsonModel.class);
   String keyStr;
   if (!"".equals(key.value())) {
     keyStr = key.value();
   } else if ("".equals(key.value()) && key.decamelize()) {
     keyStr = decamelize(element.toString());
   } else if ("".equals(key.value()) && model.decamelize()) {
     keyStr = decamelize(element.toString());
   } else {
     keyStr = element.toString();
   }
   return keyStr;
 }
    @Override
    public JsonElement visitList(DeclaredType t, Element el) {

      JsonElement jsonElement;

      String converterClassName = getConverterClassName(el);
      if (converterClassName != null) {
        jsonElement = genJsonElement(t, el, Kind.CONVERTER);

      } else {

        List<? extends TypeMirror> generics = t.getTypeArguments();
        if (generics.size() != 1) {
          Log.e("expected single type generics.", el);
          encountError = true;
          return defaultAction(t, el);
        }
        TypeMirror tm = generics.get(0);
        if (tm instanceof WildcardType) {
          WildcardType wt = (WildcardType) tm;
          TypeMirror extendsBound = wt.getExtendsBound();
          if (extendsBound != null) {
            tm = extendsBound;
          }
          TypeMirror superBound = wt.getSuperBound();
          if (superBound != null) {
            Log.e("super is not supported.", el);
            encountError = true;
            return defaultAction(t, el);
          }
        }

        Element type = processingEnv.getTypeUtils().asElement(tm);
        JsonModel hash = type.getAnnotation(JsonModel.class);
        if (hash == null) {
          Log.e("expect for use decorated class by JsonModel annotation.", el);
          encountError = true;
          return defaultAction(t, el);
        }

        jsonElement = new JsonElement();
        jsonElement.setKey(getElementKeyString(el));

        JsonKey key = el.getAnnotation(JsonKey.class);

        String setter = getElementSetter(el);
        if (key.in() && setter == null) {
          Log.e("can't find setter method", el);
          encountError = true;
          return defaultAction(t, el);
        }

        String getter = getElementGetter(el);
        if (key.out() && getter == null) {
          Log.e("can't find getter method", el);
          encountError = true;
          return defaultAction(t, el);
        }

        jsonElement.setIn(key.in());
        jsonElement.setSetter(setter);
        jsonElement.setOut(key.out());
        jsonElement.setGetter(getter);
        jsonElement.setModelName(tm.toString());
        jsonElement.setKind(Kind.LIST);
      }

      return jsonElement;
    }