// Path: elasticservice/src/main/java/elasticsearch/esapi/resp/ESGetByIdResponse.java
// public class ESGetByIdResponse extends ESBaseResponse {
//     private Boolean found;
//     @SerializedName("_source")
//     private JsonObject object;
// 
//     public Boolean getFound() {
//         return found;
//     }
// 
//     public void setFound(Boolean found) {
//         this.found = found;
//     }
// 
//     public JsonObject getObject() {
//         return object;
//     }
// 
//     public void setObject(JsonObject object) {
//         this.object = object;
//     }
// 
//     @Override
//     public String toString() {
//         return super.toString() + "ESGetByIdResponse{" +
//                 "found=" + found +
//                 ", object=" + object +
//                 '}';
//     }
// }
// 
// Path: elasticservice/src/main/java/elasticsearch/esapi/resp/ESSaveResponse.java
// public class ESSaveResponse extends ESBaseResponse {
//     protected Boolean created;
//     @SerializedName("_shards")
//     protected JsonObject shards;
// 
//     public Boolean getCreated() {
//         return created;
//     }
// 
//     public void setCreated(Boolean created) {
//         this.created = created;
//     }
// 
//     public JsonObject getShards() {
//         return shards;
//     }
// 
//     public void setShards(JsonObject shards) {
//         this.shards = shards;
//     }
// }
// 
// Path: elasticservice/src/main/java/elasticsearch/exception/ElasticVersionConflictException.java
// public class ElasticVersionConflictException extends RuntimeException {
//     public ElasticVersionConflictException(String message) {
//         super(message);
//     }
// 
//     public ElasticVersionConflictException(String message, Throwable cause) {
//         super(message, cause);
//     }
// }


import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import elasticsearch.esapi.resp.ESGetByIdResponse;
import elasticsearch.esapi.resp.ESSaveResponse;
import elasticsearch.exception.ElasticVersionConflictException;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.http.HttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.stereotype.Component;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;

package elasticsearch.esapi;

/**
 * Created by I311352 on 10/25/2016.
 */



/**
 * Some document maybe processed by multi-thread, need take care for update conflict
 * or override
 */
@Component
public class HotDocumentService {
    private final static Logger logger = Logger.getLogger(HotDocumentService.class);

    @Autowired
    private DocumentService documentService;

    @Autowired
    private CounterService counterService;

    @Autowired
    private GaugeService gaugeService;

    /**
     * @param index
     * @param type
     * @param sourceId
     * @param param    depends on have the key of version
     * @param newObj
     * @param f        ConflictHandleFunction
     * @return
     */
    public ESSaveResponse update(String index, String type, Long sourceId, HashMap<String, String> param,
                                 JsonObject newObj, BiFunction<JsonObject, JsonObject, JsonObject> f) {

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Status successful = Status.SUCCESS;

        try {
            //In case the arguments pollute
            HashMap<String, String> localParam = new HashMap<>();
            if (param != null) {
                localParam.putAll(param);
            }
            if (localParam.get("version") != null && localParam.get("version").equals("-1")) {
                localParam.remove("version");
                return createSource(index, type, sourceId, localParam, newObj);
            } else if (localParam.get("version") != null) {
                logger.debug("do update with version" + localParam + " source=" + newObj.toString());
                return updateOnInsert(index, type, sourceId, localParam, newObj);
            } else {

// Path: elasticservice/src/main/java/elasticsearch/esapi/resp/ESGetByIdResponse.java
// public class ESGetByIdResponse extends ESBaseResponse {
//     private Boolean found;
//     @SerializedName("_source")
//     private JsonObject object;
// 
//     public Boolean getFound() {
//         return found;
//     }
// 
//     public void setFound(Boolean found) {
//         this.found = found;
//     }
// 
//     public JsonObject getObject() {
//         return object;
//     }
// 
//     public void setObject(JsonObject object) {
//         this.object = object;
//     }
// 
//     @Override
//     public String toString() {
//         return super.toString() + "ESGetByIdResponse{" +
//                 "found=" + found +
//                 ", object=" + object +
//                 '}';
//     }
// }
// 
// Path: elasticservice/src/main/java/elasticsearch/esapi/resp/ESSaveResponse.java
// public class ESSaveResponse extends ESBaseResponse {
//     protected Boolean created;
//     @SerializedName("_shards")
//     protected JsonObject shards;
// 
//     public Boolean getCreated() {
//         return created;
//     }
// 
//     public void setCreated(Boolean created) {
//         this.created = created;
//     }
// 
//     public JsonObject getShards() {
//         return shards;
//     }
// 
//     public void setShards(JsonObject shards) {
//         this.shards = shards;
//     }
// }
// 
// Path: elasticservice/src/main/java/elasticsearch/exception/ElasticVersionConflictException.java
// public class ElasticVersionConflictException extends RuntimeException {
//     public ElasticVersionConflictException(String message) {
//         super(message);
//     }
// 
//     public ElasticVersionConflictException(String message, Throwable cause) {
//         super(message, cause);
//     }
// }


// Path: elasticservice/src/main/java/elasticsearch/esapi/HotDocumentService.java
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import elasticsearch.esapi.resp.ESGetByIdResponse;
import elasticsearch.esapi.resp.ESSaveResponse;
import elasticsearch.exception.ElasticVersionConflictException;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.http.HttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.stereotype.Component;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;

package elasticsearch.esapi;

/**
 * Created by I311352 on 10/25/2016.
 */



/**
 * Some document maybe processed by multi-thread, need take care for update conflict
 * or override
 */
@Component
public class HotDocumentService {
    private final static Logger logger = Logger.getLogger(HotDocumentService.class);

    @Autowired
    private DocumentService documentService;

    @Autowired
    private CounterService counterService;

    @Autowired
    private GaugeService gaugeService;

    /**
     * @param index
     * @param type
     * @param sourceId
     * @param param    depends on have the key of version
     * @param newObj
     * @param f        ConflictHandleFunction
     * @return
     */
    public ESSaveResponse update(String index, String type, Long sourceId, HashMap<String, String> param,
                                 JsonObject newObj, BiFunction<JsonObject, JsonObject, JsonObject> f) {

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Status successful = Status.SUCCESS;

        try {
            //In case the arguments pollute
            HashMap<String, String> localParam = new HashMap<>();
            if (param != null) {
                localParam.putAll(param);
            }
            if (localParam.get("version") != null && localParam.get("version").equals("-1")) {
                localParam.remove("version");
                return createSource(index, type, sourceId, localParam, newObj);
            } else if (localParam.get("version") != null) {
                logger.debug("do update with version" + localParam + " source=" + newObj.toString());
                return updateOnInsert(index, type, sourceId, localParam, newObj);
            } else {

                ESGetByIdResponse esResponse = documentService.loadSourceById(index, type, sourceId, localParam);
