private static void mapEntity(
      XContentBuilder xContentBuilder,
      Class clazz,
      boolean isRootObject,
      String idFieldName,
      String nestedObjectFieldName)
      throws IOException {

    java.lang.reflect.Field[] fields = clazz.getDeclaredFields();

    if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) {
      xContentBuilder
          .startObject(nestedObjectFieldName)
          .field(FIELD_TYPE, TYPE_VALUE_OBJECT)
          .startObject(FIELD_PROPERTIES);
    }

    for (java.lang.reflect.Field field : fields) {

      if (field.isAnnotationPresent(Transient.class)) {
        continue;
      }

      if (isEntity(field) && !isInIgnoreFields(field)) {
        mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
      }

      Field singleField = field.getAnnotation(Field.class);
      MultiField multiField = field.getAnnotation(MultiField.class);
      GeoPointField geoPoint = field.getAnnotation(GeoPointField.class);

      if (field.getType() == GeoPoint.class || geoPoint != null) {
        applyGeoPointFieldMapping(xContentBuilder, field);
      }

      if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
        applyDefaultIdFieldMapping(xContentBuilder, field);
      } else if (multiField != null) {
        addMultiFieldMapping(xContentBuilder, field, multiField);
      } else if (singleField != null) {
        addSingleFieldMapping(xContentBuilder, field, singleField);
      }
    }

    if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) {
      xContentBuilder.endObject().endObject();
    }
  }
 private static boolean isEntity(java.lang.reflect.Field field) {
   TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
   TypeInformation<?> actualType = typeInformation.getActualType();
   boolean isComplexType =
       actualType == null ? false : !SIMPLE_TYPE_HOLDER.isSimpleType(actualType.getType());
   return isComplexType
       && !actualType.isCollectionLike()
       && !Map.class.isAssignableFrom(typeInformation.getType());
 }