package io.lumify.geocoder.bing;
import io.lumify.miniweb.HandlerChain;
import com.google.inject.Inject;
import io.lumify.core.config.Configuration;
import io.lumify.core.model.user.UserRepository;
import io.lumify.core.model.workspace.WorkspaceRepository;
import io.lumify.core.util.LumifyLogger;
import io.lumify.core.util.LumifyLoggerFactory;
import io.lumify.web.BaseRequestHandler;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class BingGeocoder extends BaseRequestHandler {
private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(BingGeocoder.class);
private static final String CONFIG_KEY = "geocoder.bing.key";
private String key;
@Inject
public BingGeocoder(
UserRepository userRepository,
WorkspaceRepository workspaceRepository,
Configuration configuration) {
super(userRepository, workspaceRepository, configuration);
key = configuration.get(CONFIG_KEY, null);
if (key == null) {
LOGGER.error("Could not find bing geocoder configuration key: " + CONFIG_KEY);
}
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, HandlerChain chain) throws Exception {
String query = getRequiredParameter(request, "q");
JSONObject resultJson = queryBing(query);
respondWithJson(response, resultJson);
}
private JSONObject queryBing(String query) throws IOException {
String urlString = "http://dev.virtualearth.net/REST/v1/Locations?query=" + URLEncoder.encode(query, "utf-8") + "&output=json&key=" + URLEncoder.encode(key, "utf-8");
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
String responseText = IOUtils.toString(connection.getInputStream(), "UTF-8");
JSONObject responseJson = new JSONObject(responseText);
return toLumifyGeocodeJson(responseJson);
}
private JSONObject toLumifyGeocodeJson(JSONObject responseJson) {
JSONArray results = new JSONArray();
JSONArray resourceSets = responseJson.getJSONArray("resourceSets");
for (int resourceSetIndex = 0; resourceSetIndex < resourceSets.length(); resourceSetIndex++) {
JSONObject resourceSet = resourceSets.getJSONObject(resourceSetIndex);
JSONArray resources = resourceSet.getJSONArray("resources");
for (int resourceIndex = 0; resourceIndex < resources.length(); resourceIndex++) {
JSONObject resource = resources.getJSONObject(resourceIndex);
results.put(bingResourceToLumifyResult(resource));
}
}
JSONObject json = new JSONObject();
json.put("results", results);
return json;
}
private JSONObject bingResourceToLumifyResult(JSONObject resource) {
JSONArray coordinates = resource.getJSONObject("point").getJSONArray("coordinates");
JSONObject json = new JSONObject();
json.put("name", resource.getString("name"));
json.put("latitude", coordinates.getDouble(0));
json.put("longitude", coordinates.getDouble(1));
return json;
}
public static boolean verifyConfiguration(Configuration configuration) {
String key = configuration.get(CONFIG_KEY, null);
if (key == null) {
LOGGER.error("Could not find bing geocoder configuration key '" + CONFIG_KEY + "'. Geocoding will not be enabled.");
return false;
}
return true;
}
}