private static ObjectMapper parseValue(
     final ParseContext context,
     ObjectMapper parentMapper,
     String currentFieldName,
     XContentParser.Token token)
     throws IOException {
   if (currentFieldName == null) {
     throw new MapperParsingException(
         "object mapping ["
             + parentMapper.name()
             + "] trying to serialize a value with no field associated with it, current value ["
             + context.parser().textOrNull()
             + "]");
   }
   Mapper mapper = parentMapper.getMapper(currentFieldName);
   if (mapper != null) {
     Mapper subUpdate = parseObjectOrField(context, mapper);
     if (subUpdate == null) {
       return null;
     }
     return parentMapper.mappingUpdate(subUpdate);
   } else {
     return parseDynamicValue(context, parentMapper, currentFieldName, token);
   }
 }
 private static void parseNullValue(ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
     // we can only handle null values if we have mappings for them
     Mapper mapper = parentMapper.getMapper(lastFieldName);
     if (mapper != null) {
         // TODO: passing null to an object seems bogus?
         parseObjectOrField(context, mapper);
     } else if (parentMapper.dynamic() == ObjectMapper.Dynamic.STRICT) {
         throw new StrictDynamicMappingException(parentMapper.fullPath(), lastFieldName);
     }
 }
  private static ObjectMapper parseObject(
      final ParseContext context, ObjectMapper mapper, String currentFieldName) throws IOException {
    if (currentFieldName == null) {
      throw new MapperParsingException(
          "object mapping ["
              + mapper.name()
              + "] trying to serialize an object with no field associated with it, current value ["
              + context.parser().textOrNull()
              + "]");
    }
    context.path().add(currentFieldName);

    ObjectMapper update = null;
    Mapper objectMapper = mapper.getMapper(currentFieldName);
    if (objectMapper != null) {
      final Mapper subUpdate = parseObjectOrField(context, objectMapper);
      if (subUpdate != null) {
        // propagate mapping update
        update = mapper.mappingUpdate(subUpdate);
      }
    } else {
      ObjectMapper.Dynamic dynamic = mapper.dynamic();
      if (dynamic == null) {
        dynamic = dynamicOrDefault(context.root().dynamic());
      }
      if (dynamic == ObjectMapper.Dynamic.STRICT) {
        throw new StrictDynamicMappingException(mapper.fullPath(), currentFieldName);
      } else if (dynamic == ObjectMapper.Dynamic.TRUE) {
        // remove the current field name from path, since template search and the object builder add
        // it as well...
        context.path().remove();
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, currentFieldName, "object");
        if (builder == null) {
          builder = MapperBuilders.object(currentFieldName).enabled(true);
          // if this is a non root object, then explicitly set the dynamic behavior if set
          if (!(mapper instanceof RootObjectMapper)
              && mapper.dynamic() != ObjectMapper.Defaults.DYNAMIC) {
            ((ObjectMapper.Builder) builder).dynamic(mapper.dynamic());
          }
        }
        Mapper.BuilderContext builderContext =
            new Mapper.BuilderContext(context.indexSettings(), context.path());
        objectMapper = builder.build(builderContext);
        context.path().add(currentFieldName);
        update = mapper.mappingUpdate(parseAndMergeUpdate(objectMapper, context));
      } else {
        // not dynamic, read everything up to end object
        context.parser().skipChildren();
      }
    }

    context.path().remove();
    return update;
  }
  private static ObjectMapper parseArray(
      ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
    String arrayFieldName = lastFieldName;
    Mapper mapper = parentMapper.getMapper(lastFieldName);
    if (mapper != null) {
      // There is a concrete mapper for this field already. Need to check if the mapper
      // expects an array, if so we pass the context straight to the mapper and if not
      // we serialize the array components
      if (mapper instanceof ArrayValueMapperParser) {
        final Mapper subUpdate = parseObjectOrField(context, mapper);
        if (subUpdate != null) {
          // propagate the mapping update
          return parentMapper.mappingUpdate(subUpdate);
        } else {
          return null;
        }
      } else {
        return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
      }
    } else {

      ObjectMapper.Dynamic dynamic = parentMapper.dynamic();
      if (dynamic == null) {
        dynamic = dynamicOrDefault(context.root().dynamic());
      }
      if (dynamic == ObjectMapper.Dynamic.STRICT) {
        throw new StrictDynamicMappingException(parentMapper.fullPath(), arrayFieldName);
      } else if (dynamic == ObjectMapper.Dynamic.TRUE) {
        Mapper.Builder builder =
            context.root().findTemplateBuilder(context, arrayFieldName, "object");
        if (builder == null) {
          return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
        }
        Mapper.BuilderContext builderContext =
            new Mapper.BuilderContext(context.indexSettings(), context.path());
        mapper = builder.build(builderContext);
        if (mapper != null && mapper instanceof ArrayValueMapperParser) {
          context.path().add(arrayFieldName);
          mapper = parseAndMergeUpdate(mapper, context);
          return parentMapper.mappingUpdate(mapper);
        } else {
          return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
        }
      } else {
        return parseNonDynamicArray(context, parentMapper, lastFieldName, arrayFieldName);
      }
    }
  }