import { AWSError , DynamoDB , Request } from "aws-sdk" ; import { DynamoDBManager } from "./dynamodb/DynamoDBManager" ; import { GeoDataManagerConfiguration } from "./GeoDataManagerConfiguration" ; import { BatchWritePointOutput , DeletePointInput , DeletePointOutput , GeoPoint , GeoQueryInput , GetPointInput , GetPointOutput , PutPointInput , PutPointOutput , QueryRadiusInput , QueryRectangleInput , UpdatePointInput , UpdatePointOutput } from "./types" ; import { S2Manager } from "./s2/S2Manager" ; import { S2Util } from "./s2/S2Util" ; import { S2LatLng , S2LatLngRect } from "nodes2ts" ; import { Covering } from "./model/Covering" ; /**
 * <p>
 * Manager to hangle geo spatial data in Amazon DynamoDB tables. All service calls made using this client are blocking,
 * and will not return until the service call completes.
 * </p>
 * <p>
 * This class is designed to be thread safe; however, once constructed GeoDataManagerConfiguration should not be
 * modified. Modifying GeoDataManagerConfiguration may cause unspecified behaviors.
 * </p>
 * */ export class GeoDataManager { private config : GeoDataManagerConfiguration ; private dynamoDBManager : DynamoDBManager ; param config constructor ( config ) { this . config = config ; this . dynamoDBManager = new DynamoDBManager ( this . config ) ; } return public getGeoDataManagerConfiguration ( ) { return this . config ; } param putPointInput return public putPoint ( putPointInput ) { return this . dynamoDBManager . putPoint ( putPointInput ) ; } param putPointInputs return public batchWritePoints ( putPointInputs ) { return this . dynamoDBManager . batchWritePoints ( putPointInputs ) ; } param getPointInput return public getPoint ( getPointInput ) { return this . dynamoDBManager . getPoint ( getPointInput ) ; } param queryRectangleInput return public async queryRectangle ( queryRectangleInput ) { const latLngRect = S2Util . latLngRectFromQueryRectangleInput ( queryRectangleInput ) ; const covering = new Covering ( new this . config . S2RegionCoverer ( ) . getCoveringCells ( latLngRect ) ) ; const results = await this . dispatchQueries ( covering , queryRectangleInput ) ; return this . filterByRectangle ( results , queryRectangleInput ) ; } param queryRadiusInput return public async queryRadius ( queryRadiusInput ) { const latLngRect = S2Util . getBoundingLatLngRectFromQueryRadiusInput ( queryRadiusInput ) ; const covering = new Covering ( new this . config . S2RegionCoverer ( ) . getCoveringCells ( latLngRect ) ) ; const results = await this . dispatchQueries ( covering , queryRadiusInput ) ; return this . filterByRadius ( results , queryRadiusInput ) ; } param updatePointInput return public updatePoint ( updatePointInput ) { return this . dynamoDBManager . updatePoint ( updatePointInput ) ; } param deletePointInput return public deletePoint ( deletePointInput ) { return this . dynamoDBManager . deletePoint ( deletePointInput ) ; } param covering param geoQueryInput return private async dispatchQueries ( covering , geoQueryInput ) { const promises = covering . getGeoHashRanges ( this . config . hashKeyLength ) . map ( range => { const hashKey = S2Manager . generateHashKey ( range . rangeMin , this . config . hashKeyLength ) ; return this . dynamoDBManager . queryGeohash ( geoQueryInput . QueryInput , hashKey , range ) ; } ) ; const results = await Promise . all ( promises ) ; const mergedResults = [ ] ; results . forEach ( queryOutputs => queryOutputs . forEach ( queryOutput => mergedResults . push ( ... queryOutput . Items ) ) ) ; return mergedResults ; } param list param geoQueryInput returns private filterByRadius ( list , geoQueryInput ) { let centerLatLng = null ; let radiusInMeter = 0 ; const centerPoint = ( geoQueryInput as QueryRadiusInput ) . CenterPoint ; centerLatLng = S2LatLng . fromDegrees ( centerPoint . latitude , centerPoint . longitude ) ; radiusInMeter = ( geoQueryInput as QueryRadiusInput ) . RadiusInMeter ; return list . filter ( item => { const geoJson = item [ this . config . geoJsonAttributeName ] . S ; const coordinates = JSON . parse ( geoJson ) . coordinates ; const longitude = coordinates [ this . config . longitudeFirst ? 0 : 1 ] ; const latitude = coordinates [ this . config . longitudeFirst ? 1 : 0 ] ; const latLng = S2LatLng . fromDegrees ( latitude , longitude ) ; return ( centerLatLng . getEarthDistance ( latLng ) as any ) . toNumber ( ) <= radiusInMeter ; } ) ; } param list param geoQueryInput returns private filterByRectangle ( list , geoQueryInput ) { const latLngRect = S2Util . latLngRectFromQueryRectangleInput ( geoQueryInput ) ; return list . filter ( item => { const geoJson = item [ this . config . geoJsonAttributeName ] . S ; const coordinates = JSON . parse ( geoJson ) . coordinates ; const longitude = coordinates [ this . config . longitudeFirst ? 0 : 1 ] ; const latitude = coordinates [ this . config . longitudeFirst ? 1 : 0 ] ; const latLng = S2LatLng . fromDegrees ( latitude , longitude ) ; return latLngRect . containsLL ( latLng ) ; } ) ; } }