package com.silverforge.elasticsearchrawclient.queryDSL.generator;
import android.text.TextUtils;
import android.util.Log;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.silverforge.elasticsearchrawclient.model.QueryTypeItem;
import com.silverforge.elasticsearchrawclient.definition.Generator;
import com.silverforge.elasticsearchrawclient.queryDSL.Constants;
import com.silverforge.elasticsearchrawclient.utils.QueryTypeArrayList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import static br.com.zbra.androidlinq.Linq.stream;
public class QueryGenerator
implements Generator {
private final static String TAG = QueryGenerator.class.getName();
protected final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
protected final JsonFactory jsonFactory = new JsonFactory();
protected JsonGenerator jsonGenerator;
protected QueryGenerator() {
try {
jsonGenerator = jsonFactory.createGenerator(outputStream);
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
}
@Override
public String generate(QueryTypeArrayList<QueryTypeItem> queryBag) {
Map<String, String> childItems = stream(queryBag)
.toMap(qb -> qb.getName(), qb -> qb.getValue());
return generateChildren(childItems);
}
protected String generateCommonChildren(String queryName,
QueryTypeItem parent,
Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
String parentValue = getParentValue(parent);
if (stream(childItems).any()) {
jsonGenerator.writeObjectFieldStart(parentValue);
boolean minimumExists = stream(childItems).any(i -> i.getKey().equals(Constants.MINIMUM_SHOULD_MATCH));
Map.Entry<String, String> lowFreq = stream(childItems)
.firstOrNull(i -> i.getKey().equals(Constants.LOW_FREQ));
Map.Entry<String, String> highFreq = stream(childItems)
.firstOrNull(i -> i.getKey().equals(Constants.HIGH_FREQ));
if (!minimumExists && (lowFreq != null || highFreq != null)) {
Map<String, String> filteredChildItems = stream(childItems.entrySet())
.where(i -> !i.getKey().equals(Constants.MINIMUM_SHOULD_MATCH))
.where(i -> !i.getKey().equals(Constants.LOW_FREQ))
.where(i -> !i.getKey().equals(Constants.HIGH_FREQ))
.toMap(i -> i.getKey(), i -> i.getValue());
writeEntries(filteredChildItems);
jsonGenerator.writeObjectFieldStart(Constants.MINIMUM_SHOULD_MATCH);
if (lowFreq != null)
jsonGenerator.writeStringField(lowFreq.getKey(), lowFreq.getValue());
if (highFreq != null)
jsonGenerator.writeStringField(highFreq.getKey(), highFreq.getValue());
jsonGenerator.writeEndObject();
} else if (minimumExists) {
Map<String, String> filteredChildItems = stream(childItems.entrySet())
.where(i -> !i.getKey().equals(Constants.LOW_FREQ))
.where(i -> !i.getKey().equals(Constants.HIGH_FREQ))
.toMap(i -> i.getKey(), i -> i.getValue());
writeEntries(filteredChildItems);
} else {
writeEntries(childItems);
}
jsonGenerator.writeEndObject();
} else {
jsonGenerator.writeObjectFieldStart(parentValue);
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateMatchChildren(String queryName,
QueryTypeItem parent,
Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
String parentValue = getParentValue(parent);
if (stream(childItems).any(i -> i.getKey().equals(Constants.VALUE))) {
jsonGenerator.writeStringField(
parentValue,
stream(childItems)
.first(i -> i.getKey().equals(Constants.VALUE))
.getValue());
} else {
if (stream(childItems).any()) {
jsonGenerator.writeObjectFieldStart(parentValue);
writeEntries(childItems);
jsonGenerator.writeEndObject();
} else {
jsonGenerator.writeStringField(parentValue, "");
}
}
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateChildren(Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
writeEntries(childItems);
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateFunctionChildren(Map<String, String> childItems) {
return generateFunctionChildren(null, childItems);
}
protected String generateFunctionChildren(String queryName, Map<String, String> childItems) {
String retValue = "";
try {
Map.Entry<String, String> filter = stream(childItems)
.firstOrNull(ci -> ci.getKey().equals(Constants.FILTER));
Map<String, String> children = stream(childItems)
.where(ci -> !ci.getKey().equals(Constants.FILTER))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
jsonGenerator.writeStartObject();
if (filter != null)
jsonGenerator.writeStringField(filter.getKey(), filter.getValue());
if (!TextUtils.isEmpty(queryName))
jsonGenerator.writeObjectFieldStart(queryName);
writeEntries(children);
if (!TextUtils.isEmpty(queryName))
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateScriptScoreChildren(String queryName, Map<String, String> childItems) {
String retValue = "";
try {
Map.Entry<String, String> filter = stream(childItems)
.firstOrNull(ci -> ci.getKey().equals(Constants.FILTER));
Map.Entry<String, String> script = stream(childItems)
.firstOrNull(ci -> ci.getKey().equals(Constants.SCRIPT));
Map<String, String> children = stream(childItems)
.where(ci -> !ci.getKey().equals(Constants.FILTER))
.where(ci -> !ci.getKey().equals(Constants.SCRIPT))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
jsonGenerator.writeStartObject();
if (filter != null)
jsonGenerator.writeStringField(filter.getKey(), filter.getValue());
if (script != null)
jsonGenerator.writeStringField(queryName, script.getValue());
writeEntries(children);
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateFuzzyChildren(String queryName,
QueryTypeItem parent,
Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
String parentValue = getParentValue(parent);
if (stream(childItems).count() == 1
&& stream(childItems).any(i -> i.getKey().equals(Constants.VALUE))) {
jsonGenerator.writeStringField(
parentValue,
stream(childItems)
.first(i -> i.getKey().equals(Constants.VALUE))
.getValue());
} else {
if (stream(childItems).any()) {
jsonGenerator.writeObjectFieldStart(parentValue);
writeEntries(childItems);
jsonGenerator.writeEndObject();
} else {
jsonGenerator.writeStringField(parentValue, "");
}
}
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateGeoShapeChildren(String queryName,
QueryTypeItem parent,
Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
String parentValue = getParentValue(parent);
jsonGenerator.writeObjectFieldStart(parentValue);
Map.Entry<String, String> shapeEntry = stream(childItems)
.firstOrDefault(ci ->
ci.getKey().equals(Constants.INDEXED_SHAPE),
Maps.immutableEntry(Constants.SHAPE, Constants.SHAPE));
jsonGenerator.writeObjectFieldStart(shapeEntry.getValue());
if (shapeEntry.getKey().equals(Constants.SHAPE)) {
Map<String, String> map = stream(childItems)
.where(ci -> ci.getKey().equals(Constants.TYPE)
|| ci.getKey().equals(Constants.COORDINATES))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
writeEntries(map);
} else {
Map<String, String> map = stream(childItems)
.where(ci ->
ci.getKey().equals(Constants.ID)
|| ci.getKey().equals(Constants.TYPE)
|| ci.getKey().equals(Constants.INDEX)
|| ci.getKey().equals(Constants.PATH))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
writeEntries(map);
}
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateGeoDistance(String queryName, QueryTypeItem parent, Map<String, String> childItems) {
String retValue = "";
try {
Map.Entry<String, String> value = stream(childItems)
.firstOrDefault(ci -> ci.getKey().equals(Constants.VALUE),
Maps.immutableEntry(Constants.VALUE, ""));
Map<String, String> children = stream(childItems)
.where(ci -> !ci.getKey().equals(Constants.VALUE))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
jsonGenerator.writeStringField(parent.getValue(), value.getValue());
writeEntries(children);
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateGeoPolygon(String queryName, QueryTypeItem parent, Map<String, String> childItems) {
String retValue = "";
try {
Map<String, String> points = stream(childItems)
.where(ci -> ci.getKey().equals(Constants.POINTS))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
Map<String, String> children = stream(childItems)
.where(ci -> !ci.getKey().equals(Constants.POINTS))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
jsonGenerator.writeObjectFieldStart(parent.getValue());
writeEntries(points);
jsonGenerator.writeEndObject();
writeEntries(children);
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateParentChildren(QueryTypeItem parent, Map<String, String> childItems) {
return generateParentChildren(null, parent, childItems);
}
protected String generateParentChildren(String queryName, QueryTypeItem parent, Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
if (!TextUtils.isEmpty(queryName))
jsonGenerator.writeObjectFieldStart(queryName);
jsonGenerator.writeObjectFieldStart(parent.getValue());
writeEntries(childItems);
jsonGenerator.writeEndObject();
if (!TextUtils.isEmpty(queryName))
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateChildren(String queryName, Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
writeEntries(childItems);
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateSpanFirst(String queryName, Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(queryName);
jsonGenerator.writeObjectFieldStart("match");
jsonGenerator.writeObjectFieldStart("span_term");
jsonGenerator.writeStringField(
stream(childItems)
.firstOrDefault(c -> c.getKey().equals(Constants.FIELD_NAME), Maps.immutableEntry(Constants.FIELD_NAME, "_all")).getValue(),
stream(childItems)
.firstOrDefault(c -> c.getKey().equals(Constants.VALUE), Maps.immutableEntry(Constants.VALUE, "")).getValue()
);
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.writeStringField(Constants.END,
stream(childItems)
.firstOrDefault(c -> c.getKey().equals(Constants.END), Maps.immutableEntry(Constants.END, "3")).getValue()
);
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
protected String generateDecayFunction(
String functionName,
QueryTypeItem parent,
Map<String, String> childItems) {
String retValue = "";
try {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectFieldStart(functionName);
Map.Entry<String, String> multiValueMode = stream(childItems)
.firstOrNull(ci -> ci.getKey().equals(Constants.MULTI_VALUE_MODE));
if (parent != null) {
Map<String, String> children = stream(childItems)
.where(ci -> !ci.getKey().equals(Constants.MULTI_VALUE_MODE))
.toMap(ci -> ci.getKey(), ci -> ci.getValue());
jsonGenerator.writeObjectFieldStart(parent.getValue());
writeEntries(children);
jsonGenerator.writeEndObject();
}
if (multiValueMode != null)
jsonGenerator.writeStringField(multiValueMode.getKey(), multiValueMode.getValue());
jsonGenerator.writeEndObject();
jsonGenerator.close();
retValue = getOutputStreamValue();
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.getMessage());
}
return retValue;
}
private String getParentValue(QueryTypeItem parent) {
Optional<QueryTypeItem> parentItem = Optional.fromNullable(parent);
String parentValue = parentItem
.or(QueryTypeItem.builder().value("_all").build())
.getValue();
return parentValue;
}
private void writeEntries(Map<String, String> childItems) throws IOException {
for (Map.Entry<String, String> entry : childItems.entrySet()) {
jsonGenerator.writeStringField(entry.getKey(), entry.getValue());
}
}
private String getOutputStreamValue() {
return outputStream
.toString()
.replace("\\", "")
.replace("\"[", "[")
.replace("]\"", "]")
.replace("\"{", "{")
.replace("}\"", "}");
}
}