diff --git a/clientResources/amc/modules/MapPanel/Layer/SearchResults.js b/clientResources/amc/modules/MapPanel/Layer/SearchResults.js
index 739c93d8..5f490609 100644
--- a/clientResources/amc/modules/MapPanel/Layer/SearchResults.js
+++ b/clientResources/amc/modules/MapPanel/Layer/SearchResults.js
@@ -66,6 +66,10 @@ Atlas.Layer.SearchResults = OpenLayers.Class(Atlas.Layer.AbstractLayer, {
return;
}
+ this.mapPanel = mapPanel;
+ this.json = jsonLayer;
+ this.parent = parent;
+
this.searchCount = Atlas.Layer.SearchResults.count;
Atlas.Layer.SearchResults.count++;
@@ -161,12 +165,26 @@ Atlas.Layer.SearchResults = OpenLayers.Class(Atlas.Layer.AbstractLayer, {
var params = {
client: Atlas.conf['clientId'],
query: this.query,
- bounds: null,
offset: this.page * this.NB_RESULTS_PER_PAGE,
qty: this.NB_RESULTS_PER_PAGE,
noCache: (new Date()).getTime() // Anti-caching
};
+ // Add map bounds to the request
+ if (this.mapPanel && this.mapPanel.map) {
+ var mapBounds = this.mapPanel.map.calculateBounds();
+ if (mapBounds) {
+ var reprojectedBounds = mapBounds.transform(this.mapPanel.map.getProjectionObject(), this.mapPanel.defaultLonLatProjection);
+
+ if (reprojectedBounds) {
+ params["north"] = reprojectedBounds.top;
+ params["east"] = reprojectedBounds.right;
+ params["south"] = reprojectedBounds.bottom;
+ params["west"] = reprojectedBounds.left;
+ }
+ }
+ }
+
OpenLayers.Request.GET({
url: this.searchServiceUrl,
params: params,
diff --git a/pom.xml b/pom.xml
index 80fe4f9f..dd6b1570 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
au.gov.aims
atlasmapper
war
- 2.1.3
+ 2.1.4
AtlasMapper server and clients
This application compiled as a single War, that can be deployed in Tomcat, without any other dependency.\n\
It contains:\n\
diff --git a/src/main/java/au/gov/aims/atlasmapperserver/ClientConfig.java b/src/main/java/au/gov/aims/atlasmapperserver/ClientConfig.java
index 84f078fa..d0ad0131 100644
--- a/src/main/java/au/gov/aims/atlasmapperserver/ClientConfig.java
+++ b/src/main/java/au/gov/aims/atlasmapperserver/ClientConfig.java
@@ -1260,8 +1260,13 @@ private String getHTMLListAndHideChildrenLayers(JSONObject layers, JSONArray chi
}
- public JSONObject locationSearch(URLCache urlCache, String query, String referer, String mapBounds, int offset, int qty)
- throws JSONException, IOException, RevivableThreadInterruptedException {
+ public JSONObject locationSearch(
+ URLCache urlCache,
+ String query,
+ String referer,
+ LocationSearch.LocationSearchBoundingBox mapBounds,
+ int offset, int qty
+ ) throws JSONException, IOException, RevivableThreadInterruptedException {
if (Utils.isBlank(query) || qty <= 0) {
return null;
@@ -1293,10 +1298,16 @@ public int compare(JSONObject o1, JSONObject o2) {
try {
String googleSearchAPIKey = this.getGoogleSearchAPIKey();
- if (this.isShowGoogleResults() && Utils.isNotBlank(googleSearchAPIKey)) {
- List googleResults = LocationSearch.googleSearch(urlCache, googleSearchAPIKey, referer, encodedQuery, mapBounds);
- if (googleResults != null && !googleResults.isEmpty()) {
- resultsSet.addAll(googleResults);
+ if (this.isShowGoogleResults()) {
+ if (Utils.isBlank(googleSearchAPIKey)) {
+ LOGGER.warning(String.format("Client %s can't use Google Search. The Google search API key is blank.",
+ this.getClientId()));
+ } else {
+ List googleResults = LocationSearch.googleSearch(
+ urlCache, googleSearchAPIKey, referer, encodedQuery, mapBounds);
+ if (googleResults != null && !googleResults.isEmpty()) {
+ resultsSet.addAll(googleResults);
+ }
}
}
} catch(Exception ex) {
@@ -1306,10 +1317,16 @@ public int compare(JSONObject o1, JSONObject o2) {
try {
String osmSearchAPIKey = this.getOsmSearchAPIKey();
- if (this.isShowOSMResults() && Utils.isNotBlank(osmSearchAPIKey)) {
- List osmNominatimResults = LocationSearch.osmNominatimSearch(urlCache, osmSearchAPIKey, referer, encodedQuery, mapBounds);
- if (osmNominatimResults != null && !osmNominatimResults.isEmpty()) {
- resultsSet.addAll(osmNominatimResults);
+ if (this.isShowOSMResults()) {
+ if (Utils.isBlank(osmSearchAPIKey)) {
+ LOGGER.warning(String.format("Client %s can't use OSM Search. The OSM search API key is blank.",
+ this.getClientId()));
+ } else {
+ List osmNominatimResults = LocationSearch.osmNominatimSearch(
+ urlCache, osmSearchAPIKey, referer, encodedQuery, mapBounds);
+ if (osmNominatimResults != null && !osmNominatimResults.isEmpty()) {
+ resultsSet.addAll(osmNominatimResults);
+ }
}
}
} catch(Exception ex) {
@@ -1319,10 +1336,16 @@ public int compare(JSONObject o1, JSONObject o2) {
try {
String arcGISSearchUrl = this.getArcGISSearchUrl();
- if (this.isShowArcGISResults() && Utils.isNotBlank(arcGISSearchUrl)) {
- List arcGISResults = LocationSearch.arcGISSearch(urlCache, referer, arcGISSearchUrl, encodedQuery, mapBounds);
- if (arcGISResults != null && !arcGISResults.isEmpty()) {
- resultsSet.addAll(arcGISResults);
+ if (this.isShowArcGISResults()) {
+ if (Utils.isBlank(arcGISSearchUrl)) {
+ LOGGER.warning(String.format("Client %s can't use ArcGIS Search. The ArcGIS search URL is blank.",
+ this.getClientId()));
+ } else {
+ List arcGISResults = LocationSearch.arcGISSearch(
+ urlCache, referer, arcGISSearchUrl, encodedQuery, mapBounds);
+ if (arcGISResults != null && !arcGISResults.isEmpty()) {
+ resultsSet.addAll(arcGISResults);
+ }
}
}
} catch(Exception ex) {
diff --git a/src/main/java/au/gov/aims/atlasmapperserver/LocationSearch.java b/src/main/java/au/gov/aims/atlasmapperserver/LocationSearch.java
index 09289fb6..0e303e34 100644
--- a/src/main/java/au/gov/aims/atlasmapperserver/LocationSearch.java
+++ b/src/main/java/au/gov/aims/atlasmapperserver/LocationSearch.java
@@ -62,16 +62,37 @@ private static void incSearchCount() {
// Google
// API: https://developers.google.com/maps/documentation/geocoding/
// URL: http://maps.googleapis.com/maps/api/geocode/json?address={QUERY}&sensor=false
- public static List googleSearch(URLCache urlCache, String googleSearchAPIKey, String referer, String encodedQuery, String mapBounds)
- throws JSONException, IOException, URISyntaxException, SQLException, RevivableThreadInterruptedException, ClassNotFoundException {
-
- String googleSearchUrl = "https://maps.googleapis.com/maps/api/geocode/json?address={QUERY}&sensor=false&key={APIKEY}";
+ public static List googleSearch(
+ URLCache urlCache,
+ String googleSearchAPIKey,
+ String referer,
+ String encodedQuery,
+ LocationSearch.LocationSearchBoundingBox mapBounds
+ ) throws JSONException, IOException, URISyntaxException, SQLException, RevivableThreadInterruptedException, ClassNotFoundException {
+
+ // The bounds parameter defines the latitude/longitude coordinates of
+ // the southwest and northeast corners of this bounding box
+ // using a pipe (|) character to separate the coordinates.
+ // NOTE: The pipe needs to be URL encoded: | = %7C
+ String googleSearchUrl = "https://maps.googleapis.com/maps/api/geocode/json?" +
+ "address={QUERY}" +
+ "&sensor=false" +
+ "&key={APIKEY}" +
+ "&bounds={SOUTH},{WEST}%7C{NORTH},{EAST}";
String encodedGoogleSearchAPIKey = URLEncoder.encode(googleSearchAPIKey.trim(), "UTF-8");
String queryURLStr = googleSearchUrl
.replace("{QUERY}", encodedQuery)
.replace("{APIKEY}", encodedGoogleSearchAPIKey);
+ if (mapBounds != null) {
+ queryURLStr = queryURLStr
+ .replace("{SOUTH}", "" + mapBounds.getSouth())
+ .replace("{WEST}", "" + mapBounds.getWest())
+ .replace("{NORTH}", "" + mapBounds.getNorth())
+ .replace("{EAST}", "" + mapBounds.getEast());
+ }
+
JSONObject json = LocationSearch.getSearchJSONObjectResponse(urlCache, queryURLStr, referer);
if (json == null) {
return null;
@@ -256,8 +277,13 @@ public static List osmSearch(URLCache urlCache, String osmSearchAPIK
// OSM Nominatim
// API: https://developer.mapquest.com/documentation/open/nominatim-search/
// URL: http://open.mapquestapi.com/nominatim/v1/search?format=json&q={QUERY}
- public static List osmNominatimSearch(URLCache urlCache, String osmSearchAPIKey, String referer, String encodedQuery, String mapBounds)
- throws JSONException, IOException, URISyntaxException, SQLException, RevivableThreadInterruptedException, ClassNotFoundException {
+ public static List osmNominatimSearch(
+ URLCache urlCache,
+ String osmSearchAPIKey,
+ String referer,
+ String encodedQuery,
+ LocationSearch.LocationSearchBoundingBox mapBounds
+ ) throws JSONException, IOException, URISyntaxException, SQLException, RevivableThreadInterruptedException, ClassNotFoundException {
String osmSearchUrl = "http://open.mapquestapi.com/nominatim/v1/search?format=json&q={QUERY}&key={APIKEY}";
@@ -324,8 +350,13 @@ public static List osmNominatimSearch(URLCache urlCache, String osmS
// ArcGIS
// API: http://resources.arcgis.com/en/help/rest/apiref/index.html?find.html
// URL example: http://www.gbrmpa.gov.au/spatial_services/gbrmpaBounds/MapServer/find?f=json&contains=true&returnGeometry=true&layers=6%2C0&searchFields=LOC_NAME_L%2CNAME&searchText={QUERY}
- public static List arcGISSearch(URLCache urlCache, String referer, String arcGISSearchUrl, String encodedQuery, String mapBounds)
- throws JSONException, IOException, TransformException, FactoryException, URISyntaxException, SQLException, RevivableThreadInterruptedException, ClassNotFoundException {
+ public static List arcGISSearch(
+ URLCache urlCache,
+ String referer,
+ String arcGISSearchUrl,
+ String encodedQuery,
+ LocationSearch.LocationSearchBoundingBox mapBounds
+ ) throws JSONException, IOException, TransformException, FactoryException, URISyntaxException, SQLException, RevivableThreadInterruptedException, ClassNotFoundException {
if (Utils.isBlank(arcGISSearchUrl)) {
return null;
@@ -474,4 +505,49 @@ public static JSONObject _createSearchResult(String title, String id, double[] c
return result;
}
+
+ public static class LocationSearchBoundingBox {
+ private final float north;
+ private final float east;
+ private final float south;
+ private final float west;
+
+ public LocationSearchBoundingBox(String northStr, String eastStr, String southStr, String westStr) {
+ this(
+ Float.parseFloat(northStr),
+ Float.parseFloat(eastStr),
+ Float.parseFloat(southStr),
+ Float.parseFloat(westStr)
+ );
+ }
+
+ public LocationSearchBoundingBox(float north, float east, float south, float west) {
+ this.north = north;
+ this.east = east;
+ this.south = south;
+ this.west = west;
+ }
+
+ public float getNorth() {
+ return this.north;
+ }
+
+ public float getEast() {
+ return this.east;
+ }
+
+ public float getSouth() {
+ return this.south;
+ }
+
+ public float getWest() {
+ return this.west;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[N:%.3f, E:%.3f, S:%.3f, W:%.3f]",
+ this.north, this.east, this.south, this.west);
+ }
+ }
}
diff --git a/src/main/java/au/gov/aims/atlasmapperserver/cache/URLCache.java b/src/main/java/au/gov/aims/atlasmapperserver/cache/URLCache.java
index cf73f288..5341d574 100644
--- a/src/main/java/au/gov/aims/atlasmapperserver/cache/URLCache.java
+++ b/src/main/java/au/gov/aims/atlasmapperserver/cache/URLCache.java
@@ -355,12 +355,6 @@ private void requestHttpDocument(CacheEntry cacheEntry) throws URISyntaxExceptio
cacheEntry.setDocumentFile(tmpFile);
}
} finally {
- if (httpGet != null) {
- // Cancel the connection, if it's still alive
- httpGet.abort();
- // Close connections
- httpGet.reset();
- }
if (in != null) {
try { in.close(); } catch (Exception e) {
LOGGER.log(Level.WARNING, String.format("Error occur while closing the URL %s: %s", url, Utils.getExceptionMessage(e)), e);
@@ -376,6 +370,12 @@ private void requestHttpDocument(CacheEntry cacheEntry) throws URISyntaxExceptio
LOGGER.log(Level.WARNING, String.format("Error occur while closing the HttpResponse: %s", Utils.getExceptionMessage(e)), e);
}
}
+ if (httpGet != null) {
+ // Cancel the connection, if it's still alive
+ httpGet.abort();
+ // Close connections
+ httpGet.reset();
+ }
if (httpClient != null) {
try { httpClient.close(); } catch (Exception e) {
LOGGER.log(Level.WARNING, "Error occur while closing the HttpClient: " + Utils.getExceptionMessage(e), e);
diff --git a/src/main/webapp/public/search.jsp b/src/main/webapp/public/search.jsp
index 488957fb..1dca89a2 100644
--- a/src/main/webapp/public/search.jsp
+++ b/src/main/webapp/public/search.jsp
@@ -45,6 +45,7 @@
<%@page import="org.json.JSONArray"%>
<%@page import="org.json.JSONObject"%>
<%@page import="au.gov.aims.atlasmapperserver.cache.URLCache" %>
+<%@page import="au.gov.aims.atlasmapperserver.LocationSearch" %>
<%
// Needed by StripTagProxy:
// http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.ScriptTagProxy
@@ -66,8 +67,22 @@
// The query string, as entered by the user in the search field.
String query = request.getParameter("query");
+
// Map bounds, to help the server to order the results.
- String bounds = request.getParameter("bounds");
+ LocationSearch.LocationSearchBoundingBox bounds = null;
+ String northStr = request.getParameter("north");
+ String eastStr = request.getParameter("east");
+ String southStr = request.getParameter("south");
+ String westStr = request.getParameter("west");
+ if (
+ northStr != null && !northStr.isEmpty() &&
+ eastStr != null && !eastStr.isEmpty() &&
+ southStr != null && !southStr.isEmpty() &&
+ westStr != null && !westStr.isEmpty()
+ ) {
+ bounds = new LocationSearch.LocationSearchBoundingBox(
+ northStr, eastStr, southStr, westStr);
+ }
// Start from result (default: 0 => Start from the first result).
int offset = (request.getParameter("offset") != null ? Integer.parseInt(request.getParameter("offset")) :