Skip to content

Commit c4c9668

Browse files
committed
Handle parsing invalid Svalbard zones (32X, 34X, 36X)
1 parent 62225cb commit c4c9668

4 files changed

Lines changed: 147 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Adheres to [Semantic Versioning](http://semver.org/).
44

55
---
66

7-
## 1.0.1 (TBD)
7+
## [1.0.1](https://github.com/ngageoint/mgrs-java/releases/tag/1.0.1) (06-15-2022)
88

9-
* TBD
9+
* Handle parsing invalid Svalbard zones (32X, 34X, 36X)
1010

1111
## [1.0.0](https://github.com/ngageoint/mgrs-java/releases/tag/1.0.0) (06-14-2022)
1212

src/main/java/mil/nga/mgrs/MGRS.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ public class MGRS {
4141
"^(\\d{1,2})([C-HJ-NP-X])(?:([A-HJ-NP-Z][A-HJ-NP-V])((\\d{2}){0,5}))?$",
4242
Pattern.CASE_INSENSITIVE);
4343

44+
/**
45+
* MGRS invalid string pattern (Svalbard)
46+
*/
47+
private static final Pattern mgrsInvalidPattern = Pattern
48+
.compile("^3[246]X.*$", Pattern.CASE_INSENSITIVE);
49+
4450
/**
4551
* Zone number
4652
*/
@@ -429,18 +435,20 @@ public String toString() {
429435
* @return true if MGRS string is valid, false otherwise
430436
*/
431437
public static boolean isMGRS(String mgrs) {
432-
return mgrsMatcher(mgrs).matches();
438+
mgrs = removeSpaces(mgrs);
439+
return mgrsPattern.matcher(mgrs).matches()
440+
&& !mgrsInvalidPattern.matcher(mgrs).matches();
433441
}
434442

435443
/**
436-
* Get a MGRS pattern matcher
444+
* Removed spaces from the value
437445
*
438-
* @param mgrs
439-
* MGRS string
440-
* @return matcher
446+
* @param value
447+
* value string
448+
* @return value without spaces
441449
*/
442-
private static Matcher mgrsMatcher(String mgrs) {
443-
return mgrsPattern.matcher(mgrs.replaceAll("\\s", ""));
450+
private static String removeSpaces(String value) {
451+
return value.replaceAll("\\s", "");
444452
}
445453

446454
/**
@@ -480,14 +488,19 @@ public static MGRS from(Point latLng) {
480488
* upon failure to parse the MGRS string
481489
*/
482490
public static MGRS parse(String mgrs) throws ParseException {
483-
Matcher matcher = mgrsMatcher(mgrs);
491+
Matcher matcher = mgrsPattern.matcher(removeSpaces(mgrs));
484492
if (!matcher.matches()) {
485493
throw new ParseException("Invalid MGRS: " + mgrs, 0);
486494
}
487495

488496
int zone = Integer.parseInt(matcher.group(1));
489497
char band = matcher.group(2).toUpperCase().charAt(0);
490498

499+
GridZone gridZone = GridZones.getGridZone(zone, band);
500+
if (gridZone == null) {
501+
throw new ParseException("Invalid MGRS: " + mgrs, 0);
502+
}
503+
491504
MGRS mgrsValue = null;
492505

493506
String columnRow = matcher.group(3);
@@ -515,7 +528,6 @@ public static MGRS parse(String mgrs) throws ParseException {
515528
if (location.isEmpty()) {
516529

517530
Point point = mgrsValue.toPoint().toDegrees();
518-
GridZone gridZone = mgrsValue.getGridZone();
519531
Bounds gridBounds = gridZone.getBounds();
520532
Point gridSouthwest = gridBounds.getSouthwest().toDegrees();
521533

@@ -566,8 +578,7 @@ public static MGRS parse(String mgrs) throws ParseException {
566578
}
567579

568580
} else {
569-
mgrsValue = GridZones.getGridZone(zone, band).getBounds()
570-
.getSouthwest().toMGRS();
581+
mgrsValue = gridZone.getBounds().getSouthwest().toMGRS();
571582
}
572583

573584
return mgrsValue;
@@ -667,7 +678,7 @@ private static Point getSouthernBoundsPoint(GridZone gridZone, Point south,
667678
* upon failure to parse the MGRS string
668679
*/
669680
public static GridType precision(String mgrs) throws ParseException {
670-
Matcher matcher = mgrsMatcher(mgrs);
681+
Matcher matcher = mgrsPattern.matcher(removeSpaces(mgrs));
671682
if (!matcher.matches()) {
672683
throw new ParseException("Invalid MGRS: " + mgrs, 0);
673684
}

src/main/java/mil/nga/mgrs/gzd/GridRange.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ public class GridRange implements Iterable<GridZone> {
2424
*/
2525
private BandLetterRange bandLetterRange;
2626

27+
/**
28+
* Constructor, full range
29+
*/
30+
public GridRange() {
31+
this.zoneNumberRange = new ZoneNumberRange();
32+
this.bandLetterRange = new BandLetterRange();
33+
}
34+
2735
/**
2836
* Constructor
2937
*

src/test/java/mil/nga/mgrs/MGRSTest.java

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package mil.nga.mgrs;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertNotNull;
6+
import static org.junit.Assert.assertNull;
47
import static org.junit.Assert.assertTrue;
8+
import static org.junit.Assert.fail;
59

610
import java.text.ParseException;
711

812
import org.junit.Test;
913

1014
import mil.nga.mgrs.features.Point;
1115
import mil.nga.mgrs.grid.GridType;
16+
import mil.nga.mgrs.gzd.GridRange;
17+
import mil.nga.mgrs.gzd.GridZone;
1218
import mil.nga.mgrs.utm.UTM;
1319

1420
/**
@@ -315,6 +321,114 @@ public void testCoordinate() throws ParseException {
315321

316322
}
317323

324+
/**
325+
* Test parsing GZD coordinates
326+
*
327+
* @throws ParseException
328+
* upon failure to parse
329+
*/
330+
@Test
331+
public void testGZDParse() throws ParseException {
332+
333+
GridRange gridRange = new GridRange();
334+
335+
for (GridZone zone : gridRange) {
336+
337+
int zoneNumber = zone.getNumber();
338+
char bandLetter = zone.getLetter();
339+
340+
String gzd = String.valueOf(zoneNumber) + bandLetter;
341+
assertTrue(MGRS.isMGRS(gzd));
342+
MGRS mgrs = MGRS.parse(gzd);
343+
assertNotNull(mgrs);
344+
assertEquals(zoneNumber, mgrs.getZone());
345+
assertEquals(bandLetter, mgrs.getBand());
346+
347+
Point point = mgrs.toPoint();
348+
Point southwest = zone.getBounds().getSouthwest();
349+
350+
assertEquals(point.getLongitude(), southwest.getLongitude(),
351+
0.0001);
352+
assertEquals(point.getLatitude(), southwest.getLatitude(), 0.0001);
353+
354+
}
355+
356+
}
357+
358+
/**
359+
* Test parsing a Svalbard MGRS string values
360+
*
361+
* @throws ParseException
362+
* upon failure to parse
363+
*/
364+
@Test
365+
public void testSvalbardParse() throws ParseException {
366+
367+
assertTrue(MGRS.isMGRS("31X"));
368+
assertNotNull(MGRS.parse("31X"));
369+
assertFalse(MGRS.isMGRS("32X"));
370+
try {
371+
assertNull(MGRS.parse("32X"));
372+
fail("Expected parse exception");
373+
} catch (ParseException e) {
374+
}
375+
assertFalse(MGRS.isMGRS("32XMH"));
376+
try {
377+
MGRS.parse("32XMH");
378+
fail("Expected parse exception");
379+
} catch (ParseException e) {
380+
}
381+
assertFalse(MGRS.isMGRS("32XMH11"));
382+
try {
383+
MGRS.parse("32XMH11");
384+
fail("Expected parse exception");
385+
} catch (ParseException e) {
386+
}
387+
assertFalse(MGRS.isMGRS("32XMH1111"));
388+
try {
389+
MGRS.parse("32XMH1111");
390+
fail("Expected parse exception");
391+
} catch (ParseException e) {
392+
}
393+
assertFalse(MGRS.isMGRS("32XMH111111"));
394+
try {
395+
MGRS.parse("32XMH111111");
396+
fail("Expected parse exception");
397+
} catch (ParseException e) {
398+
}
399+
assertFalse(MGRS.isMGRS("32XMH11111111"));
400+
try {
401+
MGRS.parse("32XMH11111111");
402+
fail("Expected parse exception");
403+
} catch (ParseException e) {
404+
}
405+
assertFalse(MGRS.isMGRS("32XMH111111111"));
406+
try {
407+
MGRS.parse("32XMH111111111");
408+
fail("Expected parse exception");
409+
} catch (ParseException e) {
410+
}
411+
assertTrue(MGRS.isMGRS("33X"));
412+
assertNotNull(MGRS.parse("33X"));
413+
assertFalse(MGRS.isMGRS("34X"));
414+
try {
415+
assertNull(MGRS.parse("34X"));
416+
fail("Expected parse exception");
417+
} catch (ParseException e) {
418+
}
419+
assertTrue(MGRS.isMGRS("35X"));
420+
assertNotNull(MGRS.parse("35X"));
421+
assertFalse(MGRS.isMGRS("36X"));
422+
try {
423+
assertNull(MGRS.parse("36X"));
424+
fail("Expected parse exception");
425+
} catch (ParseException e) {
426+
}
427+
assertTrue(MGRS.isMGRS("37X"));
428+
assertNotNull(MGRS.parse("37X"));
429+
430+
}
431+
318432
/**
319433
* Test the WGS84 coordinate with expected MGSR coordinate
320434
*

0 commit comments

Comments
 (0)