|
@@ -63,13 +63,13 @@ public final class DocumentParser {
|
|
if (source.source() != null && source.source().length() == 0) {
|
|
if (source.source() != null && source.source().length() == 0) {
|
|
throw new DocumentParsingException(new XContentLocation(0, 0), "failed to parse, document is empty");
|
|
throw new DocumentParsingException(new XContentLocation(0, 0), "failed to parse, document is empty");
|
|
}
|
|
}
|
|
- final InternalDocumentParserContext context;
|
|
|
|
|
|
+ final RootDocumentParserContext context;
|
|
final XContentType xContentType = source.getXContentType();
|
|
final XContentType xContentType = source.getXContentType();
|
|
try (XContentParser parser = XContentHelper.createParser(parserConfiguration, source.source(), xContentType)) {
|
|
try (XContentParser parser = XContentHelper.createParser(parserConfiguration, source.source(), xContentType)) {
|
|
- context = new InternalDocumentParserContext(mappingLookup, mappingParserContext, source, parser);
|
|
|
|
|
|
+ context = new RootDocumentParserContext(mappingLookup, mappingParserContext, source, parser);
|
|
validateStart(context.parser());
|
|
validateStart(context.parser());
|
|
MetadataFieldMapper[] metadataFieldsMappers = mappingLookup.getMapping().getSortedMetadataMappers();
|
|
MetadataFieldMapper[] metadataFieldsMappers = mappingLookup.getMapping().getSortedMetadataMappers();
|
|
- internalParseDocument(mappingLookup.getMapping().getRoot(), metadataFieldsMappers, context);
|
|
|
|
|
|
+ internalParseDocument(metadataFieldsMappers, context);
|
|
validateEnd(context.parser());
|
|
validateEnd(context.parser());
|
|
} catch (XContentParseException e) {
|
|
} catch (XContentParseException e) {
|
|
throw new DocumentParsingException(e.getLocation(), e.getMessage(), e);
|
|
throw new DocumentParsingException(e.getLocation(), e.getMessage(), e);
|
|
@@ -77,7 +77,7 @@ public final class DocumentParser {
|
|
// IOException from jackson, we don't have any useful location information here
|
|
// IOException from jackson, we don't have any useful location information here
|
|
throw new DocumentParsingException(XContentLocation.UNKNOWN, "Error parsing document", e);
|
|
throw new DocumentParsingException(XContentLocation.UNKNOWN, "Error parsing document", e);
|
|
}
|
|
}
|
|
- assert context.path.atRoot() : "found leftover path elements: " + context.path.pathAsText("");
|
|
|
|
|
|
+ assert context.path.pathAsText("").isEmpty() : "found leftover path elements: " + context.path.pathAsText("");
|
|
|
|
|
|
return new ParsedDocument(
|
|
return new ParsedDocument(
|
|
context.version(),
|
|
context.version(),
|
|
@@ -97,24 +97,20 @@ public final class DocumentParser {
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
- private static void internalParseDocument(
|
|
|
|
- RootObjectMapper root,
|
|
|
|
- MetadataFieldMapper[] metadataFieldsMappers,
|
|
|
|
- DocumentParserContext context
|
|
|
|
- ) {
|
|
|
|
|
|
+ private static void internalParseDocument(MetadataFieldMapper[] metadataFieldsMappers, DocumentParserContext context) {
|
|
|
|
|
|
try {
|
|
try {
|
|
- final boolean emptyDoc = isEmptyDoc(root, context.parser());
|
|
|
|
|
|
+ final boolean emptyDoc = isEmptyDoc(context.root(), context.parser());
|
|
|
|
|
|
for (MetadataFieldMapper metadataMapper : metadataFieldsMappers) {
|
|
for (MetadataFieldMapper metadataMapper : metadataFieldsMappers) {
|
|
metadataMapper.preParse(context);
|
|
metadataMapper.preParse(context);
|
|
}
|
|
}
|
|
|
|
|
|
- if (root.isEnabled() == false) {
|
|
|
|
|
|
+ if (context.root().isEnabled() == false) {
|
|
// entire type is disabled
|
|
// entire type is disabled
|
|
context.parser().skipChildren();
|
|
context.parser().skipChildren();
|
|
} else if (emptyDoc == false) {
|
|
} else if (emptyDoc == false) {
|
|
- parseObjectOrNested(context, root);
|
|
|
|
|
|
+ parseObjectOrNested(context);
|
|
}
|
|
}
|
|
|
|
|
|
executeIndexTimeScripts(context);
|
|
executeIndexTimeScripts(context);
|
|
@@ -234,8 +230,8 @@ public final class DocumentParser {
|
|
return context.mappingLookup().getMapping().mappingUpdate(root);
|
|
return context.mappingLookup().getMapping().mappingUpdate(root);
|
|
}
|
|
}
|
|
|
|
|
|
- static void parseObjectOrNested(DocumentParserContext context, ObjectMapper mapper) throws IOException {
|
|
|
|
- if (mapper.isEnabled() == false) {
|
|
|
|
|
|
+ static void parseObjectOrNested(DocumentParserContext context) throws IOException {
|
|
|
|
+ if (context.parent().isEnabled() == false) {
|
|
context.parser().skipChildren();
|
|
context.parser().skipChildren();
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -248,11 +244,11 @@ public final class DocumentParser {
|
|
|
|
|
|
String currentFieldName = parser.currentName();
|
|
String currentFieldName = parser.currentName();
|
|
if (token.isValue()) {
|
|
if (token.isValue()) {
|
|
- throwOnConcreteValue(mapper, currentFieldName, context);
|
|
|
|
|
|
+ throwOnConcreteValue(context.parent(), currentFieldName, context);
|
|
}
|
|
}
|
|
|
|
|
|
- if (mapper.isNested()) {
|
|
|
|
- context = context.createNestedContext((NestedObjectMapper) mapper);
|
|
|
|
|
|
+ if (context.parent().isNested()) {
|
|
|
|
+ context = context.createNestedContext((NestedObjectMapper) context.parent());
|
|
}
|
|
}
|
|
|
|
|
|
// if we are at the end of the previous object, advance
|
|
// if we are at the end of the previous object, advance
|
|
@@ -264,10 +260,10 @@ public final class DocumentParser {
|
|
parser.nextToken();
|
|
parser.nextToken();
|
|
}
|
|
}
|
|
|
|
|
|
- innerParseObject(context, mapper);
|
|
|
|
|
|
+ innerParseObject(context);
|
|
// restore the enable path flag
|
|
// restore the enable path flag
|
|
- if (mapper.isNested()) {
|
|
|
|
- copyNestedFields(context, (NestedObjectMapper) mapper);
|
|
|
|
|
|
+ if (context.parent().isNested()) {
|
|
|
|
+ copyNestedFields(context, (NestedObjectMapper) context.parent());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -282,7 +278,7 @@ public final class DocumentParser {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
- private static void innerParseObject(DocumentParserContext context, ObjectMapper mapper) throws IOException {
|
|
|
|
|
|
+ private static void innerParseObject(DocumentParserContext context) throws IOException {
|
|
|
|
|
|
final XContentParser parser = context.parser();
|
|
final XContentParser parser = context.parser();
|
|
XContentParser.Token token = parser.currentToken();
|
|
XContentParser.Token token = parser.currentToken();
|
|
@@ -291,7 +287,7 @@ public final class DocumentParser {
|
|
|
|
|
|
while (token != XContentParser.Token.END_OBJECT) {
|
|
while (token != XContentParser.Token.END_OBJECT) {
|
|
if (token == null) {
|
|
if (token == null) {
|
|
- throwEOF(mapper, context);
|
|
|
|
|
|
+ throwEOF(context.parent(), context);
|
|
}
|
|
}
|
|
switch (token) {
|
|
switch (token) {
|
|
case FIELD_NAME:
|
|
case FIELD_NAME:
|
|
@@ -304,17 +300,17 @@ public final class DocumentParser {
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case START_OBJECT:
|
|
case START_OBJECT:
|
|
- parseObject(context, mapper, currentFieldName);
|
|
|
|
|
|
+ parseObject(context, currentFieldName);
|
|
break;
|
|
break;
|
|
case START_ARRAY:
|
|
case START_ARRAY:
|
|
- parseArray(context, mapper, currentFieldName);
|
|
|
|
|
|
+ parseArray(context, currentFieldName);
|
|
break;
|
|
break;
|
|
case VALUE_NULL:
|
|
case VALUE_NULL:
|
|
- parseNullValue(context, mapper, currentFieldName);
|
|
|
|
|
|
+ parseNullValue(context, currentFieldName);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
if (token.isValue()) {
|
|
if (token.isValue()) {
|
|
- parseValue(context, mapper, currentFieldName);
|
|
|
|
|
|
+ parseValue(context, currentFieldName);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -374,7 +370,8 @@ public final class DocumentParser {
|
|
|
|
|
|
static void parseObjectOrField(DocumentParserContext context, Mapper mapper) throws IOException {
|
|
static void parseObjectOrField(DocumentParserContext context, Mapper mapper) throws IOException {
|
|
if (mapper instanceof ObjectMapper objectMapper) {
|
|
if (mapper instanceof ObjectMapper objectMapper) {
|
|
- parseObjectOrNested(context, objectMapper);
|
|
|
|
|
|
+ context = context.createChildContext(objectMapper);
|
|
|
|
+ parseObjectOrNested(context);
|
|
} else if (mapper instanceof FieldMapper fieldMapper) {
|
|
} else if (mapper instanceof FieldMapper fieldMapper) {
|
|
fieldMapper.parse(context);
|
|
fieldMapper.parse(context);
|
|
if (context.isWithinCopyTo() == false) {
|
|
if (context.isWithinCopyTo() == false) {
|
|
@@ -419,10 +416,9 @@ public final class DocumentParser {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseObject(final DocumentParserContext context, ObjectMapper parentObjectMapper, String currentFieldName)
|
|
|
|
- throws IOException {
|
|
|
|
|
|
+ private static void parseObject(final DocumentParserContext context, String currentFieldName) throws IOException {
|
|
assert currentFieldName != null;
|
|
assert currentFieldName != null;
|
|
- Mapper objectMapper = getMapper(context, parentObjectMapper, currentFieldName);
|
|
|
|
|
|
+ Mapper objectMapper = context.getMapper(currentFieldName);
|
|
if (objectMapper != null) {
|
|
if (objectMapper != null) {
|
|
context.path().add(currentFieldName);
|
|
context.path().add(currentFieldName);
|
|
if (objectMapper instanceof ObjectMapper objMapper) {
|
|
if (objectMapper instanceof ObjectMapper objMapper) {
|
|
@@ -434,22 +430,20 @@ public final class DocumentParser {
|
|
context.path().setWithinLeafObject(false);
|
|
context.path().setWithinLeafObject(false);
|
|
context.path().remove();
|
|
context.path().remove();
|
|
} else {
|
|
} else {
|
|
- parseObjectDynamic(context, parentObjectMapper, currentFieldName);
|
|
|
|
|
|
+ parseObjectDynamic(context, currentFieldName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseObjectDynamic(DocumentParserContext context, ObjectMapper parentObjectMapper, String currentFieldName)
|
|
|
|
- throws IOException {
|
|
|
|
- ObjectMapper.Dynamic dynamic = dynamicOrDefault(parentObjectMapper, context);
|
|
|
|
- if (dynamic == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
- throw new StrictDynamicMappingException(context.parser().getTokenLocation(), parentObjectMapper.fullPath(), currentFieldName);
|
|
|
|
- } else if (dynamic == ObjectMapper.Dynamic.FALSE) {
|
|
|
|
- failIfMatchesRoutingPath(context, parentObjectMapper, currentFieldName);
|
|
|
|
|
|
+ private static void parseObjectDynamic(DocumentParserContext context, String currentFieldName) throws IOException {
|
|
|
|
+ if (context.dynamic() == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
+ throw new StrictDynamicMappingException(context.parser().getTokenLocation(), context.parent().fullPath(), currentFieldName);
|
|
|
|
+ } else if (context.dynamic() == ObjectMapper.Dynamic.FALSE) {
|
|
|
|
+ failIfMatchesRoutingPath(context, currentFieldName);
|
|
// not dynamic, read everything up to end object
|
|
// not dynamic, read everything up to end object
|
|
context.parser().skipChildren();
|
|
context.parser().skipChildren();
|
|
} else {
|
|
} else {
|
|
Mapper dynamicObjectMapper;
|
|
Mapper dynamicObjectMapper;
|
|
- if (dynamic == ObjectMapper.Dynamic.RUNTIME) {
|
|
|
|
|
|
+ if (context.dynamic() == ObjectMapper.Dynamic.RUNTIME) {
|
|
// with dynamic:runtime all leaf fields will be runtime fields unless explicitly mapped,
|
|
// with dynamic:runtime all leaf fields will be runtime fields unless explicitly mapped,
|
|
// hence we don't dynamically create empty objects under properties, but rather carry around an artificial object mapper
|
|
// hence we don't dynamically create empty objects under properties, but rather carry around an artificial object mapper
|
|
dynamicObjectMapper = new NoOpObjectMapper(currentFieldName, context.path().pathAsText(currentFieldName));
|
|
dynamicObjectMapper = new NoOpObjectMapper(currentFieldName, context.path().pathAsText(currentFieldName));
|
|
@@ -457,14 +451,14 @@ public final class DocumentParser {
|
|
dynamicObjectMapper = DynamicFieldsBuilder.createDynamicObjectMapper(context, currentFieldName);
|
|
dynamicObjectMapper = DynamicFieldsBuilder.createDynamicObjectMapper(context, currentFieldName);
|
|
context.addDynamicMapper(dynamicObjectMapper);
|
|
context.addDynamicMapper(dynamicObjectMapper);
|
|
}
|
|
}
|
|
- if (parentObjectMapper.subobjects() == false) {
|
|
|
|
|
|
+ if (context.parent().subobjects() == false) {
|
|
if (dynamicObjectMapper instanceof NestedObjectMapper) {
|
|
if (dynamicObjectMapper instanceof NestedObjectMapper) {
|
|
throw new DocumentParsingException(
|
|
throw new DocumentParsingException(
|
|
context.parser().getTokenLocation(),
|
|
context.parser().getTokenLocation(),
|
|
"Tried to add nested object ["
|
|
"Tried to add nested object ["
|
|
+ dynamicObjectMapper.simpleName()
|
|
+ dynamicObjectMapper.simpleName()
|
|
+ "] to object ["
|
|
+ "] to object ["
|
|
- + parentObjectMapper.name()
|
|
|
|
|
|
+ + context.parent().name()
|
|
+ "] which does not support subobjects"
|
|
+ "] which does not support subobjects"
|
|
);
|
|
);
|
|
}
|
|
}
|
|
@@ -474,7 +468,7 @@ public final class DocumentParser {
|
|
"Tried to add subobject ["
|
|
"Tried to add subobject ["
|
|
+ dynamicObjectMapper.simpleName()
|
|
+ dynamicObjectMapper.simpleName()
|
|
+ "] to object ["
|
|
+ "] to object ["
|
|
- + parentObjectMapper.name()
|
|
|
|
|
|
+ + context.parent().name()
|
|
+ "] which does not support subobjects"
|
|
+ "] which does not support subobjects"
|
|
);
|
|
);
|
|
}
|
|
}
|
|
@@ -501,8 +495,8 @@ public final class DocumentParser {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseArray(DocumentParserContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
|
|
|
|
- Mapper mapper = getLeafMapper(context, parentMapper, lastFieldName);
|
|
|
|
|
|
+ private static void parseArray(DocumentParserContext context, String lastFieldName) throws IOException {
|
|
|
|
+ Mapper mapper = getLeafMapper(context, lastFieldName);
|
|
if (mapper != null) {
|
|
if (mapper != null) {
|
|
// There is a concrete mapper for this field already. Need to check if the mapper
|
|
// 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
|
|
// expects an array, if so we pass the context straight to the mapper and if not
|
|
@@ -510,18 +504,17 @@ public final class DocumentParser {
|
|
if (parsesArrayValue(mapper)) {
|
|
if (parsesArrayValue(mapper)) {
|
|
parseObjectOrField(context, mapper);
|
|
parseObjectOrField(context, mapper);
|
|
} else {
|
|
} else {
|
|
- parseNonDynamicArray(context, parentMapper, lastFieldName, lastFieldName);
|
|
|
|
|
|
+ parseNonDynamicArray(context, lastFieldName, lastFieldName);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- ObjectMapper.Dynamic dynamic = dynamicOrDefault(parentMapper, context);
|
|
|
|
- if (dynamic == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
- throw new StrictDynamicMappingException(context.parser().getTokenLocation(), parentMapper.fullPath(), lastFieldName);
|
|
|
|
- } else if (dynamic == ObjectMapper.Dynamic.FALSE) {
|
|
|
|
|
|
+ if (context.dynamic() == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
+ throw new StrictDynamicMappingException(context.parser().getTokenLocation(), context.parent().fullPath(), lastFieldName);
|
|
|
|
+ } else if (context.dynamic() == ObjectMapper.Dynamic.FALSE) {
|
|
context.parser().skipChildren();
|
|
context.parser().skipChildren();
|
|
} else {
|
|
} else {
|
|
Mapper objectMapperFromTemplate = DynamicFieldsBuilder.createObjectMapperFromTemplate(context, lastFieldName);
|
|
Mapper objectMapperFromTemplate = DynamicFieldsBuilder.createObjectMapperFromTemplate(context, lastFieldName);
|
|
if (objectMapperFromTemplate == null) {
|
|
if (objectMapperFromTemplate == null) {
|
|
- parseNonDynamicArray(context, parentMapper, lastFieldName, lastFieldName);
|
|
|
|
|
|
+ parseNonDynamicArray(context, lastFieldName, lastFieldName);
|
|
} else {
|
|
} else {
|
|
if (parsesArrayValue(objectMapperFromTemplate)) {
|
|
if (parsesArrayValue(objectMapperFromTemplate)) {
|
|
context.addDynamicMapper(objectMapperFromTemplate);
|
|
context.addDynamicMapper(objectMapperFromTemplate);
|
|
@@ -529,7 +522,7 @@ public final class DocumentParser {
|
|
parseObjectOrField(context, objectMapperFromTemplate);
|
|
parseObjectOrField(context, objectMapperFromTemplate);
|
|
context.path().remove();
|
|
context.path().remove();
|
|
} else {
|
|
} else {
|
|
- parseNonDynamicArray(context, parentMapper, lastFieldName, lastFieldName);
|
|
|
|
|
|
+ parseNonDynamicArray(context, lastFieldName, lastFieldName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -540,59 +533,54 @@ public final class DocumentParser {
|
|
return mapper instanceof FieldMapper && ((FieldMapper) mapper).parsesArrayValue();
|
|
return mapper instanceof FieldMapper && ((FieldMapper) mapper).parsesArrayValue();
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseNonDynamicArray(
|
|
|
|
- DocumentParserContext context,
|
|
|
|
- ObjectMapper mapper,
|
|
|
|
- final String lastFieldName,
|
|
|
|
- String arrayFieldName
|
|
|
|
- ) throws IOException {
|
|
|
|
|
|
+ private static void parseNonDynamicArray(DocumentParserContext context, final String lastFieldName, String arrayFieldName)
|
|
|
|
+ throws IOException {
|
|
XContentParser parser = context.parser();
|
|
XContentParser parser = context.parser();
|
|
XContentParser.Token token;
|
|
XContentParser.Token token;
|
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
|
if (token == XContentParser.Token.START_OBJECT) {
|
|
if (token == XContentParser.Token.START_OBJECT) {
|
|
- parseObject(context, mapper, lastFieldName);
|
|
|
|
|
|
+ parseObject(context, lastFieldName);
|
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
|
- parseArray(context, mapper, lastFieldName);
|
|
|
|
|
|
+ parseArray(context, lastFieldName);
|
|
} else if (token == XContentParser.Token.VALUE_NULL) {
|
|
} else if (token == XContentParser.Token.VALUE_NULL) {
|
|
- parseNullValue(context, mapper, lastFieldName);
|
|
|
|
|
|
+ parseNullValue(context, lastFieldName);
|
|
} else if (token == null) {
|
|
} else if (token == null) {
|
|
- throwEOFOnParseArray(mapper, arrayFieldName, context);
|
|
|
|
|
|
+ throwEOFOnParseArray(arrayFieldName, context);
|
|
} else {
|
|
} else {
|
|
assert token.isValue();
|
|
assert token.isValue();
|
|
- parseValue(context, mapper, lastFieldName);
|
|
|
|
|
|
+ parseValue(context, lastFieldName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static void throwEOFOnParseArray(ObjectMapper mapper, String arrayFieldName, DocumentParserContext context) {
|
|
|
|
|
|
+ private static void throwEOFOnParseArray(String arrayFieldName, DocumentParserContext context) {
|
|
throw new DocumentParsingException(
|
|
throw new DocumentParsingException(
|
|
context.parser().getTokenLocation(),
|
|
context.parser().getTokenLocation(),
|
|
"object mapping for ["
|
|
"object mapping for ["
|
|
- + mapper.name()
|
|
|
|
|
|
+ + context.parent().name()
|
|
+ "] with array for ["
|
|
+ "] with array for ["
|
|
+ arrayFieldName
|
|
+ arrayFieldName
|
|
+ "] tried to parse as array, but got EOF, is there a mismatch in types for the same field?"
|
|
+ "] tried to parse as array, but got EOF, is there a mismatch in types for the same field?"
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseValue(final DocumentParserContext context, ObjectMapper parentMapper, String currentFieldName)
|
|
|
|
- throws IOException {
|
|
|
|
|
|
+ private static void parseValue(final DocumentParserContext context, String currentFieldName) throws IOException {
|
|
if (currentFieldName == null) {
|
|
if (currentFieldName == null) {
|
|
- throwOnNoFieldName(context, parentMapper);
|
|
|
|
|
|
+ throwOnNoFieldName(context);
|
|
}
|
|
}
|
|
- Mapper mapper = getLeafMapper(context, parentMapper, currentFieldName);
|
|
|
|
|
|
+ Mapper mapper = getLeafMapper(context, currentFieldName);
|
|
if (mapper != null) {
|
|
if (mapper != null) {
|
|
parseObjectOrField(context, mapper);
|
|
parseObjectOrField(context, mapper);
|
|
} else {
|
|
} else {
|
|
- parseDynamicValue(context, parentMapper, currentFieldName);
|
|
|
|
|
|
+ parseDynamicValue(context, currentFieldName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static void throwOnNoFieldName(DocumentParserContext context, ObjectMapper parentMapper) throws IOException {
|
|
|
|
|
|
+ private static void throwOnNoFieldName(DocumentParserContext context) throws IOException {
|
|
throw new DocumentParsingException(
|
|
throw new DocumentParsingException(
|
|
context.parser().getTokenLocation(),
|
|
context.parser().getTokenLocation(),
|
|
"object mapping ["
|
|
"object mapping ["
|
|
- + parentMapper.name()
|
|
|
|
|
|
+ + context.parent().name()
|
|
+ "] trying to serialize a value with"
|
|
+ "] trying to serialize a value with"
|
|
+ " no field associated with it, current value ["
|
|
+ " no field associated with it, current value ["
|
|
+ context.parser().textOrNull()
|
|
+ context.parser().textOrNull()
|
|
@@ -600,35 +588,33 @@ public final class DocumentParser {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseNullValue(DocumentParserContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
|
|
|
|
|
|
+ private static void parseNullValue(DocumentParserContext context, String lastFieldName) throws IOException {
|
|
// we can only handle null values if we have mappings for them
|
|
// we can only handle null values if we have mappings for them
|
|
- Mapper mapper = getLeafMapper(context, parentMapper, lastFieldName);
|
|
|
|
|
|
+ Mapper mapper = getLeafMapper(context, lastFieldName);
|
|
if (mapper != null) {
|
|
if (mapper != null) {
|
|
// TODO: passing null to an object seems bogus?
|
|
// TODO: passing null to an object seems bogus?
|
|
parseObjectOrField(context, mapper);
|
|
parseObjectOrField(context, mapper);
|
|
- } else if (parentMapper.dynamic() == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
- throw new StrictDynamicMappingException(context.parser().getTokenLocation(), parentMapper.fullPath(), lastFieldName);
|
|
|
|
|
|
+ } else if (context.dynamic() == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
+ throw new StrictDynamicMappingException(context.parser().getTokenLocation(), context.parent().fullPath(), lastFieldName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static void parseDynamicValue(final DocumentParserContext context, ObjectMapper parentMapper, String currentFieldName)
|
|
|
|
- throws IOException {
|
|
|
|
- ObjectMapper.Dynamic dynamic = dynamicOrDefault(parentMapper, context);
|
|
|
|
- if (dynamic == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
- throw new StrictDynamicMappingException(context.parser().getTokenLocation(), parentMapper.fullPath(), currentFieldName);
|
|
|
|
|
|
+ private static void parseDynamicValue(final DocumentParserContext context, String currentFieldName) throws IOException {
|
|
|
|
+ if (context.dynamic() == ObjectMapper.Dynamic.STRICT) {
|
|
|
|
+ throw new StrictDynamicMappingException(context.parser().getTokenLocation(), context.parent().fullPath(), currentFieldName);
|
|
}
|
|
}
|
|
- if (dynamic == ObjectMapper.Dynamic.FALSE) {
|
|
|
|
- failIfMatchesRoutingPath(context, parentMapper, currentFieldName);
|
|
|
|
|
|
+ if (context.dynamic() == ObjectMapper.Dynamic.FALSE) {
|
|
|
|
+ failIfMatchesRoutingPath(context, currentFieldName);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- dynamic.getDynamicFieldsBuilder().createDynamicFieldFromValue(context, currentFieldName);
|
|
|
|
|
|
+ context.dynamic().getDynamicFieldsBuilder().createDynamicFieldFromValue(context, currentFieldName);
|
|
}
|
|
}
|
|
|
|
|
|
- private static void failIfMatchesRoutingPath(DocumentParserContext context, ObjectMapper parentMapper, String currentFieldName) {
|
|
|
|
|
|
+ private static void failIfMatchesRoutingPath(DocumentParserContext context, String currentFieldName) {
|
|
if (context.indexSettings().getIndexMetadata().getRoutingPaths().isEmpty()) {
|
|
if (context.indexSettings().getIndexMetadata().getRoutingPaths().isEmpty()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- String path = parentMapper.fullPath().isEmpty() ? currentFieldName : parentMapper.fullPath() + "." + currentFieldName;
|
|
|
|
|
|
+ String path = context.parent().fullPath().isEmpty() ? currentFieldName : context.parent().fullPath() + "." + currentFieldName;
|
|
if (Regex.simpleMatch(context.indexSettings().getIndexMetadata().getRoutingPaths(), path)) {
|
|
if (Regex.simpleMatch(context.indexSettings().getIndexMetadata().getRoutingPaths(), path)) {
|
|
throw new DocumentParsingException(
|
|
throw new DocumentParsingException(
|
|
context.parser().getTokenLocation(),
|
|
context.parser().getTokenLocation(),
|
|
@@ -653,57 +639,15 @@ public final class DocumentParser {
|
|
}
|
|
}
|
|
assert targetDoc != null;
|
|
assert targetDoc != null;
|
|
final DocumentParserContext copyToContext = context.createCopyToContext(field, targetDoc);
|
|
final DocumentParserContext copyToContext = context.createCopyToContext(field, targetDoc);
|
|
- innerParseObject(copyToContext, context.root());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // find what the dynamic setting is given the current parse context and parent
|
|
|
|
- private static ObjectMapper.Dynamic dynamicOrDefault(ObjectMapper parentMapper, DocumentParserContext context) {
|
|
|
|
- ObjectMapper.Dynamic dynamic = parentMapper.dynamic();
|
|
|
|
- while (dynamic == null) {
|
|
|
|
- int lastDotNdx = parentMapper.name().lastIndexOf('.');
|
|
|
|
- if (lastDotNdx == -1) {
|
|
|
|
- // no dot means we the parent is the root, so just delegate to the default outside the loop
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- String parentName = parentMapper.name().substring(0, lastDotNdx);
|
|
|
|
- parentMapper = context.mappingLookup().objectMappers().get(parentName);
|
|
|
|
- if (parentMapper == null) {
|
|
|
|
- // If parentMapper is null, it means the parent of the current mapper is being dynamically created right now
|
|
|
|
- parentMapper = context.getDynamicObjectMapper(parentName);
|
|
|
|
- if (parentMapper == null) {
|
|
|
|
- // it can still happen that the path is ambiguous and we are not able to locate the parent
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- dynamic = parentMapper.dynamic();
|
|
|
|
- }
|
|
|
|
- if (dynamic == null) {
|
|
|
|
- return context.root().dynamic() == null ? ObjectMapper.Dynamic.TRUE : context.root().dynamic();
|
|
|
|
|
|
+ innerParseObject(copyToContext);
|
|
}
|
|
}
|
|
- return dynamic;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // looks up a child mapper
|
|
|
|
- // returns null if no such child mapper exists - note that unlike getLeafMapper,
|
|
|
|
- // we do not check for runtime fields with same name as they only apply to leaf
|
|
|
|
- // fields
|
|
|
|
- private static Mapper getMapper(final DocumentParserContext context, ObjectMapper objectMapper, String fieldName) {
|
|
|
|
- if (context.path().atRoot()) {
|
|
|
|
- // Check if mapper is a metadata mapper first
|
|
|
|
- Mapper mapper = context.getMetadataMapper(fieldName);
|
|
|
|
- if (mapper != null) {
|
|
|
|
- return mapper;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return objectMapper.getMapper(fieldName);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// looks up a child mapper
|
|
// looks up a child mapper
|
|
// if no mapper is found, checks to see if a runtime field with the specified
|
|
// if no mapper is found, checks to see if a runtime field with the specified
|
|
// field name exists and if so returns a no-op mapper to prevent indexing
|
|
// field name exists and if so returns a no-op mapper to prevent indexing
|
|
- private static Mapper getLeafMapper(final DocumentParserContext context, ObjectMapper objectMapper, String fieldName) {
|
|
|
|
- Mapper mapper = getMapper(context, objectMapper, fieldName);
|
|
|
|
|
|
+ private static Mapper getLeafMapper(final DocumentParserContext context, String fieldName) {
|
|
|
|
+ Mapper mapper = context.getMapper(fieldName);
|
|
if (mapper != null) {
|
|
if (mapper != null) {
|
|
return mapper;
|
|
return mapper;
|
|
}
|
|
}
|
|
@@ -743,7 +687,7 @@ public final class DocumentParser {
|
|
) {
|
|
) {
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- protected void parseCreateField(DocumentParserContext context) throws IOException {
|
|
|
|
|
|
+ protected void parseCreateField(DocumentParserContext context) {
|
|
// field defined as runtime field, don't index anything
|
|
// field defined as runtime field, don't index anything
|
|
}
|
|
}
|
|
|
|
|
|
@@ -788,7 +732,7 @@ public final class DocumentParser {
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) {
|
|
throw new UnsupportedOperationException();
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -808,7 +752,7 @@ public final class DocumentParser {
|
|
* Internal version of {@link DocumentParserContext} that is aware of implementation details like nested documents
|
|
* Internal version of {@link DocumentParserContext} that is aware of implementation details like nested documents
|
|
* and how they are stored in the lucene index.
|
|
* and how they are stored in the lucene index.
|
|
*/
|
|
*/
|
|
- private static class InternalDocumentParserContext extends DocumentParserContext {
|
|
|
|
|
|
+ private static class RootDocumentParserContext extends DocumentParserContext {
|
|
private final ContentPath path = new ContentPath();
|
|
private final ContentPath path = new ContentPath();
|
|
private final XContentParser parser;
|
|
private final XContentParser parser;
|
|
private final LuceneDocument document;
|
|
private final LuceneDocument document;
|
|
@@ -817,13 +761,19 @@ public final class DocumentParser {
|
|
private long numNestedDocs;
|
|
private long numNestedDocs;
|
|
private boolean docsReversed = false;
|
|
private boolean docsReversed = false;
|
|
|
|
|
|
- InternalDocumentParserContext(
|
|
|
|
|
|
+ RootDocumentParserContext(
|
|
MappingLookup mappingLookup,
|
|
MappingLookup mappingLookup,
|
|
MappingParserContext mappingParserContext,
|
|
MappingParserContext mappingParserContext,
|
|
SourceToParse source,
|
|
SourceToParse source,
|
|
XContentParser parser
|
|
XContentParser parser
|
|
) throws IOException {
|
|
) throws IOException {
|
|
- super(mappingLookup, mappingParserContext, source);
|
|
|
|
|
|
+ super(
|
|
|
|
+ mappingLookup,
|
|
|
|
+ mappingParserContext,
|
|
|
|
+ source,
|
|
|
|
+ mappingLookup.getMapping().getRoot(),
|
|
|
|
+ ObjectMapper.Dynamic.getRootDynamic(mappingLookup)
|
|
|
|
+ );
|
|
if (mappingLookup.getMapping().getRoot().subobjects()) {
|
|
if (mappingLookup.getMapping().getRoot().subobjects()) {
|
|
this.parser = DotExpandingXContentParser.expandDots(parser, this.path);
|
|
this.parser = DotExpandingXContentParser.expandDots(parser, this.path);
|
|
} else {
|
|
} else {
|
|
@@ -835,6 +785,15 @@ public final class DocumentParser {
|
|
this.numNestedDocs = 0L;
|
|
this.numNestedDocs = 0L;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public Mapper getMapper(String name) {
|
|
|
|
+ Mapper mapper = getMetadataMapper(name);
|
|
|
|
+ if (mapper != null) {
|
|
|
|
+ return mapper;
|
|
|
|
+ }
|
|
|
|
+ return super.getMapper(name);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public ContentPath path() {
|
|
public ContentPath path() {
|
|
return this.path;
|
|
return this.path;
|