diff --git a/.idea/dictionaries/kimchy.xml b/.idea/dictionaries/kimchy.xml
index 9d24bb5f29a..2574bef590f 100644
--- a/.idea/dictionaries/kimchy.xml
+++ b/.idea/dictionaries/kimchy.xml
@@ -95,6 +95,7 @@
queryparser
rackspace
rebalance
+ reparse
retrans
retval
rsts
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java
index 92cbdd02a0c..7f855523f2c 100644
--- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java
@@ -147,7 +147,7 @@ public class MetaDataMappingService extends AbstractComponent {
} else if (!mappingType.equals(newMappers.values().iterator().next().type())) {
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition");
}
- if (mappingType.charAt(0) == '_') {
+ if (!MapperService.DEFAULT_MAPPING.equals(mappingType) && mappingType.charAt(0) == '_') {
throw new InvalidTypeNameException("Document mapping type name can't start with '_'");
}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/xcontent/XContentMerger.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/xcontent/XContentMerger.java
new file mode 100644
index 00000000000..f1acc1efe3d
--- /dev/null
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/xcontent/XContentMerger.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.common.xcontent;
+
+import java.util.Map;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class XContentMerger {
+
+ /**
+ * Merges the defaults provided as the second parameter into the content of the first. Only does recursive merge
+ * for inner maps.
+ */
+ @SuppressWarnings({"unchecked"}) public static void mergeDefaults(Map content, Map defaults) {
+ for (Map.Entry defaultEntry : defaults.entrySet()) {
+ if (!content.containsKey(defaultEntry.getKey())) {
+ // copy it over, it does not exists in the content
+ content.put(defaultEntry.getKey(), defaultEntry.getValue());
+ } else {
+ // in the content and in the default, only merge compound ones (maps)
+ if (content.get(defaultEntry.getKey()) instanceof Map && defaultEntry.getValue() instanceof Map) {
+ mergeDefaults((Map) content.get(defaultEntry.getKey()), (Map) defaultEntry.getValue());
+ }
+ }
+ }
+ }
+}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java
index 853ec9f6d88..3e9555abaaa 100644
--- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java
@@ -26,6 +26,11 @@ import javax.annotation.Nullable;
*/
public interface DocumentMapperParser {
+ /**
+ * Parses the source mapping definition into a document mapper.
+ */
+ DocumentMapper parse(String mappingSource) throws MapperParsingException;
+
/**
* Parses the source mapping definition into a document mapper with the specified
* type (overriding the one defined in the source mapping).
@@ -33,7 +38,8 @@ public interface DocumentMapperParser {
DocumentMapper parse(@Nullable String type, String mappingSource) throws MapperParsingException;
/**
- * Parses the source mapping definition into a document mapper.
+ * Parses the source mapping definition into a document mapper with the specified
+ * type (overriding the one defined in the source mapping).
*/
- DocumentMapper parse(String mappingSource) throws MapperParsingException;
+ DocumentMapper parse(@Nullable String type, String mappingSource, String defaultMappingSource) throws MapperParsingException;
}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java
index fd9b004d1ba..655c2cd807b 100644
--- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java
@@ -51,16 +51,14 @@ import static org.elasticsearch.common.collect.MapBuilder.*;
@ThreadSafe
public class MapperService extends AbstractIndexComponent implements Iterable {
+ public static final String DEFAULT_MAPPING = "_default_";
+
/**
* Will create types automatically if they do not exists in the repo yet
*/
private final boolean dynamic;
- private final String dynamicMappingLocation;
-
- private final URL dynamicMappingUrl;
-
- private final String dynamicMappingSource;
+ private volatile String defaultMappingSource;
private volatile ImmutableMap mappers = ImmutableMap.of();
@@ -74,7 +72,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable iterator() {
@@ -145,7 +134,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable root;
- XContentParser xContentParser = null;
- try {
- xContentParser = XContentFactory.xContent(source).createParser(source);
- root = xContentParser.map();
- } catch (IOException e) {
- throw new MapperParsingException("Failed to parse mapping definition", e);
- } finally {
- if (xContentParser != null) {
- xContentParser.close();
- }
+ @Override public XContentDocumentMapper parse(@Nullable String type, String source) throws MapperParsingException {
+ return parse(type, source, null);
+ }
+
+ @Override public XContentDocumentMapper parse(@Nullable String type, String source, String defaultSource) throws MapperParsingException {
+ Map mapping = null;
+ if (source != null) {
+ Tuple> t = extractMapping(type, source);
+ type = t.v1();
+ mapping = t.v2();
}
- String rootName = root.keySet().iterator().next();
- Map rootObj;
+ if (mapping == null) {
+ mapping = Maps.newHashMap();
+ }
+
if (type == null) {
- // we have no type, we assume the first node is the type
- rootObj = (Map) root.get(rootName);
- type = rootName;
- } else {
- // we have a type, check if the top level one is the type as well
- // if it is, then the root is that node, if not then the root is the master node
- if (type.equals(rootName)) {
- Object tmpNode = root.get(type);
- if (!(tmpNode instanceof Map)) {
- throw new MapperParsingException("Expected root node name [" + rootName + "] to be of object type, but its not");
- }
- rootObj = (Map) tmpNode;
- } else if (rootName.equals("_default_")) {
- Object tmpNode = root.get("_default_");
- if (!(tmpNode instanceof Map)) {
- throw new MapperParsingException("_default_ mappings must have an inner object representing the actual mappings for the type");
- }
- rootObj = (Map) tmpNode;
- } else {
- rootObj = root;
+ throw new MapperParsingException("Failed to derive type");
+ }
+
+ if (defaultSource != null) {
+ Tuple> t = extractMapping(MapperService.DEFAULT_MAPPING, defaultSource);
+ if (t.v2() != null) {
+ XContentMerger.mergeDefaults(mapping, t.v2());
}
}
- XContentTypeParser.ParserContext parserContext = new XContentTypeParser.ParserContext(rootObj, analysisService, typeParsers);
+ XContentTypeParser.ParserContext parserContext = new XContentTypeParser.ParserContext(mapping, analysisService, typeParsers);
- XContentDocumentMapper.Builder docBuilder = doc((XContentObjectMapper.Builder) rootObjectTypeParser.parse(type, rootObj, parserContext));
+ XContentDocumentMapper.Builder docBuilder = doc((XContentObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext));
- for (Map.Entry entry : rootObj.entrySet()) {
+ for (Map.Entry entry : mapping.entrySet()) {
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
@@ -157,13 +147,11 @@ public class XContentDocumentMapperParser implements DocumentMapperParser {
}
ImmutableMap attributes = ImmutableMap.of();
- if (rootObj.containsKey("_attributes")) {
- attributes = ImmutableMap.copyOf((Map) rootObj.get("_attributes"));
+ if (mapping.containsKey("_attributes")) {
+ attributes = ImmutableMap.copyOf((Map) mapping.get("_attributes"));
}
docBuilder.attributes(attributes);
- docBuilder.mappingSource(source);
-
XContentDocumentMapper documentMapper = docBuilder.build();
// update the source with the generated one
documentMapper.mappingSource(documentMapper.buildSource());
@@ -227,4 +215,31 @@ public class XContentDocumentMapperParser implements DocumentMapperParser {
}
return builder;
}
+
+ private Tuple> extractMapping(String type, String source) throws MapperParsingException {
+ Map root;
+ XContentParser xContentParser = null;
+ try {
+ xContentParser = XContentFactory.xContent(source).createParser(source);
+ root = xContentParser.map();
+ } catch (IOException e) {
+ throw new MapperParsingException("Failed to parse mapping definition", e);
+ } finally {
+ if (xContentParser != null) {
+ xContentParser.close();
+ }
+ }
+
+ // we always assume the first and single key is the mapping type root
+ if (root.keySet().size() != 1) {
+ throw new MapperParsingException("Mapping must have the `type` as the root object");
+ }
+
+ String rootName = root.keySet().iterator().next();
+ if (type == null) {
+ type = rootName;
+ }
+
+ return new Tuple>(type, (Map) root.get(rootName));
+ }
}
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java
index 0e66f5c6683..af0efb2b14a 100644
--- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java
+++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java
@@ -314,8 +314,16 @@ public class XContentObjectMapper implements XContentMapper, XContentIncludeInAl
context.path().pathType(pathType);
String currentFieldName = parser.currentName();
- XContentParser.Token token;
- while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+ XContentParser.Token token = parser.currentToken();
+ // if we are at the end of the previous object, advance
+ if (token == XContentParser.Token.END_OBJECT) {
+ token = parser.nextToken();
+ }
+ if (token == XContentParser.Token.START_OBJECT) {
+ // if we are just starting an OBJECT, advance, this is the object we are parsing, we need the name first
+ token = parser.nextToken();
+ }
+ while (token != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.START_OBJECT) {
serializeObject(context, currentFieldName);
} else if (token == XContentParser.Token.START_ARRAY) {
@@ -324,9 +332,10 @@ public class XContentObjectMapper implements XContentMapper, XContentIncludeInAl
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.VALUE_NULL) {
serializeNullValue(context, currentFieldName);
- } else {
+ } else if (token.isValue()) {
serializeValue(context, currentFieldName, token);
}
+ token = parser.nextToken();
}
// restore the enable path flag
context.path().pathType(origPathType);
diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/dynamic-mapping.json b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/default-mapping.json
similarity index 100%
rename from modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/dynamic-mapping.json
rename to modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/default-mapping.json
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/XContentMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/XContentMapperTests.java
new file mode 100644
index 00000000000..951ba1c75a3
--- /dev/null
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/XContentMapperTests.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.mapper.xcontent;
+
+import org.elasticsearch.common.settings.ImmutableSettings;
+import org.elasticsearch.env.Environment;
+import org.elasticsearch.index.Index;
+import org.elasticsearch.index.analysis.AnalysisService;
+import org.elasticsearch.index.mapper.MapperService;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class XContentMapperTests {
+
+ public static XContentDocumentMapperParser newParser() {
+ return new XContentDocumentMapperParser(new AnalysisService(new Index("test")));
+ }
+
+ public static MapperService newMapperService() {
+ return new MapperService(new Index("test"), ImmutableSettings.Builder.EMPTY_SETTINGS, new Environment(), new AnalysisService(new Index("test")));
+ }
+}
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java
index bd00466bcb7..a8b6c9edc39 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java
@@ -23,10 +23,8 @@ import org.apache.lucene.document.Document;
import org.elasticsearch.common.lucene.all.AllEntries;
import org.elasticsearch.common.lucene.all.AllField;
import org.elasticsearch.common.lucene.all.AllTokenStream;
-import org.elasticsearch.index.Index;
-import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
-import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
import org.testng.annotations.Test;
import static org.elasticsearch.common.io.Streams.*;
@@ -41,7 +39,7 @@ public class SimpleAllMapperTests {
@Test public void testSimpleAllMappers() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/mapping.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping);
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json");
Document doc = docMapper.parse(json).doc();
AllField field = (AllField) doc.getFieldable("_all");
@@ -53,11 +51,11 @@ public class SimpleAllMapperTests {
@Test public void testSimpleAllMappersWithReparse() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/mapping.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping);
String builtMapping = docMapper.buildSource();
// System.out.println(builtMapping);
// reparse it
- XContentDocumentMapper builtDocMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(builtMapping);
+ XContentDocumentMapper builtDocMapper = XContentMapperTests.newParser().parse(builtMapping);
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json");
Document doc = builtDocMapper.parse(json).doc();
@@ -70,7 +68,7 @@ public class SimpleAllMapperTests {
@Test public void testSimpleAllMappersWithStore() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping);
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json");
Document doc = docMapper.parse(json).doc();
AllField field = (AllField) doc.getFieldable("_all");
@@ -85,11 +83,11 @@ public class SimpleAllMapperTests {
@Test public void testSimpleAllMappersWithReparseWithStore() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping);
String builtMapping = docMapper.buildSource();
System.out.println(builtMapping);
// reparse it
- XContentDocumentMapper builtDocMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(builtMapping);
+ XContentDocumentMapper builtDocMapper = XContentMapperTests.newParser().parse(builtMapping);
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json");
Document doc = builtDocMapper.parse(json).doc();
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json
index e8b8697c9d1..657743a04a4 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json
@@ -1,33 +1,33 @@
{
- person : {
- _all : {enabled : true},
- properties : {
- name : {
- type : "object",
- dynamic : false,
- properties : {
- first : {type : "string", store : "yes", include_in_all : false},
- last : {type : "string", index : "not_analyzed"}
+ "person" : {
+ "_all" : {"enabled" : true},
+ "properties" : {
+ "name" : {
+ "type" : "object",
+ "dynamic" : false,
+ "properties" : {
+ "first" : {"type" : "string", "store" : "yes", "include_in_all" : false},
+ "last" : {"type" : "string", "index" : "not_analyzed"}
}
},
- address : {
- type : "object",
- include_in_all : false,
- properties : {
- first : {
- properties : {
- location : {type : "string", store : "yes", index_name : "firstLocation"}
+ "address" : {
+ "type" : "object",
+ "include_in_all" : false,
+ "properties" : {
+ "first" : {
+ "properties" : {
+ "location" : {"type" : "string", "store" : "yes", "index_name" : "firstLocation"}
}
},
- last : {
- properties : {
- location : {type : "string"}
+ "last" : {
+ "properties" : {
+ "location" : {"type" : "string"}
}
}
}
},
- simple1 : {type : "long", include_in_all : true},
- simple2 : {type : "long", include_in_all : false}
+ "simple1" : {"type" : "long", "include_in_all" : true},
+ "simple2" : {"type" : "long", "include_in_all" : false}
}
}
}
\ No newline at end of file
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json
index 4ed84b785da..356d7ef3d29 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json
@@ -1,33 +1,33 @@
{
- person : {
- _all : {enabled : true, store : "yes"},
- properties : {
- name : {
- type : "object",
- dynamic : false,
- properties : {
- first : {type : "string", store : "yes", include_in_all : false},
- last : {type : "string", index : "not_analyzed"}
+ "person" : {
+ "_all" : {"enabled" : true, "store" : "yes"},
+ "properties" : {
+ "name" : {
+ "type" : "object",
+ "dynamic" : false,
+ "properties" : {
+ "first" : {"type" : "string", "store" : "yes", "include_in_all" : false},
+ "last" : {"type" : "string", "index" : "not_analyzed"}
}
},
- address : {
- type : "object",
- include_in_all : false,
- properties : {
- first : {
- properties : {
- location : {type : "string", store : "yes", index_name : "firstLocation"}
+ "address" : {
+ "type" : "object",
+ "include_in_all" : false,
+ "properties" : {
+ "first" : {
+ "properties" : {
+ "location" : {"type" : "string", "store" : "yes", "index_name" : "firstLocation"}
}
},
- last : {
- properties : {
- location : {type : "string"}
+ "last" : {
+ "properties" : {
+ "location" : {"type" : "string"}
}
}
}
},
- simple1 : {type : "long", include_in_all : true},
- simple2 : {type : "long", include_in_all : false}
+ "simple1" : {"type" : "long", "include_in_all" : true},
+ "simple2" : {"type" : "long", "include_in_all" : false}
}
}
}
\ No newline at end of file
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json
index 8c5e43c1c5b..378b8a2df4a 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json
@@ -1,20 +1,20 @@
{
- person : {
- _boost : 3.7,
- _id : "1",
- name : {
- first : "shay",
- last : "banon"
+ "person" : {
+ "_boost" : 3.7,
+ "_id" : "1",
+ "name" : {
+ "first" : "shay",
+ "last" : "banon"
},
- address : {
- first : {
- location : "first location"
+ "address" : {
+ "first" : {
+ "location" : "first location"
},
- last : {
- location : "last location"
+ "last" : {
+ "location" : "last location"
}
},
- simple1 : 1,
- simple2 : 2
+ "simple1" : 1,
+ "simple2" : 2
}
}
\ No newline at end of file
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/defaultsource/DefaultSourceMappingTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/defaultsource/DefaultSourceMappingTests.java
new file mode 100644
index 00000000000..137a3369947
--- /dev/null
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/defaultsource/DefaultSourceMappingTests.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.mapper.xcontent.defaultsource;
+
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.mapper.MapperParsingException;
+import org.elasticsearch.index.mapper.MapperService;
+import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
+import org.testng.annotations.Test;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class DefaultSourceMappingTests {
+
+ @Test public void testDefaultMappingAndNoMapping() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING)
+ .startObject("_source").field("enabled", false).endObject()
+ .endObject().endObject().string();
+
+ XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("my_type", null, defaultMapping);
+ assertThat(mapper.type(), equalTo("my_type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+
+ try {
+ mapper = XContentMapperTests.newParser().parse(null, null, defaultMapping);
+ assertThat(mapper.type(), equalTo("my_type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+ assert false;
+ } catch (MapperParsingException e) {
+ // all is well
+ }
+ }
+
+ @Test public void testDefaultMappingAndWithMappingOverride() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING)
+ .startObject("_source").field("enabled", false).endObject()
+ .endObject().endObject().string();
+
+ String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type")
+ .startObject("_source").field("enabled", true).endObject()
+ .endObject().endObject().string();
+
+ XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("my_type", mapping, defaultMapping);
+ assertThat(mapper.type(), equalTo("my_type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(true));
+ }
+
+ @Test public void testDefaultMappingAndNoMappingWithMapperService() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING)
+ .startObject("_source").field("enabled", false).endObject()
+ .endObject().endObject().string();
+
+ MapperService mapperService = XContentMapperTests.newMapperService();
+ mapperService.add(MapperService.DEFAULT_MAPPING, defaultMapping);
+
+ XContentDocumentMapper mapper = (XContentDocumentMapper) mapperService.type("my_type");
+ assertThat(mapper.type(), equalTo("my_type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+ }
+
+ @Test public void testDefaultMappingAndWithMappingOverrideWithMapperService() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING)
+ .startObject("_source").field("enabled", false).endObject()
+ .endObject().endObject().string();
+
+ MapperService mapperService = XContentMapperTests.newMapperService();
+ mapperService.add(MapperService.DEFAULT_MAPPING, defaultMapping);
+
+ String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type")
+ .startObject("_source").field("enabled", true).endObject()
+ .endObject().endObject().string();
+ mapperService.add("my_type", mapping);
+
+ XContentDocumentMapper mapper = (XContentDocumentMapper) mapperService.type("my_type");
+ assertThat(mapper.type(), equalTo("my_type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(true));
+ }
+}
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java
index 9774e9c4534..e39a92ec360 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java
@@ -19,11 +19,9 @@
package org.elasticsearch.index.mapper.xcontent.merge.test1;
-import org.elasticsearch.index.Index;
-import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
-import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
import org.testng.annotations.Test;
import static org.elasticsearch.common.io.Streams.*;
@@ -39,9 +37,9 @@ public class Test1MergeMapperTests {
@Test public void test1Merge() throws Exception {
String stage1Mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/merge/test1/stage1.json");
- XContentDocumentMapper stage1 = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(stage1Mapping);
+ XContentDocumentMapper stage1 = XContentMapperTests.newParser().parse(stage1Mapping);
String stage2Mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/merge/test1/stage2.json");
- XContentDocumentMapper stage2 = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(stage2Mapping);
+ XContentDocumentMapper stage2 = XContentMapperTests.newParser().parse(stage2Mapping);
DocumentMapper.MergeResult mergeResult = stage1.merge(stage2, mergeFlags().simulate(true));
assertThat(mergeResult.hasConflicts(), equalTo(false));
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java
index ec7d74d6aa2..08c141e8d95 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java
@@ -21,10 +21,8 @@ package org.elasticsearch.index.mapper.xcontent.multifield;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
-import org.elasticsearch.index.Index;
-import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
-import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
import org.testng.annotations.Test;
import static org.elasticsearch.common.io.Streams.*;
@@ -40,7 +38,7 @@ public class XContentMultiFieldTests {
@Test public void testMultiField() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping);
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json");
Document doc = docMapper.parse(json).doc();
@@ -81,7 +79,7 @@ public class XContentMultiFieldTests {
String builtMapping = builderDocMapper.buildSource();
// System.out.println(builtMapping);
// reparse it
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(builtMapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(builtMapping);
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json");
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json
index 4a1795da6b4..e3d73279543 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json
@@ -1,7 +1,7 @@
{
- _id : 1,
- name : "some name",
- object1 : {
- multi1 : "2010-01-01"
+ "_id" : 1,
+ "name" : "some name",
+ "object1" : {
+ "multi1" : "2010-01-01"
}
}
\ No newline at end of file
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json
index 489f80f4eb2..edce702ddc3 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json
@@ -1,21 +1,21 @@
{
- person : {
- properties : {
+ "person" : {
+ "properties" : {
"name" : {
- type : "multi_field",
+ "type" : "multi_field",
"fields" : {
- "name" : {type: "string", index : "analyzed", store : "yes"},
- "indexed" : {type: "string", index : "analyzed"},
- "not_indexed" : {type: "string", index : "no", store : "yes"}
+ "name" : {"type": "string", "index" : "analyzed", "store" : "yes"},
+ "indexed" : {"type": "string", "index" : "analyzed"},
+ "not_indexed" : {"type": "string", "index" : "no", "store" : "yes"}
}
},
"object1" : {
- properties : {
+ "properties" : {
"multi1" : {
- type : "multi_field",
+ "type" : "multi_field",
"fields" : {
- "multi1" : {type : "date"},
- "string" : {type: "string", index : "not_analyzed"}
+ "multi1" : {"type": "date"},
+ "string" : {"type": "string", "index" : "not_analyzed"}
}
}
}
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/overridetype/OverrideTypeMappingTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/overridetype/OverrideTypeMappingTests.java
new file mode 100644
index 00000000000..4d04ffdee61
--- /dev/null
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/overridetype/OverrideTypeMappingTests.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.mapper.xcontent.overridetype;
+
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
+import org.testng.annotations.Test;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class OverrideTypeMappingTests {
+
+ @Test public void testOverrideType() throws Exception {
+ String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type")
+ .startObject("_source").field("enabled", false).endObject()
+ .endObject().endObject().string();
+
+ XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("my_type", mapping);
+ assertThat(mapper.type(), equalTo("my_type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+
+ mapper = XContentMapperTests.newParser().parse(mapping);
+ assertThat(mapper.type(), equalTo("type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+ }
+}
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java
index 38c7ca03844..94e8ac2db3d 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java
@@ -19,10 +19,8 @@
package org.elasticsearch.index.mapper.xcontent.path;
-import org.elasticsearch.index.Index;
-import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
-import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
import org.testng.annotations.Test;
import java.io.IOException;
@@ -38,7 +36,7 @@ public class PathXContentMapperTests {
@Test public void testPathMapping() throws IOException {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/path/test-mapping.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
+ XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping);
assertThat(docMapper.mappers().indexName("first1"), notNullValue());
assertThat(docMapper.mappers().indexName("name1.first1"), nullValue());
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java
index 364e99628ce..0f93b561636 100644
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java
@@ -91,19 +91,6 @@ public class SimpleXContentMapperTests {
// System.out.println("Json: " + docMapper.sourceMapper().value(doc));
}
- @Test public void testSimpleParserMappingWithNoType() throws Exception {
- String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json");
- XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse("person", mapping);
- byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test1.json");
- Document doc = docMapper.parse(json).doc();
- assertThat(doc.get(docMapper.uidMapper().names().indexName()), equalTo(Uid.createUid("person", "1")));
- assertThat((double) doc.getBoost(), closeTo(3.7, 0.01));
- assertThat(doc.get(docMapper.mappers().name("first").mapper().names().indexName()), equalTo("shay"));
- assertThat(doc.getFields(docMapper.idMapper().names().indexName()).length, equalTo(1));
-// System.out.println("Document: " + doc);
-// System.out.println("Json: " + docMapper.sourceMapper().value(doc));
- }
-
@Test public void testSimpleParserNoTypeNoId() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json");
XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping);
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json
deleted file mode 100644
index 1a62b97657d..00000000000
--- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- date_formats : ["yyyy-MM-dd", "dd-MM-yyyy"],
- dynamic : false,
- enabled : true,
- _id : {name : "_id", index_name : "_id"},
- _source : {name : "_source" },
- _type : {name : "_type"},
- _boost : {name : "_boost", null_value : 2.0},
- properties : {
- name : {
- type : "object",
- dynamic : false,
- properties : {
- first : {type : "string", store : "yes"},
- last : {type : "string", index : "not_analyzed"}
- }
- },
- address : {
- type : "object",
- properties : {
- first : {
- properties : {
- location : {type : "string", store : "yes", index_name : "firstLocation"}
- }
- },
- last : {
- properties : {
- location : {type : "string"}
- }
- }
- }
- },
- age : {type : "integer", null_value : 0},
- birthdate : {type : "date", format : "yyyy-MM-dd"},
- nerd : {type : "boolean"},
- dogs : {type : "string", index_name : "dog"},
- complex : {
- type : "object",
- properties : {
- value1 : {type : "string"},
- value2 : {type : "string"}
- }
- },
- complex2 : {
- type : "object",
- properties : {
- value1 : {type : "string"},
- value2 : {type : "string"}
- }
- }
- }
-}
\ No newline at end of file
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseDocumentTypeLevelsTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseDocumentTypeLevelsTests.java
new file mode 100644
index 00000000000..068b62ee049
--- /dev/null
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseDocumentTypeLevelsTests.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.mapper.xcontent.typelevels;
+
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.mapper.ParsedDocument;
+import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
+import org.testng.annotations.Test;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class ParseDocumentTypeLevelsTests {
+
+ @Test public void testNoLevel() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testTypeLevel() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject().startObject("type")
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject().endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testNoLevelWithFieldTypeAsValue() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("type", "value_type")
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("type"), equalTo("value_type"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testTypeLevelWithFieldTypeAsValue() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject().startObject("type")
+ .field("type", "value_type")
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject().endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("type"), equalTo("value_type"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testNoLevelWithFieldTypeAsObject() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .startObject("type").field("type_field", "type_value").endObject()
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject()
+ .copiedBytes());
+
+ // in this case, we analyze the type object as the actual document, and ignore the other same level fields
+ assertThat(doc.doc().get("type_field"), equalTo("type_value"));
+ assertThat(doc.doc().get("test1"), nullValue());
+ assertThat(doc.doc().get("test2"), nullValue());
+ }
+
+ @Test public void testTypeLevelWithFieldTypeAsObject() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject().startObject("type")
+ .startObject("type").field("type_field", "type_value").endObject()
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject().endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("type.type_field"), equalTo("type_value"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testNoLevelWithFieldTypeAsValueNotFirst() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject().startObject("type")
+ .field("test1", "value1")
+ .field("test2", "value2")
+ .field("type", "value_type")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject().endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("type"), equalTo("value_type"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testTypeLevelWithFieldTypeAsValueNotFirst() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject().startObject("type")
+ .field("test1", "value1")
+ .field("type", "value_type")
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject().endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("type"), equalTo("value_type"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testNoLevelWithFieldTypeAsObjectNotFirst() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("test1", "value1")
+ .startObject("type").field("type_field", "type_value").endObject()
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject()
+ .copiedBytes());
+
+ // when the type is not the first one, we don't confuse it...
+ assertThat(doc.doc().get("type.type_field"), equalTo("type_value"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+
+ @Test public void testTypeLevelWithFieldTypeAsObjectNotFirst() throws Exception {
+ String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string();
+
+ XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping);
+
+ ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject().startObject("type")
+ .field("test1", "value1")
+ .startObject("type").field("type_field", "type_value").endObject()
+ .field("test2", "value2")
+ .startObject("inner").field("inner_field", "inner_value").endObject()
+ .endObject().endObject()
+ .copiedBytes());
+
+ assertThat(doc.doc().get("type.type_field"), equalTo("type_value"));
+ assertThat(doc.doc().get("test1"), equalTo("value1"));
+ assertThat(doc.doc().get("test2"), equalTo("value2"));
+ assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value"));
+ }
+}
diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseMappingTypeLevelTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseMappingTypeLevelTests.java
new file mode 100644
index 00000000000..941c4208711
--- /dev/null
+++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseMappingTypeLevelTests.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to Elastic Search and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Elastic Search licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.mapper.xcontent.typelevels;
+
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper;
+import org.elasticsearch.index.mapper.xcontent.XContentMapperTests;
+import org.testng.annotations.Test;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author kimchy (shay.banon)
+ */
+public class ParseMappingTypeLevelTests {
+
+ @Test public void testTypeLevel() throws Exception {
+ String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type")
+ .startObject("_source").field("enabled", false).endObject()
+ .endObject().endObject().string();
+
+ XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("type", mapping);
+ assertThat(mapper.type(), equalTo("type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+
+ mapper = XContentMapperTests.newParser().parse(mapping);
+ assertThat(mapper.type(), equalTo("type"));
+ assertThat(mapper.sourceMapper().enabled(), equalTo(false));
+ }
+}