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;
  }
Ejemplo n.º 2
0
 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);
     }
 }
Ejemplo n.º 3
0
    private static ObjectMapper parseDynamicValue(final ParseContext context, ObjectMapper parentMapper, String currentFieldName, XContentParser.Token token) throws IOException {
        ObjectMapper.Dynamic dynamic = parentMapper.dynamic();
        if (dynamic == null) {
            dynamic = dynamicOrDefault(context.root().dynamic());
        }
        if (dynamic == ObjectMapper.Dynamic.STRICT) {
            throw new StrictDynamicMappingException(parentMapper.fullPath(), currentFieldName);
        }
        if (dynamic == ObjectMapper.Dynamic.FALSE) {
            return null;
        }
        final Mapper.BuilderContext builderContext = new Mapper.BuilderContext(context.indexSettings(), context.path());
        final MappedFieldType existingFieldType = context.mapperService().fullName(context.path().fullPathAsText(currentFieldName));
        Mapper.Builder builder = null;
        if (existingFieldType != null) {
            // create a builder of the same type
            builder = createBuilderFromFieldType(context, existingFieldType, currentFieldName);
            if (builder != null) {
                // best-effort to not introduce a conflict
                if (builder instanceof StringFieldMapper.Builder) {
                    StringFieldMapper.Builder stringBuilder = (StringFieldMapper.Builder) builder;
                    stringBuilder.fieldDataSettings(existingFieldType.fieldDataType().getSettings());
                    stringBuilder.store(existingFieldType.stored());
                    stringBuilder.indexOptions(existingFieldType.indexOptions());
                    stringBuilder.tokenized(existingFieldType.tokenized());
                    stringBuilder.omitNorms(existingFieldType.omitNorms());
                    stringBuilder.docValues(existingFieldType.hasDocValues());
                    stringBuilder.indexAnalyzer(existingFieldType.indexAnalyzer());
                    stringBuilder.searchAnalyzer(existingFieldType.searchAnalyzer());
                } else if (builder instanceof NumberFieldMapper.Builder) {
                    NumberFieldMapper.Builder<?,?> numberBuilder = (NumberFieldMapper.Builder<?, ?>) builder;
                    numberBuilder.fieldDataSettings(existingFieldType.fieldDataType().getSettings());
                    numberBuilder.store(existingFieldType.stored());
                    numberBuilder.indexOptions(existingFieldType.indexOptions());
                    numberBuilder.tokenized(existingFieldType.tokenized());
                    numberBuilder.omitNorms(existingFieldType.omitNorms());
                    numberBuilder.docValues(existingFieldType.hasDocValues());
                    numberBuilder.precisionStep(existingFieldType.numericPrecisionStep());
                }
            }
        }
        if (builder == null) {
            builder = createBuilderFromDynamicValue(context, token, currentFieldName);
        }
        Mapper mapper = builder.build(builderContext);

        mapper = parseAndMergeUpdate(mapper, context);

        ObjectMapper update = null;
        if (mapper != null) {
            update = parentMapper.mappingUpdate(mapper);
        }
        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);
      }
    }
  }
  /** Creates an copy of the current field with given field name and boost */
  private static void parseCopy(String field, ParseContext context) throws IOException {
    FieldMapper fieldMapper = context.docMapper().mappers().getMapper(field);
    if (fieldMapper != null) {
      fieldMapper.parse(context);
    } else {
      // The path of the dest field might be completely different from the current one so we need to
      // reset it
      context = context.overridePath(new ContentPath(0));

      String[] paths = Strings.splitStringToArray(field, '.');
      String fieldName = paths[paths.length - 1];
      ObjectMapper mapper = context.root();
      ObjectMapper[] mappers = new ObjectMapper[paths.length - 1];
      if (paths.length > 1) {
        ObjectMapper parent = context.root();
        for (int i = 0; i < paths.length - 1; i++) {
          mapper = context.docMapper().objectMappers().get(context.path().pathAsText(paths[i]));
          if (mapper == null) {
            // One mapping is missing, check if we are allowed to create a dynamic one.
            ObjectMapper.Dynamic dynamic = parent.dynamic();
            if (dynamic == null) {
              dynamic = dynamicOrDefault(context.root().dynamic());
            }

            switch (dynamic) {
              case STRICT:
                throw new StrictDynamicMappingException(parent.fullPath(), paths[i]);
              case TRUE:
                Mapper.Builder builder =
                    context.root().findTemplateBuilder(context, paths[i], "object");
                if (builder == null) {
                  // if this is a non root object, then explicitly set the dynamic behavior if set
                  if (!(parent instanceof RootObjectMapper)
                      && parent.dynamic() != ObjectMapper.Defaults.DYNAMIC) {
                    ((ObjectMapper.Builder) builder).dynamic(parent.dynamic());
                  }
                  builder = MapperBuilders.object(paths[i]).enabled(true);
                }
                Mapper.BuilderContext builderContext =
                    new Mapper.BuilderContext(context.indexSettings(), context.path());
                mapper = (ObjectMapper) builder.build(builderContext);
                if (mapper.nested() != ObjectMapper.Nested.NO) {
                  throw new MapperParsingException(
                      "It is forbidden to create dynamic nested objects (["
                          + context.path().pathAsText(paths[i])
                          + "]) through `copy_to`");
                }
                break;
              case FALSE:
                // Maybe we should log something to tell the user that the copy_to is ignored in
                // this case.
                break;
              default:
                throw new AssertionError("Unexpected dynamic type " + dynamic);
            }
          }
          context.path().add(paths[i]);
          mappers[i] = mapper;
          parent = mapper;
        }
      }
      ObjectMapper update =
          parseDynamicValue(context, mapper, fieldName, context.parser().currentToken());
      assert update
          != null; // we are parsing a dynamic value so we necessarily created a new mapping

      if (paths.length > 1) {
        for (int i = paths.length - 2; i >= 0; i--) {
          ObjectMapper parent = context.root();
          if (i > 0) {
            parent = mappers[i - 1];
          }
          assert parent != null;
          update = parent.mappingUpdate(update);
        }
      }
      context.addDynamicMappingsUpdate(update);
    }
  }