diff --git a/README.md b/README.md
index c906250..3eef63d 100644
--- a/README.md
+++ b/README.md
@@ -351,6 +351,12 @@ self-hosting this service.
## Release Notes
+### 2.4.7.0
+
+* Added `?country=` parameter for mapcode encoding, to limit the result list to a specific country, given
+as a 2- or 3-character ISO 3166 country code. (In contrast with `?territory=`, which is not always a country,
+but can be a state as well.)
+
### 2.4.6.0 - 2.4.6.2
* Updated to new Mapcode library.
diff --git a/deployment/pom.xml b/deployment/pom.xml
index 61ebefc..4db8d3c 100644
--- a/deployment/pom.xml
+++ b/deployment/pom.xml
@@ -23,7 +23,7 @@
com.mapcode
mapcode-rest-service
- 2.4.6.2
+ 2.4.7.0
deployment
diff --git a/pom.xml b/pom.xml
index 6e55ff3..196e9d7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
mapcode-rest-service
pom
- 2.4.6.2
+ 2.4.7.0
Mapcode REST API Web Service
@@ -104,7 +104,7 @@
3.0.2
4.12
1.2.17
- 2.4.6
+ 2.4.7
2.18.3
3.5.1.Final
2.12.6
diff --git a/resources/pom.xml b/resources/pom.xml
index bc69a56..33e1423 100644
--- a/resources/pom.xml
+++ b/resources/pom.xml
@@ -23,7 +23,7 @@
com.mapcode
mapcode-rest-service
- 2.4.6.2
+ 2.4.7.0
resources
diff --git a/service/pom.xml b/service/pom.xml
index 3ac3777..13670fb 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -23,7 +23,7 @@
com.mapcode
mapcode-rest-service
- 2.4.6.2
+ 2.4.7.0
service
diff --git a/service/src/main/java/com/mapcode/services/MapcodeResource.java b/service/src/main/java/com/mapcode/services/MapcodeResource.java
index fd8a28e..4d83b2b 100644
--- a/service/src/main/java/com/mapcode/services/MapcodeResource.java
+++ b/service/src/main/java/com/mapcode/services/MapcodeResource.java
@@ -54,6 +54,7 @@ enum ParamInclude {
static final String PARAM_LON_DEG = "lonDeg";
static final String PARAM_PRECISION = "precision";
static final String PARAM_TERRITORY = "territory";
+ static final String PARAM_COUNTRY = "country";
static final String PARAM_ALPHABET = "alphabet";
static final String PARAM_CONTEXT = "context";
static final String PARAM_TYPE = "type";
@@ -83,6 +84,9 @@ void convertLatLonToMapcode(
* @param paramTerritory Specifies a territory context to create a local mapcode for. This is only useful for local mapcodes.
* If the mapcode cannot be created for the territory, an exception is thrown.
* Range: any valid territory code, alpha or numeric.
+ * @param paramCountry Specifies a country context to create a local mapcode for. See also 'paramTerritory'.
+ * If the mapcode cannot be created for the country, an exception is thrown.
+ * Range: any valid country code.
* @param paramAlphabet Alphabet. Range: any valid alphabet code, alpha or numeric.
* @param paramInclude Specifies whether to include the offset (in meters) from the mapcode center to the specified lat/lon.
* Range: {@link ParamInclude}.
@@ -125,6 +129,11 @@ void convertLatLonToMapcode(
"is already set by the context of the application (for example, you are only interested " +
"in mapcodes for your country). If omitted, mapcodes for all territories are considered.")
@QueryParam(PARAM_TERRITORY) @Nullable String paramTerritory,
+ @ApiParam(
+ value = "(optional) Limit the returned mapcodes to this country. This is useful if the country " +
+ "is already set by the context of the application (for example, you are only interested " +
+ "in mapcodes for your country). If omitted, mapcodes for all countries are considered.")
+ @QueryParam(PARAM_COUNTRY) @Nullable String paramCountry,
@ApiParam(hidden = true)
@QueryParam(PARAM_CONTEXT) @Nullable String paramContextMustBeNull,
@ApiParam(
@@ -156,6 +165,9 @@ void convertLatLonToMapcode(
* @param paramTerritory Specifies a territory context to create a local mapcode for. This is only useful for local mapcodes.
* If the mapcode cannot be created for the territory, an exception is thrown.
* Range: any valid territory code, alpha or numeric.
+ * @param paramCountry Specifies a country context to create a local mapcode for. See also 'paramTerritory'.
+ * If the mapcode cannot be created for the country, an exception is thrown.
+ * Range: any valid country code.
* @param paramAlphabet Alphabet. Range: any valid alphabet code, alpha or numeric.
* @param paramInclude Specifies whether to include additional info in the result, such as the offset (in meters)
* from the mapcode center to the specified lat/lon, or the encompassing rectangle.
@@ -176,6 +188,7 @@ void convertLatLonToMapcode(
@PathParam(PARAM_TYPE) @Nullable String paramType,
@QueryParam(PARAM_PRECISION) @DefaultValue("0") int paramPrecision,
@QueryParam(PARAM_TERRITORY) @Nullable String paramTerritory,
+ @QueryParam(PARAM_COUNTRY) @Nullable String paramCountry,
@QueryParam(PARAM_CONTEXT) @Nullable String paramContextMustBeNull,
@QueryParam(PARAM_ALPHABET) @Nullable String paramAlphabet,
@QueryParam(PARAM_INCLUDE) @DefaultValue("") @Nonnull String paramInclude,
diff --git a/service/src/main/java/com/mapcode/services/OnlyJsonResource.java b/service/src/main/java/com/mapcode/services/OnlyJsonResource.java
index 63fdf7e..0a67819 100644
--- a/service/src/main/java/com/mapcode/services/OnlyJsonResource.java
+++ b/service/src/main/java/com/mapcode/services/OnlyJsonResource.java
@@ -57,6 +57,7 @@ void convertLatLonToMapcodeJson(
@PathParam(PARAM_LON_DEG) double paramLonDeg,
@QueryParam(PARAM_PRECISION) @DefaultValue("0") int paramPrecision,
@QueryParam(PARAM_TERRITORY) @Nullable String paramTerritory,
+ @QueryParam(PARAM_COUNTRY) @Nullable String paramCountry,
@QueryParam(PARAM_CONTEXT) @Nullable String paramContextMustBeNull,
@QueryParam(PARAM_ALPHABET) @Nullable String paramAlphabet,
@QueryParam(PARAM_INCLUDE) @DefaultValue("") @Nonnull String paramInclude,
@@ -73,6 +74,7 @@ void convertLatLonToMapcodeJson(
@PathParam(PARAM_TYPE) @Nullable String paramType,
@QueryParam(PARAM_PRECISION) @DefaultValue("0") int paramPrecision,
@QueryParam(PARAM_TERRITORY) @Nullable String paramTerritory,
+ @QueryParam(PARAM_COUNTRY) @Nullable String paramCountry,
@QueryParam(PARAM_CONTEXT) @Nullable String paramContextMustBeNull,
@QueryParam(PARAM_ALPHABET) @Nullable String paramAlphabet,
@QueryParam(PARAM_INCLUDE) @DefaultValue("") @Nonnull String paramInclude,
diff --git a/service/src/main/java/com/mapcode/services/OnlyXmlResource.java b/service/src/main/java/com/mapcode/services/OnlyXmlResource.java
index e1207b2..ba98a6f 100644
--- a/service/src/main/java/com/mapcode/services/OnlyXmlResource.java
+++ b/service/src/main/java/com/mapcode/services/OnlyXmlResource.java
@@ -57,6 +57,7 @@ void convertLatLonToMapcodeXml(
@PathParam(PARAM_LON_DEG) double paramLonDeg,
@QueryParam(PARAM_PRECISION) @DefaultValue("0") int paramPrecision,
@QueryParam(PARAM_TERRITORY) @Nullable String paramTerritory,
+ @QueryParam(PARAM_COUNTRY) @Nullable String paramCountry,
@QueryParam(PARAM_CONTEXT) @Nullable String paramContextMustBeNull,
@QueryParam(PARAM_ALPHABET) @Nullable String paramAlphabet,
@QueryParam(PARAM_INCLUDE) @DefaultValue("") @Nonnull String paramInclude,
@@ -73,6 +74,7 @@ void convertLatLonToMapcodeXml(
@PathParam(PARAM_TYPE) @Nullable String paramType,
@QueryParam(PARAM_PRECISION) @DefaultValue("0") int paramPrecision,
@QueryParam(PARAM_TERRITORY) @Nullable String paramTerritory,
+ @QueryParam(PARAM_COUNTRY) @Nullable String paramCountry,
@QueryParam(PARAM_CONTEXT) @Nullable String paramContextMustBeNull,
@QueryParam(PARAM_ALPHABET) @Nullable String paramAlphabet,
@QueryParam(PARAM_INCLUDE) @DefaultValue("") @Nonnull String paramInclude,
diff --git a/service/src/main/java/com/mapcode/services/implementation/MapcodeResourceImpl.java b/service/src/main/java/com/mapcode/services/implementation/MapcodeResourceImpl.java
index 413e2a0..b50aedc 100644
--- a/service/src/main/java/com/mapcode/services/implementation/MapcodeResourceImpl.java
+++ b/service/src/main/java/com/mapcode/services/implementation/MapcodeResourceImpl.java
@@ -25,10 +25,7 @@
import com.mapcode.services.dto.*;
import com.mapcode.services.metrics.SystemMetricsCollector;
import com.tomtom.speedtools.apivalidation.ApiDTO;
-import com.tomtom.speedtools.apivalidation.exceptions.ApiForbiddenException;
-import com.tomtom.speedtools.apivalidation.exceptions.ApiIntegerOutOfRangeException;
-import com.tomtom.speedtools.apivalidation.exceptions.ApiInvalidFormatException;
-import com.tomtom.speedtools.apivalidation.exceptions.ApiNotFoundException;
+import com.tomtom.speedtools.apivalidation.exceptions.*;
import com.tomtom.speedtools.geometry.Geo;
import com.tomtom.speedtools.geometry.GeoPoint;
import com.tomtom.speedtools.objects.Tuple;
@@ -65,6 +62,9 @@ public class MapcodeResourceImpl implements MapcodeResource {
private static final String API_ERROR_VALID_TERRITORY_CODES = Joiner.on('|').join(Arrays.stream(Territory.values()).
collect(Collectors.toList()));
+ private static final String API_ERROR_VALID_COUNTRY_CODES = Joiner.on('|').join(Territory.allCountryISO2Codes()) +
+ '|' + Joiner.on('|').join(Territory.allCountryISO3Codes());
+
private static final String API_ERROR_VALID_ALPHABET_CODES = Joiner.on('|').join(Arrays.stream(Alphabet.values()).
collect(Collectors.toList()));
@@ -109,16 +109,18 @@ public void convertLatLonToMapcode(
final double paramLonDeg,
final int paramPrecision,
@Nullable final String paramTerritory,
+ @Nullable final String paramCountry,
@Nullable final String paramContextMustBeNull,
@Nullable final String paramAlphabet,
@Nonnull final String paramInclude,
@Nonnull final String paramClient,
@Nonnull final String paramAllowLog,
@Nonnull final AsyncResponse response) throws ApiInvalidFormatException {
- convertLatLonToMapcode(paramLatDeg, paramLonDeg, null, paramPrecision, paramTerritory, paramContextMustBeNull,
- paramAlphabet, paramInclude, paramClient, paramAllowLog, response);
+ convertLatLonToMapcode(paramLatDeg, paramLonDeg, null, paramPrecision, paramTerritory, paramCountry,
+ paramContextMustBeNull, paramAlphabet, paramInclude, paramClient, paramAllowLog, response);
}
+ @SuppressWarnings("NestedTryStatement")
@Override
public void convertLatLonToMapcode(
final double paramLatDeg,
@@ -126,6 +128,7 @@ public void convertLatLonToMapcode(
@Nullable final String paramType,
final int paramPrecision,
@Nullable final String paramTerritory,
+ @Nullable final String paramCountry,
@Nullable final String paramContextMustBeNull,
@Nullable final String paramAlphabet,
@Nonnull final String paramInclude,
@@ -164,13 +167,34 @@ public void convertLatLonToMapcode(
", " + ApiConstants.API_PRECISION_MAX + ']');
}
+ // Check if either paramTerritory or paramCountry is set (or neither).
+ if ((paramTerritory != null) && (paramCountry != null)) {
+ throw new ApiConflictException("Cannot specify both " + PARAM_TERRITORY + " and " + PARAM_COUNTRY);
+ }
+
// Get the territory.
- @Nullable final Territory territory;
- try {
- territory = (paramTerritory != null) ?
- resolveTerritory(StringEscapeUtils.unescapeHtml4(paramTerritory), null) : null;
- } catch (final IllegalArgumentException ignored) {
- throw new ApiInvalidFormatException(PARAM_TERRITORY, paramTerritory, API_ERROR_VALID_TERRITORY_CODES);
+ @Nullable Territory territory = null;
+ @Nullable String country = null;
+ if (paramTerritory != null) {
+ try {
+ territory = resolveTerritory(StringEscapeUtils.unescapeHtml4(paramTerritory), null);
+ } catch (final IllegalArgumentException ignored) {
+ throw new ApiInvalidFormatException(PARAM_TERRITORY, paramTerritory, API_ERROR_VALID_TERRITORY_CODES);
+ }
+ } else if (paramCountry != null) {
+ try {
+ final String countryUnescaped = StringEscapeUtils.unescapeHtml4(paramCountry);
+ //noinspection NestedTryStatement
+ try {
+ Territory.fromCountryISO2(countryUnescaped);
+ country = countryUnescaped;
+ } catch (final IllegalArgumentException ignored) {
+ Territory.fromCountryISO3(countryUnescaped);
+ country = countryUnescaped;
+ }
+ } catch (final IllegalArgumentException ignored) {
+ throw new ApiInvalidFormatException(PARAM_COUNTRY, paramCountry, API_ERROR_VALID_COUNTRY_CODES);
+ }
}
// Get the alphabet.
@@ -242,7 +266,11 @@ public void convertLatLonToMapcode(
// Get all mapcodes.
final List mapcodes;
- mapcodes = MapcodeCodec.encode(latDeg, lonDeg, territory);
+ if (country != null) {
+ mapcodes = MapcodeCodec.encodeRestrictToCountryISO(latDeg, lonDeg, country);
+ } else {
+ mapcodes = MapcodeCodec.encode(latDeg, lonDeg, territory);
+ }
mapcodes.forEach(mapcode -> {
try {
final Rectangle rectangle = MapcodeCodec.decodeToRectangle(mapcode.getCode(), mapcode.getTerritory());
@@ -261,10 +289,22 @@ public void convertLatLonToMapcode(
// Get the shortest local mapcode.
Mapcode mapcodeLocal = null;
- if (territory != null) {
+ if (country != null) {
// A territory was provided, so simply use first.
- mapcodeLocal = MapcodeCodec.encodeToShortest(latDeg, lonDeg, territory);
+ try {
+ mapcodeLocal = MapcodeCodec.encodeToShortest(latDeg, lonDeg, Territory.fromCountryISO(country));
+ } catch (final UnknownMapcodeException ignored) {
+ mapcodeLocal = null;
+ }
+ } else if (territory != null) {
+
+ // A territory was provided, so simply use first.
+ try {
+ mapcodeLocal = MapcodeCodec.encodeToShortest(latDeg, lonDeg, territory);
+ } catch (final UnknownMapcodeException ignored) {
+ mapcodeLocal = null;
+ }
} else {
// Get the shortest code.
diff --git a/service/src/main/java/com/mapcode/services/implementation/OnlyJsonResourceImpl.java b/service/src/main/java/com/mapcode/services/implementation/OnlyJsonResourceImpl.java
index d96f294..f841672 100644
--- a/service/src/main/java/com/mapcode/services/implementation/OnlyJsonResourceImpl.java
+++ b/service/src/main/java/com/mapcode/services/implementation/OnlyJsonResourceImpl.java
@@ -64,6 +64,7 @@ public void convertLatLonToMapcodeJson(
final double paramLonDeg,
final int paramPrecision,
@Nullable final String paramTerritory,
+ @Nullable final String paramCountry,
@Nullable final String paramContextMustBeNull,
@Nullable final String paramAlphabet,
@Nonnull final String paramInclude,
@@ -71,8 +72,8 @@ public void convertLatLonToMapcodeJson(
@Nonnull final String paramAllowLog,
@Suspended @Nonnull final AsyncResponse response)
throws ApiInvalidFormatException {
- mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramPrecision, paramTerritory, paramContextMustBeNull,
- paramAlphabet, paramInclude, paramClient, paramAllowLog, response);
+ mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramPrecision, paramTerritory, paramCountry,
+ paramContextMustBeNull, paramAlphabet, paramInclude, paramClient, paramAllowLog, response);
}
@Override
@@ -82,6 +83,7 @@ public void convertLatLonToMapcodeJson(
@Nullable final String paramType,
final int paramPrecision,
@Nullable final String paramTerritory,
+ @Nullable final String paramCountry,
@Nullable final String paramContextMustBeNull,
@Nullable final String paramAlphabet,
@Nonnull final String paramInclude,
@@ -89,8 +91,8 @@ public void convertLatLonToMapcodeJson(
@Nonnull final String paramDebug,
@Suspended @Nonnull final AsyncResponse response)
throws ApiInvalidFormatException {
- mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramType, paramPrecision, paramTerritory, paramContextMustBeNull,
- paramAlphabet, paramInclude, paramClient, paramDebug, response);
+ mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramType, paramPrecision, paramTerritory, paramCountry,
+ paramContextMustBeNull, paramAlphabet, paramInclude, paramClient, paramDebug, response);
}
@Override
diff --git a/service/src/main/java/com/mapcode/services/implementation/OnlyXmlResourceImpl.java b/service/src/main/java/com/mapcode/services/implementation/OnlyXmlResourceImpl.java
index c5ab34b..6134870 100644
--- a/service/src/main/java/com/mapcode/services/implementation/OnlyXmlResourceImpl.java
+++ b/service/src/main/java/com/mapcode/services/implementation/OnlyXmlResourceImpl.java
@@ -64,6 +64,7 @@ public void convertLatLonToMapcodeXml(
final double paramLonDeg,
final int paramPrecision,
@Nullable final String paramTerritory,
+ @Nullable final String paramCountry,
@Nullable final String paramContextMustBeNull,
@Nullable final String paramAlphabet,
@Nonnull final String paramInclude,
@@ -71,8 +72,8 @@ public void convertLatLonToMapcodeXml(
@Nonnull final String paramAllowLog,
@Suspended @Nonnull final AsyncResponse response)
throws ApiInvalidFormatException {
- mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramPrecision, paramTerritory, paramContextMustBeNull,
- paramAlphabet, paramInclude, paramClient, paramAllowLog, response);
+ mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramPrecision, paramTerritory, paramCountry,
+ paramContextMustBeNull, paramAlphabet, paramInclude, paramClient, paramAllowLog, response);
}
@Override
@@ -82,6 +83,7 @@ public void convertLatLonToMapcodeXml(
@Nullable final String paramType,
final int paramPrecision,
@Nullable final String paramTerritory,
+ @Nullable final String paramCountry,
@Nullable final String paramContextMustBeNull,
@Nullable final String paramAlphabet,
@Nonnull final String paramInclude,
@@ -89,8 +91,8 @@ public void convertLatLonToMapcodeXml(
@Nonnull final String paramDebug,
@Suspended @Nonnull final AsyncResponse response)
throws ApiInvalidFormatException {
- mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramType, paramPrecision, paramTerritory, paramContextMustBeNull,
- paramAlphabet, paramInclude, paramClient, paramDebug, response);
+ mapcodeResource.convertLatLonToMapcode(paramLatDeg, paramLonDeg, paramType, paramPrecision, paramTerritory, paramCountry,
+ paramContextMustBeNull, paramAlphabet, paramInclude, paramClient, paramDebug, response);
}
@Override
diff --git a/service/src/main/java/com/mapcode/services/implementation/RootResourceImpl.java b/service/src/main/java/com/mapcode/services/implementation/RootResourceImpl.java
index 572b479..b9f2803 100644
--- a/service/src/main/java/com/mapcode/services/implementation/RootResourceImpl.java
+++ b/service/src/main/java/com/mapcode/services/implementation/RootResourceImpl.java
@@ -69,11 +69,21 @@ public class RootResourceImpl implements RootResource {
"GET /mapcode/status Returns 200 if the service OK.\n\n" +
"GET /mapcode/codes/{lat},{lon}[/[mapcodes|local|international]]\n" +
- " [?precision=[0..8] & territory={restrictToTerritory} & alphabet={alphabet} & include={offset|territory|alphabet|rectangle}]\n\n" +
+ " [?precision=[0..8] & territory={restrictToTerritory} & country={restrictToCountry}\n" +
+ " alphabet={alphabet} & include={offset|territory|alphabet|rectangle}]\n\n" +
" Convert latitude/longitude to one or more mapcodes. The response always contains the 'international' mapcode and\n" +
" only contains a 'local' mapcode if there are any non-international mapcode AND they are all of the same territory.\n\n" +
+ " The 'country' parameter always specifies a country, by a 2 or 3 character ISO-3166 code, like 'US' or 'USA'\n" +
+ " (for the USA), and 'NL' or 'NLD' (for the Netherlands). In a web environment, the country code is often available\n" +
+ " as a 2-character code. That code can be used for this parameter.\n\n" +
+
+ " The 'territory' parameter is a 2, 3 or 5 (XX-YY) character code. These code can be countries or states within countries.\n" +
+ " Some 2 character state codes are the same as country codes. In that case, the territory implies the state, not the country.\n" +
+ " For example, the territory code 'US' is unambiguous and means USA, but 'NL' means 'IN-NL' (Nagaland, India) rather than\n" +
+ " the Netherlands. You cannot use the standard 2-character country codes in web applications for this parameter.\n\n" +
+
" Path parameters:\n" +
" lat : Latitude, range [-90, 90] (automatically limited to this range).\n" +
" lon : Longitude, range [-180, 180] (automatically wrapped to this range).\n\n" +
@@ -89,7 +99,8 @@ public class RootResourceImpl implements RootResource {
" Query parameters:\n" +
" precision : Precision, range [0..8] (default=0).\n" +
- " territory : Territory to restrict results to (name or alphacode).\n" +
+ " territory : Territory (country or state) to restrict results to (name or alphacode).\n" +
+ " country : Country to restrict results to (name or alphacode).\n" +
" alphabet : Alphabet to return results in.\n" +
" include : Multiple options may be set, separated by comma's:\n" +
" offset = Include offset from mapcode center to lat/lon (in meters).\n" +
@@ -230,7 +241,7 @@ public void getStatus(@Suspended @Nonnull final AsyncResponse response) {
final String allowLog = "false";
final TestAsyncResponse asyncResponse1 = new TestAsyncResponse();
mapcodeResource.convertLatLonToMapcode(latDeg, lonDeg, "local",
- precision, territory, null, alphabet, include, client,
+ precision, territory, null, null, alphabet, include, client,
allowLog, asyncResponse1);
waitForResponse(asyncResponse1);