@Override
 protected ObjectMapper createMapper(
     String name,
     String fullPath,
     boolean enabled,
     Nested nested,
     Dynamic dynamic,
     ContentPath.Type pathType,
     Map<String, Mapper> mappers,
     @Nullable @IndexSettings Settings settings) {
   assert !nested.isNested();
   FormatDateTimeFormatter[] dates = null;
   if (dynamicDateTimeFormatters == null) {
     dates = new FormatDateTimeFormatter[0];
   } else if (dynamicDateTimeFormatters.isEmpty()) {
     // add the default one
     dates = Defaults.DYNAMIC_DATE_TIME_FORMATTERS;
   } else {
     dates =
         dynamicDateTimeFormatters.toArray(
             new FormatDateTimeFormatter[dynamicDateTimeFormatters.size()]);
   }
   return new RootObjectMapper(
       name,
       enabled,
       dynamic,
       pathType,
       mappers,
       dates,
       dynamicTemplates.toArray(new DynamicTemplate[dynamicTemplates.size()]),
       dateDetection,
       numericDetection,
       settings);
 }
 protected boolean processField(
     ObjectMapper.Builder builder, String fieldName, Object fieldNode) {
   if (fieldName.equals("date_formats") || fieldName.equals("dynamic_date_formats")) {
     List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
     if (fieldNode instanceof List) {
       for (Object node1 : (List) fieldNode) {
         dateTimeFormatters.add(parseDateTimeFormatter(fieldName, node1));
       }
     } else if ("none".equals(fieldNode.toString())) {
       dateTimeFormatters = null;
     } else {
       dateTimeFormatters.add(parseDateTimeFormatter(fieldName, fieldNode));
     }
     if (dateTimeFormatters == null) {
       ((Builder) builder).noDynamicDateTimeFormatter();
     } else {
       ((Builder) builder).dynamicDateTimeFormatter(dateTimeFormatters);
     }
     return true;
   } else if (fieldName.equals("dynamic_templates")) {
     //  "dynamic_templates" : [
     //      {
     //          "template_1" : {
     //              "match" : "*_test",
     //              "match_mapping_type" : "string",
     //              "mapping" : { "type" : "string", "store" : "yes" }
     //          }
     //      }
     //  ]
     List tmplNodes = (List) fieldNode;
     for (Object tmplNode : tmplNodes) {
       Map<String, Object> tmpl = (Map<String, Object>) tmplNode;
       if (tmpl.size() != 1) {
         throw new MapperParsingException("A dynamic template must be defined with a name");
       }
       Map.Entry<String, Object> entry = tmpl.entrySet().iterator().next();
       ((Builder) builder)
           .add(DynamicTemplate.parse(entry.getKey(), (Map<String, Object>) entry.getValue()));
     }
     return true;
   } else if (fieldName.equals("date_detection")) {
     ((Builder) builder).dateDetection = nodeBooleanValue(fieldNode);
     return true;
   } else if (fieldName.equals("numeric_detection")) {
     ((Builder) builder).numericDetection = nodeBooleanValue(fieldNode);
     return true;
   }
   return false;
 }
 @Override
 @SuppressWarnings("unchecked")
 public Iterator<Mapper> iterator() {
   List<Mapper> extras =
       Arrays.asList(
           contentMapper,
           dateMapper,
           titleMapper,
           nameMapper,
           authorMapper,
           keywordsMapper,
           contentTypeMapper,
           contentLengthMapper,
           languageMapper);
   return Iterators.concat(super.iterator(), extras.iterator());
 }
 @Override
 protected void doMerge(ObjectMapper mergeWith, MergeContext mergeContext) {
   RootObjectMapper mergeWithObject = (RootObjectMapper) mergeWith;
   if (!mergeContext.mergeFlags().simulate()) {
     // merge them
     List<DynamicTemplate> mergedTemplates =
         Lists.newArrayList(Arrays.asList(this.dynamicTemplates));
     for (DynamicTemplate template : mergeWithObject.dynamicTemplates) {
       boolean replaced = false;
       for (int i = 0; i < mergedTemplates.size(); i++) {
         if (mergedTemplates.get(i).name().equals(template.name())) {
           mergedTemplates.set(i, template);
           replaced = true;
         }
       }
       if (!replaced) {
         mergedTemplates.add(template);
       }
     }
     this.dynamicTemplates = mergedTemplates.toArray(new DynamicTemplate[mergedTemplates.size()]);
   }
 }
  @Override
  public void merge(final Mapper mergeWith, final MergeContext mergeContext)
      throws MergeMappingException {
    if (!(mergeWith instanceof ObjectMapper)) {
      mergeContext.addConflict(
          "Can't merge a non object mapping ["
              + mergeWith.name()
              + "] with an object mapping ["
              + name()
              + "]");
      return;
    }
    ObjectMapper mergeWithObject = (ObjectMapper) mergeWith;

    if (nested().isNested()) {
      if (!mergeWithObject.nested().isNested()) {
        mergeContext.addConflict(
            "object mapping [" + name() + "] can't be changed from nested to non-nested");
        return;
      }
    } else {
      if (mergeWithObject.nested().isNested()) {
        mergeContext.addConflict(
            "object mapping [" + name() + "] can't be changed from non-nested to nested");
        return;
      }
    }

    doMerge(mergeWithObject, mergeContext);

    List<Mapper> mappersToTraverse = new ArrayList<Mapper>();
    synchronized (mutex) {
      for (Mapper mergeWithMapper : mergeWithObject.mappers.values()) {
        Mapper mergeIntoMapper = mappers.get(mergeWithMapper.name());
        if (mergeIntoMapper == null) {
          // no mapping, simply add it if not simulating
          if (!mergeContext.mergeFlags().simulate()) {
            putMapper(mergeWithMapper);
            mappersToTraverse.add(mergeWithMapper);
          }
        } else {
          if ((mergeWithMapper instanceof MultiFieldMapper)
              && !(mergeIntoMapper instanceof MultiFieldMapper)) {
            MultiFieldMapper mergeWithMultiField = (MultiFieldMapper) mergeWithMapper;
            mergeWithMultiField.merge(mergeIntoMapper, mergeContext);
            if (!mergeContext.mergeFlags().simulate()) {
              putMapper(mergeWithMultiField);
              // now, record mappers to traverse events for all mappers
              for (Mapper mapper : mergeWithMultiField.mappers().values()) {
                mappersToTraverse.add(mapper);
              }
            }
          } else {
            mergeIntoMapper.merge(mergeWithMapper, mergeContext);
          }
        }
      }
    }
    // call this outside of the mutex
    for (Mapper mapper : mappersToTraverse) {
      mapper.traverse(mergeContext.newFieldMappers());
      mapper.traverse(mergeContext.newObjectMappers());
    }
  }
 public T add(Mapper.Builder builder) {
   mappersBuilders.add(builder);
   return this.builder;
 }
  @Override
  public void merge(final Mapper mergeWith, final MergeContext mergeContext)
      throws MergeMappingException {
    if (!(mergeWith instanceof ObjectMapper)) {
      mergeContext.addConflict(
          "Can't merge a non object mapping ["
              + mergeWith.name()
              + "] with an object mapping ["
              + name()
              + "]");
      return;
    }
    ObjectMapper mergeWithObject = (ObjectMapper) mergeWith;

    if (nested().isNested()) {
      if (!mergeWithObject.nested().isNested()) {
        mergeContext.addConflict(
            "object mapping [" + name() + "] can't be changed from nested to non-nested");
        return;
      }
    } else {
      if (mergeWithObject.nested().isNested()) {
        mergeContext.addConflict(
            "object mapping [" + name() + "] can't be changed from non-nested to nested");
        return;
      }
    }

    if (!mergeContext.mergeFlags().simulate()) {
      if (mergeWithObject.dynamic != null) {
        this.dynamic = mergeWithObject.dynamic;
      }
    }

    doMerge(mergeWithObject, mergeContext);

    List<Mapper> mappersToPut = new ArrayList<>();
    FieldMapperListener.Aggregator newFieldMappers = new FieldMapperListener.Aggregator();
    ObjectMapperListener.Aggregator newObjectMappers = new ObjectMapperListener.Aggregator();
    synchronized (mutex) {
      for (Mapper mapper : mergeWithObject.mappers.values()) {
        Mapper mergeWithMapper = mapper;
        Mapper mergeIntoMapper = mappers.get(mergeWithMapper.name());
        if (mergeIntoMapper == null) {
          // no mapping, simply add it if not simulating
          if (!mergeContext.mergeFlags().simulate()) {
            mappersToPut.add(mergeWithMapper);
            mergeWithMapper.traverse(newFieldMappers);
            mergeWithMapper.traverse(newObjectMappers);
          }
        } else {
          mergeIntoMapper.merge(mergeWithMapper, mergeContext);
        }
      }
      if (!newFieldMappers.mappers.isEmpty()) {
        mergeContext.docMapper().addFieldMappers(newFieldMappers.mappers);
      }
      if (!newObjectMappers.mappers.isEmpty()) {
        mergeContext.docMapper().addObjectMappers(newObjectMappers.mappers);
      }
      // and the mappers only after the administration have been done, so it will not be visible to
      // parser (which first try to read with no lock)
      for (Mapper mapper : mappersToPut) {
        putMapper(mapper);
      }
    }
  }