/*
* 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.dynamodb.internal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.amazonaws.geo.GeoDataManagerConfiguration;
import com.amazonaws.geo.model.BatchWritePointResult;
import com.amazonaws.geo.model.DeletePointRequest;
import com.amazonaws.geo.model.DeletePointResult;
import com.amazonaws.geo.model.GeohashRange;
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.UpdatePointRequest;
import com.amazonaws.geo.model.UpdatePointResult;
import com.amazonaws.geo.s2.internal.S2Manager;
import com.amazonaws.geo.util.GeoJsonMapper;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest;
import com.amazonaws.services.dynamodbv2.model.BatchWriteItemResult;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest;
import com.amazonaws.services.dynamodbv2.model.DeleteItemResult;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.PutItemResult;
import com.amazonaws.services.dynamodbv2.model.PutRequest;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.model.QueryResult;
import com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity;
import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest;
import com.amazonaws.services.dynamodbv2.model.UpdateItemResult;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;
public class DynamoDBManager {
private GeoDataManagerConfiguration config;
public DynamoDBManager(GeoDataManagerConfiguration config) {
this.config = config;
}
/**
* Query Amazon DynamoDB
*
* @param hashKey
* Hash key for the query request.
*
* @param range
* The range of geohashs to query.
*
* @return The query result.
*/
public List<QueryResult> queryGeohash(QueryRequest queryRequest, long hashKey, GeohashRange range) {
List<QueryResult> queryResults = new ArrayList<QueryResult>();
Map<String, AttributeValue> lastEvaluatedKey = null;
do {
Map<String, Condition> keyConditions = new HashMap<String, Condition>();
Condition hashKeyCondition = new Condition().withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withN(String.valueOf(hashKey)));
keyConditions.put(config.getHashKeyAttributeName(), hashKeyCondition);
AttributeValue minRange = new AttributeValue().withN(Long.toString(range.getRangeMin()));
AttributeValue maxRange = new AttributeValue().withN(Long.toString(range.getRangeMax()));
Condition geohashCondition = new Condition().withComparisonOperator(ComparisonOperator.BETWEEN)
.withAttributeValueList(minRange, maxRange);
keyConditions.put(config.getGeohashAttributeName(), geohashCondition);
queryRequest.withTableName(config.getTableName()).withKeyConditions(keyConditions)
.withIndexName(config.getGeohashIndexName()).withConsistentRead(true)
.withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL).withExclusiveStartKey(lastEvaluatedKey);
QueryResult queryResult = config.getDynamoDBClient().query(queryRequest);
queryResults.add(queryResult);
lastEvaluatedKey = queryResult.getLastEvaluatedKey();
} while (lastEvaluatedKey != null);
return queryResults;
}
public GetPointResult getPoint(GetPointRequest getPointRequest) {
long geohash = S2Manager.generateGeohash(getPointRequest.getGeoPoint());
long hashKey = S2Manager.generateHashKey(geohash, config.getHashKeyLength());
GetItemRequest getItemRequest = getPointRequest.getGetItemRequest();
getItemRequest.setTableName(config.getTableName());
AttributeValue hashKeyValue = new AttributeValue().withN(String.valueOf(hashKey));
getItemRequest.getKey().put(config.getHashKeyAttributeName(), hashKeyValue);
getItemRequest.getKey().put(config.getRangeKeyAttributeName(), getPointRequest.getRangeKeyValue());
GetItemResult getItemResult = config.getDynamoDBClient().getItem(getItemRequest);
GetPointResult getPointResult = new GetPointResult(getItemResult);
return getPointResult;
}
public PutPointResult putPoint(PutPointRequest putPointRequest) {
long geohash = S2Manager.generateGeohash(putPointRequest.getGeoPoint());
long hashKey = S2Manager.generateHashKey(geohash, config.getHashKeyLength());
String geoJson = GeoJsonMapper.stringFromGeoObject(putPointRequest.getGeoPoint());
PutItemRequest putItemRequest = putPointRequest.getPutItemRequest();
putItemRequest.setTableName(config.getTableName());
AttributeValue hashKeyValue = new AttributeValue().withN(String.valueOf(hashKey));
putItemRequest.getItem().put(config.getHashKeyAttributeName(), hashKeyValue);
putItemRequest.getItem().put(config.getRangeKeyAttributeName(), putPointRequest.getRangeKeyValue());
AttributeValue geohashValue = new AttributeValue().withN(Long.toString(geohash));
putItemRequest.getItem().put(config.getGeohashAttributeName(), geohashValue);
AttributeValue geoJsonValue = new AttributeValue().withS(geoJson);
putItemRequest.getItem().put(config.getGeoJsonAttributeName(), geoJsonValue);
PutItemResult putItemResult = config.getDynamoDBClient().putItem(putItemRequest);
PutPointResult putPointResult = new PutPointResult(putItemResult);
return putPointResult;
}
public BatchWritePointResult batchWritePoints(List<PutPointRequest> putPointRequests) {
BatchWriteItemRequest batchItemRequest = new BatchWriteItemRequest();
List<WriteRequest> writeRequests = new ArrayList<WriteRequest>();
for (PutPointRequest putPointRequest : putPointRequests) {
long geohash = S2Manager.generateGeohash(putPointRequest.getGeoPoint());
long hashKey = S2Manager.generateHashKey(geohash, config.getHashKeyLength());
String geoJson = GeoJsonMapper.stringFromGeoObject(putPointRequest.getGeoPoint());
PutRequest putRequest = putPointRequest.getPutRequest();
AttributeValue hashKeyValue = new AttributeValue().withN(String.valueOf(hashKey));
putRequest.getItem().put(config.getHashKeyAttributeName(), hashKeyValue);
putRequest.getItem().put(config.getRangeKeyAttributeName(), putPointRequest.getRangeKeyValue());
AttributeValue geohashValue = new AttributeValue().withN(Long.toString(geohash));
putRequest.getItem().put(config.getGeohashAttributeName(), geohashValue);
AttributeValue geoJsonValue = new AttributeValue().withS(geoJson);
putRequest.getItem().put(config.getGeoJsonAttributeName(), geoJsonValue);
WriteRequest writeRequest = new WriteRequest(putRequest);
writeRequests.add(writeRequest);
}
Map<String, List<WriteRequest>> requestItems = new HashMap<String, List<WriteRequest>>();
requestItems.put(config.getTableName(), writeRequests);
batchItemRequest.setRequestItems(requestItems);
BatchWriteItemResult batchWriteItemResult = config.getDynamoDBClient().batchWriteItem(batchItemRequest);
BatchWritePointResult batchWritePointResult = new BatchWritePointResult(batchWriteItemResult);
return batchWritePointResult;
}
public UpdatePointResult updatePoint(UpdatePointRequest updatePointRequest) {
long geohash = S2Manager.generateGeohash(updatePointRequest.getGeoPoint());
long hashKey = S2Manager.generateHashKey(geohash, config.getHashKeyLength());
UpdateItemRequest updateItemRequest = updatePointRequest.getUpdateItemRequest();
updateItemRequest.setTableName(config.getTableName());
AttributeValue hashKeyValue = new AttributeValue().withN(String.valueOf(hashKey));
updateItemRequest.getKey().put(config.getHashKeyAttributeName(), hashKeyValue);
updateItemRequest.getKey().put(config.getRangeKeyAttributeName(), updatePointRequest.getRangeKeyValue());
// Geohash and geoJson cannot be updated.
updateItemRequest.getAttributeUpdates().remove(config.getGeohashAttributeName());
updateItemRequest.getAttributeUpdates().remove(config.getGeoJsonAttributeName());
UpdateItemResult updateItemResult = config.getDynamoDBClient().updateItem(updateItemRequest);
UpdatePointResult updatePointResult = new UpdatePointResult(updateItemResult);
return updatePointResult;
}
public DeletePointResult deletePoint(DeletePointRequest deletePointRequest) {
long geohash = S2Manager.generateGeohash(deletePointRequest.getGeoPoint());
long hashKey = S2Manager.generateHashKey(geohash, config.getHashKeyLength());
DeleteItemRequest deleteItemRequest = deletePointRequest.getDeleteItemRequest();
deleteItemRequest.setTableName(config.getTableName());
AttributeValue hashKeyValue = new AttributeValue().withN(String.valueOf(hashKey));
deleteItemRequest.getKey().put(config.getHashKeyAttributeName(), hashKeyValue);
deleteItemRequest.getKey().put(config.getRangeKeyAttributeName(), deletePointRequest.getRangeKeyValue());
DeleteItemResult deleteItemResult = config.getDynamoDBClient().deleteItem(deleteItemRequest);
DeletePointResult deletePointResult = new DeletePointResult(deleteItemResult);
return deletePointResult;
}
}