private static Mapper.Builder<?, ?> createBuilderFromFieldType(
     final ParseContext context, MappedFieldType fieldType, String currentFieldName) {
   Mapper.Builder builder = null;
   if (fieldType instanceof StringFieldType) {
     builder = context.root().findTemplateBuilder(context, currentFieldName, "string");
     if (builder == null) {
       builder = MapperBuilders.stringField(currentFieldName);
     }
   } else if (fieldType instanceof DateFieldType) {
     builder = context.root().findTemplateBuilder(context, currentFieldName, "date");
     if (builder == null) {
       builder = MapperBuilders.dateField(currentFieldName);
     }
   } else if (fieldType.numericType() != null) {
     switch (fieldType.numericType()) {
       case LONG:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "long");
         if (builder == null) {
           builder = MapperBuilders.longField(currentFieldName);
         }
         break;
       case DOUBLE:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "double");
         if (builder == null) {
           builder = MapperBuilders.doubleField(currentFieldName);
         }
         break;
       case INT:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "integer");
         if (builder == null) {
           builder = MapperBuilders.integerField(currentFieldName);
         }
         break;
       case FLOAT:
         builder = context.root().findTemplateBuilder(context, currentFieldName, "float");
         if (builder == null) {
           builder = MapperBuilders.floatField(currentFieldName);
         }
         break;
       default:
         throw new AssertionError("Unexpected numeric type " + fieldType.numericType());
     }
   }
   return builder;
 }
  private static Mapper.Builder<?, ?> createBuilderFromDynamicValue(
      final ParseContext context, XContentParser.Token token, String currentFieldName)
      throws IOException {
    if (token == XContentParser.Token.VALUE_STRING) {
      // do a quick test to see if its fits a dynamic template, if so, use it.
      // we need to do it here so we can handle things like attachment templates, where calling
      // text (to see if its a date) causes the binary value to be cleared
      {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "string", null);
        if (builder != null) {
          return builder;
        }
      }

      if (context.root().dateDetection()) {
        String text = context.parser().text();
        // a safe check since "1" gets parsed as well
        if (Strings.countOccurrencesOf(text, ":") > 1
            || Strings.countOccurrencesOf(text, "-") > 1
            || Strings.countOccurrencesOf(text, "/") > 1) {
          for (FormatDateTimeFormatter dateTimeFormatter :
              context.root().dynamicDateTimeFormatters()) {
            try {
              dateTimeFormatter.parser().parseMillis(text);
              Mapper.Builder builder =
                  context.root().findTemplateBuilder(context, currentFieldName, "date");
              if (builder == null) {
                builder =
                    MapperBuilders.dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter);
              }
              return builder;
            } catch (Exception e) {
              // failure to parse this, continue
            }
          }
        }
      }
      if (context.root().numericDetection()) {
        String text = context.parser().text();
        try {
          Long.parseLong(text);
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "long");
          if (builder == null) {
            builder = MapperBuilders.longField(currentFieldName);
          }
          return builder;
        } catch (NumberFormatException e) {
          // not a long number
        }
        try {
          Double.parseDouble(text);
          Mapper.Builder builder =
              context.root().findTemplateBuilder(context, currentFieldName, "double");
          if (builder == null) {
            builder = MapperBuilders.doubleField(currentFieldName);
          }
          return builder;
        } catch (NumberFormatException e) {
          // not a long number
        }
      }
      Mapper.Builder builder =
          context.root().findTemplateBuilder(context, currentFieldName, "string");
      if (builder == null) {
        builder = MapperBuilders.stringField(currentFieldName);
      }
      return builder;
    } else if (token == XContentParser.Token.VALUE_NUMBER) {
      XContentParser.NumberType numberType = context.parser().numberType();
      if (numberType == XContentParser.NumberType.INT
          || numberType == XContentParser.NumberType.LONG) {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "long");
        if (builder == null) {
          builder = MapperBuilders.longField(currentFieldName);
        }
        return builder;
      } else if (numberType == XContentParser.NumberType.FLOAT
          || numberType == XContentParser.NumberType.DOUBLE) {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "double");
        if (builder == null) {
          // no templates are defined, we use float by default instead of double
          // since this is much more space-efficient and should be enough most of
          // the time
          builder = MapperBuilders.floatField(currentFieldName);
        }
        return builder;
      }
    } else if (token == XContentParser.Token.VALUE_BOOLEAN) {
      Mapper.Builder builder =
          context.root().findTemplateBuilder(context, currentFieldName, "boolean");
      if (builder == null) {
        builder = MapperBuilders.booleanField(currentFieldName);
      }
      return builder;
    } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
      Mapper.Builder builder =
          context.root().findTemplateBuilder(context, currentFieldName, "binary");
      if (builder == null) {
        builder = MapperBuilders.binaryField(currentFieldName);
      }
      return builder;
    } else {
      Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, null);
      if (builder != null) {
        return builder;
      }
    }
    // TODO how do we identify dynamically that its a binary value?
    throw new IllegalStateException(
        "Can't handle serializing a dynamic type with content token ["
            + token
            + "] and field name ["
            + currentFieldName
            + "]");
  }