diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
index 2dd130fc634..d17f0bf94e3 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
@@ -27,6 +27,8 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
@@ -89,6 +91,29 @@ public final class IndicesClient {
listener, Collections.emptySet(), headers);
}
+ /**
+ * Updates the mappings on an index using the Put Mapping API
+ *
+ * See
+ * Put Mapping API on elastic.co
+ */
+ public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, Header... headers) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent,
+ Collections.emptySet(), headers);
+ }
+
+ /**
+ * Asynchronously updates the mappings on an index using the Put Mapping API
+ *
+ * See
+ * Put Mapping API on elastic.co
+ */
+ public void putMappingAsync(PutMappingRequest putMappingRequest, ActionListener listener,
+ Header... headers) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent,
+ listener, Collections.emptySet(), headers);
+ }
+
/**
* Opens an index using the Open Index API
*
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java
index cc3b0deff52..229e45498aa 100755
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java
@@ -32,6 +32,7 @@ import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
@@ -178,6 +179,22 @@ public final class Request {
return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
}
+ static Request putMapping(PutMappingRequest putMappingRequest) throws IOException {
+ // The concreteIndex is an internal concept, not applicable to requests made over the REST API.
+ if (putMappingRequest.getConcreteIndex() != null) {
+ throw new IllegalArgumentException("concreteIndex cannot be set on PutMapping requests made over the REST API");
+ }
+
+ String endpoint = endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type());
+
+ Params parameters = Params.builder();
+ parameters.withTimeout(putMappingRequest.timeout());
+ parameters.withMasterTimeout(putMappingRequest.masterNodeTimeout());
+
+ HttpEntity entity = createEntity(putMappingRequest, REQUEST_BODY_CONTENT_TYPE);
+ return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
+ }
+
static Request info() {
return new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null);
}
@@ -454,6 +471,10 @@ public final class Request {
return endpoint(String.join(",", indices), String.join(",", types), endpoint);
}
+ static String endpoint(String[] indices, String endpoint, String type) {
+ return endpoint(String.join(",", indices), endpoint, type);
+ }
+
/**
* Utility method to build request's endpoint.
*/
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
index 5f8702807fb..2f81479f93a 100755
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
@@ -27,6 +27,8 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.support.IndicesOptions;
@@ -108,6 +110,35 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
}
}
+ @SuppressWarnings("unchecked")
+ public void testPutMapping() throws IOException {
+ {
+ // Add mappings to index
+ String indexName = "mapping_index";
+ createIndex(indexName);
+
+ PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
+ putMappingRequest.type("type_name");
+ XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
+ mappingBuilder.startObject().startObject("properties").startObject("field");
+ mappingBuilder.field("type", "text");
+ mappingBuilder.endObject().endObject().endObject();
+ putMappingRequest.source(mappingBuilder);
+
+ PutMappingResponse putMappingResponse =
+ execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
+ assertTrue(putMappingResponse.isAcknowledged());
+
+ Map indexMetaData = getIndexMetadata(indexName);
+ Map mappingsData = (Map) indexMetaData.get("mappings");
+ Map typeData = (Map) mappingsData.get("type_name");
+ Map properties = (Map) typeData.get("properties");
+ Map field = (Map) properties.get("field");
+
+ assertEquals("text", field.get("type"));
+ }
+ }
+
public void testDeleteIndex() throws IOException {
{
// Delete index if exists
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java
index 49667a3dee2..0ddaf1de1ca 100755
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java
@@ -28,6 +28,7 @@ import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkShardRequest;
@@ -317,6 +318,39 @@ public class RequestTests extends ESTestCase {
assertToXContentBody(createIndexRequest, request.getEntity());
}
+ public void testPutMapping() throws IOException {
+ PutMappingRequest putMappingRequest = new PutMappingRequest();
+
+ int numIndices = randomIntBetween(0, 5);
+ String[] indices = new String[numIndices];
+ for (int i = 0; i < numIndices; i++) {
+ indices[i] = "index-" + randomAlphaOfLengthBetween(2, 5);
+ }
+ putMappingRequest.indices(indices);
+
+ String type = randomAlphaOfLengthBetween(3, 10);
+ putMappingRequest.type(type);
+
+ Map expectedParams = new HashMap<>();
+
+ setRandomTimeout(putMappingRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
+ setRandomMasterTimeout(putMappingRequest, expectedParams);
+
+ Request request = Request.putMapping(putMappingRequest);
+ StringJoiner endpoint = new StringJoiner("/", "/", "");
+ String index = String.join(",", indices);
+ if (Strings.hasLength(index)) {
+ endpoint.add(index);
+ }
+ endpoint.add("_mapping");
+ endpoint.add(type);
+ assertEquals(endpoint.toString(), request.getEndpoint());
+
+ assertEquals(expectedParams, request.getParameters());
+ assertEquals("PUT", request.getMethod());
+ assertToXContentBody(putMappingRequest, request.getEntity());
+ }
+
public void testDeleteIndex() {
String[] indices = randomIndicesNames(0, 5);
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indices);
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
index bc3b1698f96..23029c7c6b0 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
@@ -28,6 +28,8 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.support.ActiveShardCount;
@@ -157,15 +159,15 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
// tag::create-index-request-mappings
request.mapping("tweet", // <1>
- " {\n" +
- " \"tweet\": {\n" +
- " \"properties\": {\n" +
- " \"message\": {\n" +
- " \"type\": \"text\"\n" +
- " }\n" +
+ "{\n" +
+ " \"tweet\": {\n" +
+ " \"properties\": {\n" +
+ " \"message\": {\n" +
+ " \"type\": \"text\"\n" +
" }\n" +
" }\n" +
- " }", // <2>
+ " }\n" +
+ "}", // <2>
XContentType.JSON);
// end::create-index-request-mappings
@@ -228,6 +230,86 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
}
}
+ public void testPutMapping() throws IOException {
+ RestHighLevelClient client = highLevelClient();
+
+ {
+ CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"));
+ assertTrue(createIndexResponse.isAcknowledged());
+ }
+
+ {
+ // tag::put-mapping-request
+ PutMappingRequest request = new PutMappingRequest("twitter"); // <1>
+ request.type("tweet"); // <2>
+ // end::put-mapping-request
+
+ // tag::put-mapping-request-source
+ request.source(
+ "{\n" +
+ " \"tweet\": {\n" +
+ " \"properties\": {\n" +
+ " \"message\": {\n" +
+ " \"type\": \"text\"\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ "}", // <1>
+ XContentType.JSON);
+ // end::put-mapping-request-source
+
+ // tag::put-mapping-request-timeout
+ request.timeout(TimeValue.timeValueMinutes(2)); // <1>
+ request.timeout("2m"); // <2>
+ // end::put-mapping-request-timeout
+ // tag::put-mapping-request-masterTimeout
+ request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
+ request.masterNodeTimeout("1m"); // <2>
+ // end::put-mapping-request-masterTimeout
+
+ // tag::put-mapping-execute
+ PutMappingResponse putMappingResponse = client.indices().putMapping(request);
+ // end::put-mapping-execute
+
+ // tag::put-mapping-response
+ boolean acknowledged = putMappingResponse.isAcknowledged(); // <1>
+ // end::put-mapping-response
+ assertTrue(acknowledged);
+ }
+ }
+
+ public void testPutMappingAsync() throws Exception {
+ final RestHighLevelClient client = highLevelClient();
+
+ {
+ CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"));
+ assertTrue(createIndexResponse.isAcknowledged());
+ }
+
+ {
+ PutMappingRequest request = new PutMappingRequest("twitter").type("tweet");
+ // tag::put-mapping-execute-async
+ client.indices().putMappingAsync(request, new ActionListener() {
+ @Override
+ public void onResponse(PutMappingResponse putMappingResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ });
+ // end::put-mapping-execute-async
+
+ assertBusy(() -> {
+ // TODO Use Indices Exist API instead once it exists
+ Response response = client.getLowLevelClient().performRequest("HEAD", "twitter");
+ assertTrue(RestStatus.OK.getStatus() == response.getStatusLine().getStatusCode());
+ });
+ }
+ }
+
public void testOpenIndex() throws IOException {
RestHighLevelClient client = highLevelClient();
diff --git a/docs/java-rest/high-level/apis/index.asciidoc b/docs/java-rest/high-level/apis/index.asciidoc
index f6da998a847..f7367b6e8c2 100644
--- a/docs/java-rest/high-level/apis/index.asciidoc
+++ b/docs/java-rest/high-level/apis/index.asciidoc
@@ -6,6 +6,8 @@ include::open_index.asciidoc[]
include::close_index.asciidoc[]
+include::putmapping.asciidoc[]
+
include::_index.asciidoc[]
include::get.asciidoc[]
diff --git a/docs/java-rest/high-level/apis/putmapping.asciidoc b/docs/java-rest/high-level/apis/putmapping.asciidoc
new file mode 100644
index 00000000000..57b8ec8964a
--- /dev/null
+++ b/docs/java-rest/high-level/apis/putmapping.asciidoc
@@ -0,0 +1,71 @@
+[[java-rest-high-put-mapping]]
+=== Put Mapping API
+
+[[java-rest-high-put-mapping-request]]
+==== Put Mapping Request
+
+A `PutMappingRequest` requires an `index` argument, and a type:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request]
+--------------------------------------------------
+<1> The index to add the mapping to
+<2> The type to create (or update)
+
+==== Mapping source
+A description of the fields to create on the mapping; if not defined, the mapping will default to empty.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-source]
+--------------------------------------------------
+<1> The mapping source
+
+==== Optional arguments
+The following arguments can optionally be provided:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-timeout]
+--------------------------------------------------
+<1> Timeout to wait for the all the nodes to acknowledge the index creation as a `TimeValue`
+<2> Timeout to wait for the all the nodes to acknowledge the index creation as a `String`
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-masterTimeout]
+--------------------------------------------------
+<1> Timeout to connect to the master node as a `TimeValue`
+<2> Timeout to connect to the master node as a `String`
+
+[[java-rest-high-put-mapping-sync]]
+==== Synchronous Execution
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-execute]
+--------------------------------------------------
+
+[[java-rest-high-put-mapping-async]]
+==== Asynchronous Execution
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-execute-async]
+--------------------------------------------------
+<1> Called when the execution is successfully completed. The response is
+provided as an argument
+<2> Called in case of failure. The raised exception is provided as an argument
+
+[[java-rest-high-put-mapping-response]]
+==== Put Mapping Response
+
+The returned `PutMappingResponse` allows to retrieve information about the executed
+ operation as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-response]
+--------------------------------------------------
+<1> Indicates whether all of the nodes have acknowledged the request
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index fa71b62d64e..aede4789f4d 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -8,6 +8,7 @@ Indices APIs::
* <>
* <>
* <>
+* <>
Single document APIs::
* <>
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java
index 7b6c8f6eb6f..03c1308e1d9 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java
@@ -32,6 +32,7 @@ import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
@@ -57,7 +58,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError;
* @see org.elasticsearch.client.IndicesAdminClient#putMapping(PutMappingRequest)
* @see PutMappingResponse
*/
-public class PutMappingRequest extends AcknowledgedRequest implements IndicesRequest.Replaceable {
+public class PutMappingRequest extends AcknowledgedRequest implements IndicesRequest.Replaceable, ToXContentObject {
private static ObjectHashSet RESERVED_FIELDS = ObjectHashSet.from(
"_uid", "_id", "_type", "_source", "_all", "_analyzer", "_parent", "_routing", "_index",
@@ -318,4 +319,14 @@ public class PutMappingRequest extends AcknowledgedRequest im
}
out.writeOptionalWriteable(concreteIndex);
}
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ if (source != null) {
+ builder.rawValue(new BytesArray(source), XContentType.JSON);
+ } else {
+ builder.startObject().endObject();
+ }
+ return builder;
+ }
}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java
index 64b3c77f050..f427a316c2e 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java
@@ -22,13 +22,24 @@ package org.elasticsearch.action.admin.indices.mapping.put;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
/**
* The response of put mapping operation.
*/
-public class PutMappingResponse extends AcknowledgedResponse {
+public class PutMappingResponse extends AcknowledgedResponse implements ToXContentObject {
+
+ private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("put_mapping",
+ true, args -> new PutMappingResponse((boolean) args[0]));
+
+ static {
+ declareAcknowledgedField(PARSER);
+ }
protected PutMappingResponse() {
@@ -49,4 +60,16 @@ public class PutMappingResponse extends AcknowledgedResponse {
super.writeTo(out);
writeAcknowledged(out);
}
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ addAcknowledgedField(builder);
+ builder.endObject();
+ return builder;
+ }
+
+ public static PutMappingResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.apply(parser, null);
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java
index 41691f70c06..d7553ebf07c 100644
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java
+++ b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java
@@ -115,7 +115,7 @@ public class CreateIndexRequestTests extends ESTestCase {
final XContentType xContentType = randomFrom(XContentType.values());
BytesReference originalBytes = toShuffledXContent(createIndexRequest, xContentType, EMPTY_PARAMS, humanReadable);
- CreateIndexRequest parsedCreateIndexRequest = new CreateIndexRequest(createIndexRequest.index());
+ CreateIndexRequest parsedCreateIndexRequest = new CreateIndexRequest();
parsedCreateIndexRequest.source(originalBytes, xContentType);
assertMappingsEqual(createIndexRequest.mappings(), parsedCreateIndexRequest.mappings());
@@ -201,7 +201,7 @@ public class CreateIndexRequestTests extends ESTestCase {
return builder;
}
- private static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException {
+ public static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException {
builder.startObject("properties");
int fieldsNo = randomIntBetween(0, 5);
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java
index 96dcef700a9..902dc187093 100644
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java
+++ b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java
@@ -21,17 +21,26 @@ package org.elasticsearch.action.admin.indices.mapping.put;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequestTests;
+import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
+import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
+import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.elasticsearch.index.Index;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
+import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS;
+
public class PutMappingRequestTests extends ESTestCase {
public void testValidation() {
@@ -94,4 +103,79 @@ public class PutMappingRequestTests extends ESTestCase {
}
}
}
+
+ public void testToXContent() throws IOException {
+ PutMappingRequest request = new PutMappingRequest("foo");
+ request.type("my_type");
+
+ XContentBuilder mapping = JsonXContent.contentBuilder().startObject();
+ mapping.startObject("properties");
+ mapping.startObject("email");
+ mapping.field("type", "text");
+ mapping.endObject();
+ mapping.endObject();
+ mapping.endObject();
+ request.source(mapping);
+
+ String actualRequestBody = Strings.toString(request);
+ String expectedRequestBody = "{\"properties\":{\"email\":{\"type\":\"text\"}}}";
+ assertEquals(expectedRequestBody, actualRequestBody);
+ }
+
+ public void testToXContentWithEmptySource() throws IOException {
+ PutMappingRequest request = new PutMappingRequest("foo");
+ request.type("my_type");
+
+ String actualRequestBody = Strings.toString(request);
+ String expectedRequestBody = "{}";
+ assertEquals(expectedRequestBody, actualRequestBody);
+ }
+
+ public void testToAndFromXContent() throws IOException {
+
+ final PutMappingRequest putMappingRequest = createTestItem();
+
+ boolean humanReadable = randomBoolean();
+ final XContentType xContentType = randomFrom(XContentType.values());
+ BytesReference originalBytes = toShuffledXContent(putMappingRequest, xContentType, EMPTY_PARAMS, humanReadable);
+
+ PutMappingRequest parsedPutMappingRequest = new PutMappingRequest();
+ parsedPutMappingRequest.source(originalBytes, xContentType);
+
+ assertMappingsEqual(putMappingRequest.source(), parsedPutMappingRequest.source());
+ }
+
+ private void assertMappingsEqual(String expected, String actual) throws IOException {
+
+ XContentParser expectedJson = createParser(XContentType.JSON.xContent(), expected);
+ XContentParser actualJson = createParser(XContentType.JSON.xContent(), actual);
+ assertEquals(expectedJson.mapOrdered(), actualJson.mapOrdered());
+ }
+
+ /**
+ * Returns a random {@link PutMappingRequest}.
+ */
+ private static PutMappingRequest createTestItem() throws IOException {
+ String index = randomAlphaOfLength(5);
+
+ PutMappingRequest request = new PutMappingRequest(index);
+
+ String type = randomAlphaOfLength(5);
+ request.type(type);
+ request.source(randomMapping());
+
+ return request;
+ }
+
+ private static XContentBuilder randomMapping() throws IOException {
+ XContentBuilder builder = XContentFactory.jsonBuilder();
+ builder.startObject();
+
+ if (randomBoolean()) {
+ CreateIndexRequestTests.randomMappingFields(builder, true);
+ }
+
+ builder.endObject();
+ return builder;
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java
new file mode 100644
index 00000000000..a52969c6281
--- /dev/null
+++ b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.action.admin.indices.mapping.put;
+
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+
+import static org.elasticsearch.test.XContentTestUtils.insertRandomFields;
+
+public class PutMappingResponseTests extends ESTestCase {
+
+ public void testToXContent() {
+ PutMappingResponse response = new PutMappingResponse(true);
+ String output = Strings.toString(response);
+ assertEquals("{\"acknowledged\":true}", output);
+ }
+
+ public void testToAndFromXContent() throws IOException {
+ doFromXContentTestWithRandomFields(false);
+ }
+
+ /**
+ * This test adds random fields and objects to the xContent rendered out to
+ * ensure we can parse it back to be forward compatible with additions to
+ * the xContent
+ */
+ public void testFromXContentWithRandomFields() throws IOException {
+ doFromXContentTestWithRandomFields(true);
+ }
+
+ private void doFromXContentTestWithRandomFields(boolean addRandomFields) throws IOException {
+
+ final PutMappingResponse putMappingResponse = createTestItem();
+
+ boolean humanReadable = randomBoolean();
+ final XContentType xContentType = randomFrom(XContentType.values());
+ BytesReference originalBytes = toShuffledXContent(putMappingResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
+
+ BytesReference mutated;
+ if (addRandomFields) {
+ mutated = insertRandomFields(xContentType, originalBytes, null, random());
+ } else {
+ mutated = originalBytes;
+ }
+ PutMappingResponse parsedPutMappingResponse;
+ try (XContentParser parser = createParser(xContentType.xContent(), mutated)) {
+ parsedPutMappingResponse = PutMappingResponse.fromXContent(parser);
+ assertNull(parser.nextToken());
+ }
+
+ assertEquals(putMappingResponse.isAcknowledged(), parsedPutMappingResponse.isAcknowledged());
+ }
+
+ /**
+ * Returns a random {@link PutMappingResponse}.
+ */
+ private static PutMappingResponse createTestItem() throws IOException {
+ boolean acknowledged = randomBoolean();
+
+ return new PutMappingResponse(acknowledged);
+ }
+}