@Override
  public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
    builder.startObject(simpleName()).field(Fields.TYPE, CONTENT_TYPE);

    builder.field(Fields.ANALYZER, fieldType().indexAnalyzer().name());
    if (fieldType().indexAnalyzer().name().equals(fieldType().searchAnalyzer().name()) == false) {
      builder.field(Fields.SEARCH_ANALYZER.getPreferredName(), fieldType().searchAnalyzer().name());
    }
    builder.field(Fields.PAYLOADS, fieldType().analyzingSuggestLookupProvider.hasPayloads());
    builder.field(
        Fields.PRESERVE_SEPARATORS.getPreferredName(),
        fieldType().analyzingSuggestLookupProvider.getPreserveSep());
    builder.field(
        Fields.PRESERVE_POSITION_INCREMENTS.getPreferredName(),
        fieldType().analyzingSuggestLookupProvider.getPreservePositionsIncrements());
    builder.field(Fields.MAX_INPUT_LENGTH.getPreferredName(), this.maxInputLength);
    multiFields.toXContent(builder, params);

    if (fieldType().requiresContext()) {
      builder.startObject(Fields.CONTEXT);
      for (ContextMapping mapping : fieldType().getContextMapping().values()) {
        builder.value(mapping);
      }
      builder.endObject();
    }

    return builder.endObject();
  }
  @Override
  public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
    builder.startObject(name()).field(Fields.TYPE, CONTENT_TYPE);
    if (indexAnalyzer.name().equals(searchAnalyzer.name())) {
      builder.field(Fields.ANALYZER, indexAnalyzer.name());
    } else {
      builder
          .field(Fields.INDEX_ANALYZER.getPreferredName(), indexAnalyzer.name())
          .field(Fields.SEARCH_ANALYZER.getPreferredName(), searchAnalyzer.name());
    }
    builder.field(Fields.PAYLOADS, this.payloads);
    builder.field(Fields.PRESERVE_SEPARATORS.getPreferredName(), this.preserveSeparators);
    builder.field(
        Fields.PRESERVE_POSITION_INCREMENTS.getPreferredName(), this.preservePositionIncrements);
    builder.field(Fields.MAX_INPUT_LENGTH.getPreferredName(), this.maxInputLength);
    multiFields.toXContent(builder, params);

    if (!contextMapping.isEmpty()) {
      builder.startObject(Fields.CONTEXT);
      for (ContextMapping mapping : contextMapping.values()) {
        builder.value(mapping);
      }
      builder.endObject();
    }

    return builder.endObject();
  }
    @Override
    public Mapper.Builder<?, ?> parse(
        String name, Map<String, Object> node, ParserContext parserContext)
        throws MapperParsingException {
      CompletionFieldMapper.Builder builder = completionField(name);
      for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator();
          iterator.hasNext(); ) {
        Map.Entry<String, Object> entry = iterator.next();
        String fieldName = entry.getKey();
        Object fieldNode = entry.getValue();
        if (fieldName.equals("type")) {
          continue;
        }
        if (fieldName.equals("analyzer")) {
          NamedAnalyzer analyzer = getNamedAnalyzer(parserContext, fieldNode.toString());
          builder.indexAnalyzer(analyzer);
          builder.searchAnalyzer(analyzer);
          iterator.remove();
        } else if (Fields.INDEX_ANALYZER.match(fieldName)) {
          builder.indexAnalyzer(getNamedAnalyzer(parserContext, fieldNode.toString()));
          iterator.remove();
        } else if (Fields.SEARCH_ANALYZER.match(fieldName)) {
          builder.searchAnalyzer(getNamedAnalyzer(parserContext, fieldNode.toString()));
          iterator.remove();
        } else if (fieldName.equals(Fields.PAYLOADS)) {
          builder.payloads(Boolean.parseBoolean(fieldNode.toString()));
          iterator.remove();
        } else if (Fields.PRESERVE_SEPARATORS.match(fieldName)) {
          builder.preserveSeparators(Boolean.parseBoolean(fieldNode.toString()));
          iterator.remove();
        } else if (Fields.PRESERVE_POSITION_INCREMENTS.match(fieldName)) {
          builder.preservePositionIncrements(Boolean.parseBoolean(fieldNode.toString()));
          iterator.remove();
        } else if (Fields.MAX_INPUT_LENGTH.match(fieldName)) {
          builder.maxInputLength(Integer.parseInt(fieldNode.toString()));
          iterator.remove();
        } else if ("fields".equals(fieldName) || "path".equals(fieldName)) {
          if (parseMultiField(builder, name, parserContext, fieldName, fieldNode)) {
            iterator.remove();
          }
        } else if (fieldName.equals(Fields.CONTEXT)) {
          builder.contextMapping(
              ContextBuilder.loadMappings(fieldNode, parserContext.indexVersionCreated()));
          iterator.remove();
        }
      }

      if (builder.searchAnalyzer == null) {
        builder.searchAnalyzer(parserContext.analysisService().analyzer("simple"));
      }

      if (builder.indexAnalyzer == null) {
        builder.indexAnalyzer(parserContext.analysisService().analyzer("simple"));
      }
      // we are just using this as the default to be wrapped by the CompletionPostingsFormatProvider
      // in the SuggesteFieldMapper ctor
      builder.postingsFormat(parserContext.postingFormatService().get("default"));
      return builder;
    }
 public Builder maxInputLength(int maxInputLength) {
   if (maxInputLength <= 0) {
     throw new IllegalArgumentException(
         Fields.MAX_INPUT_LENGTH.getPreferredName()
             + " must be > 0 but was ["
             + maxInputLength
             + "]");
   }
   this.maxInputLength = maxInputLength;
   return this;
 }
    @Override
    public Mapper.Builder<?, ?> parse(
        String name, Map<String, Object> node, ParserContext parserContext)
        throws MapperParsingException {
      CompletionFieldMapper.Builder builder = completionField(name);
      NamedAnalyzer indexAnalyzer = null;
      NamedAnalyzer searchAnalyzer = null;
      for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator();
          iterator.hasNext(); ) {
        Map.Entry<String, Object> entry = iterator.next();
        String fieldName = entry.getKey();
        Object fieldNode = entry.getValue();
        if (fieldName.equals("type")) {
          continue;
        }
        if (Fields.ANALYZER.equals(fieldName)
            || // index_analyzer is for backcompat, remove for v3.0
            fieldName.equals("index_analyzer")
                && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {

          indexAnalyzer = getNamedAnalyzer(parserContext, fieldNode.toString());
          iterator.remove();
        } else if (Fields.SEARCH_ANALYZER.match(fieldName)) {
          searchAnalyzer = getNamedAnalyzer(parserContext, fieldNode.toString());
          iterator.remove();
        } else if (fieldName.equals(Fields.PAYLOADS)) {
          builder.payloads(Boolean.parseBoolean(fieldNode.toString()));
          iterator.remove();
        } else if (Fields.PRESERVE_SEPARATORS.match(fieldName)) {
          builder.preserveSeparators(Boolean.parseBoolean(fieldNode.toString()));
          iterator.remove();
        } else if (Fields.PRESERVE_POSITION_INCREMENTS.match(fieldName)) {
          builder.preservePositionIncrements(Boolean.parseBoolean(fieldNode.toString()));
          iterator.remove();
        } else if (Fields.MAX_INPUT_LENGTH.match(fieldName)) {
          builder.maxInputLength(Integer.parseInt(fieldNode.toString()));
          iterator.remove();
        } else if (parseMultiField(builder, name, parserContext, fieldName, fieldNode)) {
          iterator.remove();
        } else if (fieldName.equals(Fields.CONTEXT)) {
          builder.contextMapping(
              ContextBuilder.loadMappings(fieldNode, parserContext.indexVersionCreated()));
          iterator.remove();
        }
      }

      if (indexAnalyzer == null) {
        if (searchAnalyzer != null) {
          throw new MapperParsingException(
              "analyzer on completion field ["
                  + name
                  + "] must be set when search_analyzer is set");
        }
        indexAnalyzer = searchAnalyzer = parserContext.analysisService().analyzer("simple");
      } else if (searchAnalyzer == null) {
        searchAnalyzer = indexAnalyzer;
      }
      builder.indexAnalyzer(indexAnalyzer);
      builder.searchAnalyzer(searchAnalyzer);

      return builder;
    }