package com.visenze.visearch.internal;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.visenze.visearch.*;
import com.visenze.visearch.internal.http.ViSearchHttpClient;
import com.visenze.visearch.internal.http.ViSearchHttpResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DataOperationsImpl extends BaseViSearchOperations implements DataOperations {
public DataOperationsImpl(ViSearchHttpClient viSearchHttpClient, ObjectMapper objectMapper) {
super(viSearchHttpClient, objectMapper);
}
@Override
public InsertTrans insert(List<Image> imageList) {
return insert(imageList, new HashMap<String, String>());
}
@Override
public InsertTrans insert(List<Image> imageList, Map<String, String> customParams) {
Preconditions.checkNotNull(imageList, "image list must not be null");
Preconditions.checkNotNull(customParams, "custom params must not be null");
try {
Multimap<String, String> params = imageListToParams(imageList);
for (Map.Entry<String, String> entry : customParams.entrySet()) {
params.put(entry.getKey(), entry.getValue());
}
ViSearchHttpResponse httpResponse = viSearchHttpClient.post("/insert", params);
String response = httpResponse.getBody();
Map<String, String> headers = httpResponse.getHeaders();
try {
JsonNode responseNode = objectMapper.readTree(response);
JsonNode statusNode = responseNode.get("status");
if (statusNode == null) {
throw new InternalViSearchException(ResponseMessages.INVALID_RESPONSE_FORMAT, response);
// throw new ViSearchException("There was a malformed ViSearch response: " + response, response);
} else {
InsertTrans insertTrans = deserializeObjectResult(response, response, InsertTrans.class);
insertTrans.setHeaders(headers);
return insertTrans;
}
} catch (JsonProcessingException e) {
throw new InternalViSearchException(ResponseMessages.PARSE_RESPONSE_ERROR, e, response);
//throw new ViSearchException("Could not parse the ViSearch response: " + response, e, response);
} catch (IOException e) {
throw new InternalViSearchException(ResponseMessages.PARSE_RESPONSE_ERROR, e, response);
//throw new ViSearchException("Could not parse the ViSearch response: " + response, e, response);
}
} catch (InternalViSearchException e) {
return new InsertTrans(e.getMessage(), e.getCause(), e.getServerRawResponse());
}
}
@Override
public InsertStatus insertStatus(String transId) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(transId), "trans_id must not be null or empty");
try {
ViSearchHttpResponse response = viSearchHttpClient.get("/insert/status/" + transId, HashMultimap.<String, String>create());
return parseInsertStatus(response.getBody(), response.getHeaders());
} catch (InternalViSearchException e) {
return new InsertStatus(e.getMessage(), e.getCause(), e.getServerRawResponse());
}
}
@Override
public InsertStatus insertStatus(String transId, Integer errorPage, Integer errorLimit) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(transId), "trans_id must not be null or empty");
Preconditions.checkNotNull(errorPage, "error page must not be null");
Preconditions.checkNotNull(errorLimit, "error limit must not be null");
try {
Multimap<String, String> params = HashMultimap.create();
params.put("error_page", errorPage.toString());
params.put("error_limit", errorLimit.toString());
ViSearchHttpResponse response = viSearchHttpClient.get("/insert/status/" + transId, params);
return parseInsertStatus(response.getBody(), response.getHeaders());
} catch (InternalViSearchException e) {
return new InsertStatus(e.getMessage(), e.getCause(), e.getServerRawResponse());
}
}
private InsertStatus parseInsertStatus(String response, Map<String, String> headers) {
try {
JsonNode responseNode = objectMapper.readTree(response);
JsonNode statusNode = responseNode.get("status");
if (statusNode == null) {
throw new InternalViSearchException(ResponseMessages.INVALID_RESPONSE_FORMAT, response);
} else {
String status = statusNode.asText();
JsonNode resultArrayNode = responseNode.get("result");
if ("fail".equals(status) ||
resultArrayNode == null || !resultArrayNode.isArray() || resultArrayNode.get(0) == null) {
JsonNode errorNode = responseNode.get("error");
if (errorNode == null || !errorNode.isArray() || errorNode.get(0) == null) {
throw new InternalViSearchException(ResponseMessages.INVALID_RESPONSE_FORMAT, response);
}
String message = errorNode.path(0).asText();
throw new InternalViSearchException(message, response);
} else {
JsonNode resultNode = resultArrayNode.get(0);
InsertStatus insertStatus = deserializeObjectResult(response, resultNode.toString(), InsertStatus.class);
insertStatus.setHeaders(headers);
return insertStatus;
}
}
} catch (JsonProcessingException e) {
throw new InternalViSearchException(ResponseMessages.PARSE_RESPONSE_ERROR, e, response);
} catch (IOException e) {
throw new InternalViSearchException(ResponseMessages.PARSE_RESPONSE_ERROR, e, response);
}
}
@Override
public RemoveStatus remove(List<String> imNameList) {
Preconditions.checkNotNull(imNameList, "im_name list for remove must not be null.");
try {
Multimap<String, String> params = Multimaps.forMap(imageNameListToParams(imNameList));
ViSearchHttpResponse httpResponse = viSearchHttpClient.post("/remove", params);
String response = httpResponse.getBody();
try {
JsonNode responseNode = objectMapper.readTree(response);
JsonNode statusNode = responseNode.get("status");
JsonNode totalNode = responseNode.get("total");
if (statusNode == null || totalNode == null) {
throw new InternalViSearchException(ResponseMessages.INVALID_RESPONSE_FORMAT, response);
} else if ("fail".equals(statusNode.asText())) {
JsonNode errorNode = responseNode.get("error");
if (errorNode == null || !errorNode.isArray() || errorNode.get(0) == null) {
throw new InternalViSearchException(ResponseMessages.INVALID_RESPONSE_FORMAT, response);
}
String message = errorNode.path(0).asText();
throw new InternalViSearchException(message, response);
} else {
int total = totalNode.asInt();
return new RemoveStatus(total);
}
} catch (JsonProcessingException e) {
throw new InternalViSearchException(ResponseMessages.PARSE_RESPONSE_ERROR, e, response);
} catch (IOException e) {
throw new InternalViSearchException(ResponseMessages.PARSE_RESPONSE_ERROR, e, response);
}
} catch (InternalViSearchException e) {
return new RemoveStatus(e.getMessage(), e.getCause(), e.getServerRawResponse());
}
}
private static Multimap<String, String> imageListToParams(List<Image> imageList) {
Multimap<String, String> params = HashMultimap.create();
for (int i = 0; i < imageList.size(); i++) {
Image image = imageList.get(i);
if (image != null) {
params.put("im_name" + "[" + i + "]", image.getImName());
params.put("im_url" + "[" + i + "]", image.getImUrl());
Map<String, String> metadata = image.getMetadata();
if (metadata != null) {
for (Map.Entry<String, String> entry : metadata.entrySet()) {
params.put(entry.getKey() + "[" + i + "]", entry.getValue());
}
}
}
}
return params;
}
private static Map<String, String> imageNameListToParams(List<String> imNameList) {
Map<String, String> params = new HashMap<String, String>();
for (int i = 0; i < imNameList.size(); i++) {
String imName = imNameList.get(i);
if (imName != null) {
params.put("im_name" + "[" + i + "]", imName);
}
}
return params;
}
}