Repository: searchbox-io/Jest (java)

Issue:
Add reindex API
[reindex API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html) is a powerful new elasticsearch feature since version 2.3.
This would be great to add support for this feature in Jest API !

Pull request description:
Add reindex API support (fix #436)

Patch:
diff --git a/jest-common/src/main/java/io/searchbox/indices/reindex/Reindex.java b/jest-common/src/main/java/io/searchbox/indices/reindex/Reindex.java
new file mode 100644
index 00000000..8cb0cb9d
--- /dev/null
+++ b/jest-common/src/main/java/io/searchbox/indices/reindex/Reindex.java
@@ -0,0 +1,94 @@
+package io.searchbox.indices.reindex;
+
+import io.searchbox.action.GenericResultAbstractAction;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * @author fabien baligand
+ */
+public class Reindex extends GenericResultAbstractAction {
+
+    protected Reindex(Builder builder) {
+        super(builder);
+
+        Map<String, Object> payload = new HashMap<String, Object>();
+        payload.put("source", builder.source);
+        payload.put("dest", builder.dest);
+        if (builder.conflicts != null) {
+            payload.put("conflicts", builder.conflicts);
+        }
+        if (builder.size != null) {
+            payload.put("size", builder.size);
+        }
+        if (builder.script != null) {
+            payload.put("script", builder.script);
+        }
+        this.payload = ImmutableMap.<String, Object>copyOf(payload);
+        
+        setURI(buildURI());
+    }
+
+    @Override
+    protected String buildURI() {
+        return super.buildURI() + "/_reindex";
+    }
+
+    @Override
+    public String getRestMethodName() {
+        return "POST";
+    }
+
+    public static class Builder extends GenericResultAbstractAction.Builder<Reindex, Builder> {
+    	
+    	private Object source;
+    	private Object dest;
+    	private String conflicts;
+    	private Long size;
+    	private Object script;
+
+        public Builder(Object source, Object dest) {
+        	this.source = source;
+        	this.dest = dest;
+        }
+
+        public Builder conflicts(String conflicts) {
+        	this.conflicts = conflicts;
+            return this;
+        }
+
+        public Builder size(Long size) {
+        	this.size = size;
+            return this;
+        }
+
+        public Builder script(Object script) {
+        	this.script = script;
+            return this;
+        }
+
+        public Builder waitForCompletion(boolean waitForCompletion) {
+            return setParameter("wait_for_completion", waitForCompletion);
+        }
+
+        public Builder waitForActiveShards(int waitForActiveShards) {
+            return setParameter("wait_for_active_shards", waitForActiveShards);
+        }
+
+        public Builder timeout(long timeout) {
+            return setParameter("timeout", timeout);
+        }
+
+        public Builder requestsPerSecond(double requestsPerSecond) {
+            return setParameter("requests_per_second", requestsPerSecond);
+        }
+
+        public Reindex build() {
+            return new Reindex(this);
+        }
+    }
+
+}


Test patch:
diff --git a/jest-common/src/test/java/io/searchbox/indices/reindex/ReindexTest.java b/jest-common/src/test/java/io/searchbox/indices/reindex/ReindexTest.java
new file mode 100644
index 00000000..d527b1f2
--- /dev/null
+++ b/jest-common/src/test/java/io/searchbox/indices/reindex/ReindexTest.java
@@ -0,0 +1,77 @@
+package io.searchbox.indices.reindex;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.GsonBuilder;
+
+public class ReindexTest {
+
+	private ImmutableMap<String, Object> source = ImmutableMap.<String, Object>of("index", "sourceIndex");
+	private ImmutableMap<String, Object> dest = ImmutableMap.<String, Object>of("index", "destIndex");
+
+    @Test
+    public void testBasicUriGeneration() {
+    	Reindex reindex = new Reindex.Builder(source,dest).build();
+
+        assertEquals("POST", reindex.getRestMethodName());
+        assertEquals("/_reindex", reindex.getURI());
+    }
+
+	@Test
+	public void testQueryStringGeneration() throws Exception {
+		
+		Reindex reindex = new Reindex.Builder(source,dest)
+		                             .waitForCompletion(true)
+		                             .waitForActiveShards(1)
+		                             .timeout(5000L)
+		                             .requestsPerSecond(5d)
+		                             .build();
+
+		String generatedURI = reindex.getURI();
+		
+		String expectedURI = "/_reindex?wait_for_completion=true&wait_for_active_shards=1&timeout=5000&requests_per_second=5.0";
+		assertEquals(expectedURI, generatedURI);
+	}
+
+	@Test
+	public void testDataGeneration() throws Exception {
+		
+		Reindex reindex = new Reindex.Builder(source,dest)
+		                             .conflicts("proceed")
+		                             .build();
+
+		String generatedData = reindex.getData(new GsonBuilder().create());
+		
+		String expectedData = "{\"conflicts\":\"proceed\",\"dest\":{\"index\":\"destIndex\"},\"source\":{\"index\":\"sourceIndex\"}}";
+		assertEquals(expectedData, generatedData);
+	}
+
+    @Test
+    public void equalsReturnsTrueForSameMappings() {
+		Reindex reindex1 = new Reindex.Builder(source,dest)
+                                      .conflicts("proceed")
+                                      .build();
+		Reindex reindex2 = new Reindex.Builder(source,dest)
+                                      .conflicts("proceed")
+                                      .build();
+
+        assertEquals(reindex1, reindex2);
+    }
+
+    @Test
+    public void equalsReturnsFalseForDifferentMappings() {
+		Reindex reindex1 = new Reindex.Builder(source,dest)
+                                      .waitForCompletion(true)
+                                      .build();
+		Reindex reindex2 = new Reindex.Builder(source,dest)
+		                              .waitForCompletion(false)
+                                      .build();
+
+        assertNotEquals(reindex1, reindex2);
+    }
+
+}
diff --git a/jest/src/test/java/io/searchbox/indices/reindex/ReindexIntegrationTest.java b/jest/src/test/java/io/searchbox/indices/reindex/ReindexIntegrationTest.java
new file mode 100644
index 00000000..86d72cf3
--- /dev/null
+++ b/jest/src/test/java/io/searchbox/indices/reindex/ReindexIntegrationTest.java
@@ -0,0 +1,39 @@
+package io.searchbox.indices.reindex;
+
+import io.searchbox.client.JestResult;
+import io.searchbox.common.AbstractIntegrationTest;
+
+import java.io.IOException;
+
+import org.elasticsearch.test.ESIntegTestCase;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * @author fabien baligand
+ */
+@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.SUITE, numDataNodes = 1)
+public class ReindexIntegrationTest extends AbstractIntegrationTest {
+
+    @Test
+    public void testReindex() throws IOException {
+        String sourceIndex = "my_source_index";
+        String destIndex = "my_dest_index";
+        String documentType = "my_type";
+		String documentId = "my_id";
+        
+        createIndex(sourceIndex);
+		index(sourceIndex, documentType, documentId, "{}");
+
+    	ImmutableMap<String, Object> source = ImmutableMap.<String, Object>of("index", sourceIndex);
+    	ImmutableMap<String, Object> dest = ImmutableMap.<String, Object>of("index", destIndex);
+    	Reindex reindex = new Reindex.Builder(source, dest).build();
+    	JestResult result = client.execute(reindex);
+        
+        assertTrue(result.getErrorMessage(), result.isSucceeded());
+        assertTrue(indexExists(destIndex));
+        assertTrue(get(destIndex, documentType, documentId).isExists());
+    }
+
+}