/*
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.geo.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.geo.GeoDataManager;
import com.amazonaws.geo.GeoDataManagerConfiguration;
import com.amazonaws.geo.model.DeletePointRequest;
import com.amazonaws.geo.model.DeletePointResult;
import com.amazonaws.geo.model.GeoPoint;
import com.amazonaws.geo.model.GeoQueryResult;
import com.amazonaws.geo.model.GetPointRequest;
import com.amazonaws.geo.model.GetPointResult;
import com.amazonaws.geo.model.PutPointRequest;
import com.amazonaws.geo.model.PutPointResult;
import com.amazonaws.geo.model.QueryRadiusRequest;
import com.amazonaws.geo.model.QueryRadiusResult;
import com.amazonaws.geo.model.QueryRectangleRequest;
import com.amazonaws.geo.model.QueryRectangleResult;
import com.amazonaws.geo.model.UpdatePointRequest;
import com.amazonaws.geo.model.UpdatePointResult;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.model.AttributeAction;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;
import com.amazonaws.util.json.JSONException;
import com.amazonaws.util.json.JSONObject;
import com.amazonaws.geo.server.util.Utilities;
/**
* Servlet implementation class GeoDynamoDBServlet
*/
public class GeoDynamoDBServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private GeoDataManagerConfiguration config;
private GeoDataManager geoDataManager;
private ObjectMapper mapper;
private JsonFactory factory;
public void init() throws ServletException {
geoDataManager = Utilities.getInstance().setupGeoDataManager();
config = geoDataManager.getGeoDataManagerConfiguration();
mapper = new ObjectMapper();
factory = mapper.getJsonFactory();
Utilities.getInstance().setupTable();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
try {
StringBuffer buffer = new StringBuffer();
String line = null;
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
JSONObject jsonObject = new JSONObject(buffer.toString());
PrintWriter out = response.getWriter();
String action = jsonObject.getString("action");
log("action: " + action);
JSONObject requestObject = jsonObject.getJSONObject("request");
log("requestObject: " + requestObject);
if (action.equalsIgnoreCase("put-point")) {
putPoint(requestObject, out);
} else if (action.equalsIgnoreCase("get-point")) {
getPoint(requestObject, out);
} else if (action.equalsIgnoreCase("query-rectangle")) {
queryRectangle(requestObject, out);
} else if (action.equalsIgnoreCase("query-radius")) {
queryRadius(requestObject, out);
} else if (action.equalsIgnoreCase("delete-point")) {
deletePoint(requestObject, out);
}
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
log(sw.toString());
}
}
private void putPoint(JSONObject requestObject, PrintWriter out) throws IOException, JSONException {
GeoPoint geoPoint = new GeoPoint(requestObject.getDouble("lat"), requestObject.getDouble("lng"));
AttributeValue rangeKeyAttributeValue = new AttributeValue().withS(requestObject.getString("s3-photo-url"));
AttributeValue titleAttributeValue = new AttributeValue().withS(requestObject.getString("title"));
AttributeValue userIdAttributeValue = new AttributeValue().withS(requestObject.getString("userId"));
PutPointRequest putPointRequest = new PutPointRequest(geoPoint, rangeKeyAttributeValue);
putPointRequest.getPutItemRequest().addItemEntry("title", titleAttributeValue);
putPointRequest.getPutItemRequest().addItemEntry("userId", userIdAttributeValue);
PutPointResult putPointResult = geoDataManager.putPoint(putPointRequest);
printPutPointResult(putPointResult, out);
}
private void printPutPointResult(PutPointResult putPointResult, PrintWriter out) throws JsonParseException,
IOException {
Map<String, String> jsonMap = new HashMap<String, String>();
jsonMap.put("action", "put-point");
out.println(mapper.writeValueAsString(jsonMap));
out.flush();
}
private void getPoint(JSONObject requestObject, PrintWriter out) throws IOException, JSONException {
GeoPoint geoPoint = new GeoPoint(requestObject.getDouble("lat"), requestObject.getDouble("lng"));
AttributeValue rangeKeyAttributeValue = new AttributeValue().withS(requestObject.getString("rangeKey"));
GetPointRequest getPointRequest = new GetPointRequest(geoPoint, rangeKeyAttributeValue);
GetPointResult getPointResult = geoDataManager.getPoint(getPointRequest);
printGetPointRequest(getPointResult, out);
}
private void printGetPointRequest(GetPointResult getPointResult, PrintWriter out) throws JsonParseException,
IOException {
Map<String, AttributeValue> item = getPointResult.getGetItemResult().getItem();
String geoJsonString = item.get(config.getGeoJsonAttributeName()).getS();
JsonParser jsonParser = factory.createJsonParser(geoJsonString);
JsonNode jsonNode = mapper.readTree(jsonParser);
double latitude = jsonNode.get("coordinates").get(0).getDoubleValue();
double longitude = jsonNode.get("coordinates").get(1).getDoubleValue();
String hashKey = item.get(config.getHashKeyAttributeName()).getN();
String rangeKey = item.get(config.getRangeKeyAttributeName()).getS();
String geohash = item.get(config.getGeohashAttributeName()).getN();
String title = item.get("title").getS();
String userId = item.get("userId").getS();
Map<String, String> resultMap = new HashMap<String, String>();
resultMap.put("latitude", Double.toString(latitude));
resultMap.put("longitude", Double.toString(longitude));
resultMap.put("hashKey", hashKey);
resultMap.put("rangeKey", rangeKey);
resultMap.put("geohash", geohash);
resultMap.put("title", title);
resultMap.put("userId", userId);
Map<String, Object> jsonMap = new HashMap<String, Object>();
jsonMap.put("action", "get-point");
jsonMap.put("result", resultMap);
out.println(mapper.writeValueAsString(jsonMap));
out.flush();
}
private void queryRectangle(JSONObject requestObject, PrintWriter out) throws IOException, JSONException {
GeoPoint minPoint = new GeoPoint(requestObject.getDouble("minLat"), requestObject.getDouble("minLng"));
GeoPoint maxPoint = new GeoPoint(requestObject.getDouble("maxLat"), requestObject.getDouble("maxLng"));
String filterUserId = requestObject.getString("filterUserId");
List<String> attributesToGet = new ArrayList<String>();
attributesToGet.add(config.getRangeKeyAttributeName());
attributesToGet.add(config.getGeoJsonAttributeName());
attributesToGet.add("title");
attributesToGet.add("userId");
QueryRectangleRequest queryRectangleRequest = new QueryRectangleRequest(minPoint, maxPoint);
queryRectangleRequest.getQueryRequest().setAttributesToGet(attributesToGet);
QueryRectangleResult queryRectangleResult = geoDataManager.queryRectangle(queryRectangleRequest);
printGeoQueryResult(queryRectangleResult, out, filterUserId);
}
private void queryRadius(JSONObject requestObject, PrintWriter out) throws IOException, JSONException {
GeoPoint centerPoint = new GeoPoint(requestObject.getDouble("lat"), requestObject.getDouble("lng"));
double radiusInMeter = requestObject.getDouble("radiusInMeter");
String filterUserId = requestObject.getString("filterUserId");
List<String> attributesToGet = new ArrayList<String>();
attributesToGet.add(config.getRangeKeyAttributeName());
attributesToGet.add(config.getGeoJsonAttributeName());
attributesToGet.add("title");
attributesToGet.add("userId");
QueryRadiusRequest queryRadiusRequest = new QueryRadiusRequest(centerPoint, radiusInMeter);
queryRadiusRequest.getQueryRequest().setAttributesToGet(attributesToGet);
QueryRadiusResult queryRadiusResult = geoDataManager.queryRadius(queryRadiusRequest);
printGeoQueryResult(queryRadiusResult, out, filterUserId);
}
private void printGeoQueryResult(GeoQueryResult geoQueryResult, PrintWriter out, String filterUserId) throws JsonParseException,
IOException {
Map<String, Object> jsonMap = new HashMap<String, Object>();
List<Map<String, String>> resultArray = new ArrayList<Map<String, String>>();
for (Map<String, AttributeValue> item : geoQueryResult.getItem()) {
Map<String, String> itemMap = new HashMap<String, String>();
String geoJsonString = item.get(config.getGeoJsonAttributeName()).getS();
JsonParser jsonParser = factory.createJsonParser(geoJsonString);
JsonNode jsonNode = mapper.readTree(jsonParser);
double latitude = jsonNode.get("coordinates").get(0).getDoubleValue();
double longitude = jsonNode.get("coordinates").get(1).getDoubleValue();
String rangeKey = item.get(config.getRangeKeyAttributeName()).getS();
String title = "";
if (item.containsKey("title")) {
title = item.get("title").getS();
}
String userId = "";
if (item.containsKey("userId")) {
userId = item.get("userId").getS();
}
itemMap.put("latitude", Double.toString(latitude));
itemMap.put("longitude", Double.toString(longitude));
itemMap.put("rangeKey", rangeKey);
itemMap.put("title", title);
itemMap.put("userId", userId);
if ( filterUserId.equalsIgnoreCase( userId ) || rangeKey.startsWith( "public") ) {
resultArray.add(itemMap);
}
}
jsonMap.put("action", "query");
jsonMap.put("result", resultArray);
out.println(mapper.writeValueAsString(jsonMap));
out.flush();
}
private void deletePoint(JSONObject requestObject, PrintWriter out) throws IOException, JSONException {
GeoPoint geoPoint = new GeoPoint(requestObject.getDouble("lat"), requestObject.getDouble("lng"));
AttributeValue rangeKeyAttributeValue = new AttributeValue().withS(requestObject.getString("rangeKey"));
DeletePointRequest deletePointRequest = new DeletePointRequest(geoPoint, rangeKeyAttributeValue);
DeletePointResult deletePointResult = geoDataManager.deletePoint(deletePointRequest);
printDeletePointResult(deletePointResult, out);
}
private void printDeletePointResult(DeletePointResult deletePointResult, PrintWriter out)
throws JsonParseException, IOException {
Map<String, String> jsonMap = new HashMap<String, String>();
jsonMap.put("action", "delete-point");
out.println(mapper.writeValueAsString(jsonMap));
out.flush();
}
public void destroy() {
config.getExecutorService().shutdownNow();
}
}