Skip to content

Commit

Permalink
Reinterpret dots in field names as object structure (#79922)
Browse files Browse the repository at this point in the history
DocumentParser parses documents by following their object hierarchy, and
using a parallel hierarchy of ObjectMappers to work out how to map leaf fields.
Field names that contain dots complicate this, meaning that many methods
need to reverse-engineer the object hierarchy to check that the current parent
object mapper is the correct one; this is particularly complex when objects
are being created dynamically.

To simplify this logic, this commit introduces a DotExpandingXContentParser,
which wraps another XContentParser and re-interprets any field name containing
dots as a series of objects. So for example, `"foo.bar.baz":{ ... }` is represented
as `"foo":{"bar":{"baz":{...}}}`. DocumentParser uses this to automatically 
expand all field names containing dots when parsing the source.
  • Loading branch information
romseygeek committed Nov 23, 2021
1 parent 0ed5eab commit 2e8a973
Show file tree
Hide file tree
Showing 11 changed files with 714 additions and 311 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.xcontent;

import org.elasticsearch.core.CheckedFunction;
import org.elasticsearch.core.RestApiVersion;

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

public abstract class DelegatingXContentParser implements XContentParser {

protected abstract XContentParser delegate();

@Override
public XContentType contentType() {
return delegate().contentType();
}

@Override
public void allowDuplicateKeys(boolean allowDuplicateKeys) {
delegate().allowDuplicateKeys(allowDuplicateKeys);
}

@Override
public Token nextToken() throws IOException {
return delegate().nextToken();
}

@Override
public void skipChildren() throws IOException {
delegate().skipChildren();
}

@Override
public Token currentToken() {
return delegate().currentToken();
}

@Override
public String currentName() throws IOException {
return delegate().currentName();
}

@Override
public Map<String, Object> map() throws IOException {
return delegate().map();
}

@Override
public Map<String, Object> mapOrdered() throws IOException {
return delegate().mapOrdered();
}

@Override
public Map<String, String> mapStrings() throws IOException {
return delegate().mapStrings();
}

@Override
public <T> Map<String, T> map(Supplier<Map<String, T>> mapFactory, CheckedFunction<XContentParser, T, IOException> mapValueParser)
throws IOException {
return delegate().map(mapFactory, mapValueParser);
}

@Override
public List<Object> list() throws IOException {
return delegate().list();
}

@Override
public List<Object> listOrderedMap() throws IOException {
return delegate().listOrderedMap();
}

@Override
public String text() throws IOException {
return delegate().text();
}

@Override
public String textOrNull() throws IOException {
return delegate().textOrNull();
}

@Override
public CharBuffer charBufferOrNull() throws IOException {
return delegate().charBufferOrNull();
}

@Override
public CharBuffer charBuffer() throws IOException {
return delegate().charBuffer();
}

@Override
public Object objectText() throws IOException {
return delegate().objectText();
}

@Override
public Object objectBytes() throws IOException {
return delegate().objectBytes();
}

@Override
public boolean hasTextCharacters() {
return delegate().hasTextCharacters();
}

@Override
public char[] textCharacters() throws IOException {
return delegate().textCharacters();
}

@Override
public int textLength() throws IOException {
return delegate().textLength();
}

@Override
public int textOffset() throws IOException {
return delegate().textOffset();
}

@Override
public Number numberValue() throws IOException {
return delegate().numberValue();
}

@Override
public NumberType numberType() throws IOException {
return delegate().numberType();
}

@Override
public short shortValue(boolean coerce) throws IOException {
return delegate().shortValue(coerce);
}

@Override
public int intValue(boolean coerce) throws IOException {
return delegate().intValue(coerce);
}

@Override
public long longValue(boolean coerce) throws IOException {
return delegate().longValue(coerce);
}

@Override
public float floatValue(boolean coerce) throws IOException {
return delegate().floatValue(coerce);
}

@Override
public double doubleValue(boolean coerce) throws IOException {
return delegate().doubleValue(coerce);
}

@Override
public short shortValue() throws IOException {
return delegate().shortValue();
}

@Override
public int intValue() throws IOException {
return delegate().intValue();
}

@Override
public long longValue() throws IOException {
return delegate().longValue();
}

@Override
public float floatValue() throws IOException {
return delegate().floatValue();
}

@Override
public double doubleValue() throws IOException {
return delegate().doubleValue();
}

@Override
public boolean isBooleanValue() throws IOException {
return delegate().isBooleanValue();
}

@Override
public boolean booleanValue() throws IOException {
return delegate().booleanValue();
}

@Override
public byte[] binaryValue() throws IOException {
return delegate().binaryValue();
}

@Override
public XContentLocation getTokenLocation() {
return delegate().getTokenLocation();
}

@Override
public <T> T namedObject(Class<T> categoryClass, String name, Object context) throws IOException {
return delegate().namedObject(categoryClass, name, context);
}

@Override
public NamedXContentRegistry getXContentRegistry() {
return delegate().getXContentRegistry();
}

@Override
public boolean isClosed() {
return delegate().isClosed();
}

@Override
public RestApiVersion getRestApiVersion() {
return delegate().getRestApiVersion();
}

@Override
public DeprecationHandler getDeprecationHandler() {
return delegate().getDeprecationHandler();
}

@Override
public void close() throws IOException {
delegate().close();
}
}

0 comments on commit 2e8a973

Please sign in to comment.