package de.komoot.photon.utils;
import com.google.common.collect.Lists;
import de.komoot.photon.Constants;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
/**
* Convert a elasticsearch {@link SearchResponse} into a list of {@link JSONObject}s
* <p/>
* Created by Sachin Dole on 2/20/2015.
*/
@Slf4j
public class ConvertToJson implements OneWayConverter<SearchResponse, List<JSONObject>> {
private final static String[] KEYS_LANG_UNSPEC = {Constants.OSM_ID, Constants.OSM_VALUE, Constants.OSM_KEY, Constants.POSTCODE, Constants.HOUSENUMBER, Constants.OSM_TYPE};
private final static String[] KEYS_LANG_SPEC = {Constants.NAME, Constants.COUNTRY, Constants.CITY, Constants.STREET, Constants.STATE};
private final String lang;
public ConvertToJson(String lang) {
this.lang = lang;
}
@Override
public List<JSONObject> convert(SearchResponse searchResponse) {
SearchHit[] hits = searchResponse.getHits().hits();
final List<JSONObject> list = Lists.newArrayListWithExpectedSize(hits.length);
for (SearchHit hit : hits) {
final Map<String, Object> source = hit.getSource();
final JSONObject feature = new JSONObject();
feature.put(Constants.TYPE, Constants.FEATURE);
feature.put(Constants.GEOMETRY, getPoint(source));
// populate properties
final JSONObject properties = new JSONObject();
// language unspecific properties
for (String key : KEYS_LANG_UNSPEC) {
if (source.containsKey(key))
properties.put(key, source.get(key));
}
// language specific properties
for (String key : KEYS_LANG_SPEC) {
if (source.containsKey(key))
properties.put(key, getLocalised(source, key, lang));
}
// add extent of geometry
final Map<String, Object> extent = (Map<String, Object>) source.get("extent");
if (extent != null) {
List<List<Double>> coords = (List<List<Double>>) extent.get("coordinates");
final List<Double> nw = coords.get(0);
final List<Double> se = coords.get(1);
properties.put("extent", new JSONArray(Lists.newArrayList(nw.get(0), nw.get(1), se.get(0), se.get(1))));
}
feature.put(Constants.PROPERTIES, properties);
list.add(feature);
}
return list;
}
private String getLocalised(Map<String, Object> source, String fieldName, String lang) {
final Map<String, String> map = (Map<String, String>) source.get(fieldName);
if (map == null) return null;
if (map.get(lang) != null) {
// language specific field
return map.get(lang);
}
return map.get("default");
}
private JSONObject getPoint(Map<String, Object> source) {
JSONObject point = new JSONObject();
final Map<String, Double> coordinate = (Map<String, Double>) source.get("coordinate");
if (coordinate != null) {
point.put(Constants.TYPE, Constants.POINT);
point.put(Constants.COORDINATES, new JSONArray("[" + coordinate.get(Constants.LON) + "," + coordinate.get(Constants.LAT) + "]"));
} else {
log.error(String.format("invalid data [id=%s, type=%s], coordinate is missing!", source.get(Constants.OSM_ID), source.get(Constants.OSM_VALUE)));
}
return point;
}
}