From b3aa97f1c937510e40758b56943036bc81ff90b5 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Wed, 19 Mar 2025 15:14:35 -0600 Subject: [PATCH 01/32] Added passing unit tests for `transformNodeLL` and `nodeOffsetPointLL` methods in TravelerMessageFromHumanToAsnConverter --- ...ravelerMessageFromHumanToAsnConverter.java | 4 +-- ...lerMessageFromHumanToAsnConverterTest.java | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 9932cf061..a4645be65 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -651,7 +651,7 @@ private static ArrayNode transformNodeSetLL(JsonNode nodes) { return outputNodeList; } - private static ObjectNode transformNodeLL(JsonNode oldNode) { + public static ObjectNode transformNodeLL(JsonNode oldNode) { //// EXPECTED INPUT: @@ -703,7 +703,7 @@ private static ObjectNode transformNodeLL(JsonNode oldNode) { // node-LL5 Node-LL-44B, -- within +- 23.189096 Kmeters of last node // node-LL6 Node-LL-48B, -- within +- 92.756481 Kmeters of last node // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range - private static String nodeOffsetPointLL(long transformedLat, long transformedLon) { + public static String nodeOffsetPointLL(long transformedLat, long transformedLon) { long transformedLatabs = Math.abs(transformedLat); long transformedLonabs = Math.abs(transformedLon); if (((transformedLatabs & (-1 << 11)) == 0 diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index caea580a1..9a98dc034 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -482,4 +482,35 @@ void ensureComplianceWithJ2735Revision2024_containsMultipleOldFields() { }); } + @Test + void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { + // prepare + ObjectNode node = JsonNodeFactory.instance.objectNode(); + node.put("nodeLong", "0.0031024"); + node.put("nodeLat", "0.0014506"); + node.put("delta", "node-LL3"); + + // execute + ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); + + // verify + String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}}"; + ObjectNode expected = JsonUtils.toObjectNode(expectedJson); + + Assertions.assertEquals(expected.toString(), result.toString()); + } + + @Test + void nodeOffsetPointLL_ShouldSelectNodeLL2() { + // prepare + long transformedLat = -8000L; + long transformedLong = -8000L; + + // execute + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + + // verify + Assertions.assertEquals("node-LL2", selection); + } + } From 2276397b8d6e56085e0d5a6937a3a168b821db85 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Wed, 19 Mar 2025 15:15:17 -0600 Subject: [PATCH 02/32] Added failing unit test for `transformNodeLL` when LL type is not specified --- ...elerMessageFromHumanToAsnConverterTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 9a98dc034..e36c6129c 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -500,6 +500,24 @@ void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { Assertions.assertEquals(expected.toString(), result.toString()); } + @Test + void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { + // prepare + ObjectNode node = JsonNodeFactory.instance.objectNode(); + node.put("nodeLong", "-0.0008192"); + node.put("nodeLat", "-0.0013123"); + node.put("delta", "node-LL"); + + // execute + ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); + + // verify + String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":-13123,\"lon\":-8192}}}"; + ObjectNode expected = JsonUtils.toObjectNode(expectedJson); + + Assertions.assertEquals(expected.toString(), result.toString()); + } + @Test void nodeOffsetPointLL_ShouldSelectNodeLL2() { // prepare From efab7081e62f429ed96e7facc974e0931e89a526 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Wed, 19 Mar 2025 15:16:17 -0600 Subject: [PATCH 03/32] Added failing unit test for `nodeOffsetPointLL` for input lat/lon `-13123, -8192` --- .../TravelerMessageFromHumanToAsnConverterTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index e36c6129c..203d75e8e 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -531,4 +531,17 @@ void nodeOffsetPointLL_ShouldSelectNodeLL2() { Assertions.assertEquals("node-LL2", selection); } + @Test + void nodeOffsetPointLL_ShouldSelectNodeLL3() { + // prepare + long transformedLat = -13123L; + long transformedLong = -8192L; + + // execute + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + + // verify + Assertions.assertEquals("node-LL3", selection); + } + } From b990c1b4cfaa66e7e37509ca10d3f06d2f6f4763 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 08:07:06 -0600 Subject: [PATCH 04/32] Added more unit tests for `nodeOffsetPointLL` method, some of which are failing --- ...lerMessageFromHumanToAsnConverterTest.java | 1117 +++++++++-------- 1 file changed, 613 insertions(+), 504 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 203d75e8e..3c6a579f9 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -40,508 +40,617 @@ import us.dot.its.jpo.ode.util.JsonUtils.JsonUtilsException; class TravelerMessageFromHumanToAsnConverterTest { - @Mocked - Logger logger; - - @BeforeEach - void setup() { - new MockUp() { - @Mock - Logger getLogger(String value) { - return logger; - } - }; - } - - @Test - void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008192\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032768\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131072\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097152\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388608\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008192\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032768\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131072\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097152\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388608\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8192,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32768,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131072,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097152,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388608,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8192,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32768,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131072,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097152,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388608,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"1\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":\"-105.047355\",\"nodeLat\":\"40.572429\",\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"workZone\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"1\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"advisory\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":-105.047355,\"nodeLat\":40.572429,\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"genericSign\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryUnavailable() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"unknown\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"0\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"unknown\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"unavailable\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryExitServiceForward() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"1\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"exitService\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"forward\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryAdvisoryReverse() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"roadSignage\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"2\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"advisory\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"roadSignage\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"reverse\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testRoadSignIDWorkzone() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryBothGenericSign() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"genericSign\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testPathSpeedLimit() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"1\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"advisory\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ { \"nodeLong\": \"0.0031024\", \"nodeLat\": \"0.0014506\", \"delta\": \"node-LL3\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":\"123\"},{\"laneCrownPointCenter\":\"111\"},{\"laneCrownPointLeft\":\"5.5\"}],\"dWidth\":\"33\",\"dElevation\":\"500\"} }, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testTranslateISOTimeStampToMinuteOfYear() { - Assertions.assertEquals(232800, - TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( - "2018-06-11T16:00:00.000Z")); - - Assertions.assertEquals(232800, - TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( - "2018-06-11T10:00-06:00")); - - // Test for invalid timestamp - Assertions.assertEquals(527040, - TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( - "2018-15-44T25:66:77.999Z")); - } - - @Test - void testReplaceDataFrameTimestamp() { - String fieldName = "startDateTime"; - ObjectNode startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T16:00:00.000Z"); - TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); - Assertions.assertNull(startDateTime.get("startDateTime")); - Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); - Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); - - startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T10:00-06:00"); - TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); - Assertions.assertNull(startDateTime.get("startDateTime")); - Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); - Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); - - // Test for invalid timestamp - startDateTime = JsonUtils.newNode().put(fieldName, "2018-15-44T25:66:77.999Z"); - TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); - Assertions.assertNull(startDateTime.get("startDateTime")); - Assertions.assertEquals(0, startDateTime.get("startYear").asInt()); - Assertions.assertEquals(527040, startDateTime.get("startTime").asLong()); - } - - @Test - void testBuildItem() { - - String itisCode = "123"; - String itis = "itis"; - ObjectNode expectedItisNode = JsonUtils.newNode().put(itis, Integer.parseInt(itisCode)); - ObjectNode expecteditem = (ObjectNode) JsonUtils.newNode().set("item", expectedItisNode); - - // build ITIS code - JsonNode actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(itisCode); - Assertions.assertEquals(expecteditem, actualItem); - - // build number text - expectedItisNode.remove(itis); - expectedItisNode.put("text", itisCode); - actualItem = TravelerMessageFromHumanToAsnConverter.buildItem("'123"); - Assertions.assertEquals(expecteditem, actualItem); - - // build alphanumeric text - String test123 = "test 123"; - expectedItisNode.put("text", test123); - actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(test123); - Assertions.assertEquals(expecteditem, actualItem); - } - - @Test - void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"nodes\":[{\"x\":\"-5.12\",\"y\":\"5.11\",\"delta\":\"node-XY\"},{\"x\":\"-10.24\",\"y\":\"10.23\",\"delta\":\"node-XY\"},{\"x\":\"-20.48\",\"y\":\"20.47\",\"delta\":\"node-XY\"},{\"x\":\"-40.96\",\"y\":\"40.95\",\"delta\":\"node-XY\"},{\"x\":\"-81.92\",\"y\":\"81.91\",\"delta\":\"node-XY\"},{\"x\":\"-327.68\",\"y\":\"327.67\",\"delta\":\"node-XY\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"nodes\":[{\"delta\":{\"node-XY1\":{\"x\":-512,\"y\":511}}},{\"delta\":{\"node-XY2\":{\"x\":-1024,\"y\":1023}}},{\"delta\":{\"node-XY3\":{\"x\":-2048,\"y\":2047}}},{\"delta\":{\"node-XY4\":{\"x\":-4096,\"y\":4095}}},{\"delta\":{\"node-XY5\":{\"x\":-8192,\"y\":8191}}},{\"delta\":{\"node-XY6\":{\"x\":-32768,\"y\":32767}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"small\":111},\"offsetYaxis\":{\"small\":111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"large\":11111},\"offsetYaxis\":{\"large\":11111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithCircle() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"circle\":{\"center\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"radius\":\"2048\",\"units\":\"centimeter\"}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"circle\":{\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"radius\":\"2048\",\"units\":{\"centimeter\":\"EMPTY_TAG\"}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithRegionPointSet() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); - } - - @Test - void ensureComplianceWithJ2735Revision2024_noOldFields() - throws TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("doNotUse1", 0); - dataFrame.put("doNotUse2", 0); - dataFrame.put("doNotUse3", 0); - dataFrame.put("doNotUse4", 0); - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgContent() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgContent", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgTypes() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgTypes", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspTimRights() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspTimRights", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspLocationRights() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspLocationRights", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights1() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgRights1", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights2() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgRights2", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed1() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed1", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed2() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed2", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed3() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed3", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_duratonTime() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("duratonTime", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsMultipleOldFields() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgContent", 1); - dataFrame.put("sspMsgTypes", 1); - dataFrame.put("sspTimRights", 1); - dataFrame.put("sspLocationRights", 1); - dataFrame.put("sspMsgRights1", 1); - dataFrame.put("sspMsgRights2", 1); - dataFrame.put("notUsed", 1); - dataFrame.put("notUsed1", 1); - dataFrame.put("notUsed2", 1); - dataFrame.put("notUsed3", 1); - dataFrame.put("duratonTime", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { - // prepare - ObjectNode node = JsonNodeFactory.instance.objectNode(); - node.put("nodeLong", "0.0031024"); - node.put("nodeLat", "0.0014506"); - node.put("delta", "node-LL3"); - - // execute - ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); - - // verify - String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}}"; - ObjectNode expected = JsonUtils.toObjectNode(expectedJson); - - Assertions.assertEquals(expected.toString(), result.toString()); - } - - @Test - void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { - // prepare - ObjectNode node = JsonNodeFactory.instance.objectNode(); - node.put("nodeLong", "-0.0008192"); - node.put("nodeLat", "-0.0013123"); - node.put("delta", "node-LL"); - - // execute - ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); - - // verify - String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":-13123,\"lon\":-8192}}}"; - ObjectNode expected = JsonUtils.toObjectNode(expectedJson); - - Assertions.assertEquals(expected.toString(), result.toString()); - } - - @Test - void nodeOffsetPointLL_ShouldSelectNodeLL2() { - // prepare - long transformedLat = -8000L; - long transformedLong = -8000L; - - // execute - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - - // verify - Assertions.assertEquals("node-LL2", selection); - } - - @Test - void nodeOffsetPointLL_ShouldSelectNodeLL3() { - // prepare - long transformedLat = -13123L; - long transformedLong = -8192L; - - // execute - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - - // verify - Assertions.assertEquals("node-LL3", selection); - } - + @Mocked + Logger logger; + + @BeforeEach + void setup() { + new MockUp() { + @Mock + Logger getLogger(String value) { + return logger; + } + }; + } + + @Test + void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008192\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032768\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131072\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097152\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388608\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008192\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032768\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131072\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097152\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388608\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8192,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32768,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131072,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097152,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388608,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8192,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32768,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131072,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097152,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388608,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"1\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":\"-105.047355\",\"nodeLat\":\"40.572429\",\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"workZone\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"1\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"advisory\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":-105.047355,\"nodeLat\":40.572429,\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"genericSign\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryUnavailable() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"unknown\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"0\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"unknown\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"unavailable\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryExitServiceForward() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"1\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"exitService\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"forward\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryAdvisoryReverse() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"roadSignage\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"2\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"advisory\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"roadSignage\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"reverse\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testRoadSignIDWorkzone() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryBothGenericSign() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"genericSign\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testPathSpeedLimit() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"1\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"advisory\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ { \"nodeLong\": \"0.0031024\", \"nodeLat\": \"0.0014506\", \"delta\": \"node-LL3\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":\"123\"},{\"laneCrownPointCenter\":\"111\"},{\"laneCrownPointLeft\":\"5.5\"}],\"dWidth\":\"33\",\"dElevation\":\"500\"} }, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testTranslateISOTimeStampToMinuteOfYear() { + Assertions.assertEquals(232800, + TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( + "2018-06-11T16:00:00.000Z")); + + Assertions.assertEquals(232800, + TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( + "2018-06-11T10:00-06:00")); + + // Test for invalid timestamp + Assertions.assertEquals(527040, + TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( + "2018-15-44T25:66:77.999Z")); + } + + @Test + void testReplaceDataFrameTimestamp() { + String fieldName = "startDateTime"; + ObjectNode startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T16:00:00.000Z"); + TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); + Assertions.assertNull(startDateTime.get("startDateTime")); + Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); + Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); + + startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T10:00-06:00"); + TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); + Assertions.assertNull(startDateTime.get("startDateTime")); + Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); + Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); + + // Test for invalid timestamp + startDateTime = JsonUtils.newNode().put(fieldName, "2018-15-44T25:66:77.999Z"); + TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); + Assertions.assertNull(startDateTime.get("startDateTime")); + Assertions.assertEquals(0, startDateTime.get("startYear").asInt()); + Assertions.assertEquals(527040, startDateTime.get("startTime").asLong()); + } + + @Test + void testBuildItem() { + + String itisCode = "123"; + String itis = "itis"; + ObjectNode expectedItisNode = JsonUtils.newNode().put(itis, Integer.parseInt(itisCode)); + ObjectNode expecteditem = (ObjectNode) JsonUtils.newNode().set("item", expectedItisNode); + + // build ITIS code + JsonNode actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(itisCode); + Assertions.assertEquals(expecteditem, actualItem); + + // build number text + expectedItisNode.remove(itis); + expectedItisNode.put("text", itisCode); + actualItem = TravelerMessageFromHumanToAsnConverter.buildItem("'123"); + Assertions.assertEquals(expecteditem, actualItem); + + // build alphanumeric text + String test123 = "test 123"; + expectedItisNode.put("text", test123); + actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(test123); + Assertions.assertEquals(expecteditem, actualItem); + } + + @Test + void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"nodes\":[{\"x\":\"-5.12\",\"y\":\"5.11\",\"delta\":\"node-XY\"},{\"x\":\"-10.24\",\"y\":\"10.23\",\"delta\":\"node-XY\"},{\"x\":\"-20.48\",\"y\":\"20.47\",\"delta\":\"node-XY\"},{\"x\":\"-40.96\",\"y\":\"40.95\",\"delta\":\"node-XY\"},{\"x\":\"-81.92\",\"y\":\"81.91\",\"delta\":\"node-XY\"},{\"x\":\"-327.68\",\"y\":\"327.67\",\"delta\":\"node-XY\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"nodes\":[{\"delta\":{\"node-XY1\":{\"x\":-512,\"y\":511}}},{\"delta\":{\"node-XY2\":{\"x\":-1024,\"y\":1023}}},{\"delta\":{\"node-XY3\":{\"x\":-2048,\"y\":2047}}},{\"delta\":{\"node-XY4\":{\"x\":-4096,\"y\":4095}}},{\"delta\":{\"node-XY5\":{\"x\":-8192,\"y\":8191}}},{\"delta\":{\"node-XY6\":{\"x\":-32768,\"y\":32767}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"small\":111},\"offsetYaxis\":{\"small\":111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"large\":11111},\"offsetYaxis\":{\"large\":11111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithCircle() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"circle\":{\"center\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"radius\":\"2048\",\"units\":\"centimeter\"}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"circle\":{\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"radius\":\"2048\",\"units\":{\"centimeter\":\"EMPTY_TAG\"}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithRegionPointSet() throws JsonUtilsException, + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, + JsonUtils.toJSONObject(inputTID.toString())); + Assertions.assertNotNull(XML.toString(timObject)); + } + + @Test + void ensureComplianceWithJ2735Revision2024_noOldFields() + throws TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("doNotUse1", 0); + dataFrame.put("doNotUse2", 0); + dataFrame.put("doNotUse3", 0); + dataFrame.put("doNotUse4", 0); + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgContent() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgContent", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgTypes() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgTypes", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspTimRights() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspTimRights", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspLocationRights() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspLocationRights", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights1() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgRights1", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights2() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgRights2", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed1() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed1", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed2() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed2", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed3() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed3", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_duratonTime() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("duratonTime", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsMultipleOldFields() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgContent", 1); + dataFrame.put("sspMsgTypes", 1); + dataFrame.put("sspTimRights", 1); + dataFrame.put("sspLocationRights", 1); + dataFrame.put("sspMsgRights1", 1); + dataFrame.put("sspMsgRights2", 1); + dataFrame.put("notUsed", 1); + dataFrame.put("notUsed1", 1); + dataFrame.put("notUsed2", 1); + dataFrame.put("notUsed3", 1); + dataFrame.put("duratonTime", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { + // prepare + ObjectNode node = JsonNodeFactory.instance.objectNode(); + node.put("nodeLong", "0.0031024"); + node.put("nodeLat", "0.0014506"); + node.put("delta", "node-LL3"); + + // execute + ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); + + // verify + String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}}"; + ObjectNode expected = JsonUtils.toObjectNode(expectedJson); + + Assertions.assertEquals(expected.toString(), result.toString()); + } + + @Test + void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { + // prepare + ObjectNode node = JsonNodeFactory.instance.objectNode(); + node.put("nodeLong", "-0.0008192"); + node.put("nodeLat", "-0.0013123"); + node.put("delta", "node-LL"); + + // execute + ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); + + // verify + String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":-13123,\"lon\":-8192}}}"; + ObjectNode expected = JsonUtils.toObjectNode(expectedJson); + + Assertions.assertEquals(expected.toString(), result.toString()); + } + + long LL_1_MINIMUM_MICRO_DEGREES = -2048L; + long LL_2_MINIMUM_MICRO_DEGREES = -8192L; + long LL_3_MINIMUM_MICRO_DEGREES = -32768L; + long LL_4_MINIMUM_MICRO_DEGREES = -131072L; + long LL_5_MINIMUM_MICRO_DEGREES = -524288L; + long LL_6_MINIMUM_MICRO_DEGREES = -2097152L; + + @Test + void nodeOffsetPointLL_LatAndLonWithinLL1Constraints_ShouldSelectNodeLL1() { + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL1", selection); + } + + @Test + void nodeOffsetPointLL_LatOutsideLL1ConstraintAndLonOnCusp_ShouldSelectNodeLL2() { + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL2", selection); + } + + @Test + void nodeOffsetPointLL_LonOutsideLL1ConstraintAndLatOnCusp_ShouldSelectNodeLL2() { + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL2", selection); + } + + @Test + void nodeOffsetPointLL_LatAndLonWithinLL2Constraints_ShouldSelectNodeLL2() { + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL2", selection); + } + + @Test + void nodeOffsetPointLL_LatOutsideLL2ConstraintAndLonOnCusp_ShouldSelectNodeLL3() { + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL3", selection); + } + + + @Test + void nodeOffsetPointLL_LonOutsideLL2ConstraintAndLatOnCusp_ShouldSelectNodeLL3() { + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL3", selection); + } + + @Test + void nodeOffsetPointLL_LatAndLonWithinLL3Constraints_ShouldSelectNodeLL3() { + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL3", selection); + } + + @Test + void nodeOffsetPointLL_LatOutsideLL3ConstraintAndLonOnCusp_ShouldSelectNodeLL4() { + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL4", selection); + } + + @Test + void nodeOffsetPointLL_LonOutsideLL3ConstraintAndLatOnCusp_ShouldSelectNodeLL4() { + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL4", selection); + } + + @Test + void nodeOffsetPointLL_LatAndLonWithinLL4Constraints_ShouldSelectNodeLL4() { + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL4", selection); + } + + @Test + void nodeOffsetPointLL_LatOutsideLL4ConstraintAndLonOnCusp_ShouldSelectNodeLL5() { + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL5", selection); + } + + @Test + void nodeOffsetPointLL_LonOutsideLL4ConstraintAndLatOnCusp_ShouldSelectNodeLL5() { + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL5", selection); + } + + @Test + void nodeOffsetPointLL_LatAndLonWithinLL5Constraints_ShouldSelectNodeLL5() { + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL5", selection); + } + + @Test + void nodeOffsetPointLL_LatOutsideLL5ConstraintAndLonOnCusp_ShouldSelectNodeLL6() { + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL6", selection); + } + + @Test + void nodeOffsetPointLL_LonOutsideLL5ConstraintAndLatOnCusp_ShouldSelectNodeLL6() { + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL6", selection); + } + + @Test + void nodeOffsetPointLL_LatAndLonWithinLL6Constraints_ShouldSelectNodeLL6() { + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; + String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + Assertions.assertEquals("node-LL6", selection); + } } From 9f61fdd60cab132b414b72116b9f3ec410708c10 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 08:46:50 -0600 Subject: [PATCH 05/32] Updated LL_5_MINIMUM_MICRO_DEGREES & LL_6_MINIMUM_MICRO_DEGREES to correct values --- .../builders/TravelerMessageFromHumanToAsnConverterTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 3c6a579f9..a0992be92 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -522,8 +522,8 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { long LL_2_MINIMUM_MICRO_DEGREES = -8192L; long LL_3_MINIMUM_MICRO_DEGREES = -32768L; long LL_4_MINIMUM_MICRO_DEGREES = -131072L; - long LL_5_MINIMUM_MICRO_DEGREES = -524288L; - long LL_6_MINIMUM_MICRO_DEGREES = -2097152L; + long LL_5_MINIMUM_MICRO_DEGREES = -2097152L; + long LL_6_MINIMUM_MICRO_DEGREES = -8388608L; @Test void nodeOffsetPointLL_LatAndLonWithinLL1Constraints_ShouldSelectNodeLL1() { From 15a198b3d9bd9d8ab0abdf11e5808ec6f6c992d9 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:06:28 -0600 Subject: [PATCH 06/32] Updated some test values & added comments --- ...lerMessageFromHumanToAsnConverterTest.java | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index a0992be92..5b0d4a668 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -527,40 +527,40 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { @Test void nodeOffsetPointLL_LatAndLonWithinLL1Constraints_ShouldSelectNodeLL1() { - long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; + long transformedLat = -1500L; // within LL1 constraints + long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL1", selection); } @Test void nodeOffsetPointLL_LatOutsideLL1ConstraintAndLonOnCusp_ShouldSelectNodeLL2() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // on cusp of LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection); } @Test void nodeOffsetPointLL_LonOutsideLL1ConstraintAndLatOnCusp_ShouldSelectNodeLL2() { - long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // on cusp of LL1 constraints + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection); } @Test void nodeOffsetPointLL_LatAndLonWithinLL2Constraints_ShouldSelectNodeLL2() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; + long transformedLat = -6000; // within LL2 constraints + long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection); } @Test void nodeOffsetPointLL_LatOutsideLL2ConstraintAndLonOnCusp_ShouldSelectNodeLL3() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // on cusp of LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection); } @@ -568,88 +568,88 @@ void nodeOffsetPointLL_LatOutsideLL2ConstraintAndLonOnCusp_ShouldSelectNodeLL3() @Test void nodeOffsetPointLL_LonOutsideLL2ConstraintAndLatOnCusp_ShouldSelectNodeLL3() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // on cusp of LL2 constraints + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection); } @Test void nodeOffsetPointLL_LatAndLonWithinLL3Constraints_ShouldSelectNodeLL3() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; + long transformedLat = -25000; // within LL3 constraints + long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection); } @Test void nodeOffsetPointLL_LatOutsideLL3ConstraintAndLonOnCusp_ShouldSelectNodeLL4() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // on cusp of LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection); } @Test void nodeOffsetPointLL_LonOutsideLL3ConstraintAndLatOnCusp_ShouldSelectNodeLL4() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // on cusp of LL3 constraints + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection); } @Test void nodeOffsetPointLL_LatAndLonWithinLL4Constraints_ShouldSelectNodeLL4() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; + long transformedLat = -125000; // within LL4 constraints + long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection); } @Test void nodeOffsetPointLL_LatOutsideLL4ConstraintAndLonOnCusp_ShouldSelectNodeLL5() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // on cusp of LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection); } @Test void nodeOffsetPointLL_LonOutsideLL4ConstraintAndLatOnCusp_ShouldSelectNodeLL5() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // on cusp of LL4 constraints + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection); } @Test void nodeOffsetPointLL_LatAndLonWithinLL5Constraints_ShouldSelectNodeLL5() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; + long transformedLat = -2000000L; // within LL5 constraints + long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection); } @Test void nodeOffsetPointLL_LatOutsideLL5ConstraintAndLonOnCusp_ShouldSelectNodeLL6() { - long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // on cusp of LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection); } @Test void nodeOffsetPointLL_LonOutsideLL5ConstraintAndLatOnCusp_ShouldSelectNodeLL6() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // on cusp of LL5 constraints + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection); } @Test void nodeOffsetPointLL_LatAndLonWithinLL6Constraints_ShouldSelectNodeLL6() { - long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; - long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; + long transformedLat = -8000000L; // within LL6 constraints + long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection); } From 2a0b82b3d4645301a59f9bd60da349025d520b0b Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:15:03 -0600 Subject: [PATCH 07/32] Updated naming convention for new tests for clarity --- ...lerMessageFromHumanToAsnConverterTest.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 5b0d4a668..5f1820038 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -526,7 +526,7 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { long LL_6_MINIMUM_MICRO_DEGREES = -8388608L; @Test - void nodeOffsetPointLL_LatAndLonWithinLL1Constraints_ShouldSelectNodeLL1() { + void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnNodeLL1() { long transformedLat = -1500L; // within LL1 constraints long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -534,23 +534,23 @@ void nodeOffsetPointLL_LatAndLonWithinLL1Constraints_ShouldSelectNodeLL1() { } @Test - void nodeOffsetPointLL_LatOutsideLL1ConstraintAndLonOnCusp_ShouldSelectNodeLL2() { + void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnNodeLL2() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints - long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // on cusp of LL1 constraints + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection); } @Test - void nodeOffsetPointLL_LonOutsideLL1ConstraintAndLatOnCusp_ShouldSelectNodeLL2() { - long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // on cusp of LL1 constraints + void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnNodeLL2() { + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection); } @Test - void nodeOffsetPointLL_LatAndLonWithinLL2Constraints_ShouldSelectNodeLL2() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnNodeLL2() { long transformedLat = -6000; // within LL2 constraints long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -558,24 +558,24 @@ void nodeOffsetPointLL_LatAndLonWithinLL2Constraints_ShouldSelectNodeLL2() { } @Test - void nodeOffsetPointLL_LatOutsideLL2ConstraintAndLonOnCusp_ShouldSelectNodeLL3() { + void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnNodeLL3() { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // on cusp of LL2 constraints + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection); } @Test - void nodeOffsetPointLL_LonOutsideLL2ConstraintAndLatOnCusp_ShouldSelectNodeLL3() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // on cusp of LL2 constraints + void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnNodeLL3() { + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection); } @Test - void nodeOffsetPointLL_LatAndLonWithinLL3Constraints_ShouldSelectNodeLL3() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnNodeLL3() { long transformedLat = -25000; // within LL3 constraints long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -583,23 +583,23 @@ void nodeOffsetPointLL_LatAndLonWithinLL3Constraints_ShouldSelectNodeLL3() { } @Test - void nodeOffsetPointLL_LatOutsideLL3ConstraintAndLonOnCusp_ShouldSelectNodeLL4() { + void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnNodeLL4() { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // on cusp of LL3 constraints + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection); } @Test - void nodeOffsetPointLL_LonOutsideLL3ConstraintAndLatOnCusp_ShouldSelectNodeLL4() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // on cusp of LL3 constraints + void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnNodeLL4() { + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection); } @Test - void nodeOffsetPointLL_LatAndLonWithinLL4Constraints_ShouldSelectNodeLL4() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnNodeLL4() { long transformedLat = -125000; // within LL4 constraints long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -607,23 +607,23 @@ void nodeOffsetPointLL_LatAndLonWithinLL4Constraints_ShouldSelectNodeLL4() { } @Test - void nodeOffsetPointLL_LatOutsideLL4ConstraintAndLonOnCusp_ShouldSelectNodeLL5() { + void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnNodeLL5() { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // on cusp of LL4 constraints + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection); } @Test - void nodeOffsetPointLL_LonOutsideLL4ConstraintAndLatOnCusp_ShouldSelectNodeLL5() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // on cusp of LL4 constraints + void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnNodeLL5() { + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection); } @Test - void nodeOffsetPointLL_LatAndLonWithinLL5Constraints_ShouldSelectNodeLL5() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnNodeLL5() { long transformedLat = -2000000L; // within LL5 constraints long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -631,23 +631,23 @@ void nodeOffsetPointLL_LatAndLonWithinLL5Constraints_ShouldSelectNodeLL5() { } @Test - void nodeOffsetPointLL_LatOutsideLL5ConstraintAndLonOnCusp_ShouldSelectNodeLL6() { + void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnNodeLL6() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // on cusp of LL5 constraints + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection); } @Test - void nodeOffsetPointLL_LonOutsideLL5ConstraintAndLatOnCusp_ShouldSelectNodeLL6() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // on cusp of LL5 constraints + void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnNodeLL6() { + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection); } @Test - void nodeOffsetPointLL_LatAndLonWithinLL6Constraints_ShouldSelectNodeLL6() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnNodeLL6() { long transformedLat = -8000000L; // within LL6 constraints long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); From 2bbf9ab56e9070a2aa6f9e9b87a4054dadd47a69 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:21:28 -0600 Subject: [PATCH 08/32] Added descriptive failure messages to nodeOffsetPointLL unit tests for improved debugging clarity --- ...lerMessageFromHumanToAsnConverterTest.java | 82 +++++++++++++++---- 1 file changed, 65 insertions(+), 17 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 5f1820038..61f23d45f 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -530,7 +530,10 @@ void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnNodeLL1() { long transformedLat = -1500L; // within LL1 constraints long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL1", selection); + + Assertions.assertEquals("node-LL1", selection, + "Expected node-LL1 for latitude and longitude within LL1 constraints, " + + "but got " + selection + " instead."); } @Test @@ -538,7 +541,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldRetu long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection); + + Assertions.assertEquals("node-LL2", selection, + "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + + "but got " + selection + " instead."); } @Test @@ -546,7 +552,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldRetu long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection); + + Assertions.assertEquals("node-LL2", selection, + "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + + "but got " + selection + " instead."); } @Test @@ -554,7 +563,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnNodeLL2() { long transformedLat = -6000; // within LL2 constraints long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection); + + Assertions.assertEquals("node-LL2", selection, + "Expected node-LL2 for latitude and longitude within LL2 constraints, " + + "but got " + selection + " instead."); } @Test @@ -562,16 +574,21 @@ void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldRetu long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection); - } + Assertions.assertEquals("node-LL3", selection, + "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + + "but got " + selection + " instead."); + } @Test void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnNodeLL3() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection); + + Assertions.assertEquals("node-LL3", selection, + "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + + "but got " + selection + " instead."); } @Test @@ -579,7 +596,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnNodeLL3() { long transformedLat = -25000; // within LL3 constraints long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection); + + Assertions.assertEquals("node-LL3", selection, + "Expected node-LL3 for latitude and longitude within LL3 constraints, " + + "but got " + selection + " instead."); } @Test @@ -587,7 +607,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldRetu long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection); + + Assertions.assertEquals("node-LL4", selection, + "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + + "but got " + selection + " instead."); } @Test @@ -595,7 +618,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldRetu long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection); + + Assertions.assertEquals("node-LL4", selection, + "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + + "but got " + selection + " instead."); } @Test @@ -603,7 +629,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnNodeLL4() { long transformedLat = -125000; // within LL4 constraints long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection); + + Assertions.assertEquals("node-LL4", selection, + "Expected node-LL4 for latitude and longitude within LL4 constraints, " + + "but got " + selection + " instead."); } @Test @@ -611,7 +640,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldRetu long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection); + + Assertions.assertEquals("node-LL5", selection, + "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + + "but got " + selection + " instead."); } @Test @@ -619,7 +651,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldRetu long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection); + + Assertions.assertEquals("node-LL5", selection, + "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + + "but got " + selection + " instead."); } @Test @@ -627,7 +662,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnNodeLL5() { long transformedLat = -2000000L; // within LL5 constraints long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection); + + Assertions.assertEquals("node-LL5", selection, + "Expected node-LL5 for latitude and longitude within LL5 constraints, " + + "but got " + selection + " instead."); } @Test @@ -635,7 +673,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldRetu long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection); + + Assertions.assertEquals("node-LL6", selection, + "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + + "but got " + selection + " instead."); } @Test @@ -643,7 +684,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldRetu long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection); + + Assertions.assertEquals("node-LL6", selection, + "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + + "but got " + selection + " instead."); } @Test @@ -651,6 +695,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnNodeLL6() { long transformedLat = -8000000L; // within LL6 constraints long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection); + + Assertions.assertEquals("node-LL6", selection, + "Expected node-LL6 for latitude and longitude within LL6 constraints, " + + "but got " + selection + " instead."); } + } From 36c9a501959252a780e11d62a7d9de8f3bbd0ad2 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:24:01 -0600 Subject: [PATCH 09/32] Updated test values outside LL constraints --- ...lerMessageFromHumanToAsnConverterTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 61f23d45f..ef711f009 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -538,7 +538,7 @@ void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnNodeLL1() { @Test void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnNodeLL2() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -550,7 +550,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldRetu @Test void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnNodeLL2() { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // outside LL1 constraints + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, @@ -571,7 +571,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnNodeLL2() { @Test void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnNodeLL3() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -583,7 +583,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldRetu @Test void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnNodeLL3() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // outside LL2 constraints + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, @@ -604,7 +604,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnNodeLL3() { @Test void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnNodeLL4() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -616,7 +616,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldRetu @Test void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnNodeLL4() { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // outside LL3 constraints + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, @@ -637,7 +637,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnNodeLL4() { @Test void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnNodeLL5() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -649,7 +649,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldRetu @Test void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnNodeLL5() { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // outside LL4 constraints + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, @@ -670,7 +670,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnNodeLL5() { @Test void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnNodeLL6() { - long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); @@ -682,7 +682,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldRetu @Test void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnNodeLL6() { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary - long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // outside LL5 constraints + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, From c9f345f074682c2e72d354156fec62cb63ed56f5 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:28:09 -0600 Subject: [PATCH 10/32] Fixed failing unit tests by adding missing parentheses to `nodeOffsetPointLL` method --- ...ravelerMessageFromHumanToAsnConverter.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index a4645be65..6264ec306 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -708,38 +708,38 @@ public static String nodeOffsetPointLL(long transformedLat, long transformedLon) long transformedLonabs = Math.abs(transformedLon); if (((transformedLatabs & (-1 << 11)) == 0 || (transformedLat < 0 && (transformedLatabs ^ (1 << 11)) == 0)) - && (transformedLonabs & (-1 << 11)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 11)) == 0))) { + && ((transformedLonabs & (-1 << 11)) == 0 + || (transformedLon < 0 && ((transformedLonabs ^ (1 << 11)) == 0)))) { // 11 bit value return "node-LL1"; } else if (((transformedLatabs & (-1 << 13)) == 0 || (transformedLat < 0 && (transformedLatabs ^ (1 << 13)) == 0)) - && (transformedLonabs & (-1 << 13)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 13)) == 0))) { + && ((transformedLonabs & (-1 << 13)) == 0 + || (transformedLon < 0 && ((transformedLonabs ^ (1 << 13)) == 0)))) { // 13 bit value return "node-LL2"; } else if (((transformedLatabs & (-1 << 15)) == 0 || (transformedLat < 0 && (transformedLatabs ^ (1 << 15)) == 0)) - && (transformedLonabs & (-1 << 15)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 15)) == 0))) { + && ((transformedLonabs & (-1 << 15)) == 0 + || (transformedLon < 0 && ((transformedLonabs ^ (1 << 15)) == 0)))) { // 15 bit value return "node-LL3"; } else if (((transformedLatabs & (-1 << 17)) == 0 || (transformedLat < 0 && (transformedLatabs ^ (1 << 17)) == 0)) - && (transformedLonabs & (-1 << 17)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 17)) == 0))) { + && ((transformedLonabs & (-1 << 17)) == 0 + || (transformedLon < 0 && ((transformedLonabs ^ (1 << 17)) == 0)))) { // 17 bit value return "node-LL4"; } else if (((transformedLatabs & (-1 << 21)) == 0 || (transformedLat < 0 && (transformedLatabs ^ (1 << 21)) == 0)) - && (transformedLonabs & (-1 << 21)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 21)) == 0))) { + && ((transformedLonabs & (-1 << 21)) == 0 + || (transformedLon < 0 && ((transformedLonabs ^ (1 << 21)) == 0)))) { // 21 bit value return "node-LL5"; } else if (((transformedLatabs & (-1 << 23)) == 0 || (transformedLat < 0 && (transformedLatabs ^ (1 << 23)) == 0)) - && (transformedLonabs & (-1 << 23)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 23)) == 0))) { + && ((transformedLonabs & (-1 << 23)) == 0 + || (transformedLon < 0 && ((transformedLonabs ^ (1 << 23)) == 0)))) { // 23 bit value return "node-LL6"; } else { From d0165eb8fd010753a5accebd47503daeaf022035 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:38:32 -0600 Subject: [PATCH 11/32] Refactored bitmask range validation by extracting methods and improving names for clarity --- ...ravelerMessageFromHumanToAsnConverter.java | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 6264ec306..b11068ced 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -695,6 +695,14 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { return deltaNode; } + // Constants for bitmask shifts + private static final int BITMASK_11 = 11; + private static final int BITMASK_13 = 13; + private static final int BITMASK_15 = 15; + private static final int BITMASK_17 = 17; + private static final int BITMASK_21 = 21; + private static final int BITMASK_23 = 23; + // -- Nodes with LL content Span at the equator when using a zoom of one: // node-LL1 Node-LL-24B, -- within +- 22.634554 meters of last node // node-LL2 Node-LL-28B, -- within +- 90.571389 meters of last node @@ -703,51 +711,36 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { // node-LL5 Node-LL-44B, -- within +- 23.189096 Kmeters of last node // node-LL6 Node-LL-48B, -- within +- 92.756481 Kmeters of last node // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range - public static String nodeOffsetPointLL(long transformedLat, long transformedLon) { - long transformedLatabs = Math.abs(transformedLat); - long transformedLonabs = Math.abs(transformedLon); - if (((transformedLatabs & (-1 << 11)) == 0 - || (transformedLat < 0 && (transformedLatabs ^ (1 << 11)) == 0)) - && ((transformedLonabs & (-1 << 11)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 11)) == 0)))) { - // 11 bit value + public static String nodeOffsetPointLL(long latDelta, long lonDelta) { + long absLatDelta = Math.abs(latDelta); + long absLonDelta = Math.abs(lonDelta); + + if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_11)) { return "node-LL1"; - } else if (((transformedLatabs & (-1 << 13)) == 0 - || (transformedLat < 0 && (transformedLatabs ^ (1 << 13)) == 0)) - && ((transformedLonabs & (-1 << 13)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 13)) == 0)))) { - // 13 bit value + } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_13)) { return "node-LL2"; - } else if (((transformedLatabs & (-1 << 15)) == 0 - || (transformedLat < 0 && (transformedLatabs ^ (1 << 15)) == 0)) - && ((transformedLonabs & (-1 << 15)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 15)) == 0)))) { - // 15 bit value + } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_15)) { return "node-LL3"; - } else if (((transformedLatabs & (-1 << 17)) == 0 - || (transformedLat < 0 && (transformedLatabs ^ (1 << 17)) == 0)) - && ((transformedLonabs & (-1 << 17)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 17)) == 0)))) { - // 17 bit value + } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_17)) { return "node-LL4"; - } else if (((transformedLatabs & (-1 << 21)) == 0 - || (transformedLat < 0 && (transformedLatabs ^ (1 << 21)) == 0)) - && ((transformedLonabs & (-1 << 21)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 21)) == 0)))) { - // 21 bit value + } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_21)) { return "node-LL5"; - } else if (((transformedLatabs & (-1 << 23)) == 0 - || (transformedLat < 0 && (transformedLatabs ^ (1 << 23)) == 0)) - && ((transformedLonabs & (-1 << 23)) == 0 - || (transformedLon < 0 && ((transformedLonabs ^ (1 << 23)) == 0)))) { - // 23 bit value + } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_23)) { return "node-LL6"; } else { throw new IllegalArgumentException( - "Invalid node lat/long offset: " + transformedLat + "/" + transformedLon - + ". Values must be between a range of -0.8388608/+0.8388607 degrees."); + "Invalid node lat/long offset: " + latDelta + "/" + lonDelta + + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); } + } + + private static boolean areCoordinatesWithinBitMaskRange(long absLat, long lat, long absLon, long lon, int bitmaskShift) { + return isCoordinateWithinBitMaskRange(absLat, lat, bitmaskShift) && isCoordinateWithinBitMaskRange(absLon, lon, bitmaskShift); + } + private static boolean isCoordinateWithinBitMaskRange(long absValue, long value, int bitmaskShift) { + return (absValue & (-1L << bitmaskShift)) == 0 + || (value < 0 && (absValue ^ (1L << bitmaskShift)) == 0); } /** From fe83de84d4b1a368de1f8770b1eac3af5a736519 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:40:10 -0600 Subject: [PATCH 12/32] Renamed `nodeOffsetPointLL` method to `determineNodeOffsetPointLLType` --- ...ravelerMessageFromHumanToAsnConverter.java | 6 +- ...lerMessageFromHumanToAsnConverterTest.java | 64 +++++++++---------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index b11068ced..f0f4bf913 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -682,7 +682,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { transformedLat = OffsetLLBuilder.offsetLL(latOffset); transformedLong = OffsetLLBuilder.offsetLL(longOffset); if (deltaText.equals("node-LL")) { - deltaText = nodeOffsetPointLL(transformedLat, transformedLong); + deltaText = determineNodeOffsetPointLLType(transformedLat, transformedLong); } } else if (NODE_LAT_LON.equals(deltaText)) { transformedLat = LatitudeBuilder.j2735Latitude(latOffset); @@ -711,7 +711,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { // node-LL5 Node-LL-44B, -- within +- 23.189096 Kmeters of last node // node-LL6 Node-LL-48B, -- within +- 92.756481 Kmeters of last node // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range - public static String nodeOffsetPointLL(long latDelta, long lonDelta) { + public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { long absLatDelta = Math.abs(latDelta); long absLonDelta = Math.abs(lonDelta); @@ -1197,7 +1197,7 @@ public static ObjectNode transformNodeOffsetPointXY(JsonNode oldNode) { Long transformedLat = LongitudeBuilder.j2735Longitude(latOffset); ObjectNode latLong = JsonUtils.newNode().put(LON, transformedLon).put(LAT, transformedLat); if (deltaText.equals(NODE_XY)) { - innerNode.set(nodeOffsetPointLL(transformedLat, transformedLon), latLong); + innerNode.set(determineNodeOffsetPointLLType(transformedLat, transformedLon), latLong); } else { innerNode.set(deltaText, latLong); } diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index ef711f009..0990bfbe8 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -526,10 +526,10 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { long LL_6_MINIMUM_MICRO_DEGREES = -8388608L; @Test - void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnNodeLL1() { + void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { long transformedLat = -1500L; // within LL1 constraints long transformedLong = -1500L; // within LL1 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL1", selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + @@ -537,10 +537,10 @@ void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnNodeLL1() { } @Test - void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnNodeLL2() { + void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + @@ -548,10 +548,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnNodeLL2() { + void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + @@ -559,10 +559,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnNodeLL2() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() { long transformedLat = -6000; // within LL2 constraints long transformedLong = -6000; // within LL2 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + @@ -570,10 +570,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnNodeLL2() { } @Test - void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnNodeLL3() { + void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + @@ -581,10 +581,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnNodeLL3() { + void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + @@ -592,10 +592,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnNodeLL3() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() { long transformedLat = -25000; // within LL3 constraints long transformedLong = -25000; // within LL3 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + @@ -603,10 +603,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnNodeLL3() { } @Test - void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnNodeLL4() { + void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + @@ -614,10 +614,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnNodeLL4() { + void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + @@ -625,10 +625,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnNodeLL4() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() { long transformedLat = -125000; // within LL4 constraints long transformedLong = -125000; // within LL4 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + @@ -636,10 +636,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnNodeLL4() { } @Test - void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnNodeLL5() { + void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + @@ -647,10 +647,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnNodeLL5() { + void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + @@ -658,10 +658,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnNodeLL5() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() { long transformedLat = -2000000L; // within LL5 constraints long transformedLong = -2000000L; // within LL5 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + @@ -669,10 +669,10 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnNodeLL5() { } @Test - void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnNodeLL6() { + void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + @@ -680,10 +680,10 @@ void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnNodeLL6() { + void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + @@ -691,10 +691,10 @@ void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnNodeLL6() { + void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() { long transformedLat = -8000000L; // within LL6 constraints long transformedLong = -8000000L; // within LL6 constraints - String selection = TravelerMessageFromHumanToAsnConverter.nodeOffsetPointLL(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + From ad10132ef80e83d3e691d360095f00ea7dfea0c7 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:48:39 -0600 Subject: [PATCH 13/32] Introduced constants for NODE_LL types and added JavaDocs --- ...ravelerMessageFromHumanToAsnConverter.java | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index f0f4bf913..91d62abdf 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -695,6 +695,14 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { return deltaNode; } + // -- Nodes with LL content Span at the equator when using a zoom of one: + public static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node + public static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node + public static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node + public static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node + public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node + public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node + // Constants for bitmask shifts private static final int BITMASK_11 = 11; private static final int BITMASK_13 = 13; @@ -703,30 +711,39 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { private static final int BITMASK_21 = 21; private static final int BITMASK_23 = 23; - // -- Nodes with LL content Span at the equator when using a zoom of one: - // node-LL1 Node-LL-24B, -- within +- 22.634554 meters of last node - // node-LL2 Node-LL-28B, -- within +- 90.571389 meters of last node - // node-LL3 Node-LL-32B, -- within +- 362.31873 meters of last node - // node-LL4 Node-LL-36B, -- within +- 01.449308 Kmeters of last node - // node-LL5 Node-LL-44B, -- within +- 23.189096 Kmeters of last node - // node-LL6 Node-LL-48B, -- within +- 92.756481 Kmeters of last node - // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range + /** + * Determines the node offset point LL type based on latitude and longitude deltas. + * + * This method evaluates the given latitude and longitude offsets and returns a + * String identifier indicating the appropriate LL node type based on predefined + * bitmask ranges. Valid lat/lon offsets must be within specific bounds, otherwise, + * an exception is thrown. + * + * @param latDelta the latitude offset in long format, representing the delta + * from the base latitude. + * @param lonDelta the longitude offset in long format, representing the delta + * from the base longitude. + * @return a String representing the LL node type, such as "node-LL1", "node-LL2", + * and so on, corresponding to the calculated offset ranges. + * @throws IllegalArgumentException if the provided latitude or longitude offsets + * are out of the acceptable range. + */ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { long absLatDelta = Math.abs(latDelta); long absLonDelta = Math.abs(lonDelta); if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_11)) { - return "node-LL1"; + return NODE_LL1; } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_13)) { - return "node-LL2"; + return NODE_LL2; } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_15)) { - return "node-LL3"; + return NODE_LL3; } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_17)) { - return "node-LL4"; + return NODE_LL4; } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_21)) { - return "node-LL5"; + return NODE_LL5; } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_23)) { - return "node-LL6"; + return NODE_LL6; } else { throw new IllegalArgumentException( "Invalid node lat/long offset: " + latDelta + "/" + lonDelta @@ -734,10 +751,29 @@ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta } } + /** + * Determines whether the given latitude and longitude coordinates are within the range + * specified by the bitmask shift. + * + * @param absLat The absolute value of the latitude. + * @param lat The original latitude value. + * @param absLon The absolute value of the longitude. + * @param lon The original longitude value. + * @param bitmaskShift The bitmask shift value to use for range calculation. + * @return {@code true} if both the latitude and longitude coordinates are within the specified bitmask range, {@code false} otherwise. + */ private static boolean areCoordinatesWithinBitMaskRange(long absLat, long lat, long absLon, long lon, int bitmaskShift) { return isCoordinateWithinBitMaskRange(absLat, lat, bitmaskShift) && isCoordinateWithinBitMaskRange(absLon, lon, bitmaskShift); } + /** + * Determines if a given coordinate value is within the range of a bitmask shift. + * + * @param absValue The absolute value of the coordinate to be checked. + * @param value The original value of the coordinate. + * @param bitmaskShift The number of bits to shift in the bitmask operation. + * @return true if the coordinate value is within the defined range, false otherwise. + */ private static boolean isCoordinateWithinBitMaskRange(long absValue, long value, int bitmaskShift) { return (absValue & (-1L << bitmaskShift)) == 0 || (value < 0 && (absValue ^ (1L << bitmaskShift)) == 0); From 1bdca1214c384742ab0ddf4973962ea6391bc2b7 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 09:50:02 -0600 Subject: [PATCH 14/32] Updated JavaDocs --- .../builders/TravelerMessageFromHumanToAsnConverter.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 91d62abdf..fec423023 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -719,10 +719,8 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { * bitmask ranges. Valid lat/lon offsets must be within specific bounds, otherwise, * an exception is thrown. * - * @param latDelta the latitude offset in long format, representing the delta - * from the base latitude. - * @param lonDelta the longitude offset in long format, representing the delta - * from the base longitude. + * @param latDelta the latitude offset in long format + * @param lonDelta the longitude offset in long format * @return a String representing the LL node type, such as "node-LL1", "node-LL2", * and so on, corresponding to the calculated offset ranges. * @throws IllegalArgumentException if the provided latitude or longitude offsets From d3fddedd30eb07c5f2a889a64b5882dabe20e865 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:26:24 -0600 Subject: [PATCH 15/32] Refactored `determineNodeOffsetPointLLType` to check numerical limits instead of using bitwise operations --- ...ravelerMessageFromHumanToAsnConverter.java | 75 ++++++------------- ...lerMessageFromHumanToAsnConverterTest.java | 68 ++++++++++------- 2 files changed, 65 insertions(+), 78 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index fec423023..6c5471854 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -703,44 +703,41 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node - // Constants for bitmask shifts - private static final int BITMASK_11 = 11; - private static final int BITMASK_13 = 13; - private static final int BITMASK_15 = 15; - private static final int BITMASK_17 = 17; - private static final int BITMASK_21 = 21; - private static final int BITMASK_23 = 23; + // -- Limits for each node type + public final static long NODE_LL1_LIMIT = 2047; + public final static long NODE_LL2_LIMIT = 8191; + public final static long NODE_LL3_LIMIT = 32767; + public final static long NODE_LL4_LIMIT = 131071; + public final static long NODE_LL5_LIMIT = 2097151; + public final static long NODE_LL6_LIMIT = 8388607; // TODO: add note about -8388608 not being valid due to J2735 /** - * Determines the node offset point LL type based on latitude and longitude deltas. + * Determines the node offset point LL type based on the latitude and longitude deltas. + * The method evaluates the absolute values of the deltas against predefined limits to determine + * the appropriate node type. If the deltas do not fit within any allowed ranges, an exception + * is thrown. * - * This method evaluates the given latitude and longitude offsets and returns a - * String identifier indicating the appropriate LL node type based on predefined - * bitmask ranges. Valid lat/lon offsets must be within specific bounds, otherwise, - * an exception is thrown. - * - * @param latDelta the latitude offset in long format - * @param lonDelta the longitude offset in long format - * @return a String representing the LL node type, such as "node-LL1", "node-LL2", - * and so on, corresponding to the calculated offset ranges. - * @throws IllegalArgumentException if the provided latitude or longitude offsets - * are out of the acceptable range. + * @param latDelta The latitude delta as a long value. + * @param lonDelta The longitude delta as a long value. + * @return A string representing the node offset point LL type (e.g., NODE_LL1, NODE_LL2, etc.). + * @throws IllegalArgumentException if latDelta or lonDelta are outside the permissible range + * of -0.8388608 to +0.8388607 degrees. */ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { long absLatDelta = Math.abs(latDelta); long absLonDelta = Math.abs(lonDelta); - if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_11)) { + if (absLatDelta <= NODE_LL1_LIMIT && absLonDelta <= NODE_LL1_LIMIT) { return NODE_LL1; - } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_13)) { + } else if (absLatDelta <= NODE_LL2_LIMIT && absLonDelta <= NODE_LL2_LIMIT) { return NODE_LL2; - } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_15)) { + } else if (absLatDelta <= NODE_LL3_LIMIT && absLonDelta <= NODE_LL3_LIMIT) { return NODE_LL3; - } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_17)) { + } else if (absLatDelta <= NODE_LL4_LIMIT && absLonDelta <= NODE_LL4_LIMIT) { return NODE_LL4; - } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_21)) { + } else if (absLatDelta <= NODE_LL5_LIMIT && absLonDelta <= NODE_LL5_LIMIT) { return NODE_LL5; - } else if (areCoordinatesWithinBitMaskRange(absLatDelta, latDelta, absLonDelta, lonDelta, BITMASK_23)) { + } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { return NODE_LL6; } else { throw new IllegalArgumentException( @@ -749,34 +746,6 @@ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta } } - /** - * Determines whether the given latitude and longitude coordinates are within the range - * specified by the bitmask shift. - * - * @param absLat The absolute value of the latitude. - * @param lat The original latitude value. - * @param absLon The absolute value of the longitude. - * @param lon The original longitude value. - * @param bitmaskShift The bitmask shift value to use for range calculation. - * @return {@code true} if both the latitude and longitude coordinates are within the specified bitmask range, {@code false} otherwise. - */ - private static boolean areCoordinatesWithinBitMaskRange(long absLat, long lat, long absLon, long lon, int bitmaskShift) { - return isCoordinateWithinBitMaskRange(absLat, lat, bitmaskShift) && isCoordinateWithinBitMaskRange(absLon, lon, bitmaskShift); - } - - /** - * Determines if a given coordinate value is within the range of a bitmask shift. - * - * @param absValue The absolute value of the coordinate to be checked. - * @param value The original value of the coordinate. - * @param bitmaskShift The number of bits to shift in the bitmask operation. - * @return true if the coordinate value is within the defined range, false otherwise. - */ - private static boolean isCoordinateWithinBitMaskRange(long absValue, long value, int bitmaskShift) { - return (absValue & (-1L << bitmaskShift)) == 0 - || (value < 0 && (absValue ^ (1L << bitmaskShift)) == 0); - } - /** * Replaces geometry. * diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 0990bfbe8..b859b65e7 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -16,6 +16,7 @@ package us.dot.its.jpo.ode.plugin.j2735.builders; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import com.fasterxml.jackson.databind.node.JsonNodeFactory; @@ -58,16 +59,16 @@ void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtils TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008192\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032768\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131072\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097152\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388608\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008192\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032768\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131072\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097152\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388608\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8192,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32768,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131072,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097152,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388608,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8192,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32768,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131072,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097152,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388608,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -84,7 +85,7 @@ void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -101,7 +102,7 @@ void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -118,7 +119,7 @@ void testGeometryUnavailable() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -135,7 +136,7 @@ void testGeometryExitServiceForward() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -152,23 +153,23 @@ void testGeometryAdvisoryReverse() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002048\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2048,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -185,7 +186,7 @@ void testGeometryBothGenericSign() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -201,7 +202,7 @@ void testPathSpeedLimit() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -282,7 +283,7 @@ void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -299,7 +300,7 @@ void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsExce JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -316,7 +317,7 @@ void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsExce JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -333,7 +334,7 @@ void testOldRegionWithCircle() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -350,7 +351,7 @@ void testOldRegionWithRegionPointSet() throws JsonUtilsException, JSONObject timObject = new JSONObject(); timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - Assertions.assertNotNull(XML.toString(timObject)); + assertNotNull(XML.toString(timObject)); } @Test @@ -518,12 +519,12 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { Assertions.assertEquals(expected.toString(), result.toString()); } - long LL_1_MINIMUM_MICRO_DEGREES = -2048L; - long LL_2_MINIMUM_MICRO_DEGREES = -8192L; - long LL_3_MINIMUM_MICRO_DEGREES = -32768L; - long LL_4_MINIMUM_MICRO_DEGREES = -131072L; - long LL_5_MINIMUM_MICRO_DEGREES = -2097152L; - long LL_6_MINIMUM_MICRO_DEGREES = -8388608L; + long LL_1_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL1_LIMIT * -1; + long LL_2_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL2_LIMIT * -1; + long LL_3_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL3_LIMIT * -1; + long LL_4_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL4_LIMIT * -1; + long LL_5_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL5_LIMIT * -1; + long LL_6_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL6_LIMIT * -1; @Test void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { @@ -701,4 +702,21 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNo "but got " + selection + " instead."); } -} + @Test + void nodeOffsetPointLL_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary + assertThrows(IllegalArgumentException.class, () -> { + TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + }); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints + assertThrows(IllegalArgumentException.class, () -> { + TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + }); + } +} \ No newline at end of file From 4491431bc4970e8ab0c5b5f2cada8c529a52d92c Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:30:03 -0600 Subject: [PATCH 16/32] Added J2735 note regarding the value -8388608 --- .../j2735/builders/TravelerMessageFromHumanToAsnConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 6c5471854..b30021699 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -709,7 +709,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { public final static long NODE_LL3_LIMIT = 32767; public final static long NODE_LL4_LIMIT = 131071; public final static long NODE_LL5_LIMIT = 2097151; - public final static long NODE_LL6_LIMIT = 8388607; // TODO: add note about -8388608 not being valid due to J2735 + public final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. /** * Determines the node offset point LL type based on the latitude and longitude deltas. From 476ce882ce7cb16200a24a839a4b2d48c2b5aaf1 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:31:13 -0600 Subject: [PATCH 17/32] Formatted TravelerMessageFromHumanToAsnConverter.java --- ...ravelerMessageFromHumanToAsnConverter.java | 2211 ++++++++--------- 1 file changed, 1077 insertions(+), 1134 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index b30021699..5c8d462b1 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -44,1248 +44,1191 @@ */ public class TravelerMessageFromHumanToAsnConverter { - private static final String SPEED = "speed"; - private static final String TYPE = "type"; - private static final String ATTRIBUTES = "attributes"; - public static final String TRAVELER_INFORMATION = "TravelerInformation"; - private static final String EXTENT = "extent"; - private static final String UNITS = "units"; - private static final String DIRECTIONALITY = "directionality"; - private static final String CENTER = "center"; - private static final String NODE_LAT = "nodeLat"; - private static final String NODE_LONG = "nodeLong"; - private static final String Y = "y"; - private static final String X = "x"; - private static final String NODE_LAT_LON = "node-LatLon"; - private static final String LON = "lon"; - private static final String LAT = "lat"; - private static final String NODE_XY = "node-XY"; - private static final String NODE_XY2 = "NodeXY"; - private static final String COMPUTED = "computed"; - private static final String SPEED_LIMITS = "speedLimits"; - private static final String LANE_ANGLE = "laneAngle"; - private static final String LANE_CROWN_POINT_RIGHT = "laneCrownPointRight"; - private static final String LANE_CROWN_POINT_LEFT = "laneCrownPointLeft"; - private static final String LANE_CROWN_POINT_CENTER = "laneCrownPointCenter"; - private static final String D_ELEVATION = "dElevation"; - private static final String D_WIDTH = "dWidth"; - private static final String DATA = "data"; - private static final String OFFSET_X_AXIS = "offsetXaxis"; - private static final String OFFSET_Y_AXIS = "offsetYaxis"; - private static final String ROTATE_XY = "rotateXY"; - private static final String SCALE_X_AXIS = "scaleXaxis"; - private static final String SCALE_Y_AXIS = "scaleYaxis"; - private static final String NODE_LIST = "nodeList"; - private static final String REGION_POINT_SET = "regionPointSet"; - private static final String CIRCLE = "circle"; - private static final String SHAPE_POINT_SET = "shapePointSet"; - private static final String DELTA = "delta"; - private static final String OFFSET = "offset"; - private static final String NODES = "nodes"; - private static final String XY = "xy"; - private static final String LL = "ll"; - private static final String OLD_REGION = "oldRegion"; - private static final String GEOMETRY = "geometry"; - private static final String PATH = "path"; - private static final String DESCRIPTION = "description"; - private static final String CLOSED_PATH = "closedPath"; - private static final String ANCHOR = "anchor"; - private static final String ID = "id"; - private static final String REGION = "region"; - private static final String LANE_WIDTH = "laneWidth"; - private static final String ANCHOR_POSITION = "anchorPosition"; - private static final String REGULATOR_ID = "regulatorID"; - private static final String SEGMENT_ID = "segmentID"; - private static final String POSITION = "position"; - private static final String TEXT = "text"; - private static final String ITIS = "itis"; - private static final String ITEM = "item"; - private static final String START_DATE_TIME = "startDateTime"; - private static final String DURATON_TIME_MISSPELLED = "duratonTime"; // J2735 2016 Misspelling - private static final String SSP_TIM_RIGHTS = "sspTimRights"; // used in J2735 2016 - private static final String NOT_USED = "notUsed"; // used in J2735 2020 - private static final String SSP_LOCATION_RIGHTS = "sspLocationRights"; // used in J2735 2016 - private static final String NOT_USED_1 = "notUsed1"; // used in J2735 2020 - private static final String SSP_MSG_TYPES = "sspMsgTypes"; // used previously - private static final String SSP_MSG_RIGHTS_1 = "sspMsgRights1"; // used in J2735 2016 - private static final String NOT_USED_2 = "notUsed2"; // used in J2735 2020 - private static final String SSP_MSG_CONTENT = "sspMsgContent"; // used previously - private static final String SSP_MSG_RIGHTS_2 = "sspMsgRights2"; // used in J2735 2016 - private static final String NOT_USED_3 = "notUsed3"; // used in J2735 2020 - private static final String DATAFRAMES = "dataframes"; - private static final String TIME_STAMP = "timeStamp"; - public static final String GEOGRAPHICAL_PATH_STRING = "GeographicalPath"; - public static final String REGIONS_STRING = "regions"; - public static final String TRAVELER_DATA_FRAME_STRING = "TravelerDataFrame"; - public static final String DATA_FRAMES_STRING = "dataFrames"; - public static final String SEQUENCE_STRING = "SEQUENCE"; - public static final String TCONTENT_STRING = "tcontent"; - // JSON cannot have empty fields like XML, so the XML must be modified by - // removing all flag field values - public static final String EMPTY_FIELD_FLAG = "EMPTY_TAG"; - public static final String BOOLEAN_OBJECT_TRUE = "BOOLEAN_OBJECT_TRUE"; - public static final String BOOLEAN_OBJECT_FALSE = "BOOLEAN_OBJECT_FALSE"; - - private static final Logger logger = - LoggerFactory.getLogger(TravelerMessageFromHumanToAsnConverter.class); - - private TravelerMessageFromHumanToAsnConverter() { - super(); - } - - /** - * Converts a JsonNode representing an OdeTravelerInputData object to a format - * that can be encoded by the asn1_codec submodule. - * - * @param tid TravelerInputData object serialized as a JsonNode - * @throws JsonUtilsException if there is an issue converting the JsonNode - * @throws IllegalArgumentException if the JsonNode contains old fields that are no longer used - */ - public static void convertTravelerInputDataToEncodableTim(JsonNode tid) - throws JsonUtilsException, NoncompliantFieldsException { - // msgCnt MsgCount, - // timeStamp MinuteOfTheYear OPTIONAL - // packetID UniqueMSGID OPTIONAL - // urlB URL-Base OPTIONAL - // dataFrames TravelerDataFrameList - - // Cast to ObjectNode to allow manipulation in place - ObjectNode timDataObjectNode = (ObjectNode) tid.get("tim"); - - // timeStamp is optional - if (timDataObjectNode.get(TIME_STAMP) != null) { - timDataObjectNode.put(TIME_STAMP, - translateISOTimeStampToMinuteOfYear(timDataObjectNode.get(TIME_STAMP).asText())); + private static final String SPEED = "speed"; + private static final String TYPE = "type"; + private static final String ATTRIBUTES = "attributes"; + public static final String TRAVELER_INFORMATION = "TravelerInformation"; + private static final String EXTENT = "extent"; + private static final String UNITS = "units"; + private static final String DIRECTIONALITY = "directionality"; + private static final String CENTER = "center"; + private static final String NODE_LAT = "nodeLat"; + private static final String NODE_LONG = "nodeLong"; + private static final String Y = "y"; + private static final String X = "x"; + private static final String NODE_LAT_LON = "node-LatLon"; + private static final String LON = "lon"; + private static final String LAT = "lat"; + private static final String NODE_XY = "node-XY"; + private static final String NODE_XY2 = "NodeXY"; + private static final String COMPUTED = "computed"; + private static final String SPEED_LIMITS = "speedLimits"; + private static final String LANE_ANGLE = "laneAngle"; + private static final String LANE_CROWN_POINT_RIGHT = "laneCrownPointRight"; + private static final String LANE_CROWN_POINT_LEFT = "laneCrownPointLeft"; + private static final String LANE_CROWN_POINT_CENTER = "laneCrownPointCenter"; + private static final String D_ELEVATION = "dElevation"; + private static final String D_WIDTH = "dWidth"; + private static final String DATA = "data"; + private static final String OFFSET_X_AXIS = "offsetXaxis"; + private static final String OFFSET_Y_AXIS = "offsetYaxis"; + private static final String ROTATE_XY = "rotateXY"; + private static final String SCALE_X_AXIS = "scaleXaxis"; + private static final String SCALE_Y_AXIS = "scaleYaxis"; + private static final String NODE_LIST = "nodeList"; + private static final String REGION_POINT_SET = "regionPointSet"; + private static final String CIRCLE = "circle"; + private static final String SHAPE_POINT_SET = "shapePointSet"; + private static final String DELTA = "delta"; + private static final String OFFSET = "offset"; + private static final String NODES = "nodes"; + private static final String XY = "xy"; + private static final String LL = "ll"; + private static final String OLD_REGION = "oldRegion"; + private static final String GEOMETRY = "geometry"; + private static final String PATH = "path"; + private static final String DESCRIPTION = "description"; + private static final String CLOSED_PATH = "closedPath"; + private static final String ANCHOR = "anchor"; + private static final String ID = "id"; + private static final String REGION = "region"; + private static final String LANE_WIDTH = "laneWidth"; + private static final String ANCHOR_POSITION = "anchorPosition"; + private static final String REGULATOR_ID = "regulatorID"; + private static final String SEGMENT_ID = "segmentID"; + private static final String POSITION = "position"; + private static final String TEXT = "text"; + private static final String ITIS = "itis"; + private static final String ITEM = "item"; + private static final String START_DATE_TIME = "startDateTime"; + private static final String DURATON_TIME_MISSPELLED = "duratonTime"; // J2735 2016 Misspelling + private static final String SSP_TIM_RIGHTS = "sspTimRights"; // used in J2735 2016 + private static final String NOT_USED = "notUsed"; // used in J2735 2020 + private static final String SSP_LOCATION_RIGHTS = "sspLocationRights"; // used in J2735 2016 + private static final String NOT_USED_1 = "notUsed1"; // used in J2735 2020 + private static final String SSP_MSG_TYPES = "sspMsgTypes"; // used previously + private static final String SSP_MSG_RIGHTS_1 = "sspMsgRights1"; // used in J2735 2016 + private static final String NOT_USED_2 = "notUsed2"; // used in J2735 2020 + private static final String SSP_MSG_CONTENT = "sspMsgContent"; // used previously + private static final String SSP_MSG_RIGHTS_2 = "sspMsgRights2"; // used in J2735 2016 + private static final String NOT_USED_3 = "notUsed3"; // used in J2735 2020 + private static final String DATAFRAMES = "dataframes"; + private static final String TIME_STAMP = "timeStamp"; + public static final String GEOGRAPHICAL_PATH_STRING = "GeographicalPath"; + public static final String REGIONS_STRING = "regions"; + public static final String TRAVELER_DATA_FRAME_STRING = "TravelerDataFrame"; + public static final String DATA_FRAMES_STRING = "dataFrames"; + public static final String SEQUENCE_STRING = "SEQUENCE"; + public static final String TCONTENT_STRING = "tcontent"; + // JSON cannot have empty fields like XML, so the XML must be modified by + // removing all flag field values + public static final String EMPTY_FIELD_FLAG = "EMPTY_TAG"; + public static final String BOOLEAN_OBJECT_TRUE = "BOOLEAN_OBJECT_TRUE"; + public static final String BOOLEAN_OBJECT_FALSE = "BOOLEAN_OBJECT_FALSE"; + + private static final Logger logger = LoggerFactory.getLogger(TravelerMessageFromHumanToAsnConverter.class); + + private TravelerMessageFromHumanToAsnConverter() { + super(); } - // urlB is optional but does not need replacement - - // dataFrames are required - timDataObjectNode.set(DATA_FRAMES_STRING, - transformDataFrames(timDataObjectNode.get(DATAFRAMES))); - timDataObjectNode.remove(DATAFRAMES); - } - - /** - * Transforms the dataFrames field. - * - * @param dataFrames JsonNode representing the dataFrames field - * @return ObjectNode representing the transformed dataFrames field - * @throws JsonUtilsException if there is an issue converting the JsonNode - * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used - */ - public static ObjectNode transformDataFrames(JsonNode dataFrames) - throws JsonUtilsException, NoncompliantFieldsException { - - if (dataFrames == null) { - return JsonUtils.newNode(); + /** + * Converts a JsonNode representing an OdeTravelerInputData object to a format + * that can be encoded by the asn1_codec submodule. + * + * @param tid TravelerInputData object serialized as a JsonNode + * @throws JsonUtilsException if there is an issue converting the JsonNode + * @throws IllegalArgumentException if the JsonNode contains old fields that are no longer used + */ + public static void convertTravelerInputDataToEncodableTim(JsonNode tid) throws JsonUtilsException, NoncompliantFieldsException { + // msgCnt MsgCount, + // timeStamp MinuteOfTheYear OPTIONAL + // packetID UniqueMSGID OPTIONAL + // urlB URL-Base OPTIONAL + // dataFrames TravelerDataFrameList + + // Cast to ObjectNode to allow manipulation in place + ObjectNode timDataObjectNode = (ObjectNode) tid.get("tim"); + + // timeStamp is optional + if (timDataObjectNode.get(TIME_STAMP) != null) { + timDataObjectNode.put(TIME_STAMP, translateISOTimeStampToMinuteOfYear(timDataObjectNode.get(TIME_STAMP).asText())); + } + + // urlB is optional but does not need replacement + + // dataFrames are required + timDataObjectNode.set(DATA_FRAMES_STRING, transformDataFrames(timDataObjectNode.get(DATAFRAMES))); + timDataObjectNode.remove(DATAFRAMES); } - ArrayNode replacedDataFrames = JsonUtils.newNode().arrayNode(); - if (dataFrames.isArray()) { - Iterator dataFramesIter = dataFrames.elements(); + /** + * Transforms the dataFrames field. + * + * @param dataFrames JsonNode representing the dataFrames field + * @return ObjectNode representing the transformed dataFrames field + * @throws JsonUtilsException if there is an issue converting the JsonNode + * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used + */ + public static ObjectNode transformDataFrames(JsonNode dataFrames) throws JsonUtilsException, NoncompliantFieldsException { + + if (dataFrames == null) { + return JsonUtils.newNode(); + } + + ArrayNode replacedDataFrames = JsonUtils.newNode().arrayNode(); + if (dataFrames.isArray()) { + Iterator dataFramesIter = dataFrames.elements(); + + while (dataFramesIter.hasNext()) { + ObjectNode oldFrame = (ObjectNode) dataFramesIter.next(); + replaceDataFrame(oldFrame); + // wrap each data frame inside a TravelerDataFrame + replacedDataFrames.add(oldFrame); + } + } - while (dataFramesIter.hasNext()) { - ObjectNode oldFrame = (ObjectNode) dataFramesIter.next(); - replaceDataFrame(oldFrame); - // wrap each data frame inside a TravelerDataFrame - replacedDataFrames.add(oldFrame); - } + return JsonUtils.newObjectNode(TRAVELER_DATA_FRAME_STRING, replacedDataFrames); } - return JsonUtils.newObjectNode(TRAVELER_DATA_FRAME_STRING, replacedDataFrames); - } - - /** - * Replaces a data frame. - * - * @param dataFrame ObjectNode representing the data frame - * @throws JsonUtilsException if there is an issue converting the JsonNode - * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used - */ - public static void replaceDataFrame(ObjectNode dataFrame) - throws JsonUtilsException, NoncompliantFieldsException { - - // INPUT - ////// - // "dataframes": [ - // "startDateTime": "2017-08-02T22:25:00.000Z", - // "durationTime": 1, - // "frameType": "1", - // "sspTimRights": "0", - // "msgID": "RoadSignID", - // "position": { - // "latitude": "41.678473", - // "longitude": "-108.782775", - // "elevation": "917.1432" - // }, - // "viewAngle": "1010101010101010", - // "mutcd": "5", - // "crc": "0000000000000000", - // "priority": "0", - // "sspLocationRights": "3", - // "regions": [] - // "sspMsgTypes": "2", - // "sspMsgContent": "3", - // "content": "advisory", - // "items": [ - // "513" - // ], - // "url": "null" - // ] - - /// OUTPUT: - ////// - // - // - // 2017 - // 308065 - // - // - - // set frameType value - dataFrame.set("frameType", - JsonUtils.newNode().put(dataFrame.get("frameType").asText(), EMPTY_FIELD_FLAG)); - - ensureComplianceWithJ2735Revision2024(dataFrame); - - // priority does not need replacement - - // url does not need replacement - - replaceDataFrameTimestamp(dataFrame); - - // replace the geographical path regions - dataFrame.set(REGIONS_STRING, transformRegions(dataFrame.get(REGIONS_STRING))); - // replace content - replaceContent(dataFrame); - - // replace the msgID and relevant fields - replaceMsgId(dataFrame); - } - - /** - * Translates ISO timestamp to minute of year. - * - * @param isoTime ISO timestamp - * @return minute of year - */ - public static long translateISOTimeStampToMinuteOfYear(String isoTime) { - int startYear = 0; - int startMinute = 527040; - try { - ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(isoTime); - startYear = zonedDateTime.getYear(); - startMinute = - (int) Duration.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, - 0, 0, 0), zonedDateTime) - .toMinutes(); - } catch (Exception e) { // NOSONAR - logger.error("Failed to parse datetime {}, defaulting to unknown value {}", isoTime, - startMinute); + /** + * Replaces a data frame. + * + * @param dataFrame ObjectNode representing the data frame + * @throws JsonUtilsException if there is an issue converting the JsonNode + * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used + */ + public static void replaceDataFrame(ObjectNode dataFrame) throws JsonUtilsException, NoncompliantFieldsException { + + // INPUT + ////// + // "dataframes": [ + // "startDateTime": "2017-08-02T22:25:00.000Z", + // "durationTime": 1, + // "frameType": "1", + // "sspTimRights": "0", + // "msgID": "RoadSignID", + // "position": { + // "latitude": "41.678473", + // "longitude": "-108.782775", + // "elevation": "917.1432" + // }, + // "viewAngle": "1010101010101010", + // "mutcd": "5", + // "crc": "0000000000000000", + // "priority": "0", + // "sspLocationRights": "3", + // "regions": [] + // "sspMsgTypes": "2", + // "sspMsgContent": "3", + // "content": "advisory", + // "items": [ + // "513" + // ], + // "url": "null" + // ] + + /// OUTPUT: + ////// + // + // + // 2017 + // 308065 + // + // + + // set frameType value + dataFrame.set("frameType", JsonUtils.newNode().put(dataFrame.get("frameType").asText(), EMPTY_FIELD_FLAG)); + + ensureComplianceWithJ2735Revision2024(dataFrame); + + // priority does not need replacement + + // url does not need replacement + + replaceDataFrameTimestamp(dataFrame); + + // replace the geographical path regions + dataFrame.set(REGIONS_STRING, transformRegions(dataFrame.get(REGIONS_STRING))); + // replace content + replaceContent(dataFrame); + + // replace the msgID and relevant fields + replaceMsgId(dataFrame); } - return startMinute; - } - - /** - * Replaces the data frame timestamp. - * - * @param dataFrame ObjectNode representing the data frame - */ - public static void replaceDataFrameTimestamp(ObjectNode dataFrame) { - - // EXPECTED INPUT: - // "timeStamp": "2017-08-03T22:25:36.297Z" - - // EXPECTED OUTPUT: - // 2017 - // 308065 - - // unknown year value = 0 - // unknown minuteofyear = 527040 - int startYear = 0; - int startMinute = 527040; - String startDateTime = dataFrame.get(START_DATE_TIME).asText(); - try { - ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(startDateTime); - startYear = zonedDateTime.getYear(); - startMinute = - (int) ChronoUnit.MINUTES.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), - zonedDateTime); - } catch (Exception e) { - logger.error("Failed to startDateTime {}, defaulting to unknown value {}.", startDateTime, - startMinute); + /** + * Translates ISO timestamp to minute of year. + * + * @param isoTime ISO timestamp + * @return minute of year + */ + public static long translateISOTimeStampToMinuteOfYear(String isoTime) { + int startYear = 0; + int startMinute = 527040; + try { + ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(isoTime); + startYear = zonedDateTime.getYear(); + startMinute = (int) Duration.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), zonedDateTime).toMinutes(); + } catch (Exception e) { // NOSONAR + logger.error("Failed to parse datetime {}, defaulting to unknown value {}", isoTime, startMinute); + } + + return startMinute; } - dataFrame.put("startYear", startYear); - dataFrame.put("startTime", startMinute); - dataFrame.remove(START_DATE_TIME); - } - - /** - * Replaces content. - * - * @param dataFrame ObjectNode representing the data frame - */ - public static void replaceContent(ObjectNode dataFrame) { - - // EXPECTED OUTPUT: - /////// - // - // - // - // - // 513 - // - // - // - // - - // EXPECTED INPUT: - //////// - // "content": "advisory", - // "items":["513", "Text you need to send", "'1234567'", "255"]}, - - // step 1, reformat item list - ArrayNode items = (ArrayNode) dataFrame.get("items"); - ArrayNode newItems = JsonUtils.newNode().arrayNode(); - if (items.isArray()) { - // take the array of ITIScodesAndText items and transform it into - // schema-appropriate array - - Iterator itemsIter = items.elements(); - - while (itemsIter.hasNext()) { - JsonNode curItem = itemsIter.next(); - newItems.add(buildItem(curItem.asText())); - } + /** + * Replaces the data frame timestamp. + * + * @param dataFrame ObjectNode representing the data frame + */ + public static void replaceDataFrameTimestamp(ObjectNode dataFrame) { + + // EXPECTED INPUT: + // "timeStamp": "2017-08-03T22:25:36.297Z" + + // EXPECTED OUTPUT: + // 2017 + // 308065 + + // unknown year value = 0 + // unknown minuteofyear = 527040 + int startYear = 0; + int startMinute = 527040; + String startDateTime = dataFrame.get(START_DATE_TIME).asText(); + try { + ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(startDateTime); + startYear = zonedDateTime.getYear(); + startMinute = (int) ChronoUnit.MINUTES.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), zonedDateTime); + } catch (Exception e) { + logger.error("Failed to startDateTime {}, defaulting to unknown value {}.", startDateTime, startMinute); + } + + dataFrame.put("startYear", startYear); + dataFrame.put("startTime", startMinute); + dataFrame.remove(START_DATE_TIME); } - JsonNode sequence = JsonUtils.newNode().set(SEQUENCE_STRING, newItems); + /** + * Replaces content. + * + * @param dataFrame ObjectNode representing the data frame + */ + public static void replaceContent(ObjectNode dataFrame) { + + // EXPECTED OUTPUT: + /////// + // + // + // + // + // 513 + // + // + // + // + + // EXPECTED INPUT: + //////// + // "content": "advisory", + // "items":["513", "Text you need to send", "'1234567'", "255"]}, + + // step 1, reformat item list + ArrayNode items = (ArrayNode) dataFrame.get("items"); + ArrayNode newItems = JsonUtils.newNode().arrayNode(); + if (items.isArray()) { + // take the array of ITIScodesAndText items and transform it into + // schema-appropriate array + + Iterator itemsIter = items.elements(); + + while (itemsIter.hasNext()) { + JsonNode curItem = itemsIter.next(); + newItems.add(buildItem(curItem.asText())); + } + } + + JsonNode sequence = JsonUtils.newNode().set(SEQUENCE_STRING, newItems); - dataFrame.remove("items"); + dataFrame.remove("items"); - // step 2, set the content CHOICE - String replacedContentName = dataFrame.get("content").asText(); - if (replacedContentName.equals("Advisory")) { - replacedContentName = "advisory"; - } + // step 2, set the content CHOICE + String replacedContentName = dataFrame.get("content").asText(); + if (replacedContentName.equals("Advisory")) { + replacedContentName = "advisory"; + } - // The following field is called "content" but this results in a - // failed conversion to XML - // see @us.dot.its.jpo.ode.traveler.TimController.publish - dataFrame.set(TCONTENT_STRING, JsonUtils.newNode().set(replacedContentName, sequence)); - dataFrame.remove("content"); - } - - /** - * Builds an item. - * - * @param itemStr String representing the item - * @return JsonNode representing the item - */ - public static JsonNode buildItem(String itemStr) { - JsonNode item = null; - // check to see if it is an itis code or text - try { - item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(ITIS, Integer.valueOf(itemStr))); - // it's a number, so create "itis" code - } catch (NumberFormatException e) { - // it's not a number, so create "text" - if (itemStr.startsWith("'")) { - item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr.substring(1))); - } else { - item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr)); - } + // The following field is called "content" but this results in a + // failed conversion to XML + // see @us.dot.its.jpo.ode.traveler.TimController.publish + dataFrame.set(TCONTENT_STRING, JsonUtils.newNode().set(replacedContentName, sequence)); + dataFrame.remove("content"); } - return item; - } - - /** - * Replaces msg id. - * - * @param dataFrame ObjectNode representing the data frame - */ - public static void replaceMsgId(ObjectNode dataFrame) { - - // - // - // - // 416784730 - // -1087827750 - // 9171 - // - // 0101010101010100 - // - // - // - // 0000 - // - // - - JsonNode msgId = dataFrame.get("msgId"); - if (msgId != null) { - ObjectNode roadSignID = (ObjectNode) msgId.get("roadSignID"); - if (roadSignID != null) { - - DsrcPosition3D position = Position3DBuilder - .dsrcPosition3D(Position3DBuilder.odePosition3D(roadSignID.get(POSITION))); - - roadSignID.putPOJO(POSITION, position); - - // mutcdCode is optional - JsonNode mutcdNode = roadSignID.get("mutcdCode"); - if (mutcdNode != null) { - roadSignID.set("mutcdCode", - JsonUtils.newNode().put(mutcdNode.asText(), EMPTY_FIELD_FLAG)); + /** + * Builds an item. + * + * @param itemStr String representing the item + * @return JsonNode representing the item + */ + public static JsonNode buildItem(String itemStr) { + JsonNode item = null; + // check to see if it is an itis code or text + try { + item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(ITIS, Integer.valueOf(itemStr))); + // it's a number, so create "itis" code + } catch (NumberFormatException e) { + // it's not a number, so create "text" + if (itemStr.startsWith("'")) { + item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr.substring(1))); + } else { + item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr)); + } } - } - } - } - - /** - * Transforms regions. - * - * @param regions JsonNode representing the regions - * @return ObjectNode representing the transformed regions - * @throws JsonUtilsException if there is an issue converting the JsonNode - */ - public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsException { - ArrayNode replacedRegions = JsonUtils.newNode().arrayNode(); - - if (regions.isArray()) { - Iterator regionsIter = regions.elements(); - - while (regionsIter.hasNext()) { - JsonNode curRegion = regionsIter.next(); - replaceRegion((ObjectNode) curRegion); - replacedRegions.add(curRegion); - } - } - return JsonUtils.newObjectNode(GEOGRAPHICAL_PATH_STRING, replacedRegions); - } - - /** - * Replaces a region. - * - * @param region ObjectNode representing the region - * @throws JsonUtilsException if there is an issue converting the JsonNode - */ - public static void replaceRegion(ObjectNode region) throws JsonUtilsException { - - //// EXPECTED INPUT: - // "name": "Testing TIM", - // "regulatorID": "0", - // "segmentID": "33", - // "anchorPosition": - // "latitude": "41.2500807", - // "longitude": "-111.0093847", - // "elevation": "2020.6969900289998" - // , - // "laneWidth": "7", - // "directionality": "3", - // "closedPath": "false", - // "description": "path", - // "path": {}, - // "direction": "0000000000001010" - - //// EXPECTED OUTPUT: - // - // .Testing TIM - // . - // ..0 - // ..33 - // . - // . - // ..412500807 - // ..-1110093847 - // ..20206 - // . - // .700 - // . - // .. - // . - // . - // .. - // . - // .0000000000010100 - // . - // . - // - - // name does not need to be replaced - - // id optional, consists of segmentID (required) - // and regulatorID (optional) - JsonNode segmentID = region.get(SEGMENT_ID); - if (segmentID != null) { - ObjectNode id = JsonUtils.newNode().put(ID, segmentID.asInt()); - JsonNode regulatorID = region.get(REGULATOR_ID); - if (regulatorID != null) { - id.put(REGION, regulatorID.asInt()); - } - region.set(ID, id); - } - // replace regulatorID and segmentID with id - ObjectNode id = JsonUtils.newNode().put(REGION, region.get(REGULATOR_ID).asInt()).put(ID, - region.get(SEGMENT_ID).asInt()); - - region.set(ID, id); - region.remove(REGULATOR_ID); - region.remove(SEGMENT_ID); - - // anchorPosition --> anchor (optional) - JsonNode anchorPos = region.get(ANCHOR_POSITION); - if (anchorPos != null) { - region.set(ANCHOR, JsonUtils.toObjectNode(Position3DBuilder - .dsrcPosition3D(Position3DBuilder.odePosition3D(region.get(ANCHOR_POSITION))).toJson())); - region.remove(ANCHOR_POSITION); + return item; } - // lane width (optional) - JsonNode laneWidth = region.get(LANE_WIDTH); - if (laneWidth != null) { - region.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); + /** + * Replaces msg id. + * + * @param dataFrame ObjectNode representing the data frame + */ + public static void replaceMsgId(ObjectNode dataFrame) { + + // + // + // + // 416784730 + // -1087827750 + // 9171 + // + // 0101010101010100 + // + // + // + // 0000 + // + // + + JsonNode msgId = dataFrame.get("msgId"); + if (msgId != null) { + ObjectNode roadSignID = (ObjectNode) msgId.get("roadSignID"); + if (roadSignID != null) { + + DsrcPosition3D position = Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(roadSignID.get(POSITION))); + + roadSignID.putPOJO(POSITION, position); + + // mutcdCode is optional + JsonNode mutcdNode = roadSignID.get("mutcdCode"); + if (mutcdNode != null) { + roadSignID.set("mutcdCode", JsonUtils.newNode().put(mutcdNode.asText(), EMPTY_FIELD_FLAG)); + } + } + } } - // directionality (optional) - if (region.has(DIRECTIONALITY)) { - JsonNode directionality = region.get(DIRECTIONALITY); - String enumString = - CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); - if (enumString != null) { - region.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); - } - } + /** + * Transforms regions. + * + * @param regions JsonNode representing the regions + * @return ObjectNode representing the transformed regions + * @throws JsonUtilsException if there is an issue converting the JsonNode + */ + public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsException { + ArrayNode replacedRegions = JsonUtils.newNode().arrayNode(); + + if (regions.isArray()) { + Iterator regionsIter = regions.elements(); + + while (regionsIter.hasNext()) { + JsonNode curRegion = regionsIter.next(); + replaceRegion((ObjectNode) curRegion); + replacedRegions.add(curRegion); + } + } - // closed path (optional) - JsonNode closedPath = region.get(CLOSED_PATH); - if (closedPath != null) { - region.put(CLOSED_PATH, - (closedPath.asBoolean() ? BOOLEAN_OBJECT_TRUE : BOOLEAN_OBJECT_FALSE)); + return JsonUtils.newObjectNode(GEOGRAPHICAL_PATH_STRING, replacedRegions); } - // description (optional) - JsonNode descriptionNode = region.get(DESCRIPTION); - if (descriptionNode != null) { - String descriptionType = descriptionNode.asText(); - if (PATH.equals(descriptionType)) { - ObjectNode pathNode = (ObjectNode) region.get(PATH); - replacePath(pathNode); - region.set(DESCRIPTION, JsonUtils.newNode().set(PATH, pathNode)); - } else if (GEOMETRY.equals(descriptionType)) { - ObjectNode newGeometry = (ObjectNode) region.get(GEOMETRY); - replaceGeometry(newGeometry); - region.set(DESCRIPTION, JsonUtils.newNode().set(GEOMETRY, newGeometry)); - } else if (OLD_REGION.equals(descriptionType)) { - ObjectNode newOldRegion = (ObjectNode) region.get(OLD_REGION); - replaceOldRegion(newOldRegion); - region.set(DESCRIPTION, JsonUtils.newNode().set(OLD_REGION, newOldRegion)); - } - region.remove(descriptionType); + /** + * Replaces a region. + * + * @param region ObjectNode representing the region + * @throws JsonUtilsException if there is an issue converting the JsonNode + */ + public static void replaceRegion(ObjectNode region) throws JsonUtilsException { + + //// EXPECTED INPUT: + // "name": "Testing TIM", + // "regulatorID": "0", + // "segmentID": "33", + // "anchorPosition": + // "latitude": "41.2500807", + // "longitude": "-111.0093847", + // "elevation": "2020.6969900289998" + // , + // "laneWidth": "7", + // "directionality": "3", + // "closedPath": "false", + // "description": "path", + // "path": {}, + // "direction": "0000000000001010" + + //// EXPECTED OUTPUT: + // + // .Testing TIM + // . + // ..0 + // ..33 + // . + // . + // ..412500807 + // ..-1110093847 + // ..20206 + // . + // .700 + // . + // .. + // . + // . + // .. + // . + // .0000000000010100 + // . + // . + // + + // name does not need to be replaced + + // id optional, consists of segmentID (required) + // and regulatorID (optional) + JsonNode segmentID = region.get(SEGMENT_ID); + if (segmentID != null) { + ObjectNode id = JsonUtils.newNode().put(ID, segmentID.asInt()); + JsonNode regulatorID = region.get(REGULATOR_ID); + if (regulatorID != null) { + id.put(REGION, regulatorID.asInt()); + } + region.set(ID, id); + } + // replace regulatorID and segmentID with id + ObjectNode id = JsonUtils.newNode().put(REGION, region.get(REGULATOR_ID).asInt()).put(ID, region.get(SEGMENT_ID).asInt()); + + region.set(ID, id); + region.remove(REGULATOR_ID); + region.remove(SEGMENT_ID); + + // anchorPosition --> anchor (optional) + JsonNode anchorPos = region.get(ANCHOR_POSITION); + if (anchorPos != null) { + region.set(ANCHOR, JsonUtils.toObjectNode(Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(region.get(ANCHOR_POSITION))).toJson())); + region.remove(ANCHOR_POSITION); + } + + // lane width (optional) + JsonNode laneWidth = region.get(LANE_WIDTH); + if (laneWidth != null) { + region.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); + } + + // directionality (optional) + if (region.has(DIRECTIONALITY)) { + JsonNode directionality = region.get(DIRECTIONALITY); + String enumString = CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); + if (enumString != null) { + region.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); + } + } + + // closed path (optional) + JsonNode closedPath = region.get(CLOSED_PATH); + if (closedPath != null) { + region.put(CLOSED_PATH, (closedPath.asBoolean() ? BOOLEAN_OBJECT_TRUE : BOOLEAN_OBJECT_FALSE)); + } + + // description (optional) + JsonNode descriptionNode = region.get(DESCRIPTION); + if (descriptionNode != null) { + String descriptionType = descriptionNode.asText(); + if (PATH.equals(descriptionType)) { + ObjectNode pathNode = (ObjectNode) region.get(PATH); + replacePath(pathNode); + region.set(DESCRIPTION, JsonUtils.newNode().set(PATH, pathNode)); + } else if (GEOMETRY.equals(descriptionType)) { + ObjectNode newGeometry = (ObjectNode) region.get(GEOMETRY); + replaceGeometry(newGeometry); + region.set(DESCRIPTION, JsonUtils.newNode().set(GEOMETRY, newGeometry)); + } else if (OLD_REGION.equals(descriptionType)) { + ObjectNode newOldRegion = (ObjectNode) region.get(OLD_REGION); + replaceOldRegion(newOldRegion); + region.set(DESCRIPTION, JsonUtils.newNode().set(OLD_REGION, newOldRegion)); + } + region.remove(descriptionType); + } } - } - - private static void replacePath(ObjectNode pathNode) { - - //// EXPECTED INPUT: - // "path": - // "scale": "0", - // "type": "ll", - // "nodes": [] - - //// EXPECTED OUTPUT: - // - // .0 - // . - // .. - // ... - // ... - // .. - // . - // - - // zoom does not need to be replaced - String nodeType = pathNode.get(TYPE).asText(); - JsonNode nodes = pathNode.get(NODES); - JsonNode nodeList; - if (LL.equals(nodeType)) { - nodeList = JsonUtils.newNode().set("NodeLL", transformNodeSetLL(nodes)); - pathNode.set(OFFSET, JsonUtils.newNode().set(LL, JsonUtils.newNode().set(NODES, nodeList))); - } else if (XY.equals(nodeType)) { - nodeList = JsonUtils.newNode().set(NODE_XY2, transformNodeSetXY(nodes)); - pathNode.set(OFFSET, JsonUtils.newNode().set(XY, JsonUtils.newNode().set(NODES, nodeList))); + + private static void replacePath(ObjectNode pathNode) { + + //// EXPECTED INPUT: + // "path": + // "scale": "0", + // "type": "ll", + // "nodes": [] + + //// EXPECTED OUTPUT: + // + // .0 + // . + // .. + // ... + // ... + // .. + // . + // + + // zoom does not need to be replaced + String nodeType = pathNode.get(TYPE).asText(); + JsonNode nodes = pathNode.get(NODES); + JsonNode nodeList; + if (LL.equals(nodeType)) { + nodeList = JsonUtils.newNode().set("NodeLL", transformNodeSetLL(nodes)); + pathNode.set(OFFSET, JsonUtils.newNode().set(LL, JsonUtils.newNode().set(NODES, nodeList))); + } else if (XY.equals(nodeType)) { + nodeList = JsonUtils.newNode().set(NODE_XY2, transformNodeSetXY(nodes)); + pathNode.set(OFFSET, JsonUtils.newNode().set(XY, JsonUtils.newNode().set(NODES, nodeList))); + } + pathNode.remove(NODES); + pathNode.remove(TYPE); + } - pathNode.remove(NODES); - pathNode.remove(TYPE); - } + private static ArrayNode transformNodeSetLL(JsonNode nodes) { - private static ArrayNode transformNodeSetLL(JsonNode nodes) { + //// EXPECTED INPUT: + // "nodes": [] - //// EXPECTED INPUT: - // "nodes": [] + // EXPECTED OUTPUT: + // + // . + // . + // . + // . + // - // EXPECTED OUTPUT: - // - // . - // . - // . - // . - // + ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); - ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); + if (nodes.isArray()) { + Iterator nodeListIter = nodes.elements(); - if (nodes.isArray()) { - Iterator nodeListIter = nodes.elements(); + while (nodeListIter.hasNext()) { + JsonNode inputNode = nodeListIter.next(); + outputNodeList.add(transformNodeLL(inputNode)); + } + } - while (nodeListIter.hasNext()) { - JsonNode inputNode = nodeListIter.next(); - outputNodeList.add(transformNodeLL(inputNode)); - } + return outputNodeList; } - return outputNodeList; - } - - public static ObjectNode transformNodeLL(JsonNode oldNode) { - - //// EXPECTED INPUT: - - // "nodeLong": "0.0031024", - // "nodeLat": "0.0014506", - // "delta": "node-LL3" - - //// EXPECTED OUTPUT: - // - // . - // .. - // ...14506 - // ...31024 - // .. - // . - // - - BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); - BigDecimal longOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); - JsonNode delta = oldNode.get(DELTA); - Long transformedLat = null; - Long transformedLong = null; - - ObjectNode innerNode = JsonUtils.newNode(); - ObjectNode latLong = JsonUtils.newNode(); - String deltaText = delta.asText(); - if (deltaText.startsWith("node-LL")) { - transformedLat = OffsetLLBuilder.offsetLL(latOffset); - transformedLong = OffsetLLBuilder.offsetLL(longOffset); - if (deltaText.equals("node-LL")) { - deltaText = determineNodeOffsetPointLLType(transformedLat, transformedLong); - } - } else if (NODE_LAT_LON.equals(deltaText)) { - transformedLat = LatitudeBuilder.j2735Latitude(latOffset); - transformedLong = LongitudeBuilder.j2735Longitude(longOffset); + public static ObjectNode transformNodeLL(JsonNode oldNode) { + + //// EXPECTED INPUT: + + // "nodeLong": "0.0031024", + // "nodeLat": "0.0014506", + // "delta": "node-LL3" + + //// EXPECTED OUTPUT: + // + // . + // .. + // ...14506 + // ...31024 + // .. + // . + // + + BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); + BigDecimal longOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); + JsonNode delta = oldNode.get(DELTA); + Long transformedLat = null; + Long transformedLong = null; + + ObjectNode innerNode = JsonUtils.newNode(); + ObjectNode latLong = JsonUtils.newNode(); + String deltaText = delta.asText(); + if (deltaText.startsWith("node-LL")) { + transformedLat = OffsetLLBuilder.offsetLL(latOffset); + transformedLong = OffsetLLBuilder.offsetLL(longOffset); + if (deltaText.equals("node-LL")) { + deltaText = determineNodeOffsetPointLLType(transformedLat, transformedLong); + } + } else if (NODE_LAT_LON.equals(deltaText)) { + transformedLat = LatitudeBuilder.j2735Latitude(latOffset); + transformedLong = LongitudeBuilder.j2735Longitude(longOffset); + } + + innerNode.set(deltaText, latLong); + latLong.put(LAT, transformedLat).put(LON, transformedLong); + ObjectNode deltaNode = JsonUtils.newNode().set(DELTA, innerNode); + return deltaNode; } - innerNode.set(deltaText, latLong); - latLong.put(LAT, transformedLat).put(LON, transformedLong); - ObjectNode deltaNode = JsonUtils.newNode().set(DELTA, innerNode); - return deltaNode; - } - - // -- Nodes with LL content Span at the equator when using a zoom of one: - public static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node - public static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node - public static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node - public static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node - public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node - public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node - - // -- Limits for each node type - public final static long NODE_LL1_LIMIT = 2047; - public final static long NODE_LL2_LIMIT = 8191; - public final static long NODE_LL3_LIMIT = 32767; - public final static long NODE_LL4_LIMIT = 131071; - public final static long NODE_LL5_LIMIT = 2097151; - public final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. - - /** - * Determines the node offset point LL type based on the latitude and longitude deltas. - * The method evaluates the absolute values of the deltas against predefined limits to determine - * the appropriate node type. If the deltas do not fit within any allowed ranges, an exception - * is thrown. - * - * @param latDelta The latitude delta as a long value. - * @param lonDelta The longitude delta as a long value. - * @return A string representing the node offset point LL type (e.g., NODE_LL1, NODE_LL2, etc.). - * @throws IllegalArgumentException if latDelta or lonDelta are outside the permissible range - * of -0.8388608 to +0.8388607 degrees. - */ - public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { - long absLatDelta = Math.abs(latDelta); - long absLonDelta = Math.abs(lonDelta); - - if (absLatDelta <= NODE_LL1_LIMIT && absLonDelta <= NODE_LL1_LIMIT) { - return NODE_LL1; - } else if (absLatDelta <= NODE_LL2_LIMIT && absLonDelta <= NODE_LL2_LIMIT) { - return NODE_LL2; - } else if (absLatDelta <= NODE_LL3_LIMIT && absLonDelta <= NODE_LL3_LIMIT) { - return NODE_LL3; - } else if (absLatDelta <= NODE_LL4_LIMIT && absLonDelta <= NODE_LL4_LIMIT) { - return NODE_LL4; - } else if (absLatDelta <= NODE_LL5_LIMIT && absLonDelta <= NODE_LL5_LIMIT) { - return NODE_LL5; - } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { - return NODE_LL6; - } else { - throw new IllegalArgumentException( - "Invalid node lat/long offset: " + latDelta + "/" + lonDelta - + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); + // -- Nodes with LL content Span at the equator when using a zoom of one: + public static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node + public static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node + public static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node + public static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node + public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node + public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node + + // -- Limits for each node type + public final static long NODE_LL1_LIMIT = 2047; + public final static long NODE_LL2_LIMIT = 8191; + public final static long NODE_LL3_LIMIT = 32767; + public final static long NODE_LL4_LIMIT = 131071; + public final static long NODE_LL5_LIMIT = 2097151; + public final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. + + /** + * Determines the node offset point LL type based on the latitude and longitude deltas. + * The method evaluates the absolute values of the deltas against predefined limits to determine + * the appropriate node type. If the deltas do not fit within any allowed ranges, an exception + * is thrown. + * + * @param latDelta The latitude delta as a long value. + * @param lonDelta The longitude delta as a long value. + * @return A string representing the node offset point LL type (e.g., NODE_LL1, NODE_LL2, etc.). + * @throws IllegalArgumentException if latDelta or lonDelta are outside the permissible range + * of -0.8388608 to +0.8388607 degrees. + */ + public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { + long absLatDelta = Math.abs(latDelta); + long absLonDelta = Math.abs(lonDelta); + + if (absLatDelta <= NODE_LL1_LIMIT && absLonDelta <= NODE_LL1_LIMIT) { + return NODE_LL1; + } else if (absLatDelta <= NODE_LL2_LIMIT && absLonDelta <= NODE_LL2_LIMIT) { + return NODE_LL2; + } else if (absLatDelta <= NODE_LL3_LIMIT && absLonDelta <= NODE_LL3_LIMIT) { + return NODE_LL3; + } else if (absLatDelta <= NODE_LL4_LIMIT && absLonDelta <= NODE_LL4_LIMIT) { + return NODE_LL4; + } else if (absLatDelta <= NODE_LL5_LIMIT && absLonDelta <= NODE_LL5_LIMIT) { + return NODE_LL5; + } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { + return NODE_LL6; + } else { + throw new IllegalArgumentException("Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); + } } - } - /** - * Replaces geometry. - * - * @param geometry ObjectNode representing the geometry - */ - public static void replaceGeometry(ObjectNode geometry) { + /** + * Replaces geometry. + * + * @param geometry ObjectNode representing the geometry + */ + public static void replaceGeometry(ObjectNode geometry) { - // direction HeadingSlice - // extent Extent OPTIONAL - // laneWidth LaneWidth OPTIONAL - // circle Circle + // direction HeadingSlice + // extent Extent OPTIONAL + // laneWidth LaneWidth OPTIONAL + // circle Circle - // direction does not need to be replaced + // direction does not need to be replaced - // extent does not need to be replaced (optional) + // extent does not need to be replaced (optional) - // replace lane width - JsonNode laneWidth = geometry.get(LANE_WIDTH); - if (laneWidth != null) { - geometry.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); + // replace lane width + JsonNode laneWidth = geometry.get(LANE_WIDTH); + if (laneWidth != null) { + geometry.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); + } + + // replace circle + replaceCircle(geometry.get(CIRCLE)); } - // replace circle - replaceCircle(geometry.get(CIRCLE)); - } - - /** - * Replaces old region. - * - * @param oldRegion ObjectNode representing the old region - */ - public static void replaceOldRegion(ObjectNode oldRegion) { - - // old region == ValidRegion - // elements: - // direction - no changes - - // extent - no changes - JsonNode extentNode = oldRegion.get(EXTENT); - String extent = CommonUtils.enumToString(Extent.ExtentEnum.class, extentNode.asText()); - oldRegion.set(EXTENT, JsonUtils.newNode().put(extent, EMPTY_FIELD_FLAG)); - - // area - needs changes - replaceArea(oldRegion.get("area")); - } - - /** - * Replaces area. - * - * @param area JsonNode representing the area - */ - public static void replaceArea(JsonNode area) { - - // area contains one of: - // shapePointSet - // circle - // regionPointSet - - ObjectNode updatedNode = (ObjectNode) area; - - if (updatedNode.has(SHAPE_POINT_SET)) { - JsonNode shapePointSet = updatedNode.get(SHAPE_POINT_SET); - replaceShapePointSet(shapePointSet); - updatedNode.set(SHAPE_POINT_SET, shapePointSet); - } else if (updatedNode.has(CIRCLE)) { - replaceCircle(updatedNode.get(CIRCLE)); - } else if (updatedNode.has(REGION_POINT_SET)) { - replaceRegionPointSet(updatedNode.get(REGION_POINT_SET)); + /** + * Replaces old region. + * + * @param oldRegion ObjectNode representing the old region + */ + public static void replaceOldRegion(ObjectNode oldRegion) { + + // old region == ValidRegion + // elements: + // direction - no changes + + // extent - no changes + JsonNode extentNode = oldRegion.get(EXTENT); + String extent = CommonUtils.enumToString(Extent.ExtentEnum.class, extentNode.asText()); + oldRegion.set(EXTENT, JsonUtils.newNode().put(extent, EMPTY_FIELD_FLAG)); + + // area - needs changes + replaceArea(oldRegion.get("area")); } - } - - private static void replaceRegionPointSet(JsonNode regionPointSet) { - // regionPointSet contains: - // anchor - // zoom - // nodeList (regionList) - ObjectNode updatedNode = (ObjectNode) regionPointSet; - - // replace anchor (optional) - if (updatedNode.get(ANCHOR_POSITION) != null) { - JsonUtils.addNode(updatedNode, ANCHOR, - Position3DBuilder.dsrcPosition3D( - Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR_POSITION)))); - updatedNode.remove(ANCHOR_POSITION); + + /** + * Replaces area. + * + * @param area JsonNode representing the area + */ + public static void replaceArea(JsonNode area) { + + // area contains one of: + // shapePointSet + // circle + // regionPointSet + + ObjectNode updatedNode = (ObjectNode) area; + + if (updatedNode.has(SHAPE_POINT_SET)) { + JsonNode shapePointSet = updatedNode.get(SHAPE_POINT_SET); + replaceShapePointSet(shapePointSet); + updatedNode.set(SHAPE_POINT_SET, shapePointSet); + } else if (updatedNode.has(CIRCLE)) { + replaceCircle(updatedNode.get(CIRCLE)); + } else if (updatedNode.has(REGION_POINT_SET)) { + replaceRegionPointSet(updatedNode.get(REGION_POINT_SET)); + } } - // zoom doesn't need replacement (also optional) + private static void replaceRegionPointSet(JsonNode regionPointSet) { + // regionPointSet contains: + // anchor + // zoom + // nodeList (regionList) + ObjectNode updatedNode = (ObjectNode) regionPointSet; + + // replace anchor (optional) + if (updatedNode.get(ANCHOR_POSITION) != null) { + JsonUtils.addNode(updatedNode, ANCHOR, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR_POSITION)))); + updatedNode.remove(ANCHOR_POSITION); + } - // regionList is good as is and does not need replacement (required) - } + // zoom doesn't need replacement (also optional) - /** - * Replaces circle. - * - * @param circle JsonNode representing the circle - */ - public static void replaceCircle(JsonNode circle) { + // regionList is good as is and does not need replacement (required) + } + + /** + * Replaces circle. + * + * @param circle JsonNode representing the circle + */ + public static void replaceCircle(JsonNode circle) { + + // Circle ::= SEQUENCE + // center Position3D, + // radius Radius-B12, + // units DistanceUnits + + ObjectNode updatedNode = (ObjectNode) circle; + + JsonNode centerPosition = null; + if (updatedNode.has(POSITION)) { + centerPosition = updatedNode.get(POSITION); + updatedNode.remove(POSITION); + } else { + centerPosition = updatedNode.get(CENTER); + } - // Circle ::= SEQUENCE - // center Position3D, - // radius Radius-B12, - // units DistanceUnits + // replace center + JsonUtils.addNode(updatedNode, CENTER, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(centerPosition))); - ObjectNode updatedNode = (ObjectNode) circle; + // radius does not need replacement - JsonNode centerPosition = null; - if (updatedNode.has(POSITION)) { - centerPosition = updatedNode.get(POSITION); - updatedNode.remove(POSITION); - } else { - centerPosition = updatedNode.get(CENTER); + // replace units + if (updatedNode.has(UNITS)) { + JsonNode units = updatedNode.get(UNITS); + String enumString = CommonUtils.enumToString(DistanceUnitsEnum.class, units.asText()); + if (enumString != null) { + updatedNode.set(UNITS, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); + } + } } - // replace center - JsonUtils.addNode(updatedNode, CENTER, - Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(centerPosition))); + /** + * Replaces shape point set. + * + * @param shapePointSet JsonNode representing the shape point set + */ + public static void replaceShapePointSet(JsonNode shapePointSet) { + // shape point set contains: + // anchor + // lane width + // directionality + // node list + + ObjectNode updatedNode = (ObjectNode) shapePointSet; + + // replace anchor + if (updatedNode.has(ANCHOR)) { + JsonUtils.addNode(updatedNode, ANCHOR, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR)))); + } - // radius does not need replacement + // replace lane width + if (updatedNode.has(LANE_WIDTH)) { + updatedNode.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(updatedNode.get(LANE_WIDTH)))); + } - // replace units - if (updatedNode.has(UNITS)) { - JsonNode units = updatedNode.get(UNITS); - String enumString = CommonUtils.enumToString(DistanceUnitsEnum.class, units.asText()); - if (enumString != null) { - updatedNode.set(UNITS, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); - } - } - } - - /** - * Replaces shape point set. - * - * @param shapePointSet JsonNode representing the shape point set - */ - public static void replaceShapePointSet(JsonNode shapePointSet) { - // shape point set contains: - // anchor - // lane width - // directionality - // node list - - ObjectNode updatedNode = (ObjectNode) shapePointSet; - - // replace anchor - if (updatedNode.has(ANCHOR)) { - JsonUtils.addNode(updatedNode, ANCHOR, - Position3DBuilder.dsrcPosition3D( - Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR)))); - } + // replace directionality + if (updatedNode.has(DIRECTIONALITY)) { + JsonNode directionality = updatedNode.get(DIRECTIONALITY); + String enumString = CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); + if (enumString != null) { + updatedNode.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); + } + } - // replace lane width - if (updatedNode.has(LANE_WIDTH)) { - updatedNode.put(LANE_WIDTH, - LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(updatedNode.get(LANE_WIDTH)))); + // replace node list + if (updatedNode.has(NODE_LIST)) { + ObjectNode nodeList = (ObjectNode) updatedNode.get(NODE_LIST); + if (nodeList.has(NODES)) { + ArrayNode nodes = transformNodeSetXY(nodeList.get(NODES)); + nodeList.set(NODES, nodes); + } else if (nodeList.has(COMPUTED)) { + JsonNode computedLane = nodeList.get(COMPUTED); + replaceComputedLane(computedLane); + } + } } - // replace directionality - if (updatedNode.has(DIRECTIONALITY)) { - JsonNode directionality = updatedNode.get(DIRECTIONALITY); - String enumString = - CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); - if (enumString != null) { - updatedNode.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); - } - } + /** + * Replaces computed lane. + * + * @param jsonNode JsonNode representing the computed lane + */ + public static void replaceComputedLane(JsonNode jsonNode) { + ObjectNode updatedNode = (ObjectNode) jsonNode; - // replace node list - if (updatedNode.has(NODE_LIST)) { - ObjectNode nodeList = (ObjectNode) updatedNode.get(NODE_LIST); - if (nodeList.has(NODES)) { - ArrayNode nodes = transformNodeSetXY(nodeList.get(NODES)); - nodeList.set(NODES, nodes); - } else if (nodeList.has(COMPUTED)) { - JsonNode computedLane = nodeList.get(COMPUTED); - replaceComputedLane(computedLane); - } - } - } + // Nothing to do for referenceLaneId LaneID - /** - * Replaces computed lane. - * - * @param jsonNode JsonNode representing the computed lane - */ - public static void replaceComputedLane(JsonNode jsonNode) { - ObjectNode updatedNode = (ObjectNode) jsonNode; + // offsetXaxis CHOICE + // small DrivenLineOffsetSm, + // large DrivenLineOffsetLg - // Nothing to do for referenceLaneId LaneID + replaceScale(updatedNode, OFFSET_X_AXIS); - // offsetXaxis CHOICE - // small DrivenLineOffsetSm, - // large DrivenLineOffsetLg + // offsetYaxis CHOICE + // small DrivenLineOffsetSm, + // large DrivenLineOffsetLg - replaceScale(updatedNode, OFFSET_X_AXIS); + replaceScale(updatedNode, OFFSET_Y_AXIS); - // offsetYaxis CHOICE - // small DrivenLineOffsetSm, - // large DrivenLineOffsetLg + // rotateXY Angle OPTIONAL + if (updatedNode.has(ROTATE_XY)) { + updatedNode.put(ROTATE_XY, AngleBuilder.angle(JsonUtils.decimalValue(updatedNode.get(ROTATE_XY)))); + } - replaceScale(updatedNode, OFFSET_Y_AXIS); + // scaleXaxis Scale-B12 OPTIONAL + if (updatedNode.has(SCALE_X_AXIS)) { + updatedNode.put(SCALE_X_AXIS, ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_X_AXIS)))); + } - // rotateXY Angle OPTIONAL - if (updatedNode.has(ROTATE_XY)) { - updatedNode.put(ROTATE_XY, - AngleBuilder.angle(JsonUtils.decimalValue(updatedNode.get(ROTATE_XY)))); + // scaleYaxis Scale-B12 OPTIONAL + if (updatedNode.has(SCALE_Y_AXIS)) { + updatedNode.put(SCALE_Y_AXIS, ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_Y_AXIS)))); + } } - // scaleXaxis Scale-B12 OPTIONAL - if (updatedNode.has(SCALE_X_AXIS)) { - updatedNode.put(SCALE_X_AXIS, - ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_X_AXIS)))); + /** + * Replaces scale. + * + * @param updatedNode ObjectNode representing the updated node + * @param scale String representing the scale + */ + public static void replaceScale(ObjectNode updatedNode, String scale) { + if (updatedNode.has(scale)) { + int scaleX = updatedNode.get(scale).asInt(); + String key = "large"; + if (-2048 <= scaleX && scaleX <= 2047) { + key = "small"; + } + + ObjectNode node = JsonUtils.newObjectNode(key, scaleX); + updatedNode.set(scale, node); + } } - // scaleYaxis Scale-B12 OPTIONAL - if (updatedNode.has(SCALE_Y_AXIS)) { - updatedNode.put(SCALE_Y_AXIS, - ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_Y_AXIS)))); - } - } - - /** - * Replaces scale. - * - * @param updatedNode ObjectNode representing the updated node - * @param scale String representing the scale - */ - public static void replaceScale(ObjectNode updatedNode, String scale) { - if (updatedNode.has(scale)) { - int scaleX = updatedNode.get(scale).asInt(); - String key = "large"; - if (-2048 <= scaleX && scaleX <= 2047) { - key = "small"; - } - - ObjectNode node = JsonUtils.newObjectNode(key, scaleX); - updatedNode.set(scale, node); - } - } - - /** - * Transforms node set XY. - * - * @param inputNodeList JsonNode representing the input node list - * @return ArrayNode representing the transformed node list - */ - public static ArrayNode transformNodeSetXY(JsonNode inputNodeList) { - - //// EXPECTED INPUT: - // "nodes": [] - - // EXPECTED OUTPUT: - // - // . - // . - // . - // . - // - - ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); - - if (inputNodeList.isArray()) { - Iterator nodeListIter = inputNodeList.elements(); - - while (nodeListIter.hasNext()) { - JsonNode inputNode = nodeListIter.next(); - outputNodeList.add(transformNodeXY(inputNode)); - } + /** + * Transforms node set XY. + * + * @param inputNodeList JsonNode representing the input node list + * @return ArrayNode representing the transformed node list + */ + public static ArrayNode transformNodeSetXY(JsonNode inputNodeList) { + + //// EXPECTED INPUT: + // "nodes": [] + + // EXPECTED OUTPUT: + // + // . + // . + // . + // . + // + + ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); + + if (inputNodeList.isArray()) { + Iterator nodeListIter = inputNodeList.elements(); + + while (nodeListIter.hasNext()) { + JsonNode inputNode = nodeListIter.next(); + outputNodeList.add(transformNodeXY(inputNode)); + } + } + + return outputNodeList; } - return outputNodeList; - } + /** + * Transformed a NodeXY. + * + * @param oldNode JsonNode representing the old node + * @return ObjectNode representing the transformed node + */ + public static JsonNode transformNodeXY(JsonNode oldNode) { - /** - * Transformed a NodeXY. - * - * @param oldNode JsonNode representing the old node - * @return ObjectNode representing the transformed node - */ - public static JsonNode transformNodeXY(JsonNode oldNode) { + // nodexy contains: + // delta NodeOffsetPointXY + // attributes NodeAttributeSetXY (optional) - // nodexy contains: - // delta NodeOffsetPointXY - // attributes NodeAttributeSetXY (optional) + ObjectNode nodexy = transformNodeOffsetPointXY(oldNode); - ObjectNode nodexy = transformNodeOffsetPointXY(oldNode); + if (oldNode.has(ATTRIBUTES)) { + nodexy.set(ATTRIBUTES, transformNodeAttributeSetXY(oldNode.get(ATTRIBUTES))); + } - if (oldNode.has(ATTRIBUTES)) { - nodexy.set(ATTRIBUTES, transformNodeAttributeSetXY(oldNode.get(ATTRIBUTES))); + return nodexy; } - return nodexy; - } + private static ObjectNode transformNodeAttributeSetXY(JsonNode jsonNode) { + // localNode NodeAttributeXYList OPTIONAL, + // disabled SegmentAttributeXYList OPTIONAL, + // enabled SegmentAttributeXYList OPTIONAL, + // data LaneDataAttributeList OPTIONAL, + // dWidth Offset-B10 OPTIONAL, + // dElevation Offset-B10 OPTIONAL, - private static ObjectNode transformNodeAttributeSetXY(JsonNode jsonNode) { - // localNode NodeAttributeXYList OPTIONAL, - // disabled SegmentAttributeXYList OPTIONAL, - // enabled SegmentAttributeXYList OPTIONAL, - // data LaneDataAttributeList OPTIONAL, - // dWidth Offset-B10 OPTIONAL, - // dElevation Offset-B10 OPTIONAL, + ObjectNode updatedNode = JsonUtils.newNode(); - ObjectNode updatedNode = JsonUtils.newNode(); + // localNode NodeAttributeXYList does not need to be replaced - // localNode NodeAttributeXYList does not need to be replaced + // disabled SegmentAttributeXYList does not need to be replaced + // enabled SegmentAttributeXYList does not need to be replaced - // disabled SegmentAttributeXYList does not need to be replaced - // enabled SegmentAttributeXYList does not need to be replaced - - if (jsonNode.has(DATA)) { - updatedNode.set(DATA, transformLaneDataAttributeList(jsonNode.get(DATA))); - } - if (jsonNode.has(D_WIDTH)) { - updatedNode.put(D_WIDTH, - OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_WIDTH)))); - } + if (jsonNode.has(DATA)) { + updatedNode.set(DATA, transformLaneDataAttributeList(jsonNode.get(DATA))); + } + if (jsonNode.has(D_WIDTH)) { + updatedNode.put(D_WIDTH, OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_WIDTH)))); + } - if (jsonNode.has(D_ELEVATION)) { - updatedNode.put(D_ELEVATION, - OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_ELEVATION)))); + if (jsonNode.has(D_ELEVATION)) { + updatedNode.put(D_ELEVATION, OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_ELEVATION)))); + } + return updatedNode; } - return updatedNode; - } - private static ArrayNode transformLaneDataAttributeList(JsonNode laneDataAttribute) { + private static ArrayNode transformLaneDataAttributeList(JsonNode laneDataAttribute) { - ArrayNode updatedLaneDataAttributeList = JsonUtils.newNode().arrayNode(); + ArrayNode updatedLaneDataAttributeList = JsonUtils.newNode().arrayNode(); - if (laneDataAttribute.isArray()) { - Iterator laneDataAttributeListIter = laneDataAttribute.elements(); + if (laneDataAttribute.isArray()) { + Iterator laneDataAttributeListIter = laneDataAttribute.elements(); - while (laneDataAttributeListIter.hasNext()) { - JsonNode oldNode = laneDataAttributeListIter.next(); - replaceLaneDataAttribute(oldNode); - updatedLaneDataAttributeList.add(oldNode); - } + while (laneDataAttributeListIter.hasNext()) { + JsonNode oldNode = laneDataAttributeListIter.next(); + replaceLaneDataAttribute(oldNode); + updatedLaneDataAttributeList.add(oldNode); + } + } + return updatedLaneDataAttributeList; } - return updatedLaneDataAttributeList; - } - - /** - * Replaces lane data attribute. - * - * @param oldNode JsonNode representing the old node - */ - public static void replaceLaneDataAttribute(JsonNode oldNode) { - // choice between 1 of the following: - // pathEndPointAngle DeltaAngle - // laneCrownPointCenter RoadwayCrownAngle - // laneCrownPointLeft RoadwayCrownAngle - // laneCrownPointRight RoadwayCrownAngle - // laneAngle MergeDivergeNodeAngle - // speedLimits SpeedLimitList - - ObjectNode updatedNode = (ObjectNode) oldNode; - - // pathEndPointAngle DeltaAngle does not need to be replaced - if (oldNode.has("pathEndPointAngle")) { - // do nothing - } else if (oldNode.has(LANE_CROWN_POINT_CENTER)) { - updatedNode.put(LANE_CROWN_POINT_CENTER, RoadwayCrownAngleBuilder - .roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_CENTER)))); - } else if (oldNode.has(LANE_CROWN_POINT_LEFT)) { - updatedNode.put(LANE_CROWN_POINT_LEFT, RoadwayCrownAngleBuilder - .roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_LEFT)))); - } else if (oldNode.has(LANE_CROWN_POINT_RIGHT)) { - updatedNode.put(LANE_CROWN_POINT_RIGHT, RoadwayCrownAngleBuilder - .roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_RIGHT)))); - } else if (oldNode.has(LANE_ANGLE)) { - updatedNode.put(LANE_ANGLE, - MergeDivergeNodeAngleBuilder.mergeDivergeNodeAngle( - JsonUtils.decimalValue(updatedNode.get(LANE_ANGLE)))); - } else if (oldNode.has(SPEED_LIMITS)) { - replaceSpeedLimitList(updatedNode.get(SPEED_LIMITS)); + + /** + * Replaces lane data attribute. + * + * @param oldNode JsonNode representing the old node + */ + public static void replaceLaneDataAttribute(JsonNode oldNode) { + // choice between 1 of the following: + // pathEndPointAngle DeltaAngle + // laneCrownPointCenter RoadwayCrownAngle + // laneCrownPointLeft RoadwayCrownAngle + // laneCrownPointRight RoadwayCrownAngle + // laneAngle MergeDivergeNodeAngle + // speedLimits SpeedLimitList + + ObjectNode updatedNode = (ObjectNode) oldNode; + + // pathEndPointAngle DeltaAngle does not need to be replaced + if (oldNode.has("pathEndPointAngle")) { + // do nothing + } else if (oldNode.has(LANE_CROWN_POINT_CENTER)) { + updatedNode.put(LANE_CROWN_POINT_CENTER, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_CENTER)))); + } else if (oldNode.has(LANE_CROWN_POINT_LEFT)) { + updatedNode.put(LANE_CROWN_POINT_LEFT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_LEFT)))); + } else if (oldNode.has(LANE_CROWN_POINT_RIGHT)) { + updatedNode.put(LANE_CROWN_POINT_RIGHT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_RIGHT)))); + } else if (oldNode.has(LANE_ANGLE)) { + updatedNode.put(LANE_ANGLE, MergeDivergeNodeAngleBuilder.mergeDivergeNodeAngle(JsonUtils.decimalValue(updatedNode.get(LANE_ANGLE)))); + } else if (oldNode.has(SPEED_LIMITS)) { + replaceSpeedLimitList(updatedNode.get(SPEED_LIMITS)); + } } - } - private static void replaceSpeedLimitList(JsonNode speedLimitList) { + private static void replaceSpeedLimitList(JsonNode speedLimitList) { - if (speedLimitList.isArray()) { - Iterator speedLimitListIter = speedLimitList.elements(); + if (speedLimitList.isArray()) { + Iterator speedLimitListIter = speedLimitList.elements(); - while (speedLimitListIter.hasNext()) { - JsonNode oldNode = speedLimitListIter.next(); - replaceRegulatorySpeedLimit(oldNode); - } + while (speedLimitListIter.hasNext()) { + JsonNode oldNode = speedLimitListIter.next(); + replaceRegulatorySpeedLimit(oldNode); + } + } } - } - private static void replaceRegulatorySpeedLimit(JsonNode regulatorySpeedLimitNode) { - // contains: - // type SpeedLimitType - // speed Velocity + private static void replaceRegulatorySpeedLimit(JsonNode regulatorySpeedLimitNode) { + // contains: + // type SpeedLimitType + // speed Velocity - ObjectNode updatedNode = (ObjectNode) regulatorySpeedLimitNode; + ObjectNode updatedNode = (ObjectNode) regulatorySpeedLimitNode; - // type - JsonNode typeNode = regulatorySpeedLimitNode.get(TYPE); - String type = CommonUtils.enumToString(SpeedLimitTypeEnum.class, typeNode.asText()); - if (type != null) { - updatedNode.set(TYPE, JsonUtils.newNode().put(type, EMPTY_FIELD_FLAG)); - } + // type + JsonNode typeNode = regulatorySpeedLimitNode.get(TYPE); + String type = CommonUtils.enumToString(SpeedLimitTypeEnum.class, typeNode.asText()); + if (type != null) { + updatedNode.set(TYPE, JsonUtils.newNode().put(type, EMPTY_FIELD_FLAG)); + } + + // replace velocity + updatedNode.put(SPEED, VelocityBuilder.velocity(JsonUtils.decimalValue(updatedNode.get(SPEED)))); - // replace velocity - updatedNode.put(SPEED, - VelocityBuilder.velocity(JsonUtils.decimalValue(updatedNode.get(SPEED)))); - - } - - /** - * Transformed node offset point XY. - * - * @param oldNode JsonNode representing the old node - * @return ObjectNode representing the transformed node - */ - public static ObjectNode transformNodeOffsetPointXY(JsonNode oldNode) { - //// EXPECTED INPUT: - - // "nodeLong": "0.0031024", - // "nodeLat": "0.0014506", - // "delta": "node-LL3" - - //// EXPECTED OUTPUT: - // - // . - // .. - // ...14506 - // ...31024 - // .. - // . - // - - JsonNode delta = oldNode.get(DELTA); - - ObjectNode innerNode = JsonUtils.newNode(); - ObjectNode deltaNode = JsonUtils.newNode(); - String deltaText = delta.asText(); - if (deltaText.startsWith(NODE_XY)) { - BigDecimal offsetX = JsonUtils.decimalValue(oldNode.get(X)); - BigDecimal offsetY = JsonUtils.decimalValue(oldNode.get(Y)); - Long transformedX = OffsetXyBuilder.offsetXy(offsetX); - Long transformedY = OffsetXyBuilder.offsetXy(offsetY); - ObjectNode xy = JsonUtils.newNode().put(X, transformedX).put(Y, transformedY); - if (deltaText.equals(NODE_XY)) { - innerNode.set(nodeOffsetPointXY(transformedX, transformedY), xy); - } else { - innerNode.set(deltaText, xy); - } - } else if (deltaText.startsWith(NODE_LAT_LON)) { - BigDecimal lonOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); - BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); - Long transformedLon = LatitudeBuilder.j2735Latitude(lonOffset); - Long transformedLat = LongitudeBuilder.j2735Longitude(latOffset); - ObjectNode latLong = JsonUtils.newNode().put(LON, transformedLon).put(LAT, transformedLat); - if (deltaText.equals(NODE_XY)) { - innerNode.set(determineNodeOffsetPointLLType(transformedLat, transformedLon), latLong); - } else { - innerNode.set(deltaText, latLong); - } } - deltaNode.set(DELTA, innerNode); - - return deltaNode; - - } - - // NodeOffsetPointXY contains one of: - // node-XY1 Node-XY-20b, -- node is within 5.11m of last node - // node-XY2 Node-XY-22b, -- node is within 10.23m of last node - // node-XY3 Node-XY-24b, -- node is within 20.47m of last node - // node-XY4 Node-XY-26b, -- node is within 40.96m of last node - // node-XY5 Node-XY-28b, -- node is within 81.91m of last node - // node-XY6 Node-XY-32b, -- node is within 327.67m of last node - // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range - private static String nodeOffsetPointXY(long transformedX, long transformedY) { - long transformed = Math.abs(transformedX) | Math.abs(transformedY); - if ((transformed & (-1 << 10)) == 0) { - return "node-XY1"; - } else if ((transformed & (-1 << 11)) == 0) { - return "node-XY2"; - } else if ((transformed & (-1 << 12)) == 0) { - return "node-XY3"; - } else if ((transformed & (-1 << 13)) == 0) { - return "node-XY4"; - } else if ((transformed & (-1 << 14)) == 0) { - return "node-XY5"; - } else if ((transformed & (-1 << 16)) == 0) { - return "node-XY6"; - } else { - throw new IllegalArgumentException( - "Invalid node X/Y offset: " + transformedX + "/" + transformedY - + ". Values must be between a range of -327.68/+327.67 meters."); + /** + * Transformed node offset point XY. + * + * @param oldNode JsonNode representing the old node + * @return ObjectNode representing the transformed node + */ + public static ObjectNode transformNodeOffsetPointXY(JsonNode oldNode) { + //// EXPECTED INPUT: + + // "nodeLong": "0.0031024", + // "nodeLat": "0.0014506", + // "delta": "node-LL3" + + //// EXPECTED OUTPUT: + // + // . + // .. + // ...14506 + // ...31024 + // .. + // . + // + + JsonNode delta = oldNode.get(DELTA); + + ObjectNode innerNode = JsonUtils.newNode(); + ObjectNode deltaNode = JsonUtils.newNode(); + String deltaText = delta.asText(); + if (deltaText.startsWith(NODE_XY)) { + BigDecimal offsetX = JsonUtils.decimalValue(oldNode.get(X)); + BigDecimal offsetY = JsonUtils.decimalValue(oldNode.get(Y)); + Long transformedX = OffsetXyBuilder.offsetXy(offsetX); + Long transformedY = OffsetXyBuilder.offsetXy(offsetY); + ObjectNode xy = JsonUtils.newNode().put(X, transformedX).put(Y, transformedY); + if (deltaText.equals(NODE_XY)) { + innerNode.set(nodeOffsetPointXY(transformedX, transformedY), xy); + } else { + innerNode.set(deltaText, xy); + } + } else if (deltaText.startsWith(NODE_LAT_LON)) { + BigDecimal lonOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); + BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); + Long transformedLon = LatitudeBuilder.j2735Latitude(lonOffset); + Long transformedLat = LongitudeBuilder.j2735Longitude(latOffset); + ObjectNode latLong = JsonUtils.newNode().put(LON, transformedLon).put(LAT, transformedLat); + if (deltaText.equals(NODE_XY)) { + innerNode.set(determineNodeOffsetPointLLType(transformedLat, transformedLon), latLong); + } else { + innerNode.set(deltaText, latLong); + } + } + + deltaNode.set(DELTA, innerNode); + + return deltaNode; + } - } - - /** - * Ensures compliance with the J2735 2024 standard by checking - * for old fields in the given data frame. - * - * @param dataFrame the JSON object representing the data frame to be checked - * @throws NoncompliantFieldsException if any old fields are found - */ - public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) - throws NoncompliantFieldsException { - // Check and throw exception if old fields are found - Set nonCompliantFields = Set.of( - SSP_MSG_CONTENT, - SSP_MSG_TYPES, - SSP_LOCATION_RIGHTS, - SSP_TIM_RIGHTS, - SSP_MSG_RIGHTS_1, - SSP_MSG_RIGHTS_2, - NOT_USED, - NOT_USED_1, - NOT_USED_2, - NOT_USED_3, - DURATON_TIME_MISSPELLED - ); - ArrayList violations = new ArrayList<>(); - for (String violationName : nonCompliantFields) { - if (dataFrame.has(violationName)) { - violations.add(violationName); - } + + // NodeOffsetPointXY contains one of: + // node-XY1 Node-XY-20b, -- node is within 5.11m of last node + // node-XY2 Node-XY-22b, -- node is within 10.23m of last node + // node-XY3 Node-XY-24b, -- node is within 20.47m of last node + // node-XY4 Node-XY-26b, -- node is within 40.96m of last node + // node-XY5 Node-XY-28b, -- node is within 81.91m of last node + // node-XY6 Node-XY-32b, -- node is within 327.67m of last node + // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range + private static String nodeOffsetPointXY(long transformedX, long transformedY) { + long transformed = Math.abs(transformedX) | Math.abs(transformedY); + if ((transformed & (-1 << 10)) == 0) { + return "node-XY1"; + } else if ((transformed & (-1 << 11)) == 0) { + return "node-XY2"; + } else if ((transformed & (-1 << 12)) == 0) { + return "node-XY3"; + } else if ((transformed & (-1 << 13)) == 0) { + return "node-XY4"; + } else if ((transformed & (-1 << 14)) == 0) { + return "node-XY5"; + } else if ((transformed & (-1 << 16)) == 0) { + return "node-XY6"; + } else { + throw new IllegalArgumentException("Invalid node X/Y offset: " + transformedX + "/" + transformedY + ". Values must be between a range of -327.68/+327.67 meters."); + } } - if (!violations.isEmpty()) { - throw new NoncompliantFieldsException( - String.format( - "Data frame contains the following old fields that are not compliant with " - + "J2735 2024: [%s]. Deserialization should prevent this.", - violations)); + + /** + * Ensures compliance with the J2735 2024 standard by checking + * for old fields in the given data frame. + * + * @param dataFrame the JSON object representing the data frame to be checked + * @throws NoncompliantFieldsException if any old fields are found + */ + public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) throws NoncompliantFieldsException { + // Check and throw exception if old fields are found + Set nonCompliantFields = + Set.of(SSP_MSG_CONTENT, SSP_MSG_TYPES, SSP_LOCATION_RIGHTS, SSP_TIM_RIGHTS, SSP_MSG_RIGHTS_1, SSP_MSG_RIGHTS_2, NOT_USED, NOT_USED_1, NOT_USED_2, NOT_USED_3, DURATON_TIME_MISSPELLED); + ArrayList violations = new ArrayList<>(); + for (String violationName : nonCompliantFields) { + if (dataFrame.has(violationName)) { + violations.add(violationName); + } + } + if (!violations.isEmpty()) { + throw new NoncompliantFieldsException( + String.format("Data frame contains the following old fields that are not compliant with " + "J2735 2024: [%s]. Deserialization should prevent this.", violations)); + } } - } - - /** - * Exception thrown when noncompliant fields are found in the data frame. - */ - public static class NoncompliantFieldsException extends Exception { - public NoncompliantFieldsException(String message) { - super(message); + + /** + * Exception thrown when noncompliant fields are found in the data frame. + */ + public static class NoncompliantFieldsException extends Exception { + public NoncompliantFieldsException(String message) { + super(message); + } } - } } From 5b9a1d5b8c5d26b72e9dd75823a2ae06226a06ae Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:31:17 -0600 Subject: [PATCH 18/32] Formatted TravelerMessageFromHumanToAsnConverterTest.java --- ...lerMessageFromHumanToAsnConverterTest.java | 163 ++++++------------ 1 file changed, 48 insertions(+), 115 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index b859b65e7..f5d51ef8f 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -55,8 +55,7 @@ Logger getLogger(String value) { } @Test - void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); @@ -66,14 +65,12 @@ void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtils "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"1\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":\"-105.047355\",\"nodeLat\":\"40.572429\",\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"workZone\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); @@ -83,14 +80,12 @@ void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"1\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"advisory\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":-105.047355,\"nodeLat\":40.572429,\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"genericSign\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); @@ -100,14 +95,12 @@ void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testGeometryUnavailable() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryUnavailable() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"unknown\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"0\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -117,14 +110,12 @@ void testGeometryUnavailable() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testGeometryExitServiceForward() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryExitServiceForward() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"1\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"exitService\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -134,14 +125,12 @@ void testGeometryExitServiceForward() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testGeometryAdvisoryReverse() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryAdvisoryReverse() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"roadSignage\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"2\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"advisory\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -151,14 +140,12 @@ void testGeometryAdvisoryReverse() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testRoadSignIDWorkzone() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -167,14 +154,12 @@ void testRoadSignIDWorkzone() throws JsonUtilsException, "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testGeometryBothGenericSign() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryBothGenericSign() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"genericSign\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -184,14 +169,12 @@ void testGeometryBothGenericSign() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testPathSpeedLimit() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testPathSpeedLimit() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"1\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"advisory\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ { \"nodeLong\": \"0.0031024\", \"nodeLat\": \"0.0014506\", \"delta\": \"node-LL3\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":\"123\"},{\"laneCrownPointCenter\":\"111\"},{\"laneCrownPointLeft\":\"5.5\"}],\"dWidth\":\"33\",\"dElevation\":\"500\"} }, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -200,25 +183,18 @@ void testPathSpeedLimit() throws JsonUtilsException, "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test void testTranslateISOTimeStampToMinuteOfYear() { - Assertions.assertEquals(232800, - TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( - "2018-06-11T16:00:00.000Z")); + Assertions.assertEquals(232800, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-06-11T16:00:00.000Z")); - Assertions.assertEquals(232800, - TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( - "2018-06-11T10:00-06:00")); + Assertions.assertEquals(232800, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-06-11T10:00-06:00")); // Test for invalid timestamp - Assertions.assertEquals(527040, - TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear( - "2018-15-44T25:66:77.999Z")); + Assertions.assertEquals(527040, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-15-44T25:66:77.999Z")); } @Test @@ -270,8 +246,7 @@ void testBuildItem() { } @Test - void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"nodes\":[{\"x\":\"-5.12\",\"y\":\"5.11\",\"delta\":\"node-XY\"},{\"x\":\"-10.24\",\"y\":\"10.23\",\"delta\":\"node-XY\"},{\"x\":\"-20.48\",\"y\":\"20.47\",\"delta\":\"node-XY\"},{\"x\":\"-40.96\",\"y\":\"40.95\",\"delta\":\"node-XY\"},{\"x\":\"-81.92\",\"y\":\"81.91\",\"delta\":\"node-XY\"},{\"x\":\"-327.68\",\"y\":\"327.67\",\"delta\":\"node-XY\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -281,14 +256,12 @@ void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -298,14 +271,12 @@ void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsExce Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -315,14 +286,12 @@ void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsExce Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testOldRegionWithCircle() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithCircle() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"circle\":{\"center\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"radius\":\"2048\",\"units\":\"centimeter\"}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -332,14 +301,12 @@ void testOldRegionWithCircle() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void testOldRegionWithRegionPointSet() throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithRegionPointSet() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -349,14 +316,12 @@ void testOldRegionWithRegionPointSet() throws JsonUtilsException, Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, - JsonUtils.toJSONObject(inputTID.toString())); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); assertNotNull(XML.toString(timObject)); } @Test - void ensureComplianceWithJ2735Revision2024_noOldFields() - throws TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void ensureComplianceWithJ2735Revision2024_noOldFields() throws TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); dataFrame.put("doNotUse1", 0); dataFrame.put("doNotUse2", 0); @@ -532,9 +497,7 @@ void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeL long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL1", selection, - "Expected node-LL1 for latitude and longitude within LL1 constraints, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL1", selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); } @Test @@ -543,9 +506,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldRetu long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, - "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); } @Test @@ -554,9 +515,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldRetu long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, - "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); } @Test @@ -565,9 +524,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNo long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, - "Expected node-LL2 for latitude and longitude within LL2 constraints, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); } @Test @@ -576,9 +533,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldRetu long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, - "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); } @Test @@ -587,9 +542,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldRetu long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, - "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); } @Test @@ -598,9 +551,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNo long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, - "Expected node-LL3 for latitude and longitude within LL3 constraints, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); } @Test @@ -609,9 +560,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldRetu long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, - "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); } @Test @@ -620,9 +569,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldRetu long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, - "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); } @Test @@ -631,9 +578,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNo long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, - "Expected node-LL4 for latitude and longitude within LL4 constraints, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); } @Test @@ -642,9 +587,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldRetu long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, - "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); } @Test @@ -653,9 +596,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldRetu long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, - "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); } @Test @@ -664,9 +605,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNo long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, - "Expected node-LL5 for latitude and longitude within LL5 constraints, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); } @Test @@ -675,9 +614,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldRetu long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, - "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); } @Test @@ -686,9 +623,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldRetu long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, - "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); } @Test @@ -697,9 +632,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNo long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, - "Expected node-LL6 for latitude and longitude within LL6 constraints, " + - "but got " + selection + " instead."); + Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); } @Test From 7528128ec25c4c70a453050ce60eb8fc8cd806cc Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:33:37 -0600 Subject: [PATCH 19/32] Addressed a couple warnings in TravelerMessageFromHumanToAsnConverter class --- .../builders/TravelerMessageFromHumanToAsnConverter.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 5c8d462b1..2ea7db8f3 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -671,8 +671,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { innerNode.set(deltaText, latLong); latLong.put(LAT, transformedLat).put(LON, transformedLong); - ObjectNode deltaNode = JsonUtils.newNode().set(DELTA, innerNode); - return deltaNode; + return JsonUtils.newNode().set(DELTA, innerNode); } // -- Nodes with LL content Span at the equator when using a zoom of one: @@ -1159,11 +1158,7 @@ public static ObjectNode transformNodeOffsetPointXY(JsonNode oldNode) { Long transformedLon = LatitudeBuilder.j2735Latitude(lonOffset); Long transformedLat = LongitudeBuilder.j2735Longitude(latOffset); ObjectNode latLong = JsonUtils.newNode().put(LON, transformedLon).put(LAT, transformedLat); - if (deltaText.equals(NODE_XY)) { - innerNode.set(determineNodeOffsetPointLLType(transformedLat, transformedLon), latLong); - } else { - innerNode.set(deltaText, latLong); - } + innerNode.set(deltaText, latLong); } deltaNode.set(DELTA, innerNode); From 4caf2ca8e76bb822824bd14971e32addc9cb158b Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:41:38 -0600 Subject: [PATCH 20/32] Reindented TravelerMessageFromHumanToAsnConverter & TravelerMessageFromHumanToAsnConverterTest classes with 2 spaces --- ...ravelerMessageFromHumanToAsnConverter.java | 2144 ++++++++--------- ...lerMessageFromHumanToAsnConverterTest.java | 1222 +++++----- 2 files changed, 1683 insertions(+), 1683 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 2ea7db8f3..fe462019b 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -44,1186 +44,1186 @@ */ public class TravelerMessageFromHumanToAsnConverter { - private static final String SPEED = "speed"; - private static final String TYPE = "type"; - private static final String ATTRIBUTES = "attributes"; - public static final String TRAVELER_INFORMATION = "TravelerInformation"; - private static final String EXTENT = "extent"; - private static final String UNITS = "units"; - private static final String DIRECTIONALITY = "directionality"; - private static final String CENTER = "center"; - private static final String NODE_LAT = "nodeLat"; - private static final String NODE_LONG = "nodeLong"; - private static final String Y = "y"; - private static final String X = "x"; - private static final String NODE_LAT_LON = "node-LatLon"; - private static final String LON = "lon"; - private static final String LAT = "lat"; - private static final String NODE_XY = "node-XY"; - private static final String NODE_XY2 = "NodeXY"; - private static final String COMPUTED = "computed"; - private static final String SPEED_LIMITS = "speedLimits"; - private static final String LANE_ANGLE = "laneAngle"; - private static final String LANE_CROWN_POINT_RIGHT = "laneCrownPointRight"; - private static final String LANE_CROWN_POINT_LEFT = "laneCrownPointLeft"; - private static final String LANE_CROWN_POINT_CENTER = "laneCrownPointCenter"; - private static final String D_ELEVATION = "dElevation"; - private static final String D_WIDTH = "dWidth"; - private static final String DATA = "data"; - private static final String OFFSET_X_AXIS = "offsetXaxis"; - private static final String OFFSET_Y_AXIS = "offsetYaxis"; - private static final String ROTATE_XY = "rotateXY"; - private static final String SCALE_X_AXIS = "scaleXaxis"; - private static final String SCALE_Y_AXIS = "scaleYaxis"; - private static final String NODE_LIST = "nodeList"; - private static final String REGION_POINT_SET = "regionPointSet"; - private static final String CIRCLE = "circle"; - private static final String SHAPE_POINT_SET = "shapePointSet"; - private static final String DELTA = "delta"; - private static final String OFFSET = "offset"; - private static final String NODES = "nodes"; - private static final String XY = "xy"; - private static final String LL = "ll"; - private static final String OLD_REGION = "oldRegion"; - private static final String GEOMETRY = "geometry"; - private static final String PATH = "path"; - private static final String DESCRIPTION = "description"; - private static final String CLOSED_PATH = "closedPath"; - private static final String ANCHOR = "anchor"; - private static final String ID = "id"; - private static final String REGION = "region"; - private static final String LANE_WIDTH = "laneWidth"; - private static final String ANCHOR_POSITION = "anchorPosition"; - private static final String REGULATOR_ID = "regulatorID"; - private static final String SEGMENT_ID = "segmentID"; - private static final String POSITION = "position"; - private static final String TEXT = "text"; - private static final String ITIS = "itis"; - private static final String ITEM = "item"; - private static final String START_DATE_TIME = "startDateTime"; - private static final String DURATON_TIME_MISSPELLED = "duratonTime"; // J2735 2016 Misspelling - private static final String SSP_TIM_RIGHTS = "sspTimRights"; // used in J2735 2016 - private static final String NOT_USED = "notUsed"; // used in J2735 2020 - private static final String SSP_LOCATION_RIGHTS = "sspLocationRights"; // used in J2735 2016 - private static final String NOT_USED_1 = "notUsed1"; // used in J2735 2020 - private static final String SSP_MSG_TYPES = "sspMsgTypes"; // used previously - private static final String SSP_MSG_RIGHTS_1 = "sspMsgRights1"; // used in J2735 2016 - private static final String NOT_USED_2 = "notUsed2"; // used in J2735 2020 - private static final String SSP_MSG_CONTENT = "sspMsgContent"; // used previously - private static final String SSP_MSG_RIGHTS_2 = "sspMsgRights2"; // used in J2735 2016 - private static final String NOT_USED_3 = "notUsed3"; // used in J2735 2020 - private static final String DATAFRAMES = "dataframes"; - private static final String TIME_STAMP = "timeStamp"; - public static final String GEOGRAPHICAL_PATH_STRING = "GeographicalPath"; - public static final String REGIONS_STRING = "regions"; - public static final String TRAVELER_DATA_FRAME_STRING = "TravelerDataFrame"; - public static final String DATA_FRAMES_STRING = "dataFrames"; - public static final String SEQUENCE_STRING = "SEQUENCE"; - public static final String TCONTENT_STRING = "tcontent"; - // JSON cannot have empty fields like XML, so the XML must be modified by - // removing all flag field values - public static final String EMPTY_FIELD_FLAG = "EMPTY_TAG"; - public static final String BOOLEAN_OBJECT_TRUE = "BOOLEAN_OBJECT_TRUE"; - public static final String BOOLEAN_OBJECT_FALSE = "BOOLEAN_OBJECT_FALSE"; - - private static final Logger logger = LoggerFactory.getLogger(TravelerMessageFromHumanToAsnConverter.class); - - private TravelerMessageFromHumanToAsnConverter() { - super(); + private static final String SPEED = "speed"; + private static final String TYPE = "type"; + private static final String ATTRIBUTES = "attributes"; + public static final String TRAVELER_INFORMATION = "TravelerInformation"; + private static final String EXTENT = "extent"; + private static final String UNITS = "units"; + private static final String DIRECTIONALITY = "directionality"; + private static final String CENTER = "center"; + private static final String NODE_LAT = "nodeLat"; + private static final String NODE_LONG = "nodeLong"; + private static final String Y = "y"; + private static final String X = "x"; + private static final String NODE_LAT_LON = "node-LatLon"; + private static final String LON = "lon"; + private static final String LAT = "lat"; + private static final String NODE_XY = "node-XY"; + private static final String NODE_XY2 = "NodeXY"; + private static final String COMPUTED = "computed"; + private static final String SPEED_LIMITS = "speedLimits"; + private static final String LANE_ANGLE = "laneAngle"; + private static final String LANE_CROWN_POINT_RIGHT = "laneCrownPointRight"; + private static final String LANE_CROWN_POINT_LEFT = "laneCrownPointLeft"; + private static final String LANE_CROWN_POINT_CENTER = "laneCrownPointCenter"; + private static final String D_ELEVATION = "dElevation"; + private static final String D_WIDTH = "dWidth"; + private static final String DATA = "data"; + private static final String OFFSET_X_AXIS = "offsetXaxis"; + private static final String OFFSET_Y_AXIS = "offsetYaxis"; + private static final String ROTATE_XY = "rotateXY"; + private static final String SCALE_X_AXIS = "scaleXaxis"; + private static final String SCALE_Y_AXIS = "scaleYaxis"; + private static final String NODE_LIST = "nodeList"; + private static final String REGION_POINT_SET = "regionPointSet"; + private static final String CIRCLE = "circle"; + private static final String SHAPE_POINT_SET = "shapePointSet"; + private static final String DELTA = "delta"; + private static final String OFFSET = "offset"; + private static final String NODES = "nodes"; + private static final String XY = "xy"; + private static final String LL = "ll"; + private static final String OLD_REGION = "oldRegion"; + private static final String GEOMETRY = "geometry"; + private static final String PATH = "path"; + private static final String DESCRIPTION = "description"; + private static final String CLOSED_PATH = "closedPath"; + private static final String ANCHOR = "anchor"; + private static final String ID = "id"; + private static final String REGION = "region"; + private static final String LANE_WIDTH = "laneWidth"; + private static final String ANCHOR_POSITION = "anchorPosition"; + private static final String REGULATOR_ID = "regulatorID"; + private static final String SEGMENT_ID = "segmentID"; + private static final String POSITION = "position"; + private static final String TEXT = "text"; + private static final String ITIS = "itis"; + private static final String ITEM = "item"; + private static final String START_DATE_TIME = "startDateTime"; + private static final String DURATON_TIME_MISSPELLED = "duratonTime"; // J2735 2016 Misspelling + private static final String SSP_TIM_RIGHTS = "sspTimRights"; // used in J2735 2016 + private static final String NOT_USED = "notUsed"; // used in J2735 2020 + private static final String SSP_LOCATION_RIGHTS = "sspLocationRights"; // used in J2735 2016 + private static final String NOT_USED_1 = "notUsed1"; // used in J2735 2020 + private static final String SSP_MSG_TYPES = "sspMsgTypes"; // used previously + private static final String SSP_MSG_RIGHTS_1 = "sspMsgRights1"; // used in J2735 2016 + private static final String NOT_USED_2 = "notUsed2"; // used in J2735 2020 + private static final String SSP_MSG_CONTENT = "sspMsgContent"; // used previously + private static final String SSP_MSG_RIGHTS_2 = "sspMsgRights2"; // used in J2735 2016 + private static final String NOT_USED_3 = "notUsed3"; // used in J2735 2020 + private static final String DATAFRAMES = "dataframes"; + private static final String TIME_STAMP = "timeStamp"; + public static final String GEOGRAPHICAL_PATH_STRING = "GeographicalPath"; + public static final String REGIONS_STRING = "regions"; + public static final String TRAVELER_DATA_FRAME_STRING = "TravelerDataFrame"; + public static final String DATA_FRAMES_STRING = "dataFrames"; + public static final String SEQUENCE_STRING = "SEQUENCE"; + public static final String TCONTENT_STRING = "tcontent"; + // JSON cannot have empty fields like XML, so the XML must be modified by + // removing all flag field values + public static final String EMPTY_FIELD_FLAG = "EMPTY_TAG"; + public static final String BOOLEAN_OBJECT_TRUE = "BOOLEAN_OBJECT_TRUE"; + public static final String BOOLEAN_OBJECT_FALSE = "BOOLEAN_OBJECT_FALSE"; + + private static final Logger logger = LoggerFactory.getLogger(TravelerMessageFromHumanToAsnConverter.class); + + private TravelerMessageFromHumanToAsnConverter() { + super(); + } + + /** + * Converts a JsonNode representing an OdeTravelerInputData object to a format + * that can be encoded by the asn1_codec submodule. + * + * @param tid TravelerInputData object serialized as a JsonNode + * @throws JsonUtilsException if there is an issue converting the JsonNode + * @throws IllegalArgumentException if the JsonNode contains old fields that are no longer used + */ + public static void convertTravelerInputDataToEncodableTim(JsonNode tid) throws JsonUtilsException, NoncompliantFieldsException { + // msgCnt MsgCount, + // timeStamp MinuteOfTheYear OPTIONAL + // packetID UniqueMSGID OPTIONAL + // urlB URL-Base OPTIONAL + // dataFrames TravelerDataFrameList + + // Cast to ObjectNode to allow manipulation in place + ObjectNode timDataObjectNode = (ObjectNode) tid.get("tim"); + + // timeStamp is optional + if (timDataObjectNode.get(TIME_STAMP) != null) { + timDataObjectNode.put(TIME_STAMP, translateISOTimeStampToMinuteOfYear(timDataObjectNode.get(TIME_STAMP).asText())); } - /** - * Converts a JsonNode representing an OdeTravelerInputData object to a format - * that can be encoded by the asn1_codec submodule. - * - * @param tid TravelerInputData object serialized as a JsonNode - * @throws JsonUtilsException if there is an issue converting the JsonNode - * @throws IllegalArgumentException if the JsonNode contains old fields that are no longer used - */ - public static void convertTravelerInputDataToEncodableTim(JsonNode tid) throws JsonUtilsException, NoncompliantFieldsException { - // msgCnt MsgCount, - // timeStamp MinuteOfTheYear OPTIONAL - // packetID UniqueMSGID OPTIONAL - // urlB URL-Base OPTIONAL - // dataFrames TravelerDataFrameList - - // Cast to ObjectNode to allow manipulation in place - ObjectNode timDataObjectNode = (ObjectNode) tid.get("tim"); - - // timeStamp is optional - if (timDataObjectNode.get(TIME_STAMP) != null) { - timDataObjectNode.put(TIME_STAMP, translateISOTimeStampToMinuteOfYear(timDataObjectNode.get(TIME_STAMP).asText())); - } - - // urlB is optional but does not need replacement - - // dataFrames are required - timDataObjectNode.set(DATA_FRAMES_STRING, transformDataFrames(timDataObjectNode.get(DATAFRAMES))); - timDataObjectNode.remove(DATAFRAMES); + // urlB is optional but does not need replacement + + // dataFrames are required + timDataObjectNode.set(DATA_FRAMES_STRING, transformDataFrames(timDataObjectNode.get(DATAFRAMES))); + timDataObjectNode.remove(DATAFRAMES); + } + + /** + * Transforms the dataFrames field. + * + * @param dataFrames JsonNode representing the dataFrames field + * @return ObjectNode representing the transformed dataFrames field + * @throws JsonUtilsException if there is an issue converting the JsonNode + * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used + */ + public static ObjectNode transformDataFrames(JsonNode dataFrames) throws JsonUtilsException, NoncompliantFieldsException { + + if (dataFrames == null) { + return JsonUtils.newNode(); } - /** - * Transforms the dataFrames field. - * - * @param dataFrames JsonNode representing the dataFrames field - * @return ObjectNode representing the transformed dataFrames field - * @throws JsonUtilsException if there is an issue converting the JsonNode - * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used - */ - public static ObjectNode transformDataFrames(JsonNode dataFrames) throws JsonUtilsException, NoncompliantFieldsException { - - if (dataFrames == null) { - return JsonUtils.newNode(); - } - - ArrayNode replacedDataFrames = JsonUtils.newNode().arrayNode(); - if (dataFrames.isArray()) { - Iterator dataFramesIter = dataFrames.elements(); - - while (dataFramesIter.hasNext()) { - ObjectNode oldFrame = (ObjectNode) dataFramesIter.next(); - replaceDataFrame(oldFrame); - // wrap each data frame inside a TravelerDataFrame - replacedDataFrames.add(oldFrame); - } - } + ArrayNode replacedDataFrames = JsonUtils.newNode().arrayNode(); + if (dataFrames.isArray()) { + Iterator dataFramesIter = dataFrames.elements(); - return JsonUtils.newObjectNode(TRAVELER_DATA_FRAME_STRING, replacedDataFrames); + while (dataFramesIter.hasNext()) { + ObjectNode oldFrame = (ObjectNode) dataFramesIter.next(); + replaceDataFrame(oldFrame); + // wrap each data frame inside a TravelerDataFrame + replacedDataFrames.add(oldFrame); + } } - /** - * Replaces a data frame. - * - * @param dataFrame ObjectNode representing the data frame - * @throws JsonUtilsException if there is an issue converting the JsonNode - * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used - */ - public static void replaceDataFrame(ObjectNode dataFrame) throws JsonUtilsException, NoncompliantFieldsException { - - // INPUT - ////// - // "dataframes": [ - // "startDateTime": "2017-08-02T22:25:00.000Z", - // "durationTime": 1, - // "frameType": "1", - // "sspTimRights": "0", - // "msgID": "RoadSignID", - // "position": { - // "latitude": "41.678473", - // "longitude": "-108.782775", - // "elevation": "917.1432" - // }, - // "viewAngle": "1010101010101010", - // "mutcd": "5", - // "crc": "0000000000000000", - // "priority": "0", - // "sspLocationRights": "3", - // "regions": [] - // "sspMsgTypes": "2", - // "sspMsgContent": "3", - // "content": "advisory", - // "items": [ - // "513" - // ], - // "url": "null" - // ] - - /// OUTPUT: - ////// - // - // - // 2017 - // 308065 - // - // - - // set frameType value - dataFrame.set("frameType", JsonUtils.newNode().put(dataFrame.get("frameType").asText(), EMPTY_FIELD_FLAG)); - - ensureComplianceWithJ2735Revision2024(dataFrame); - - // priority does not need replacement - - // url does not need replacement - - replaceDataFrameTimestamp(dataFrame); - - // replace the geographical path regions - dataFrame.set(REGIONS_STRING, transformRegions(dataFrame.get(REGIONS_STRING))); - // replace content - replaceContent(dataFrame); - - // replace the msgID and relevant fields - replaceMsgId(dataFrame); + return JsonUtils.newObjectNode(TRAVELER_DATA_FRAME_STRING, replacedDataFrames); + } + + /** + * Replaces a data frame. + * + * @param dataFrame ObjectNode representing the data frame + * @throws JsonUtilsException if there is an issue converting the JsonNode + * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used + */ + public static void replaceDataFrame(ObjectNode dataFrame) throws JsonUtilsException, NoncompliantFieldsException { + + // INPUT + ////// + // "dataframes": [ + // "startDateTime": "2017-08-02T22:25:00.000Z", + // "durationTime": 1, + // "frameType": "1", + // "sspTimRights": "0", + // "msgID": "RoadSignID", + // "position": { + // "latitude": "41.678473", + // "longitude": "-108.782775", + // "elevation": "917.1432" + // }, + // "viewAngle": "1010101010101010", + // "mutcd": "5", + // "crc": "0000000000000000", + // "priority": "0", + // "sspLocationRights": "3", + // "regions": [] + // "sspMsgTypes": "2", + // "sspMsgContent": "3", + // "content": "advisory", + // "items": [ + // "513" + // ], + // "url": "null" + // ] + + /// OUTPUT: + ////// + // + // + // 2017 + // 308065 + // + // + + // set frameType value + dataFrame.set("frameType", JsonUtils.newNode().put(dataFrame.get("frameType").asText(), EMPTY_FIELD_FLAG)); + + ensureComplianceWithJ2735Revision2024(dataFrame); + + // priority does not need replacement + + // url does not need replacement + + replaceDataFrameTimestamp(dataFrame); + + // replace the geographical path regions + dataFrame.set(REGIONS_STRING, transformRegions(dataFrame.get(REGIONS_STRING))); + // replace content + replaceContent(dataFrame); + + // replace the msgID and relevant fields + replaceMsgId(dataFrame); + } + + /** + * Translates ISO timestamp to minute of year. + * + * @param isoTime ISO timestamp + * @return minute of year + */ + public static long translateISOTimeStampToMinuteOfYear(String isoTime) { + int startYear = 0; + int startMinute = 527040; + try { + ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(isoTime); + startYear = zonedDateTime.getYear(); + startMinute = (int) Duration.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), zonedDateTime).toMinutes(); + } catch (Exception e) { // NOSONAR + logger.error("Failed to parse datetime {}, defaulting to unknown value {}", isoTime, startMinute); } - /** - * Translates ISO timestamp to minute of year. - * - * @param isoTime ISO timestamp - * @return minute of year - */ - public static long translateISOTimeStampToMinuteOfYear(String isoTime) { - int startYear = 0; - int startMinute = 527040; - try { - ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(isoTime); - startYear = zonedDateTime.getYear(); - startMinute = (int) Duration.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), zonedDateTime).toMinutes(); - } catch (Exception e) { // NOSONAR - logger.error("Failed to parse datetime {}, defaulting to unknown value {}", isoTime, startMinute); - } - - return startMinute; + return startMinute; + } + + /** + * Replaces the data frame timestamp. + * + * @param dataFrame ObjectNode representing the data frame + */ + public static void replaceDataFrameTimestamp(ObjectNode dataFrame) { + + // EXPECTED INPUT: + // "timeStamp": "2017-08-03T22:25:36.297Z" + + // EXPECTED OUTPUT: + // 2017 + // 308065 + + // unknown year value = 0 + // unknown minuteofyear = 527040 + int startYear = 0; + int startMinute = 527040; + String startDateTime = dataFrame.get(START_DATE_TIME).asText(); + try { + ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(startDateTime); + startYear = zonedDateTime.getYear(); + startMinute = (int) ChronoUnit.MINUTES.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), zonedDateTime); + } catch (Exception e) { + logger.error("Failed to startDateTime {}, defaulting to unknown value {}.", startDateTime, startMinute); } - /** - * Replaces the data frame timestamp. - * - * @param dataFrame ObjectNode representing the data frame - */ - public static void replaceDataFrameTimestamp(ObjectNode dataFrame) { - - // EXPECTED INPUT: - // "timeStamp": "2017-08-03T22:25:36.297Z" - - // EXPECTED OUTPUT: - // 2017 - // 308065 - - // unknown year value = 0 - // unknown minuteofyear = 527040 - int startYear = 0; - int startMinute = 527040; - String startDateTime = dataFrame.get(START_DATE_TIME).asText(); - try { - ZonedDateTime zonedDateTime = DateTimeUtils.isoDateTime(startDateTime); - startYear = zonedDateTime.getYear(); - startMinute = (int) ChronoUnit.MINUTES.between(DateTimeUtils.isoDateTime(startYear, 1, 1, 0, 0, 0, 0), zonedDateTime); - } catch (Exception e) { - logger.error("Failed to startDateTime {}, defaulting to unknown value {}.", startDateTime, startMinute); - } - - dataFrame.put("startYear", startYear); - dataFrame.put("startTime", startMinute); - dataFrame.remove(START_DATE_TIME); + dataFrame.put("startYear", startYear); + dataFrame.put("startTime", startMinute); + dataFrame.remove(START_DATE_TIME); + } + + /** + * Replaces content. + * + * @param dataFrame ObjectNode representing the data frame + */ + public static void replaceContent(ObjectNode dataFrame) { + + // EXPECTED OUTPUT: + /////// + // + // + // + // + // 513 + // + // + // + // + + // EXPECTED INPUT: + //////// + // "content": "advisory", + // "items":["513", "Text you need to send", "'1234567'", "255"]}, + + // step 1, reformat item list + ArrayNode items = (ArrayNode) dataFrame.get("items"); + ArrayNode newItems = JsonUtils.newNode().arrayNode(); + if (items.isArray()) { + // take the array of ITIScodesAndText items and transform it into + // schema-appropriate array + + Iterator itemsIter = items.elements(); + + while (itemsIter.hasNext()) { + JsonNode curItem = itemsIter.next(); + newItems.add(buildItem(curItem.asText())); + } } - /** - * Replaces content. - * - * @param dataFrame ObjectNode representing the data frame - */ - public static void replaceContent(ObjectNode dataFrame) { - - // EXPECTED OUTPUT: - /////// - // - // - // - // - // 513 - // - // - // - // - - // EXPECTED INPUT: - //////// - // "content": "advisory", - // "items":["513", "Text you need to send", "'1234567'", "255"]}, - - // step 1, reformat item list - ArrayNode items = (ArrayNode) dataFrame.get("items"); - ArrayNode newItems = JsonUtils.newNode().arrayNode(); - if (items.isArray()) { - // take the array of ITIScodesAndText items and transform it into - // schema-appropriate array - - Iterator itemsIter = items.elements(); - - while (itemsIter.hasNext()) { - JsonNode curItem = itemsIter.next(); - newItems.add(buildItem(curItem.asText())); - } - } + JsonNode sequence = JsonUtils.newNode().set(SEQUENCE_STRING, newItems); - JsonNode sequence = JsonUtils.newNode().set(SEQUENCE_STRING, newItems); + dataFrame.remove("items"); - dataFrame.remove("items"); - - // step 2, set the content CHOICE - String replacedContentName = dataFrame.get("content").asText(); - if (replacedContentName.equals("Advisory")) { - replacedContentName = "advisory"; - } - - // The following field is called "content" but this results in a - // failed conversion to XML - // see @us.dot.its.jpo.ode.traveler.TimController.publish - dataFrame.set(TCONTENT_STRING, JsonUtils.newNode().set(replacedContentName, sequence)); - dataFrame.remove("content"); + // step 2, set the content CHOICE + String replacedContentName = dataFrame.get("content").asText(); + if (replacedContentName.equals("Advisory")) { + replacedContentName = "advisory"; } - /** - * Builds an item. - * - * @param itemStr String representing the item - * @return JsonNode representing the item - */ - public static JsonNode buildItem(String itemStr) { - JsonNode item = null; - // check to see if it is an itis code or text - try { - item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(ITIS, Integer.valueOf(itemStr))); - // it's a number, so create "itis" code - } catch (NumberFormatException e) { - // it's not a number, so create "text" - if (itemStr.startsWith("'")) { - item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr.substring(1))); - } else { - item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr)); - } - } - - return item; + // The following field is called "content" but this results in a + // failed conversion to XML + // see @us.dot.its.jpo.ode.traveler.TimController.publish + dataFrame.set(TCONTENT_STRING, JsonUtils.newNode().set(replacedContentName, sequence)); + dataFrame.remove("content"); + } + + /** + * Builds an item. + * + * @param itemStr String representing the item + * @return JsonNode representing the item + */ + public static JsonNode buildItem(String itemStr) { + JsonNode item = null; + // check to see if it is an itis code or text + try { + item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(ITIS, Integer.valueOf(itemStr))); + // it's a number, so create "itis" code + } catch (NumberFormatException e) { + // it's not a number, so create "text" + if (itemStr.startsWith("'")) { + item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr.substring(1))); + } else { + item = JsonUtils.newNode().set(ITEM, JsonUtils.newNode().put(TEXT, itemStr)); + } } - /** - * Replaces msg id. - * - * @param dataFrame ObjectNode representing the data frame - */ - public static void replaceMsgId(ObjectNode dataFrame) { - - // - // - // - // 416784730 - // -1087827750 - // 9171 - // - // 0101010101010100 - // - // - // - // 0000 - // - // - - JsonNode msgId = dataFrame.get("msgId"); - if (msgId != null) { - ObjectNode roadSignID = (ObjectNode) msgId.get("roadSignID"); - if (roadSignID != null) { - - DsrcPosition3D position = Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(roadSignID.get(POSITION))); - - roadSignID.putPOJO(POSITION, position); - - // mutcdCode is optional - JsonNode mutcdNode = roadSignID.get("mutcdCode"); - if (mutcdNode != null) { - roadSignID.set("mutcdCode", JsonUtils.newNode().put(mutcdNode.asText(), EMPTY_FIELD_FLAG)); - } - } + return item; + } + + /** + * Replaces msg id. + * + * @param dataFrame ObjectNode representing the data frame + */ + public static void replaceMsgId(ObjectNode dataFrame) { + + // + // + // + // 416784730 + // -1087827750 + // 9171 + // + // 0101010101010100 + // + // + // + // 0000 + // + // + + JsonNode msgId = dataFrame.get("msgId"); + if (msgId != null) { + ObjectNode roadSignID = (ObjectNode) msgId.get("roadSignID"); + if (roadSignID != null) { + + DsrcPosition3D position = Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(roadSignID.get(POSITION))); + + roadSignID.putPOJO(POSITION, position); + + // mutcdCode is optional + JsonNode mutcdNode = roadSignID.get("mutcdCode"); + if (mutcdNode != null) { + roadSignID.set("mutcdCode", JsonUtils.newNode().put(mutcdNode.asText(), EMPTY_FIELD_FLAG)); } + } } - - /** - * Transforms regions. - * - * @param regions JsonNode representing the regions - * @return ObjectNode representing the transformed regions - * @throws JsonUtilsException if there is an issue converting the JsonNode - */ - public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsException { - ArrayNode replacedRegions = JsonUtils.newNode().arrayNode(); - - if (regions.isArray()) { - Iterator regionsIter = regions.elements(); - - while (regionsIter.hasNext()) { - JsonNode curRegion = regionsIter.next(); - replaceRegion((ObjectNode) curRegion); - replacedRegions.add(curRegion); - } - } - - return JsonUtils.newObjectNode(GEOGRAPHICAL_PATH_STRING, replacedRegions); + } + + /** + * Transforms regions. + * + * @param regions JsonNode representing the regions + * @return ObjectNode representing the transformed regions + * @throws JsonUtilsException if there is an issue converting the JsonNode + */ + public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsException { + ArrayNode replacedRegions = JsonUtils.newNode().arrayNode(); + + if (regions.isArray()) { + Iterator regionsIter = regions.elements(); + + while (regionsIter.hasNext()) { + JsonNode curRegion = regionsIter.next(); + replaceRegion((ObjectNode) curRegion); + replacedRegions.add(curRegion); + } } - /** - * Replaces a region. - * - * @param region ObjectNode representing the region - * @throws JsonUtilsException if there is an issue converting the JsonNode - */ - public static void replaceRegion(ObjectNode region) throws JsonUtilsException { - - //// EXPECTED INPUT: - // "name": "Testing TIM", - // "regulatorID": "0", - // "segmentID": "33", - // "anchorPosition": - // "latitude": "41.2500807", - // "longitude": "-111.0093847", - // "elevation": "2020.6969900289998" - // , - // "laneWidth": "7", - // "directionality": "3", - // "closedPath": "false", - // "description": "path", - // "path": {}, - // "direction": "0000000000001010" - - //// EXPECTED OUTPUT: - // - // .Testing TIM - // . - // ..0 - // ..33 - // . - // . - // ..412500807 - // ..-1110093847 - // ..20206 - // . - // .700 - // . - // .. - // . - // . - // .. - // . - // .0000000000010100 - // . - // . - // - - // name does not need to be replaced - - // id optional, consists of segmentID (required) - // and regulatorID (optional) - JsonNode segmentID = region.get(SEGMENT_ID); - if (segmentID != null) { - ObjectNode id = JsonUtils.newNode().put(ID, segmentID.asInt()); - JsonNode regulatorID = region.get(REGULATOR_ID); - if (regulatorID != null) { - id.put(REGION, regulatorID.asInt()); - } - region.set(ID, id); - } - // replace regulatorID and segmentID with id - ObjectNode id = JsonUtils.newNode().put(REGION, region.get(REGULATOR_ID).asInt()).put(ID, region.get(SEGMENT_ID).asInt()); - - region.set(ID, id); - region.remove(REGULATOR_ID); - region.remove(SEGMENT_ID); - - // anchorPosition --> anchor (optional) - JsonNode anchorPos = region.get(ANCHOR_POSITION); - if (anchorPos != null) { - region.set(ANCHOR, JsonUtils.toObjectNode(Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(region.get(ANCHOR_POSITION))).toJson())); - region.remove(ANCHOR_POSITION); - } - - // lane width (optional) - JsonNode laneWidth = region.get(LANE_WIDTH); - if (laneWidth != null) { - region.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); - } - - // directionality (optional) - if (region.has(DIRECTIONALITY)) { - JsonNode directionality = region.get(DIRECTIONALITY); - String enumString = CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); - if (enumString != null) { - region.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); - } - } + return JsonUtils.newObjectNode(GEOGRAPHICAL_PATH_STRING, replacedRegions); + } + + /** + * Replaces a region. + * + * @param region ObjectNode representing the region + * @throws JsonUtilsException if there is an issue converting the JsonNode + */ + public static void replaceRegion(ObjectNode region) throws JsonUtilsException { + + //// EXPECTED INPUT: + // "name": "Testing TIM", + // "regulatorID": "0", + // "segmentID": "33", + // "anchorPosition": + // "latitude": "41.2500807", + // "longitude": "-111.0093847", + // "elevation": "2020.6969900289998" + // , + // "laneWidth": "7", + // "directionality": "3", + // "closedPath": "false", + // "description": "path", + // "path": {}, + // "direction": "0000000000001010" + + //// EXPECTED OUTPUT: + // + // .Testing TIM + // . + // ..0 + // ..33 + // . + // . + // ..412500807 + // ..-1110093847 + // ..20206 + // . + // .700 + // . + // .. + // . + // . + // .. + // . + // .0000000000010100 + // . + // . + // + + // name does not need to be replaced + + // id optional, consists of segmentID (required) + // and regulatorID (optional) + JsonNode segmentID = region.get(SEGMENT_ID); + if (segmentID != null) { + ObjectNode id = JsonUtils.newNode().put(ID, segmentID.asInt()); + JsonNode regulatorID = region.get(REGULATOR_ID); + if (regulatorID != null) { + id.put(REGION, regulatorID.asInt()); + } + region.set(ID, id); + } + // replace regulatorID and segmentID with id + ObjectNode id = JsonUtils.newNode().put(REGION, region.get(REGULATOR_ID).asInt()).put(ID, region.get(SEGMENT_ID).asInt()); + + region.set(ID, id); + region.remove(REGULATOR_ID); + region.remove(SEGMENT_ID); + + // anchorPosition --> anchor (optional) + JsonNode anchorPos = region.get(ANCHOR_POSITION); + if (anchorPos != null) { + region.set(ANCHOR, JsonUtils.toObjectNode(Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(region.get(ANCHOR_POSITION))).toJson())); + region.remove(ANCHOR_POSITION); + } - // closed path (optional) - JsonNode closedPath = region.get(CLOSED_PATH); - if (closedPath != null) { - region.put(CLOSED_PATH, (closedPath.asBoolean() ? BOOLEAN_OBJECT_TRUE : BOOLEAN_OBJECT_FALSE)); - } + // lane width (optional) + JsonNode laneWidth = region.get(LANE_WIDTH); + if (laneWidth != null) { + region.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); + } - // description (optional) - JsonNode descriptionNode = region.get(DESCRIPTION); - if (descriptionNode != null) { - String descriptionType = descriptionNode.asText(); - if (PATH.equals(descriptionType)) { - ObjectNode pathNode = (ObjectNode) region.get(PATH); - replacePath(pathNode); - region.set(DESCRIPTION, JsonUtils.newNode().set(PATH, pathNode)); - } else if (GEOMETRY.equals(descriptionType)) { - ObjectNode newGeometry = (ObjectNode) region.get(GEOMETRY); - replaceGeometry(newGeometry); - region.set(DESCRIPTION, JsonUtils.newNode().set(GEOMETRY, newGeometry)); - } else if (OLD_REGION.equals(descriptionType)) { - ObjectNode newOldRegion = (ObjectNode) region.get(OLD_REGION); - replaceOldRegion(newOldRegion); - region.set(DESCRIPTION, JsonUtils.newNode().set(OLD_REGION, newOldRegion)); - } - region.remove(descriptionType); - } + // directionality (optional) + if (region.has(DIRECTIONALITY)) { + JsonNode directionality = region.get(DIRECTIONALITY); + String enumString = CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); + if (enumString != null) { + region.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); + } } - private static void replacePath(ObjectNode pathNode) { - - //// EXPECTED INPUT: - // "path": - // "scale": "0", - // "type": "ll", - // "nodes": [] - - //// EXPECTED OUTPUT: - // - // .0 - // . - // .. - // ... - // ... - // .. - // . - // - - // zoom does not need to be replaced - String nodeType = pathNode.get(TYPE).asText(); - JsonNode nodes = pathNode.get(NODES); - JsonNode nodeList; - if (LL.equals(nodeType)) { - nodeList = JsonUtils.newNode().set("NodeLL", transformNodeSetLL(nodes)); - pathNode.set(OFFSET, JsonUtils.newNode().set(LL, JsonUtils.newNode().set(NODES, nodeList))); - } else if (XY.equals(nodeType)) { - nodeList = JsonUtils.newNode().set(NODE_XY2, transformNodeSetXY(nodes)); - pathNode.set(OFFSET, JsonUtils.newNode().set(XY, JsonUtils.newNode().set(NODES, nodeList))); - } - pathNode.remove(NODES); - pathNode.remove(TYPE); + // closed path (optional) + JsonNode closedPath = region.get(CLOSED_PATH); + if (closedPath != null) { + region.put(CLOSED_PATH, (closedPath.asBoolean() ? BOOLEAN_OBJECT_TRUE : BOOLEAN_OBJECT_FALSE)); + } + // description (optional) + JsonNode descriptionNode = region.get(DESCRIPTION); + if (descriptionNode != null) { + String descriptionType = descriptionNode.asText(); + if (PATH.equals(descriptionType)) { + ObjectNode pathNode = (ObjectNode) region.get(PATH); + replacePath(pathNode); + region.set(DESCRIPTION, JsonUtils.newNode().set(PATH, pathNode)); + } else if (GEOMETRY.equals(descriptionType)) { + ObjectNode newGeometry = (ObjectNode) region.get(GEOMETRY); + replaceGeometry(newGeometry); + region.set(DESCRIPTION, JsonUtils.newNode().set(GEOMETRY, newGeometry)); + } else if (OLD_REGION.equals(descriptionType)) { + ObjectNode newOldRegion = (ObjectNode) region.get(OLD_REGION); + replaceOldRegion(newOldRegion); + region.set(DESCRIPTION, JsonUtils.newNode().set(OLD_REGION, newOldRegion)); + } + region.remove(descriptionType); + } + } + + private static void replacePath(ObjectNode pathNode) { + + //// EXPECTED INPUT: + // "path": + // "scale": "0", + // "type": "ll", + // "nodes": [] + + //// EXPECTED OUTPUT: + // + // .0 + // . + // .. + // ... + // ... + // .. + // . + // + + // zoom does not need to be replaced + String nodeType = pathNode.get(TYPE).asText(); + JsonNode nodes = pathNode.get(NODES); + JsonNode nodeList; + if (LL.equals(nodeType)) { + nodeList = JsonUtils.newNode().set("NodeLL", transformNodeSetLL(nodes)); + pathNode.set(OFFSET, JsonUtils.newNode().set(LL, JsonUtils.newNode().set(NODES, nodeList))); + } else if (XY.equals(nodeType)) { + nodeList = JsonUtils.newNode().set(NODE_XY2, transformNodeSetXY(nodes)); + pathNode.set(OFFSET, JsonUtils.newNode().set(XY, JsonUtils.newNode().set(NODES, nodeList))); } + pathNode.remove(NODES); + pathNode.remove(TYPE); - private static ArrayNode transformNodeSetLL(JsonNode nodes) { + } - //// EXPECTED INPUT: - // "nodes": [] + private static ArrayNode transformNodeSetLL(JsonNode nodes) { - // EXPECTED OUTPUT: - // - // . - // . - // . - // . - // + //// EXPECTED INPUT: + // "nodes": [] - ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); + // EXPECTED OUTPUT: + // + // . + // . + // . + // . + // - if (nodes.isArray()) { - Iterator nodeListIter = nodes.elements(); + ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); - while (nodeListIter.hasNext()) { - JsonNode inputNode = nodeListIter.next(); - outputNodeList.add(transformNodeLL(inputNode)); - } - } + if (nodes.isArray()) { + Iterator nodeListIter = nodes.elements(); - return outputNodeList; + while (nodeListIter.hasNext()) { + JsonNode inputNode = nodeListIter.next(); + outputNodeList.add(transformNodeLL(inputNode)); + } } - public static ObjectNode transformNodeLL(JsonNode oldNode) { - - //// EXPECTED INPUT: - - // "nodeLong": "0.0031024", - // "nodeLat": "0.0014506", - // "delta": "node-LL3" - - //// EXPECTED OUTPUT: - // - // . - // .. - // ...14506 - // ...31024 - // .. - // . - // - - BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); - BigDecimal longOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); - JsonNode delta = oldNode.get(DELTA); - Long transformedLat = null; - Long transformedLong = null; - - ObjectNode innerNode = JsonUtils.newNode(); - ObjectNode latLong = JsonUtils.newNode(); - String deltaText = delta.asText(); - if (deltaText.startsWith("node-LL")) { - transformedLat = OffsetLLBuilder.offsetLL(latOffset); - transformedLong = OffsetLLBuilder.offsetLL(longOffset); - if (deltaText.equals("node-LL")) { - deltaText = determineNodeOffsetPointLLType(transformedLat, transformedLong); - } - } else if (NODE_LAT_LON.equals(deltaText)) { - transformedLat = LatitudeBuilder.j2735Latitude(latOffset); - transformedLong = LongitudeBuilder.j2735Longitude(longOffset); - } - - innerNode.set(deltaText, latLong); - latLong.put(LAT, transformedLat).put(LON, transformedLong); - return JsonUtils.newNode().set(DELTA, innerNode); + return outputNodeList; + } + + public static ObjectNode transformNodeLL(JsonNode oldNode) { + + //// EXPECTED INPUT: + + // "nodeLong": "0.0031024", + // "nodeLat": "0.0014506", + // "delta": "node-LL3" + + //// EXPECTED OUTPUT: + // + // . + // .. + // ...14506 + // ...31024 + // .. + // . + // + + BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); + BigDecimal longOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); + JsonNode delta = oldNode.get(DELTA); + Long transformedLat = null; + Long transformedLong = null; + + ObjectNode innerNode = JsonUtils.newNode(); + ObjectNode latLong = JsonUtils.newNode(); + String deltaText = delta.asText(); + if (deltaText.startsWith("node-LL")) { + transformedLat = OffsetLLBuilder.offsetLL(latOffset); + transformedLong = OffsetLLBuilder.offsetLL(longOffset); + if (deltaText.equals("node-LL")) { + deltaText = determineNodeOffsetPointLLType(transformedLat, transformedLong); + } + } else if (NODE_LAT_LON.equals(deltaText)) { + transformedLat = LatitudeBuilder.j2735Latitude(latOffset); + transformedLong = LongitudeBuilder.j2735Longitude(longOffset); } - // -- Nodes with LL content Span at the equator when using a zoom of one: - public static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node - public static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node - public static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node - public static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node - public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node - public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node - - // -- Limits for each node type - public final static long NODE_LL1_LIMIT = 2047; - public final static long NODE_LL2_LIMIT = 8191; - public final static long NODE_LL3_LIMIT = 32767; - public final static long NODE_LL4_LIMIT = 131071; - public final static long NODE_LL5_LIMIT = 2097151; - public final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. - - /** - * Determines the node offset point LL type based on the latitude and longitude deltas. - * The method evaluates the absolute values of the deltas against predefined limits to determine - * the appropriate node type. If the deltas do not fit within any allowed ranges, an exception - * is thrown. - * - * @param latDelta The latitude delta as a long value. - * @param lonDelta The longitude delta as a long value. - * @return A string representing the node offset point LL type (e.g., NODE_LL1, NODE_LL2, etc.). - * @throws IllegalArgumentException if latDelta or lonDelta are outside the permissible range - * of -0.8388608 to +0.8388607 degrees. - */ - public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { - long absLatDelta = Math.abs(latDelta); - long absLonDelta = Math.abs(lonDelta); - - if (absLatDelta <= NODE_LL1_LIMIT && absLonDelta <= NODE_LL1_LIMIT) { - return NODE_LL1; - } else if (absLatDelta <= NODE_LL2_LIMIT && absLonDelta <= NODE_LL2_LIMIT) { - return NODE_LL2; - } else if (absLatDelta <= NODE_LL3_LIMIT && absLonDelta <= NODE_LL3_LIMIT) { - return NODE_LL3; - } else if (absLatDelta <= NODE_LL4_LIMIT && absLonDelta <= NODE_LL4_LIMIT) { - return NODE_LL4; - } else if (absLatDelta <= NODE_LL5_LIMIT && absLonDelta <= NODE_LL5_LIMIT) { - return NODE_LL5; - } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { - return NODE_LL6; - } else { - throw new IllegalArgumentException("Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); - } + innerNode.set(deltaText, latLong); + latLong.put(LAT, transformedLat).put(LON, transformedLong); + return JsonUtils.newNode().set(DELTA, innerNode); + } + + // -- Nodes with LL content Span at the equator when using a zoom of one: + public static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node + public static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node + public static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node + public static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node + public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node + public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node + + // -- Limits for each node type + public final static long NODE_LL1_LIMIT = 2047; + public final static long NODE_LL2_LIMIT = 8191; + public final static long NODE_LL3_LIMIT = 32767; + public final static long NODE_LL4_LIMIT = 131071; + public final static long NODE_LL5_LIMIT = 2097151; + public final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. + + /** + * Determines the node offset point LL type based on the latitude and longitude deltas. + * The method evaluates the absolute values of the deltas against predefined limits to determine + * the appropriate node type. If the deltas do not fit within any allowed ranges, an exception + * is thrown. + * + * @param latDelta The latitude delta as a long value. + * @param lonDelta The longitude delta as a long value. + * @return A string representing the node offset point LL type (e.g., NODE_LL1, NODE_LL2, etc.). + * @throws IllegalArgumentException if latDelta or lonDelta are outside the permissible range + * of -0.8388608 to +0.8388607 degrees. + */ + public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { + long absLatDelta = Math.abs(latDelta); + long absLonDelta = Math.abs(lonDelta); + + if (absLatDelta <= NODE_LL1_LIMIT && absLonDelta <= NODE_LL1_LIMIT) { + return NODE_LL1; + } else if (absLatDelta <= NODE_LL2_LIMIT && absLonDelta <= NODE_LL2_LIMIT) { + return NODE_LL2; + } else if (absLatDelta <= NODE_LL3_LIMIT && absLonDelta <= NODE_LL3_LIMIT) { + return NODE_LL3; + } else if (absLatDelta <= NODE_LL4_LIMIT && absLonDelta <= NODE_LL4_LIMIT) { + return NODE_LL4; + } else if (absLatDelta <= NODE_LL5_LIMIT && absLonDelta <= NODE_LL5_LIMIT) { + return NODE_LL5; + } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { + return NODE_LL6; + } else { + throw new IllegalArgumentException("Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); } + } - /** - * Replaces geometry. - * - * @param geometry ObjectNode representing the geometry - */ - public static void replaceGeometry(ObjectNode geometry) { + /** + * Replaces geometry. + * + * @param geometry ObjectNode representing the geometry + */ + public static void replaceGeometry(ObjectNode geometry) { - // direction HeadingSlice - // extent Extent OPTIONAL - // laneWidth LaneWidth OPTIONAL - // circle Circle + // direction HeadingSlice + // extent Extent OPTIONAL + // laneWidth LaneWidth OPTIONAL + // circle Circle - // direction does not need to be replaced + // direction does not need to be replaced - // extent does not need to be replaced (optional) + // extent does not need to be replaced (optional) - // replace lane width - JsonNode laneWidth = geometry.get(LANE_WIDTH); - if (laneWidth != null) { - geometry.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); - } - - // replace circle - replaceCircle(geometry.get(CIRCLE)); + // replace lane width + JsonNode laneWidth = geometry.get(LANE_WIDTH); + if (laneWidth != null) { + geometry.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(laneWidth))); } - /** - * Replaces old region. - * - * @param oldRegion ObjectNode representing the old region - */ - public static void replaceOldRegion(ObjectNode oldRegion) { - - // old region == ValidRegion - // elements: - // direction - no changes - - // extent - no changes - JsonNode extentNode = oldRegion.get(EXTENT); - String extent = CommonUtils.enumToString(Extent.ExtentEnum.class, extentNode.asText()); - oldRegion.set(EXTENT, JsonUtils.newNode().put(extent, EMPTY_FIELD_FLAG)); - - // area - needs changes - replaceArea(oldRegion.get("area")); + // replace circle + replaceCircle(geometry.get(CIRCLE)); + } + + /** + * Replaces old region. + * + * @param oldRegion ObjectNode representing the old region + */ + public static void replaceOldRegion(ObjectNode oldRegion) { + + // old region == ValidRegion + // elements: + // direction - no changes + + // extent - no changes + JsonNode extentNode = oldRegion.get(EXTENT); + String extent = CommonUtils.enumToString(Extent.ExtentEnum.class, extentNode.asText()); + oldRegion.set(EXTENT, JsonUtils.newNode().put(extent, EMPTY_FIELD_FLAG)); + + // area - needs changes + replaceArea(oldRegion.get("area")); + } + + /** + * Replaces area. + * + * @param area JsonNode representing the area + */ + public static void replaceArea(JsonNode area) { + + // area contains one of: + // shapePointSet + // circle + // regionPointSet + + ObjectNode updatedNode = (ObjectNode) area; + + if (updatedNode.has(SHAPE_POINT_SET)) { + JsonNode shapePointSet = updatedNode.get(SHAPE_POINT_SET); + replaceShapePointSet(shapePointSet); + updatedNode.set(SHAPE_POINT_SET, shapePointSet); + } else if (updatedNode.has(CIRCLE)) { + replaceCircle(updatedNode.get(CIRCLE)); + } else if (updatedNode.has(REGION_POINT_SET)) { + replaceRegionPointSet(updatedNode.get(REGION_POINT_SET)); } - - /** - * Replaces area. - * - * @param area JsonNode representing the area - */ - public static void replaceArea(JsonNode area) { - - // area contains one of: - // shapePointSet - // circle - // regionPointSet - - ObjectNode updatedNode = (ObjectNode) area; - - if (updatedNode.has(SHAPE_POINT_SET)) { - JsonNode shapePointSet = updatedNode.get(SHAPE_POINT_SET); - replaceShapePointSet(shapePointSet); - updatedNode.set(SHAPE_POINT_SET, shapePointSet); - } else if (updatedNode.has(CIRCLE)) { - replaceCircle(updatedNode.get(CIRCLE)); - } else if (updatedNode.has(REGION_POINT_SET)) { - replaceRegionPointSet(updatedNode.get(REGION_POINT_SET)); - } + } + + private static void replaceRegionPointSet(JsonNode regionPointSet) { + // regionPointSet contains: + // anchor + // zoom + // nodeList (regionList) + ObjectNode updatedNode = (ObjectNode) regionPointSet; + + // replace anchor (optional) + if (updatedNode.get(ANCHOR_POSITION) != null) { + JsonUtils.addNode(updatedNode, ANCHOR, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR_POSITION)))); + updatedNode.remove(ANCHOR_POSITION); } - private static void replaceRegionPointSet(JsonNode regionPointSet) { - // regionPointSet contains: - // anchor - // zoom - // nodeList (regionList) - ObjectNode updatedNode = (ObjectNode) regionPointSet; - - // replace anchor (optional) - if (updatedNode.get(ANCHOR_POSITION) != null) { - JsonUtils.addNode(updatedNode, ANCHOR, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR_POSITION)))); - updatedNode.remove(ANCHOR_POSITION); - } + // zoom doesn't need replacement (also optional) - // zoom doesn't need replacement (also optional) + // regionList is good as is and does not need replacement (required) + } - // regionList is good as is and does not need replacement (required) - } - - /** - * Replaces circle. - * - * @param circle JsonNode representing the circle - */ - public static void replaceCircle(JsonNode circle) { - - // Circle ::= SEQUENCE - // center Position3D, - // radius Radius-B12, - // units DistanceUnits - - ObjectNode updatedNode = (ObjectNode) circle; - - JsonNode centerPosition = null; - if (updatedNode.has(POSITION)) { - centerPosition = updatedNode.get(POSITION); - updatedNode.remove(POSITION); - } else { - centerPosition = updatedNode.get(CENTER); - } + /** + * Replaces circle. + * + * @param circle JsonNode representing the circle + */ + public static void replaceCircle(JsonNode circle) { - // replace center - JsonUtils.addNode(updatedNode, CENTER, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(centerPosition))); + // Circle ::= SEQUENCE + // center Position3D, + // radius Radius-B12, + // units DistanceUnits - // radius does not need replacement + ObjectNode updatedNode = (ObjectNode) circle; - // replace units - if (updatedNode.has(UNITS)) { - JsonNode units = updatedNode.get(UNITS); - String enumString = CommonUtils.enumToString(DistanceUnitsEnum.class, units.asText()); - if (enumString != null) { - updatedNode.set(UNITS, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); - } - } + JsonNode centerPosition = null; + if (updatedNode.has(POSITION)) { + centerPosition = updatedNode.get(POSITION); + updatedNode.remove(POSITION); + } else { + centerPosition = updatedNode.get(CENTER); } - /** - * Replaces shape point set. - * - * @param shapePointSet JsonNode representing the shape point set - */ - public static void replaceShapePointSet(JsonNode shapePointSet) { - // shape point set contains: - // anchor - // lane width - // directionality - // node list - - ObjectNode updatedNode = (ObjectNode) shapePointSet; - - // replace anchor - if (updatedNode.has(ANCHOR)) { - JsonUtils.addNode(updatedNode, ANCHOR, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR)))); - } + // replace center + JsonUtils.addNode(updatedNode, CENTER, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(centerPosition))); - // replace lane width - if (updatedNode.has(LANE_WIDTH)) { - updatedNode.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(updatedNode.get(LANE_WIDTH)))); - } + // radius does not need replacement - // replace directionality - if (updatedNode.has(DIRECTIONALITY)) { - JsonNode directionality = updatedNode.get(DIRECTIONALITY); - String enumString = CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); - if (enumString != null) { - updatedNode.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); - } - } + // replace units + if (updatedNode.has(UNITS)) { + JsonNode units = updatedNode.get(UNITS); + String enumString = CommonUtils.enumToString(DistanceUnitsEnum.class, units.asText()); + if (enumString != null) { + updatedNode.set(UNITS, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); + } + } + } + + /** + * Replaces shape point set. + * + * @param shapePointSet JsonNode representing the shape point set + */ + public static void replaceShapePointSet(JsonNode shapePointSet) { + // shape point set contains: + // anchor + // lane width + // directionality + // node list + + ObjectNode updatedNode = (ObjectNode) shapePointSet; + + // replace anchor + if (updatedNode.has(ANCHOR)) { + JsonUtils.addNode(updatedNode, ANCHOR, Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(updatedNode.get(ANCHOR)))); + } - // replace node list - if (updatedNode.has(NODE_LIST)) { - ObjectNode nodeList = (ObjectNode) updatedNode.get(NODE_LIST); - if (nodeList.has(NODES)) { - ArrayNode nodes = transformNodeSetXY(nodeList.get(NODES)); - nodeList.set(NODES, nodes); - } else if (nodeList.has(COMPUTED)) { - JsonNode computedLane = nodeList.get(COMPUTED); - replaceComputedLane(computedLane); - } - } + // replace lane width + if (updatedNode.has(LANE_WIDTH)) { + updatedNode.put(LANE_WIDTH, LaneWidthBuilder.laneWidth(JsonUtils.decimalValue(updatedNode.get(LANE_WIDTH)))); } - /** - * Replaces computed lane. - * - * @param jsonNode JsonNode representing the computed lane - */ - public static void replaceComputedLane(JsonNode jsonNode) { - ObjectNode updatedNode = (ObjectNode) jsonNode; + // replace directionality + if (updatedNode.has(DIRECTIONALITY)) { + JsonNode directionality = updatedNode.get(DIRECTIONALITY); + String enumString = CommonUtils.enumToString(DirectionOfUseEnum.class, directionality.asText()); + if (enumString != null) { + updatedNode.set(DIRECTIONALITY, JsonUtils.newNode().put(enumString, EMPTY_FIELD_FLAG)); + } + } - // Nothing to do for referenceLaneId LaneID + // replace node list + if (updatedNode.has(NODE_LIST)) { + ObjectNode nodeList = (ObjectNode) updatedNode.get(NODE_LIST); + if (nodeList.has(NODES)) { + ArrayNode nodes = transformNodeSetXY(nodeList.get(NODES)); + nodeList.set(NODES, nodes); + } else if (nodeList.has(COMPUTED)) { + JsonNode computedLane = nodeList.get(COMPUTED); + replaceComputedLane(computedLane); + } + } + } - // offsetXaxis CHOICE - // small DrivenLineOffsetSm, - // large DrivenLineOffsetLg + /** + * Replaces computed lane. + * + * @param jsonNode JsonNode representing the computed lane + */ + public static void replaceComputedLane(JsonNode jsonNode) { + ObjectNode updatedNode = (ObjectNode) jsonNode; - replaceScale(updatedNode, OFFSET_X_AXIS); + // Nothing to do for referenceLaneId LaneID - // offsetYaxis CHOICE - // small DrivenLineOffsetSm, - // large DrivenLineOffsetLg + // offsetXaxis CHOICE + // small DrivenLineOffsetSm, + // large DrivenLineOffsetLg - replaceScale(updatedNode, OFFSET_Y_AXIS); + replaceScale(updatedNode, OFFSET_X_AXIS); - // rotateXY Angle OPTIONAL - if (updatedNode.has(ROTATE_XY)) { - updatedNode.put(ROTATE_XY, AngleBuilder.angle(JsonUtils.decimalValue(updatedNode.get(ROTATE_XY)))); - } + // offsetYaxis CHOICE + // small DrivenLineOffsetSm, + // large DrivenLineOffsetLg - // scaleXaxis Scale-B12 OPTIONAL - if (updatedNode.has(SCALE_X_AXIS)) { - updatedNode.put(SCALE_X_AXIS, ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_X_AXIS)))); - } + replaceScale(updatedNode, OFFSET_Y_AXIS); - // scaleYaxis Scale-B12 OPTIONAL - if (updatedNode.has(SCALE_Y_AXIS)) { - updatedNode.put(SCALE_Y_AXIS, ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_Y_AXIS)))); - } + // rotateXY Angle OPTIONAL + if (updatedNode.has(ROTATE_XY)) { + updatedNode.put(ROTATE_XY, AngleBuilder.angle(JsonUtils.decimalValue(updatedNode.get(ROTATE_XY)))); } - /** - * Replaces scale. - * - * @param updatedNode ObjectNode representing the updated node - * @param scale String representing the scale - */ - public static void replaceScale(ObjectNode updatedNode, String scale) { - if (updatedNode.has(scale)) { - int scaleX = updatedNode.get(scale).asInt(); - String key = "large"; - if (-2048 <= scaleX && scaleX <= 2047) { - key = "small"; - } - - ObjectNode node = JsonUtils.newObjectNode(key, scaleX); - updatedNode.set(scale, node); - } + // scaleXaxis Scale-B12 OPTIONAL + if (updatedNode.has(SCALE_X_AXIS)) { + updatedNode.put(SCALE_X_AXIS, ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_X_AXIS)))); } - /** - * Transforms node set XY. - * - * @param inputNodeList JsonNode representing the input node list - * @return ArrayNode representing the transformed node list - */ - public static ArrayNode transformNodeSetXY(JsonNode inputNodeList) { - - //// EXPECTED INPUT: - // "nodes": [] - - // EXPECTED OUTPUT: - // - // . - // . - // . - // . - // - - ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); - - if (inputNodeList.isArray()) { - Iterator nodeListIter = inputNodeList.elements(); - - while (nodeListIter.hasNext()) { - JsonNode inputNode = nodeListIter.next(); - outputNodeList.add(transformNodeXY(inputNode)); - } - } - - return outputNodeList; + // scaleYaxis Scale-B12 OPTIONAL + if (updatedNode.has(SCALE_Y_AXIS)) { + updatedNode.put(SCALE_Y_AXIS, ScaleB12Builder.scaleB12(JsonUtils.decimalValue(updatedNode.get(SCALE_Y_AXIS)))); + } + } + + /** + * Replaces scale. + * + * @param updatedNode ObjectNode representing the updated node + * @param scale String representing the scale + */ + public static void replaceScale(ObjectNode updatedNode, String scale) { + if (updatedNode.has(scale)) { + int scaleX = updatedNode.get(scale).asInt(); + String key = "large"; + if (-2048 <= scaleX && scaleX <= 2047) { + key = "small"; + } + + ObjectNode node = JsonUtils.newObjectNode(key, scaleX); + updatedNode.set(scale, node); + } + } + + /** + * Transforms node set XY. + * + * @param inputNodeList JsonNode representing the input node list + * @return ArrayNode representing the transformed node list + */ + public static ArrayNode transformNodeSetXY(JsonNode inputNodeList) { + + //// EXPECTED INPUT: + // "nodes": [] + + // EXPECTED OUTPUT: + // + // . + // . + // . + // . + // + + ArrayNode outputNodeList = JsonUtils.newNode().arrayNode(); + + if (inputNodeList.isArray()) { + Iterator nodeListIter = inputNodeList.elements(); + + while (nodeListIter.hasNext()) { + JsonNode inputNode = nodeListIter.next(); + outputNodeList.add(transformNodeXY(inputNode)); + } } - /** - * Transformed a NodeXY. - * - * @param oldNode JsonNode representing the old node - * @return ObjectNode representing the transformed node - */ - public static JsonNode transformNodeXY(JsonNode oldNode) { + return outputNodeList; + } - // nodexy contains: - // delta NodeOffsetPointXY - // attributes NodeAttributeSetXY (optional) + /** + * Transformed a NodeXY. + * + * @param oldNode JsonNode representing the old node + * @return ObjectNode representing the transformed node + */ + public static JsonNode transformNodeXY(JsonNode oldNode) { - ObjectNode nodexy = transformNodeOffsetPointXY(oldNode); + // nodexy contains: + // delta NodeOffsetPointXY + // attributes NodeAttributeSetXY (optional) - if (oldNode.has(ATTRIBUTES)) { - nodexy.set(ATTRIBUTES, transformNodeAttributeSetXY(oldNode.get(ATTRIBUTES))); - } + ObjectNode nodexy = transformNodeOffsetPointXY(oldNode); - return nodexy; + if (oldNode.has(ATTRIBUTES)) { + nodexy.set(ATTRIBUTES, transformNodeAttributeSetXY(oldNode.get(ATTRIBUTES))); } - private static ObjectNode transformNodeAttributeSetXY(JsonNode jsonNode) { - // localNode NodeAttributeXYList OPTIONAL, - // disabled SegmentAttributeXYList OPTIONAL, - // enabled SegmentAttributeXYList OPTIONAL, - // data LaneDataAttributeList OPTIONAL, - // dWidth Offset-B10 OPTIONAL, - // dElevation Offset-B10 OPTIONAL, + return nodexy; + } - ObjectNode updatedNode = JsonUtils.newNode(); + private static ObjectNode transformNodeAttributeSetXY(JsonNode jsonNode) { + // localNode NodeAttributeXYList OPTIONAL, + // disabled SegmentAttributeXYList OPTIONAL, + // enabled SegmentAttributeXYList OPTIONAL, + // data LaneDataAttributeList OPTIONAL, + // dWidth Offset-B10 OPTIONAL, + // dElevation Offset-B10 OPTIONAL, - // localNode NodeAttributeXYList does not need to be replaced + ObjectNode updatedNode = JsonUtils.newNode(); - // disabled SegmentAttributeXYList does not need to be replaced - // enabled SegmentAttributeXYList does not need to be replaced + // localNode NodeAttributeXYList does not need to be replaced - if (jsonNode.has(DATA)) { - updatedNode.set(DATA, transformLaneDataAttributeList(jsonNode.get(DATA))); - } - if (jsonNode.has(D_WIDTH)) { - updatedNode.put(D_WIDTH, OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_WIDTH)))); - } + // disabled SegmentAttributeXYList does not need to be replaced + // enabled SegmentAttributeXYList does not need to be replaced - if (jsonNode.has(D_ELEVATION)) { - updatedNode.put(D_ELEVATION, OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_ELEVATION)))); - } - return updatedNode; + if (jsonNode.has(DATA)) { + updatedNode.set(DATA, transformLaneDataAttributeList(jsonNode.get(DATA))); } - - private static ArrayNode transformLaneDataAttributeList(JsonNode laneDataAttribute) { - - ArrayNode updatedLaneDataAttributeList = JsonUtils.newNode().arrayNode(); - - if (laneDataAttribute.isArray()) { - Iterator laneDataAttributeListIter = laneDataAttribute.elements(); - - while (laneDataAttributeListIter.hasNext()) { - JsonNode oldNode = laneDataAttributeListIter.next(); - replaceLaneDataAttribute(oldNode); - updatedLaneDataAttributeList.add(oldNode); - } - } - return updatedLaneDataAttributeList; + if (jsonNode.has(D_WIDTH)) { + updatedNode.put(D_WIDTH, OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_WIDTH)))); } - /** - * Replaces lane data attribute. - * - * @param oldNode JsonNode representing the old node - */ - public static void replaceLaneDataAttribute(JsonNode oldNode) { - // choice between 1 of the following: - // pathEndPointAngle DeltaAngle - // laneCrownPointCenter RoadwayCrownAngle - // laneCrownPointLeft RoadwayCrownAngle - // laneCrownPointRight RoadwayCrownAngle - // laneAngle MergeDivergeNodeAngle - // speedLimits SpeedLimitList - - ObjectNode updatedNode = (ObjectNode) oldNode; - - // pathEndPointAngle DeltaAngle does not need to be replaced - if (oldNode.has("pathEndPointAngle")) { - // do nothing - } else if (oldNode.has(LANE_CROWN_POINT_CENTER)) { - updatedNode.put(LANE_CROWN_POINT_CENTER, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_CENTER)))); - } else if (oldNode.has(LANE_CROWN_POINT_LEFT)) { - updatedNode.put(LANE_CROWN_POINT_LEFT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_LEFT)))); - } else if (oldNode.has(LANE_CROWN_POINT_RIGHT)) { - updatedNode.put(LANE_CROWN_POINT_RIGHT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_RIGHT)))); - } else if (oldNode.has(LANE_ANGLE)) { - updatedNode.put(LANE_ANGLE, MergeDivergeNodeAngleBuilder.mergeDivergeNodeAngle(JsonUtils.decimalValue(updatedNode.get(LANE_ANGLE)))); - } else if (oldNode.has(SPEED_LIMITS)) { - replaceSpeedLimitList(updatedNode.get(SPEED_LIMITS)); - } + if (jsonNode.has(D_ELEVATION)) { + updatedNode.put(D_ELEVATION, OffsetXyBuilder.offsetXy(JsonUtils.decimalValue(jsonNode.get(D_ELEVATION)))); } + return updatedNode; + } - private static void replaceSpeedLimitList(JsonNode speedLimitList) { + private static ArrayNode transformLaneDataAttributeList(JsonNode laneDataAttribute) { - if (speedLimitList.isArray()) { - Iterator speedLimitListIter = speedLimitList.elements(); + ArrayNode updatedLaneDataAttributeList = JsonUtils.newNode().arrayNode(); - while (speedLimitListIter.hasNext()) { - JsonNode oldNode = speedLimitListIter.next(); - replaceRegulatorySpeedLimit(oldNode); - } - } - } + if (laneDataAttribute.isArray()) { + Iterator laneDataAttributeListIter = laneDataAttribute.elements(); - private static void replaceRegulatorySpeedLimit(JsonNode regulatorySpeedLimitNode) { - // contains: - // type SpeedLimitType - // speed Velocity - - ObjectNode updatedNode = (ObjectNode) regulatorySpeedLimitNode; + while (laneDataAttributeListIter.hasNext()) { + JsonNode oldNode = laneDataAttributeListIter.next(); + replaceLaneDataAttribute(oldNode); + updatedLaneDataAttributeList.add(oldNode); + } + } + return updatedLaneDataAttributeList; + } + + /** + * Replaces lane data attribute. + * + * @param oldNode JsonNode representing the old node + */ + public static void replaceLaneDataAttribute(JsonNode oldNode) { + // choice between 1 of the following: + // pathEndPointAngle DeltaAngle + // laneCrownPointCenter RoadwayCrownAngle + // laneCrownPointLeft RoadwayCrownAngle + // laneCrownPointRight RoadwayCrownAngle + // laneAngle MergeDivergeNodeAngle + // speedLimits SpeedLimitList + + ObjectNode updatedNode = (ObjectNode) oldNode; + + // pathEndPointAngle DeltaAngle does not need to be replaced + if (oldNode.has("pathEndPointAngle")) { + // do nothing + } else if (oldNode.has(LANE_CROWN_POINT_CENTER)) { + updatedNode.put(LANE_CROWN_POINT_CENTER, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_CENTER)))); + } else if (oldNode.has(LANE_CROWN_POINT_LEFT)) { + updatedNode.put(LANE_CROWN_POINT_LEFT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_LEFT)))); + } else if (oldNode.has(LANE_CROWN_POINT_RIGHT)) { + updatedNode.put(LANE_CROWN_POINT_RIGHT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_RIGHT)))); + } else if (oldNode.has(LANE_ANGLE)) { + updatedNode.put(LANE_ANGLE, MergeDivergeNodeAngleBuilder.mergeDivergeNodeAngle(JsonUtils.decimalValue(updatedNode.get(LANE_ANGLE)))); + } else if (oldNode.has(SPEED_LIMITS)) { + replaceSpeedLimitList(updatedNode.get(SPEED_LIMITS)); + } + } - // type - JsonNode typeNode = regulatorySpeedLimitNode.get(TYPE); - String type = CommonUtils.enumToString(SpeedLimitTypeEnum.class, typeNode.asText()); - if (type != null) { - updatedNode.set(TYPE, JsonUtils.newNode().put(type, EMPTY_FIELD_FLAG)); - } + private static void replaceSpeedLimitList(JsonNode speedLimitList) { - // replace velocity - updatedNode.put(SPEED, VelocityBuilder.velocity(JsonUtils.decimalValue(updatedNode.get(SPEED)))); + if (speedLimitList.isArray()) { + Iterator speedLimitListIter = speedLimitList.elements(); + while (speedLimitListIter.hasNext()) { + JsonNode oldNode = speedLimitListIter.next(); + replaceRegulatorySpeedLimit(oldNode); + } } + } - /** - * Transformed node offset point XY. - * - * @param oldNode JsonNode representing the old node - * @return ObjectNode representing the transformed node - */ - public static ObjectNode transformNodeOffsetPointXY(JsonNode oldNode) { - //// EXPECTED INPUT: - - // "nodeLong": "0.0031024", - // "nodeLat": "0.0014506", - // "delta": "node-LL3" - - //// EXPECTED OUTPUT: - // - // . - // .. - // ...14506 - // ...31024 - // .. - // . - // - - JsonNode delta = oldNode.get(DELTA); - - ObjectNode innerNode = JsonUtils.newNode(); - ObjectNode deltaNode = JsonUtils.newNode(); - String deltaText = delta.asText(); - if (deltaText.startsWith(NODE_XY)) { - BigDecimal offsetX = JsonUtils.decimalValue(oldNode.get(X)); - BigDecimal offsetY = JsonUtils.decimalValue(oldNode.get(Y)); - Long transformedX = OffsetXyBuilder.offsetXy(offsetX); - Long transformedY = OffsetXyBuilder.offsetXy(offsetY); - ObjectNode xy = JsonUtils.newNode().put(X, transformedX).put(Y, transformedY); - if (deltaText.equals(NODE_XY)) { - innerNode.set(nodeOffsetPointXY(transformedX, transformedY), xy); - } else { - innerNode.set(deltaText, xy); - } - } else if (deltaText.startsWith(NODE_LAT_LON)) { - BigDecimal lonOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); - BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); - Long transformedLon = LatitudeBuilder.j2735Latitude(lonOffset); - Long transformedLat = LongitudeBuilder.j2735Longitude(latOffset); - ObjectNode latLong = JsonUtils.newNode().put(LON, transformedLon).put(LAT, transformedLat); - innerNode.set(deltaText, latLong); - } - - deltaNode.set(DELTA, innerNode); + private static void replaceRegulatorySpeedLimit(JsonNode regulatorySpeedLimitNode) { + // contains: + // type SpeedLimitType + // speed Velocity - return deltaNode; + ObjectNode updatedNode = (ObjectNode) regulatorySpeedLimitNode; + // type + JsonNode typeNode = regulatorySpeedLimitNode.get(TYPE); + String type = CommonUtils.enumToString(SpeedLimitTypeEnum.class, typeNode.asText()); + if (type != null) { + updatedNode.set(TYPE, JsonUtils.newNode().put(type, EMPTY_FIELD_FLAG)); } - // NodeOffsetPointXY contains one of: - // node-XY1 Node-XY-20b, -- node is within 5.11m of last node - // node-XY2 Node-XY-22b, -- node is within 10.23m of last node - // node-XY3 Node-XY-24b, -- node is within 20.47m of last node - // node-XY4 Node-XY-26b, -- node is within 40.96m of last node - // node-XY5 Node-XY-28b, -- node is within 81.91m of last node - // node-XY6 Node-XY-32b, -- node is within 327.67m of last node - // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range - private static String nodeOffsetPointXY(long transformedX, long transformedY) { - long transformed = Math.abs(transformedX) | Math.abs(transformedY); - if ((transformed & (-1 << 10)) == 0) { - return "node-XY1"; - } else if ((transformed & (-1 << 11)) == 0) { - return "node-XY2"; - } else if ((transformed & (-1 << 12)) == 0) { - return "node-XY3"; - } else if ((transformed & (-1 << 13)) == 0) { - return "node-XY4"; - } else if ((transformed & (-1 << 14)) == 0) { - return "node-XY5"; - } else if ((transformed & (-1 << 16)) == 0) { - return "node-XY6"; - } else { - throw new IllegalArgumentException("Invalid node X/Y offset: " + transformedX + "/" + transformedY + ". Values must be between a range of -327.68/+327.67 meters."); - } + // replace velocity + updatedNode.put(SPEED, VelocityBuilder.velocity(JsonUtils.decimalValue(updatedNode.get(SPEED)))); + + } + + /** + * Transformed node offset point XY. + * + * @param oldNode JsonNode representing the old node + * @return ObjectNode representing the transformed node + */ + public static ObjectNode transformNodeOffsetPointXY(JsonNode oldNode) { + //// EXPECTED INPUT: + + // "nodeLong": "0.0031024", + // "nodeLat": "0.0014506", + // "delta": "node-LL3" + + //// EXPECTED OUTPUT: + // + // . + // .. + // ...14506 + // ...31024 + // .. + // . + // + + JsonNode delta = oldNode.get(DELTA); + + ObjectNode innerNode = JsonUtils.newNode(); + ObjectNode deltaNode = JsonUtils.newNode(); + String deltaText = delta.asText(); + if (deltaText.startsWith(NODE_XY)) { + BigDecimal offsetX = JsonUtils.decimalValue(oldNode.get(X)); + BigDecimal offsetY = JsonUtils.decimalValue(oldNode.get(Y)); + Long transformedX = OffsetXyBuilder.offsetXy(offsetX); + Long transformedY = OffsetXyBuilder.offsetXy(offsetY); + ObjectNode xy = JsonUtils.newNode().put(X, transformedX).put(Y, transformedY); + if (deltaText.equals(NODE_XY)) { + innerNode.set(nodeOffsetPointXY(transformedX, transformedY), xy); + } else { + innerNode.set(deltaText, xy); + } + } else if (deltaText.startsWith(NODE_LAT_LON)) { + BigDecimal lonOffset = JsonUtils.decimalValue(oldNode.get(NODE_LONG)); + BigDecimal latOffset = JsonUtils.decimalValue(oldNode.get(NODE_LAT)); + Long transformedLon = LatitudeBuilder.j2735Latitude(lonOffset); + Long transformedLat = LongitudeBuilder.j2735Longitude(latOffset); + ObjectNode latLong = JsonUtils.newNode().put(LON, transformedLon).put(LAT, transformedLat); + innerNode.set(deltaText, latLong); } - /** - * Ensures compliance with the J2735 2024 standard by checking - * for old fields in the given data frame. - * - * @param dataFrame the JSON object representing the data frame to be checked - * @throws NoncompliantFieldsException if any old fields are found - */ - public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) throws NoncompliantFieldsException { - // Check and throw exception if old fields are found - Set nonCompliantFields = - Set.of(SSP_MSG_CONTENT, SSP_MSG_TYPES, SSP_LOCATION_RIGHTS, SSP_TIM_RIGHTS, SSP_MSG_RIGHTS_1, SSP_MSG_RIGHTS_2, NOT_USED, NOT_USED_1, NOT_USED_2, NOT_USED_3, DURATON_TIME_MISSPELLED); - ArrayList violations = new ArrayList<>(); - for (String violationName : nonCompliantFields) { - if (dataFrame.has(violationName)) { - violations.add(violationName); - } - } - if (!violations.isEmpty()) { - throw new NoncompliantFieldsException( - String.format("Data frame contains the following old fields that are not compliant with " + "J2735 2024: [%s]. Deserialization should prevent this.", violations)); - } + deltaNode.set(DELTA, innerNode); + + return deltaNode; + + } + + // NodeOffsetPointXY contains one of: + // node-XY1 Node-XY-20b, -- node is within 5.11m of last node + // node-XY2 Node-XY-22b, -- node is within 10.23m of last node + // node-XY3 Node-XY-24b, -- node is within 20.47m of last node + // node-XY4 Node-XY-26b, -- node is within 40.96m of last node + // node-XY5 Node-XY-28b, -- node is within 81.91m of last node + // node-XY6 Node-XY-32b, -- node is within 327.67m of last node + // node-LatLon Node-LLmD-64b, -- node is a full 32b Lat/Lon range + private static String nodeOffsetPointXY(long transformedX, long transformedY) { + long transformed = Math.abs(transformedX) | Math.abs(transformedY); + if ((transformed & (-1 << 10)) == 0) { + return "node-XY1"; + } else if ((transformed & (-1 << 11)) == 0) { + return "node-XY2"; + } else if ((transformed & (-1 << 12)) == 0) { + return "node-XY3"; + } else if ((transformed & (-1 << 13)) == 0) { + return "node-XY4"; + } else if ((transformed & (-1 << 14)) == 0) { + return "node-XY5"; + } else if ((transformed & (-1 << 16)) == 0) { + return "node-XY6"; + } else { + throw new IllegalArgumentException("Invalid node X/Y offset: " + transformedX + "/" + transformedY + ". Values must be between a range of -327.68/+327.67 meters."); } - - /** - * Exception thrown when noncompliant fields are found in the data frame. - */ - public static class NoncompliantFieldsException extends Exception { - public NoncompliantFieldsException(String message) { - super(message); - } + } + + /** + * Ensures compliance with the J2735 2024 standard by checking + * for old fields in the given data frame. + * + * @param dataFrame the JSON object representing the data frame to be checked + * @throws NoncompliantFieldsException if any old fields are found + */ + public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) throws NoncompliantFieldsException { + // Check and throw exception if old fields are found + Set nonCompliantFields = + Set.of(SSP_MSG_CONTENT, SSP_MSG_TYPES, SSP_LOCATION_RIGHTS, SSP_TIM_RIGHTS, SSP_MSG_RIGHTS_1, SSP_MSG_RIGHTS_2, NOT_USED, NOT_USED_1, NOT_USED_2, NOT_USED_3, DURATON_TIME_MISSPELLED); + ArrayList violations = new ArrayList<>(); + for (String violationName : nonCompliantFields) { + if (dataFrame.has(violationName)) { + violations.add(violationName); + } + } + if (!violations.isEmpty()) { + throw new NoncompliantFieldsException( + String.format("Data frame contains the following old fields that are not compliant with " + "J2735 2024: [%s]. Deserialization should prevent this.", violations)); + } + } + + /** + * Exception thrown when noncompliant fields are found in the data frame. + */ + public static class NoncompliantFieldsException extends Exception { + public NoncompliantFieldsException(String message) { + super(message); } + } } diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index f5d51ef8f..89ff2c8d5 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -41,615 +41,615 @@ import us.dot.its.jpo.ode.util.JsonUtils.JsonUtilsException; class TravelerMessageFromHumanToAsnConverterTest { - @Mocked - Logger logger; - - @BeforeEach - void setup() { - new MockUp() { - @Mock - Logger getLogger(String value) { - return logger; - } - }; - } - - @Test - void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"1\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":\"-105.047355\",\"nodeLat\":\"40.572429\",\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"workZone\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"1\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"advisory\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":-105.047355,\"nodeLat\":40.572429,\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"genericSign\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryUnavailable() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"unknown\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"0\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"unknown\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"unavailable\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryExitServiceForward() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"1\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"exitService\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"forward\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryAdvisoryReverse() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"roadSignage\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"2\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"advisory\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"roadSignage\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"reverse\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testGeometryBothGenericSign() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"genericSign\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testPathSpeedLimit() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"1\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"advisory\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ { \"nodeLong\": \"0.0031024\", \"nodeLat\": \"0.0014506\", \"delta\": \"node-LL3\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":\"123\"},{\"laneCrownPointCenter\":\"111\"},{\"laneCrownPointLeft\":\"5.5\"}],\"dWidth\":\"33\",\"dElevation\":\"500\"} }, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testTranslateISOTimeStampToMinuteOfYear() { - Assertions.assertEquals(232800, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-06-11T16:00:00.000Z")); - - Assertions.assertEquals(232800, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-06-11T10:00-06:00")); - - // Test for invalid timestamp - Assertions.assertEquals(527040, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-15-44T25:66:77.999Z")); - } - - @Test - void testReplaceDataFrameTimestamp() { - String fieldName = "startDateTime"; - ObjectNode startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T16:00:00.000Z"); - TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); - Assertions.assertNull(startDateTime.get("startDateTime")); - Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); - Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); - - startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T10:00-06:00"); - TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); - Assertions.assertNull(startDateTime.get("startDateTime")); - Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); - Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); - - // Test for invalid timestamp - startDateTime = JsonUtils.newNode().put(fieldName, "2018-15-44T25:66:77.999Z"); - TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); - Assertions.assertNull(startDateTime.get("startDateTime")); - Assertions.assertEquals(0, startDateTime.get("startYear").asInt()); - Assertions.assertEquals(527040, startDateTime.get("startTime").asLong()); - } - - @Test - void testBuildItem() { - - String itisCode = "123"; - String itis = "itis"; - ObjectNode expectedItisNode = JsonUtils.newNode().put(itis, Integer.parseInt(itisCode)); - ObjectNode expecteditem = (ObjectNode) JsonUtils.newNode().set("item", expectedItisNode); - - // build ITIS code - JsonNode actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(itisCode); - Assertions.assertEquals(expecteditem, actualItem); - - // build number text - expectedItisNode.remove(itis); - expectedItisNode.put("text", itisCode); - actualItem = TravelerMessageFromHumanToAsnConverter.buildItem("'123"); - Assertions.assertEquals(expecteditem, actualItem); - - // build alphanumeric text - String test123 = "test 123"; - expectedItisNode.put("text", test123); - actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(test123); - Assertions.assertEquals(expecteditem, actualItem); - } - - @Test - void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"nodes\":[{\"x\":\"-5.12\",\"y\":\"5.11\",\"delta\":\"node-XY\"},{\"x\":\"-10.24\",\"y\":\"10.23\",\"delta\":\"node-XY\"},{\"x\":\"-20.48\",\"y\":\"20.47\",\"delta\":\"node-XY\"},{\"x\":\"-40.96\",\"y\":\"40.95\",\"delta\":\"node-XY\"},{\"x\":\"-81.92\",\"y\":\"81.91\",\"delta\":\"node-XY\"},{\"x\":\"-327.68\",\"y\":\"327.67\",\"delta\":\"node-XY\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"nodes\":[{\"delta\":{\"node-XY1\":{\"x\":-512,\"y\":511}}},{\"delta\":{\"node-XY2\":{\"x\":-1024,\"y\":1023}}},{\"delta\":{\"node-XY3\":{\"x\":-2048,\"y\":2047}}},{\"delta\":{\"node-XY4\":{\"x\":-4096,\"y\":4095}}},{\"delta\":{\"node-XY5\":{\"x\":-8192,\"y\":8191}}},{\"delta\":{\"node-XY6\":{\"x\":-32768,\"y\":32767}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"small\":111},\"offsetYaxis\":{\"small\":111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"large\":11111},\"offsetYaxis\":{\"large\":11111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithCircle() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"circle\":{\"center\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"radius\":\"2048\",\"units\":\"centimeter\"}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"circle\":{\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"radius\":\"2048\",\"units\":{\"centimeter\":\"EMPTY_TAG\"}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void testOldRegionWithRegionPointSet() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode inputTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); - TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); - - ObjectNode expectedTID = JsonUtils.toObjectNode( - "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); - Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); - - JSONObject timObject = new JSONObject(); - timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); - assertNotNull(XML.toString(timObject)); - } - - @Test - void ensureComplianceWithJ2735Revision2024_noOldFields() throws TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("doNotUse1", 0); - dataFrame.put("doNotUse2", 0); - dataFrame.put("doNotUse3", 0); - dataFrame.put("doNotUse4", 0); - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgContent() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgContent", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgTypes() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgTypes", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspTimRights() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspTimRights", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspLocationRights() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspLocationRights", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights1() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgRights1", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights2() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgRights2", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed1() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed1", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed2() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed2", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed3() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("notUsed3", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsOldField_duratonTime() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("duratonTime", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void ensureComplianceWithJ2735Revision2024_containsMultipleOldFields() { - ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); - dataFrame.put("sspMsgContent", 1); - dataFrame.put("sspMsgTypes", 1); - dataFrame.put("sspTimRights", 1); - dataFrame.put("sspLocationRights", 1); - dataFrame.put("sspMsgRights1", 1); - dataFrame.put("sspMsgRights2", 1); - dataFrame.put("notUsed", 1); - dataFrame.put("notUsed1", 1); - dataFrame.put("notUsed2", 1); - dataFrame.put("notUsed3", 1); - dataFrame.put("duratonTime", 1); - assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { - TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); - }); - } - - @Test - void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { - // prepare - ObjectNode node = JsonNodeFactory.instance.objectNode(); - node.put("nodeLong", "0.0031024"); - node.put("nodeLat", "0.0014506"); - node.put("delta", "node-LL3"); - - // execute - ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); - - // verify - String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}}"; - ObjectNode expected = JsonUtils.toObjectNode(expectedJson); - - Assertions.assertEquals(expected.toString(), result.toString()); - } - - @Test - void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { - // prepare - ObjectNode node = JsonNodeFactory.instance.objectNode(); - node.put("nodeLong", "-0.0008192"); - node.put("nodeLat", "-0.0013123"); - node.put("delta", "node-LL"); - - // execute - ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); - - // verify - String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":-13123,\"lon\":-8192}}}"; - ObjectNode expected = JsonUtils.toObjectNode(expectedJson); - - Assertions.assertEquals(expected.toString(), result.toString()); - } - - long LL_1_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL1_LIMIT * -1; - long LL_2_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL2_LIMIT * -1; - long LL_3_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL3_LIMIT * -1; - long LL_4_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL4_LIMIT * -1; - long LL_5_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL5_LIMIT * -1; - long LL_6_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL6_LIMIT * -1; - - @Test - void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { - long transformedLat = -1500L; // within LL1 constraints - long transformedLong = -1500L; // within LL1 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL1", selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { - long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints - long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { - long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary - long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() { - long transformedLat = -6000; // within LL2 constraints - long transformedLong = -6000; // within LL2 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { - long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary - long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() { - long transformedLat = -25000; // within LL3 constraints - long transformedLong = -25000; // within LL3 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { - long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary - long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() { - long transformedLat = -125000; // within LL4 constraints - long transformedLong = -125000; // within LL4 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { - long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary - long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() { - long transformedLat = -2000000L; // within LL5 constraints - long transformedLong = -2000000L; // within LL5 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { - long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary - long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() { - long transformedLat = -8000000L; // within LL6 constraints - long transformedLong = -8000000L; // within LL6 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - - Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); - } - - @Test - void nodeOffsetPointLL_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { - long transformedLat = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints - long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary - assertThrows(IllegalArgumentException.class, () -> { - TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - }); - } - - @Test - void nodeOffsetPointLL_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { - long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary - long transformedLong = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints - assertThrows(IllegalArgumentException.class, () -> { - TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - }); - } + @Mocked + Logger logger; + + @BeforeEach + void setup() { + new MockUp() { + @Mock + Logger getLogger(String value) { + return logger; + } + }; + } + + @Test + void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL2\":{\"lat\":-8191,\"lon\":8191}}},{\"delta\":{\"node-LL3\":{\"lat\":-32767,\"lon\":32767}}},{\"delta\":{\"node-LL4\":{\"lat\":-131071,\"lon\":131071}}},{\"delta\":{\"node-LL5\":{\"lat\":-2097151,\"lon\":2097151}}},{\"delta\":{\"node-LL6\":{\"lat\":-8388607,\"lon\":8388607}}},{\"delta\":{\"node-LatLon\":{\"lat\":412500807,\"lon\":-1110093847}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"1\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":\"-105.047355\",\"nodeLat\":\"40.572429\",\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"workZone\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"1\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"advisory\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":-105.047355,\"nodeLat\":40.572429,\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"genericSign\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":431644,\"packetID\":\"3\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":100,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":32700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"xy\":{\"nodes\":{\"NodeXY\":[{\"delta\":{\"node-LatLon\":{\"lon\":-1050473550,\"lat\":405724290}},\"attributes\":{\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":41},{\"laneCrownPointLeft\":78},{\"laneCrownPointRight\":115},{\"laneAngle\":1},{\"speedLimits\":[{\"type\":{\"maxSpeedInSchoolZoneWhenChildrenArePresent\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"maxSpeedInSchoolZone\":\"EMPTY_TAG\"},\"speed\":1170},{\"type\":{\"maxSpeedInConstructionZone\":\"EMPTY_TAG\"},\"speed\":615},{\"type\":{\"vehicleMinSpeed\":\"EMPTY_TAG\"},\"speed\":1170}]}],\"dWidth\":123,\"dElevation\":234}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050468440,\"lat\":405722280}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050465900,\"lat\":405721130}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050462430,\"lat\":405719100}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050459360,\"lat\":405716750}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050456740,\"lat\":405714220}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050454500,\"lat\":405711310}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050452350,\"lat\":405707240}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050451130,\"lat\":405702930}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"direction\":\"1111111111111111\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":405730680,\"long\":-1050490160,\"elevation\":15009}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":420802,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":7425}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryUnavailable() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"unknown\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"0\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"unknown\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"unavailable\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryExitServiceForward() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"1\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"exitService\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"forward\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryAdvisoryReverse() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"roadSignage\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"2\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"advisory\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"roadSignage\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"reverse\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"2\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"commercialSignage\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL1\":{\"lat\":-2047,\"lon\":2047}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"workZone\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testGeometryBothGenericSign() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"genericSign\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"1\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"0\":\"EMPTY_TAG\"},\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcd\":\"5\",\"crc\":\"0000\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"geometry\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"laneWidth\":3300,\"circle\":{\"radius\":\"15\",\"units\":{\"mile\":\"EMPTY_TAG\"},\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"genericSign\":{\"SEQUENCE\":[{\"item\":{\"itis\":250}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testPathSpeedLimit() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"1\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"advisory\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ { \"nodeLong\": \"0.0031024\", \"nodeLat\": \"0.0014506\", \"delta\": \"node-LL3\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":\"123\"},{\"laneCrownPointCenter\":\"111\"},{\"laneCrownPointLeft\":\"5.5\"}],\"dWidth\":\"33\",\"dElevation\":\"500\"} }, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":309505,\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataFrames\":{\"TravelerDataFrame\":[{\"durationTime\":1,\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"Testing TIM\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"description\":{\"path\":{\"scale\":\"0\",\"offset\":{\"ll\":{\"nodes\":{\"NodeLL\":[{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}},{\"delta\":{\"node-LL3\":{\"lat\":14568,\"lon\":30974}}},{\"delta\":{\"node-LL3\":{\"lat\":14559,\"lon\":30983}}},{\"delta\":{\"node-LL3\":{\"lat\":14563,\"lon\":30980}}},{\"delta\":{\"node-LL3\":{\"lat\":14562,\"lon\":30982}}}]}}}}},\"direction\":\"0000000000001010\",\"id\":{\"region\":0,\"id\":33},\"anchor\":{\"lat\":412500807,\"long\":-1110093847,\"elevation\":20207}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":308065,\"tcontent\":{\"speedLimit\":{\"SEQUENCE\":[{\"item\":{\"itis\":513}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testTranslateISOTimeStampToMinuteOfYear() { + Assertions.assertEquals(232800, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-06-11T16:00:00.000Z")); + + Assertions.assertEquals(232800, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-06-11T10:00-06:00")); + + // Test for invalid timestamp + Assertions.assertEquals(527040, TravelerMessageFromHumanToAsnConverter.translateISOTimeStampToMinuteOfYear("2018-15-44T25:66:77.999Z")); + } + + @Test + void testReplaceDataFrameTimestamp() { + String fieldName = "startDateTime"; + ObjectNode startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T16:00:00.000Z"); + TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); + Assertions.assertNull(startDateTime.get("startDateTime")); + Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); + Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); + + startDateTime = JsonUtils.newNode().put(fieldName, "2018-06-11T10:00-06:00"); + TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); + Assertions.assertNull(startDateTime.get("startDateTime")); + Assertions.assertEquals(2018, startDateTime.get("startYear").asInt()); + Assertions.assertEquals(232800, startDateTime.get("startTime").asLong()); + + // Test for invalid timestamp + startDateTime = JsonUtils.newNode().put(fieldName, "2018-15-44T25:66:77.999Z"); + TravelerMessageFromHumanToAsnConverter.replaceDataFrameTimestamp(startDateTime); + Assertions.assertNull(startDateTime.get("startDateTime")); + Assertions.assertEquals(0, startDateTime.get("startYear").asInt()); + Assertions.assertEquals(527040, startDateTime.get("startTime").asLong()); + } + + @Test + void testBuildItem() { + + String itisCode = "123"; + String itis = "itis"; + ObjectNode expectedItisNode = JsonUtils.newNode().put(itis, Integer.parseInt(itisCode)); + ObjectNode expecteditem = (ObjectNode) JsonUtils.newNode().set("item", expectedItisNode); + + // build ITIS code + JsonNode actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(itisCode); + Assertions.assertEquals(expecteditem, actualItem); + + // build number text + expectedItisNode.remove(itis); + expectedItisNode.put("text", itisCode); + actualItem = TravelerMessageFromHumanToAsnConverter.buildItem("'123"); + Assertions.assertEquals(expecteditem, actualItem); + + // build alphanumeric text + String test123 = "test 123"; + expectedItisNode.put("text", test123); + actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(test123); + Assertions.assertEquals(expecteditem, actualItem); + } + + @Test + void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"nodes\":[{\"x\":\"-5.12\",\"y\":\"5.11\",\"delta\":\"node-XY\"},{\"x\":\"-10.24\",\"y\":\"10.23\",\"delta\":\"node-XY\"},{\"x\":\"-20.48\",\"y\":\"20.47\",\"delta\":\"node-XY\"},{\"x\":\"-40.96\",\"y\":\"40.95\",\"delta\":\"node-XY\"},{\"x\":\"-81.92\",\"y\":\"81.91\",\"delta\":\"node-XY\"},{\"x\":\"-327.68\",\"y\":\"327.67\",\"delta\":\"node-XY\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"nodes\":[{\"delta\":{\"node-XY1\":{\"x\":-512,\"y\":511}}},{\"delta\":{\"node-XY2\":{\"x\":-1024,\"y\":1023}}},{\"delta\":{\"node-XY3\":{\"x\":-2048,\"y\":2047}}},{\"delta\":{\"node-XY4\":{\"x\":-4096,\"y\":4095}}},{\"delta\":{\"node-XY5\":{\"x\":-8192,\"y\":8191}}},{\"delta\":{\"node-XY6\":{\"x\":-32768,\"y\":32767}}},{\"delta\":{\"node-LatLon\":{\"lon\":-1050450870,\"lat\":405698480}}}]}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"small\":111},\"offsetYaxis\":{\"small\":111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"shapePointSet\":{\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"laneWidth\":3300,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":{\"large\":11111},\"offsetYaxis\":{\"large\":11111},\"rotateXY\":9876,\"scaleXaxis\":469,\"scaleYaxis\":469}}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"exitService\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithCircle() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"circle\":{\"center\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"radius\":\"2048\",\"units\":\"centimeter\"}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"circle\":{\"center\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"radius\":\"2048\",\"units\":{\"centimeter\":\"EMPTY_TAG\"}}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void testOldRegionWithRegionPointSet() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode inputTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); + TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); + + ObjectNode expectedTID = JsonUtils.toObjectNode( + "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":102607,\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataFrames\":{\"TravelerDataFrame\":[{\"doNotUse1\":0,\"frameType\":{\"advisory\":\"EMPTY_TAG\"},\"msgId\":{\"roadSignID\":{\"position\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":{\"warning\":\"EMPTY_TAG\"},\"crc\":\"0000\"}},\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":{\"GeographicalPath\":[{\"name\":\"bob\",\"laneWidth\":700,\"directionality\":{\"both\":\"EMPTY_TAG\"},\"closedPath\":\"BOOLEAN_OBJECT_FALSE\",\"direction\":\"1010101010101010\",\"description\":{\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":{\"useFor3meters\":\"EMPTY_TAG\"},\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}},\"id\":{\"region\":23,\"id\":33},\"anchor\":{\"lat\":416784730,\"long\":-1087827750,\"elevation\":9171}}]},\"doNotUse4\":0,\"doNotUse3\":0,\"url\":\"null\",\"startYear\":2017,\"startTime\":482327,\"tcontent\":{\"advisory\":{\"SEQUENCE\":[{\"item\":{\"itis\":125}},{\"item\":{\"text\":\"some text\"}},{\"item\":{\"itis\":250}},{\"item\":{\"text\":\"98765\"}}]}}}]}}}"); + Assertions.assertEquals(expectedTID.toString(), inputTID.toString()); + + JSONObject timObject = new JSONObject(); + timObject.put(TravelerMessageFromHumanToAsnConverter.TRAVELER_INFORMATION, JsonUtils.toJSONObject(inputTID.toString())); + assertNotNull(XML.toString(timObject)); + } + + @Test + void ensureComplianceWithJ2735Revision2024_noOldFields() throws TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("doNotUse1", 0); + dataFrame.put("doNotUse2", 0); + dataFrame.put("doNotUse3", 0); + dataFrame.put("doNotUse4", 0); + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgContent() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgContent", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgTypes() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgTypes", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspTimRights() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspTimRights", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspLocationRights() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspLocationRights", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights1() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgRights1", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_sspMsgRights2() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgRights2", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed1() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed1", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed2() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed2", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_notUsed3() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("notUsed3", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsOldField_duratonTime() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("duratonTime", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void ensureComplianceWithJ2735Revision2024_containsMultipleOldFields() { + ObjectNode dataFrame = JsonNodeFactory.instance.objectNode(); + dataFrame.put("sspMsgContent", 1); + dataFrame.put("sspMsgTypes", 1); + dataFrame.put("sspTimRights", 1); + dataFrame.put("sspLocationRights", 1); + dataFrame.put("sspMsgRights1", 1); + dataFrame.put("sspMsgRights2", 1); + dataFrame.put("notUsed", 1); + dataFrame.put("notUsed1", 1); + dataFrame.put("notUsed2", 1); + dataFrame.put("notUsed3", 1); + dataFrame.put("duratonTime", 1); + assertThrows(TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException.class, () -> { + TravelerMessageFromHumanToAsnConverter.ensureComplianceWithJ2735Revision2024(dataFrame); + }); + } + + @Test + void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { + // prepare + ObjectNode node = JsonNodeFactory.instance.objectNode(); + node.put("nodeLong", "0.0031024"); + node.put("nodeLat", "0.0014506"); + node.put("delta", "node-LL3"); + + // execute + ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); + + // verify + String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":14506,\"lon\":31024}}}"; + ObjectNode expected = JsonUtils.toObjectNode(expectedJson); + + Assertions.assertEquals(expected.toString(), result.toString()); + } + + @Test + void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { + // prepare + ObjectNode node = JsonNodeFactory.instance.objectNode(); + node.put("nodeLong", "-0.0008192"); + node.put("nodeLat", "-0.0013123"); + node.put("delta", "node-LL"); + + // execute + ObjectNode result = TravelerMessageFromHumanToAsnConverter.transformNodeLL(node); + + // verify + String expectedJson = "{\"delta\":{\"node-LL3\":{\"lat\":-13123,\"lon\":-8192}}}"; + ObjectNode expected = JsonUtils.toObjectNode(expectedJson); + + Assertions.assertEquals(expected.toString(), result.toString()); + } + + long LL_1_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL1_LIMIT * -1; + long LL_2_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL2_LIMIT * -1; + long LL_3_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL3_LIMIT * -1; + long LL_4_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL4_LIMIT * -1; + long LL_5_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL5_LIMIT * -1; + long LL_6_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL6_LIMIT * -1; + + @Test + void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { + long transformedLat = -1500L; // within LL1 constraints + long transformedLong = -1500L; // within LL1 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL1", selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { + long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary + long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() { + long transformedLat = -6000; // within LL2 constraints + long transformedLong = -6000; // within LL2 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { + long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary + long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() { + long transformedLat = -25000; // within LL3 constraints + long transformedLong = -25000; // within LL3 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { + long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary + long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() { + long transformedLat = -125000; // within LL4 constraints + long transformedLong = -125000; // within LL4 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { + long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary + long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() { + long transformedLat = -2000000L; // within LL5 constraints + long transformedLong = -2000000L; // within LL5 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { + long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary + long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() { + long transformedLat = -8000000L; // within LL6 constraints + long transformedLong = -8000000L; // within LL6 constraints + String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + + Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); + } + + @Test + void nodeOffsetPointLL_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary + assertThrows(IllegalArgumentException.class, () -> { + TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + }); + } + + @Test + void nodeOffsetPointLL_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { + long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary + long transformedLong = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints + assertThrows(IllegalArgumentException.class, () -> { + TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + }); + } } \ No newline at end of file From 9b58b256f84f4f2daeb9ebb7674879a178febc31 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:44:19 -0600 Subject: [PATCH 21/32] Reformatted TravelerMessageFromHumanToAsnConverter & TravelerMessageFromHumanToAsnConverterTest classes --- ...ravelerMessageFromHumanToAsnConverter.java | 29 ++++++---- ...lerMessageFromHumanToAsnConverterTest.java | 57 ++++++++++++------- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index fe462019b..bc79571e2 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -523,7 +523,8 @@ public static void replaceRegion(ObjectNode region) throws JsonUtilsException { // anchorPosition --> anchor (optional) JsonNode anchorPos = region.get(ANCHOR_POSITION); if (anchorPos != null) { - region.set(ANCHOR, JsonUtils.toObjectNode(Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(region.get(ANCHOR_POSITION))).toJson())); + region.set(ANCHOR, + JsonUtils.toObjectNode(Position3DBuilder.dsrcPosition3D(Position3DBuilder.odePosition3D(region.get(ANCHOR_POSITION))).toJson())); region.remove(ANCHOR_POSITION); } @@ -688,7 +689,8 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { public final static long NODE_LL3_LIMIT = 32767; public final static long NODE_LL4_LIMIT = 131071; public final static long NODE_LL5_LIMIT = 2097151; - public final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. + public final static long NODE_LL6_LIMIT = 8388607; + // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. /** * Determines the node offset point LL type based on the latitude and longitude deltas. @@ -719,7 +721,8 @@ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { return NODE_LL6; } else { - throw new IllegalArgumentException("Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); + throw new IllegalArgumentException( + "Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); } } @@ -1070,11 +1073,14 @@ public static void replaceLaneDataAttribute(JsonNode oldNode) { if (oldNode.has("pathEndPointAngle")) { // do nothing } else if (oldNode.has(LANE_CROWN_POINT_CENTER)) { - updatedNode.put(LANE_CROWN_POINT_CENTER, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_CENTER)))); + updatedNode.put(LANE_CROWN_POINT_CENTER, + RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_CENTER)))); } else if (oldNode.has(LANE_CROWN_POINT_LEFT)) { - updatedNode.put(LANE_CROWN_POINT_LEFT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_LEFT)))); + updatedNode.put(LANE_CROWN_POINT_LEFT, + RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_LEFT)))); } else if (oldNode.has(LANE_CROWN_POINT_RIGHT)) { - updatedNode.put(LANE_CROWN_POINT_RIGHT, RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_RIGHT)))); + updatedNode.put(LANE_CROWN_POINT_RIGHT, + RoadwayCrownAngleBuilder.roadwayCrownAngle(JsonUtils.decimalValue(updatedNode.get(LANE_CROWN_POINT_RIGHT)))); } else if (oldNode.has(LANE_ANGLE)) { updatedNode.put(LANE_ANGLE, MergeDivergeNodeAngleBuilder.mergeDivergeNodeAngle(JsonUtils.decimalValue(updatedNode.get(LANE_ANGLE)))); } else if (oldNode.has(SPEED_LIMITS)) { @@ -1190,7 +1196,8 @@ private static String nodeOffsetPointXY(long transformedX, long transformedY) { } else if ((transformed & (-1 << 16)) == 0) { return "node-XY6"; } else { - throw new IllegalArgumentException("Invalid node X/Y offset: " + transformedX + "/" + transformedY + ". Values must be between a range of -327.68/+327.67 meters."); + throw new IllegalArgumentException( + "Invalid node X/Y offset: " + transformedX + "/" + transformedY + ". Values must be between a range of -327.68/+327.67 meters."); } } @@ -1204,7 +1211,8 @@ private static String nodeOffsetPointXY(long transformedX, long transformedY) { public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) throws NoncompliantFieldsException { // Check and throw exception if old fields are found Set nonCompliantFields = - Set.of(SSP_MSG_CONTENT, SSP_MSG_TYPES, SSP_LOCATION_RIGHTS, SSP_TIM_RIGHTS, SSP_MSG_RIGHTS_1, SSP_MSG_RIGHTS_2, NOT_USED, NOT_USED_1, NOT_USED_2, NOT_USED_3, DURATON_TIME_MISSPELLED); + Set.of(SSP_MSG_CONTENT, SSP_MSG_TYPES, SSP_LOCATION_RIGHTS, SSP_TIM_RIGHTS, SSP_MSG_RIGHTS_1, SSP_MSG_RIGHTS_2, NOT_USED, NOT_USED_1, + NOT_USED_2, NOT_USED_3, DURATON_TIME_MISSPELLED); ArrayList violations = new ArrayList<>(); for (String violationName : nonCompliantFields) { if (dataFrame.has(violationName)) { @@ -1212,8 +1220,9 @@ public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) t } } if (!violations.isEmpty()) { - throw new NoncompliantFieldsException( - String.format("Data frame contains the following old fields that are not compliant with " + "J2735 2024: [%s]. Deserialization should prevent this.", violations)); + throw new NoncompliantFieldsException(String.format( + "Data frame contains the following old fields that are not compliant with " + "J2735 2024: [%s]. Deserialization should prevent this.", + violations)); } } diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 89ff2c8d5..bf1d8eb2b 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -55,7 +55,8 @@ Logger getLogger(String value) { } @Test - void testAdvisoryNodeLL() throws JsonProcessingException, IOException, JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testAdvisoryNodeLL() + throws JsonProcessingException, IOException, JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); @@ -261,7 +262,8 @@ void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, Tra } @Test - void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithShapePointSetWithComputedLanesSmall() + throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -276,7 +278,8 @@ void testOldRegionWithShapePointSetWithComputedLanesSmall() throws JsonUtilsExce } @Test - void testOldRegionWithShapePointSetWithComputedLanesLarge() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithShapePointSetWithComputedLanesLarge() + throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -497,7 +500,8 @@ void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeL long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL1", selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL1", selection, + "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); } @Test @@ -506,7 +510,8 @@ void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldRetu long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL2", selection, + "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); } @Test @@ -515,7 +520,8 @@ void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldRetu long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL2", selection, + "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); } @Test @@ -524,7 +530,8 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNo long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL2", selection, + "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); } @Test @@ -533,7 +540,8 @@ void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldRetu long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL3", selection, + "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); } @Test @@ -542,7 +550,8 @@ void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldRetu long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL3", selection, + "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); } @Test @@ -551,7 +560,8 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNo long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL3", selection, + "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); } @Test @@ -560,7 +570,8 @@ void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldRetu long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL4", selection, + "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); } @Test @@ -569,7 +580,8 @@ void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldRetu long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL4", selection, + "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); } @Test @@ -578,7 +590,8 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNo long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL4", selection, + "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); } @Test @@ -587,7 +600,8 @@ void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldRetu long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL5", selection, + "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); } @Test @@ -596,7 +610,8 @@ void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldRetu long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL5", selection, + "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); } @Test @@ -605,7 +620,8 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNo long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL5", selection, + "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); } @Test @@ -614,7 +630,8 @@ void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldRetu long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL6", selection, + "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); } @Test @@ -623,7 +640,8 @@ void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldRetu long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL6", selection, + "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); } @Test @@ -632,7 +650,8 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNo long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); + Assertions.assertEquals("node-LL6", selection, + "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); } @Test From e051c08def284e256676c62f0c9d8da0b81601f1 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 13:47:39 -0600 Subject: [PATCH 22/32] Removed unnecessary imports, initializations, casts & throws lists in TravelerMessageFromHumanToAsnConverter & TravelerMessageFromHumanToAsnConverterTest classes --- .../builders/TravelerMessageFromHumanToAsnConverter.java | 2 +- .../TravelerMessageFromHumanToAsnConverterTest.java | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index bc79571e2..cffee2a1c 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -829,7 +829,7 @@ public static void replaceCircle(JsonNode circle) { ObjectNode updatedNode = (ObjectNode) circle; - JsonNode centerPosition = null; + JsonNode centerPosition; if (updatedNode.has(POSITION)) { centerPosition = updatedNode.get(POSITION); updatedNode.remove(POSITION); diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index bf1d8eb2b..f9e8d8bc3 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import java.io.IOException; import org.json.JSONObject; import org.json.XML; @@ -30,7 +29,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -56,7 +54,7 @@ Logger getLogger(String value) { @Test void testAdvisoryNodeLL() - throws JsonProcessingException, IOException, JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); @@ -227,7 +225,7 @@ void testBuildItem() { String itisCode = "123"; String itis = "itis"; ObjectNode expectedItisNode = JsonUtils.newNode().put(itis, Integer.parseInt(itisCode)); - ObjectNode expecteditem = (ObjectNode) JsonUtils.newNode().set("item", expectedItisNode); + ObjectNode expecteditem = JsonUtils.newNode().set("item", expectedItisNode); // build ITIS code JsonNode actualItem = TravelerMessageFromHumanToAsnConverter.buildItem(itisCode); From a98074bc0859bd7c31d3594f0d8eecb78fb4a1a1 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 14:23:02 -0600 Subject: [PATCH 23/32] Renamed unit tests --- ...lerMessageFromHumanToAsnConverterTest.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index f9e8d8bc3..639993919 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -493,7 +493,7 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { long LL_6_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL6_LIMIT * -1; @Test - void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { + void determineNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { long transformedLat = -1500L; // within LL1 constraints long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -503,7 +503,7 @@ void nodeOffsetPointLL_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeL } @Test - void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -513,7 +513,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -523,7 +523,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() { long transformedLat = -6000; // within LL2 constraints long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -533,7 +533,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNo } @Test - void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -543,7 +543,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -553,7 +553,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() { long transformedLat = -25000; // within LL3 constraints long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -563,7 +563,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNo } @Test - void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -573,7 +573,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -583,7 +583,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() { long transformedLat = -125000; // within LL4 constraints long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -593,7 +593,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNo } @Test - void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -603,7 +603,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -613,7 +613,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() { long transformedLat = -2000000L; // within LL5 constraints long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -623,7 +623,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNo } @Test - void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -633,7 +633,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -643,7 +643,7 @@ void nodeOffsetPointLL_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldRetu } @Test - void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() { long transformedLat = -8000000L; // within LL6 constraints long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -653,7 +653,7 @@ void nodeOffsetPointLL_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNo } @Test - void nodeOffsetPointLL_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary assertThrows(IllegalArgumentException.class, () -> { @@ -662,7 +662,7 @@ void nodeOffsetPointLL_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThro } @Test - void nodeOffsetPointLL_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary long transformedLong = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints assertThrows(IllegalArgumentException.class, () -> { From e8b4b72c255734cda1735b9974a8c28e6dcd3d75 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 15:19:45 -0600 Subject: [PATCH 24/32] Updated illegal argument exception message --- .../j2735/builders/TravelerMessageFromHumanToAsnConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index cffee2a1c..4a5457f05 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -722,7 +722,7 @@ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta return NODE_LL6; } else { throw new IllegalArgumentException( - "Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388608/+0.8388607 degrees."); + "Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388607/+0.8388607 degrees."); } } From ab17e1f7f7e145b4162e38d260436f4b96c55ed2 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 15:29:31 -0600 Subject: [PATCH 25/32] Updated `determineNodeOffsetPointLLType` to throw custom InvalidNodeLatLonOffsetException instead of IllegalArgumentException --- ...ravelerMessageFromHumanToAsnConverter.java | 32 +++--- ...lerMessageFromHumanToAsnConverterTest.java | 99 ++++++++++++------- .../ode/traveler/TimDepositController.java | 6 ++ .../traveler/TimDepositControllerTest.java | 2 +- .../ode/traveler/TimTransmogrifierTest.java | 2 +- 5 files changed, 92 insertions(+), 49 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 4a5457f05..8e9758cbf 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -140,7 +140,8 @@ private TravelerMessageFromHumanToAsnConverter() { * @throws JsonUtilsException if there is an issue converting the JsonNode * @throws IllegalArgumentException if the JsonNode contains old fields that are no longer used */ - public static void convertTravelerInputDataToEncodableTim(JsonNode tid) throws JsonUtilsException, NoncompliantFieldsException { + public static void convertTravelerInputDataToEncodableTim(JsonNode tid) + throws JsonUtilsException, NoncompliantFieldsException, InvalidNodeLatLonOffsetException { // msgCnt MsgCount, // timeStamp MinuteOfTheYear OPTIONAL // packetID UniqueMSGID OPTIONAL @@ -170,7 +171,8 @@ public static void convertTravelerInputDataToEncodableTim(JsonNode tid) throws J * @throws JsonUtilsException if there is an issue converting the JsonNode * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used */ - public static ObjectNode transformDataFrames(JsonNode dataFrames) throws JsonUtilsException, NoncompliantFieldsException { + public static ObjectNode transformDataFrames(JsonNode dataFrames) + throws JsonUtilsException, NoncompliantFieldsException, InvalidNodeLatLonOffsetException { if (dataFrames == null) { return JsonUtils.newNode(); @@ -198,7 +200,7 @@ public static ObjectNode transformDataFrames(JsonNode dataFrames) throws JsonUti * @throws JsonUtilsException if there is an issue converting the JsonNode * @throws NoncompliantFieldsException if the JsonNode contains old fields that are no longer used */ - public static void replaceDataFrame(ObjectNode dataFrame) throws JsonUtilsException, NoncompliantFieldsException { + public static void replaceDataFrame(ObjectNode dataFrame) throws JsonUtilsException, NoncompliantFieldsException, InvalidNodeLatLonOffsetException { // INPUT ////// @@ -436,7 +438,7 @@ public static void replaceMsgId(ObjectNode dataFrame) { * @return ObjectNode representing the transformed regions * @throws JsonUtilsException if there is an issue converting the JsonNode */ - public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsException { + public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsException, InvalidNodeLatLonOffsetException { ArrayNode replacedRegions = JsonUtils.newNode().arrayNode(); if (regions.isArray()) { @@ -458,7 +460,7 @@ public static ObjectNode transformRegions(JsonNode regions) throws JsonUtilsExce * @param region ObjectNode representing the region * @throws JsonUtilsException if there is an issue converting the JsonNode */ - public static void replaceRegion(ObjectNode region) throws JsonUtilsException { + public static void replaceRegion(ObjectNode region) throws JsonUtilsException, InvalidNodeLatLonOffsetException { //// EXPECTED INPUT: // "name": "Testing TIM", @@ -570,7 +572,7 @@ public static void replaceRegion(ObjectNode region) throws JsonUtilsException { } } - private static void replacePath(ObjectNode pathNode) { + private static void replacePath(ObjectNode pathNode) throws InvalidNodeLatLonOffsetException { //// EXPECTED INPUT: // "path": @@ -605,7 +607,7 @@ private static void replacePath(ObjectNode pathNode) { } - private static ArrayNode transformNodeSetLL(JsonNode nodes) { + private static ArrayNode transformNodeSetLL(JsonNode nodes) throws InvalidNodeLatLonOffsetException { //// EXPECTED INPUT: // "nodes": [] @@ -632,7 +634,7 @@ private static ArrayNode transformNodeSetLL(JsonNode nodes) { return outputNodeList; } - public static ObjectNode transformNodeLL(JsonNode oldNode) { + public static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLatLonOffsetException { //// EXPECTED INPUT: @@ -701,10 +703,10 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) { * @param latDelta The latitude delta as a long value. * @param lonDelta The longitude delta as a long value. * @return A string representing the node offset point LL type (e.g., NODE_LL1, NODE_LL2, etc.). - * @throws IllegalArgumentException if latDelta or lonDelta are outside the permissible range - * of -0.8388608 to +0.8388607 degrees. + * @throws InvalidNodeLatLonOffsetException if latDelta or lonDelta are outside the permissible range + * of -0.8388608 to +0.8388607 degrees. */ - public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) { + public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) throws InvalidNodeLatLonOffsetException { long absLatDelta = Math.abs(latDelta); long absLonDelta = Math.abs(lonDelta); @@ -721,7 +723,7 @@ public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta } else if (absLatDelta <= NODE_LL6_LIMIT && absLonDelta <= NODE_LL6_LIMIT) { return NODE_LL6; } else { - throw new IllegalArgumentException( + throw new InvalidNodeLatLonOffsetException( "Invalid node lat/long offset: " + latDelta + "/" + lonDelta + ". Values must be within a range of -0.8388607/+0.8388607 degrees."); } } @@ -1235,4 +1237,10 @@ public NoncompliantFieldsException(String message) { } } + public static class InvalidNodeLatLonOffsetException extends Exception { + public InvalidNodeLatLonOffsetException(String message) { + super(message); + } + } + } diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 639993919..27aaf3fc9 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -53,8 +53,8 @@ Logger getLogger(String value) { } @Test - void testAdvisoryNodeLL() - throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testAdvisoryNodeLL() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.2\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.2500807\",\"longitude\":\"-111.0093847\",\"elevation\":\"2020.6969900289998\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"ll\",\"nodes\":[{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL\"},{\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL1\"},{\"nodeLong\":\"0.0008191\",\"nodeLat\":\"-0.0008191\",\"delta\":\"node-LL2\"},{\"nodeLong\":\"0.0032767\",\"nodeLat\":\"-0.0032767\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"0.0131071\",\"nodeLat\":\"-0.0131071\",\"delta\":\"node-LL4\"},{\"nodeLong\":\"0.2097151\",\"nodeLat\":\"-0.2097151\",\"delta\":\"node-LL5\"},{\"nodeLong\":\"0.8388607\",\"nodeLat\":\"-0.8388607\",\"delta\":\"node-LL6\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); @@ -69,7 +69,8 @@ void testAdvisoryNodeLL() } @Test - void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"1\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"40.573068\",\"longitude\":\"-105.049016\",\"elevation\":\"1500.8999999999999\"},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":\"-105.047355\",\"nodeLat\":\"40.572429\",\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"workZone\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); @@ -84,7 +85,8 @@ void testWorkzoneNodeXYWithStringLatLon() throws JsonUtilsException, TravelerMes } @Test - void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":44.998459,\"longitude\":-111.040817},\"seCorner\":{\"latitude\":41.104674,\"longitude\":-104.111312}}}},\"tim\":{\"msgCnt\":\"1\",\"timeStamp\":\"2017-10-27T18:04:43.045Z\",\"packetID\":\"3\",\"urlB\":\"null\",\"dataframes\":[{\"startDateTime\":\"2017-10-20T05:22:33.985Z\",\"durationTime\":100,\"frameType\":\"advisory\",\"doNotUse1\":0,\"msgId\":\"roadSignID\",\"position\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"viewAngle\":\"1111111111111111\",\"mutcd\":\"2\",\"crc\":\"0000\",\"priority\":\"5\",\"doNotUse2\":0,\"regions\":[{\"name\":\"Testing TIM\",\"regulatorID\":\"0\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":40.573068,\"longitude\":-105.049016,\"elevation\":1500.8999999999999},\"laneWidth\":\"327\",\"directionality\":\"3\",\"closedPath\":\"false\",\"description\":\"path\",\"path\":{\"scale\":\"0\",\"type\":\"xy\",\"nodes\":[{\"nodeLong\":-105.047355,\"nodeLat\":40.572429,\"delta\":\"node-LatLon\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}},{\"nodeLong\":\"-105.046844\",\"nodeLat\":\"40.572228\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04659\",\"nodeLat\":\"40.572113\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.046243\",\"nodeLat\":\"40.57191\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045936\",\"nodeLat\":\"40.571675\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045674\",\"nodeLat\":\"40.571422\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.04545\",\"nodeLat\":\"40.571131\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045235\",\"nodeLat\":\"40.570724\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045113\",\"nodeLat\":\"40.570293\",\"delta\":\"node-LatLon\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]},\"direction\":\"1111111111111111\"}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"genericSign\",\"items\":[\"7425\"],\"url\":\"null\"}]}}"); @@ -99,7 +101,8 @@ void testGenericSignNodeXYWithNumericLatLon() throws JsonUtilsException, Travele } @Test - void testGeometryUnavailable() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryUnavailable() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"unknown\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"0\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -114,7 +117,8 @@ void testGeometryUnavailable() throws JsonUtilsException, TravelerMessageFromHum } @Test - void testGeometryExitServiceForward() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryExitServiceForward() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"1\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"exitService\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -129,7 +133,8 @@ void testGeometryExitServiceForward() throws JsonUtilsException, TravelerMessage } @Test - void testGeometryAdvisoryReverse() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryAdvisoryReverse() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"roadSignage\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"2\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"advisory\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -144,7 +149,8 @@ void testGeometryAdvisoryReverse() throws JsonUtilsException, TravelerMessageFro } @Test - void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"2\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"commercialSignage\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ {\"nodeLong\":\"0.0002047\",\"nodeLat\":\"-0.0002047\",\"delta\":\"node-LL\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":123},{\"laneCrownPointCenter\":12.3},{\"laneCrownPointLeft\":\"23.4\"},{\"laneCrownPointRight\":34.5},{\"laneAngle\":\"1.23\"},{\"speedLimits\":[{\"type\":\"2\",\"speed\":\"12.3\"},{\"type\":\"maxSpeedInSchoolZone\",\"speed\":\"23.4\"},{\"type\":3,\"speed\":12.3},{\"type\":\"vehicleMinSpeed\",\"speed\":23.4}]}],\"dWidth\":\"1.23\",\"dElevation\":\"2.34\"}}, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"workZone\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -158,7 +164,8 @@ void testRoadSignIDWorkzone() throws JsonUtilsException, TravelerMessageFromHuma } @Test - void testGeometryBothGenericSign() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testGeometryBothGenericSign() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}}, \"tim\": { \"msgCnt\": \"13\", \"timeStamp\": \"2017-03-13T01:07:11-05:00\", \"packetID\": \"1\", \"urlB\": \"null\", \"dataframes\": [ { \"doNotUse1\": 0, \"frameType\": \"0\", \"msgId\": \"roadSignID\", \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcd\": \"5\", \"crc\": \"0000\", \"startDateTime\": \"2017-12-01T17:47:11-05:00\", \"durationTime\": \"22\", \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"bob\", \"regulatorID\": \"23\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"direction\": \"1010101010101010\", \"description\": \"geometry\", \"geometry\": { \"direction\": \"1010101010101010\", \"extent\": \"1\", \"laneWidth\": \"33\", \"circle\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"radius\": \"15\", \"units\": \"7\" } } } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"genericSign\", \"items\": [ \"250\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -173,7 +180,8 @@ void testGeometryBothGenericSign() throws JsonUtilsException, TravelerMessageFro } @Test - void testPathSpeedLimit() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testPathSpeedLimit() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\": \"1\", \"timeStamp\": \"2017-08-03T22:25:36.297Z\", \"urlB\": \"null\", \"packetID\": \"EC9C236B0000000000\", \"dataframes\": [ { \"startDateTime\": \"2017-08-02T22:25:00.000Z\", \"durationTime\": 1, \"doNotUse1\": 0, \"frameType\": \"advisory\", \"msgId\": { \"roadSignID\": { \"position\": { \"latitude\": \"41.678473\", \"longitude\": \"-108.782775\", \"elevation\": \"917.1432\" }, \"viewAngle\": \"1010101010101010\", \"mutcdCode\": \"warning\", \"crc\": \"0000\" } }, \"priority\": \"0\", \"doNotUse2\": 0, \"regions\": [ { \"name\": \"Testing TIM\", \"regulatorID\": \"0\", \"segmentID\": \"33\", \"anchorPosition\": { \"latitude\": \"41.2500807\", \"longitude\": \"-111.0093847\", \"elevation\": \"2020.6969900289998\" }, \"laneWidth\": \"7\", \"directionality\": \"3\", \"closedPath\": \"false\", \"description\": \"path\", \"path\": { \"scale\": \"0\", \"type\": \"ll\", \"nodes\": [ { \"nodeLong\": \"0.0031024\", \"nodeLat\": \"0.0014506\", \"delta\": \"node-LL3\",\"attributes\":{\"localNode\":[\"stopLine\",\"roundedCapStyleA\",\"roundedCapStyleB\",\"mergePoint\",\"divergePoint\",\"downstreamStopLine\",\"downstreamStartNode\",\"closedToTraffic\",\"safeIsland\",\"curbPresentAtStepOff\",\"hydrantPresent\",\"reserved\"],\"disabled\":[\"reserved\",\"doNotBlock\",\"whiteLine\",\"mergingLaneLeft\",\"mergingLaneRight\",\"curbOnLeft\",\"curbOnRight\",\"loadingzoneOnLeft\",\"loadingzoneOnRight\",\"turnOutPointOnLeft\",\"turnOutPointOnRight\"],\"enabled\":[\"adjacentParkingOnLeft\",\"adjacentParkingOnRight\",\"adjacentBikeLaneOnLeft\"],\"data\":[{\"pathEndPointAngle\":\"123\"},{\"laneCrownPointCenter\":\"111\"},{\"laneCrownPointLeft\":\"5.5\"}],\"dWidth\":\"33\",\"dElevation\":\"500\"} }, { \"nodeLong\": \"0.0030974\", \"nodeLat\": \"0.0014568\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030983\", \"nodeLat\": \"0.0014559\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030980\", \"nodeLat\": \"0.0014563\", \"delta\": \"node-LL3\" }, { \"nodeLong\": \"0.0030982\", \"nodeLat\": \"0.0014562\", \"delta\": \"node-LL3\" } ] }, \"direction\": \"0000000000001010\" } ], \"doNotUse4\": 0, \"doNotUse3\": 0, \"content\": \"speedLimit\", \"items\": [ \"513\" ], \"url\": \"null\" } ] }}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -245,7 +253,8 @@ void testBuildItem() { } @Test - void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"nodes\":[{\"x\":\"-5.12\",\"y\":\"5.11\",\"delta\":\"node-XY\"},{\"x\":\"-10.24\",\"y\":\"10.23\",\"delta\":\"node-XY\"},{\"x\":\"-20.48\",\"y\":\"20.47\",\"delta\":\"node-XY\"},{\"x\":\"-40.96\",\"y\":\"40.95\",\"delta\":\"node-XY\"},{\"x\":\"-81.92\",\"y\":\"81.91\",\"delta\":\"node-XY\"},{\"x\":\"-327.68\",\"y\":\"327.67\",\"delta\":\"node-XY\"},{\"nodeLong\":\"-105.045087\",\"nodeLat\":\"40.569848\",\"delta\":\"node-LatLon\"}]}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -261,7 +270,8 @@ void testOldRegionWithShapePointSetWithNodeList() throws JsonUtilsException, Tra @Test void testOldRegionWithShapePointSetWithComputedLanesSmall() - throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"111\",\"offsetYaxis\":\"111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -277,7 +287,8 @@ void testOldRegionWithShapePointSetWithComputedLanesSmall() @Test void testOldRegionWithShapePointSetWithComputedLanesLarge() - throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"shapePointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"33\",\"directionality\":\"3\",\"nodeList\":{\"computed\":{\"referenceLaneId\":\"123\",\"offsetXaxis\":\"11111\",\"offsetYaxis\":\"11111\",\"rotateXY\":\"123.45\",\"scaleXaxis\":\"123.45\",\"scaleYaxis\":\"123.45\"}}}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"exitService\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -292,7 +303,8 @@ void testOldRegionWithShapePointSetWithComputedLanesLarge() } @Test - void testOldRegionWithCircle() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithCircle() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"circle\":{\"center\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"radius\":\"2048\",\"units\":\"centimeter\"}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -307,7 +319,8 @@ void testOldRegionWithCircle() throws JsonUtilsException, TravelerMessageFromHum } @Test - void testOldRegionWithRegionPointSet() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + void testOldRegionWithRegionPointSet() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, + TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { ObjectNode inputTID = JsonUtils.toObjectNode( "{\"request\":{\"rsus\":[{\"rsuIndex\":\"10\",\"rsuTarget\":\"127.0.0.3\",\"rsuUsername\":\"v3user\",\"rsuPassword\":\"password\",\"rsuRetries\":\"1\",\"rsuTimeout\":\"1000\"}],\"snmp\":{\"rsuid\":\"00000083\",\"msgid\":\"31\",\"mode\":\"1\",\"channel\":\"178\",\"interval\":\"2\",\"deliverystart\":\"2017-06-01T17:47:11-05:00\",\"deliverystop\":\"2018-01-01T17:47:11-05:15\",\"enable\":\"1\",\"status\":\"4\"},\"sdw\":{\"ttl\":\"oneweek\",\"serviceRegion\":{\"nwCorner\":{\"latitude\":\"44.998459\",\"longitude\":\"-111.040817\"},\"seCorner\":{\"latitude\":\"41.104674\",\"longitude\":\"-104.111312\"}}}},\"tim\":{\"msgCnt\":\"13\",\"timeStamp\":\"2017-03-13T01:07:11-05:00\",\"packetID\":\"EC9C236B0000000000\",\"urlB\":\"null\",\"dataframes\":[{\"doNotUse1\":0,\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"startDateTime\":\"2017-12-01T17:47:11-05:00\",\"durationTime\":\"22\",\"priority\":\"0\",\"doNotUse2\":0,\"regions\":[{\"name\":\"bob\",\"regulatorID\":\"23\",\"segmentID\":\"33\",\"anchorPosition\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"laneWidth\":\"7\",\"directionality\":\"3\",\"closedPath\":\"false\",\"direction\":\"1010101010101010\",\"description\":\"oldRegion\",\"oldRegion\":{\"direction\":\"1010101010101010\",\"extent\":\"1\",\"area\":{\"regionPointSet\":{\"anchor\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"scale\":\"0\",\"nodeList\":[{\"xOffset\":\"-0.003\",\"yOffset\":\"0.003\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.002\",\"yOffset\":\"0.002\",\"zOffset\":\"0\"},{\"xOffset\":\"-0.001\",\"yOffset\":\"0.001\",\"zOffset\":\"0\"}]}}}}],\"doNotUse4\":0,\"doNotUse3\":0,\"content\":\"advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}}"); TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(inputTID); @@ -450,7 +463,7 @@ void ensureComplianceWithJ2735Revision2024_containsMultipleOldFields() { } @Test - void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { + void transformNodeLL_LLTypeSpecified() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { // prepare ObjectNode node = JsonNodeFactory.instance.objectNode(); node.put("nodeLong", "0.0031024"); @@ -468,7 +481,7 @@ void transformNodeLL_LLTypeSpecified() throws JsonUtilsException { } @Test - void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { + void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException, TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { // prepare ObjectNode node = JsonNodeFactory.instance.objectNode(); node.put("nodeLong", "-0.0008192"); @@ -493,7 +506,8 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException { long LL_6_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL6_LIMIT * -1; @Test - void determineNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() { + void determineNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -1500L; // within LL1 constraints long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -503,7 +517,8 @@ void determineNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnD } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -513,7 +528,8 @@ void determineNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Bounda } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -523,7 +539,8 @@ void determineNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Bounda } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -6000; // within LL2 constraints long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -533,7 +550,8 @@ void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldRetu } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -543,7 +561,8 @@ void determineNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Bounda } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -553,7 +572,8 @@ void determineNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Bounda } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -25000; // within LL3 constraints long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -563,7 +583,8 @@ void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldRetu } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -573,7 +594,8 @@ void determineNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Bounda } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -583,7 +605,8 @@ void determineNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Bounda } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -125000; // within LL4 constraints long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -593,7 +616,8 @@ void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldRetu } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -603,7 +627,8 @@ void determineNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Bounda } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -613,7 +638,8 @@ void determineNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Bounda } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -2000000L; // within LL5 constraints long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -623,7 +649,8 @@ void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldRetu } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { + void determineNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -633,7 +660,8 @@ void determineNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Bounda } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() { + void determineNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -643,7 +671,8 @@ void determineNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Bounda } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() { + void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() + throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -8000000L; // within LL6 constraints long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); @@ -656,7 +685,7 @@ void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldRetu void determineNodeOffsetPointLLType_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException.class, () -> { TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); }); } @@ -665,7 +694,7 @@ void determineNodeOffsetPointLLType_WhenLatOutsideLL6ConstraintAndLonAtLL6Bounda void determineNodeOffsetPointLLType_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary long transformedLong = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException.class, () -> { TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); }); } diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java index c7a238c0c..9d1e9ebbe 100644 --- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java +++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java @@ -286,6 +286,12 @@ public synchronized ResponseEntity depositTim(String jsonString, Request return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body( JsonUtils.jsonKeyValue(ERRSTR, errMsg)); + } catch (TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException e) { + String errMsg = "Invalid node lat/lon offset in TIM: " + e.getMessage(); + log.error(errMsg, e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body( + JsonUtils.jsonKeyValue(ERRSTR, errMsg)); } try { diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimDepositControllerTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimDepositControllerTest.java index 53ba2bead..408ceb838 100644 --- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimDepositControllerTest.java +++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimDepositControllerTest.java @@ -116,7 +116,7 @@ void messageWithNoRSUsOrSDWShouldReturnWarning() { void failedObjectNodeConversionShouldReturnConvertingError(@Capturing TravelerMessageFromHumanToAsnConverter capturingTravelerMessageFromHumanToAsnConverter) throws JsonUtilsException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { new Expectations() { diff --git a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimTransmogrifierTest.java b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimTransmogrifierTest.java index cce0a3419..3f46d6224 100644 --- a/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimTransmogrifierTest.java +++ b/jpo-ode-svcs/src/test/java/us/dot/its/jpo/ode/traveler/TimTransmogrifierTest.java @@ -282,7 +282,7 @@ void testConvertToXMLMessageFrame() @Test void testConvertToXML_VerifyPositionElementNotInCircleElementAfterConversion() throws IOException, JsonUtilsException, XmlUtilsException, ParseException, - TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException { + TravelerMessageFromHumanToAsnConverter.NoncompliantFieldsException, TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { // prepare String timRequestContainingCircleGeometry = new String(Files.readAllBytes(Paths.get( "src/test/resources/us/dot/its/jpo/ode/traveler/timRequestContainingCircleGeometry.json"))); From f3ebbbf8f9a4e753609c6c2eb9e545e540a30098 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 15:31:28 -0600 Subject: [PATCH 26/32] Added JavaDocs for InvalidNodeLatLonOffsetException --- .../j2735/builders/TravelerMessageFromHumanToAsnConverter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 8e9758cbf..5e2e95a9c 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -1237,6 +1237,9 @@ public NoncompliantFieldsException(String message) { } } + /** + * Exception thrown when an invalid node latitude or longitude offset is encountered. + */ public static class InvalidNodeLatLonOffsetException extends Exception { public InvalidNodeLatLonOffsetException(String message) { super(message); From 7bea8544bcfaf96e4fd1595e65139afb85784a78 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Thu, 20 Mar 2025 15:34:19 -0600 Subject: [PATCH 27/32] Updated catch block in TimDepositController for InvalidNodeLatLonOffsetException to prevent printing stack trace --- .../java/us/dot/its/jpo/ode/traveler/TimDepositController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java index 9d1e9ebbe..fc5f67fd9 100644 --- a/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java +++ b/jpo-ode-svcs/src/main/java/us/dot/its/jpo/ode/traveler/TimDepositController.java @@ -288,7 +288,7 @@ public synchronized ResponseEntity depositTim(String jsonString, Request JsonUtils.jsonKeyValue(ERRSTR, errMsg)); } catch (TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException e) { String errMsg = "Invalid node lat/lon offset in TIM: " + e.getMessage(); - log.error(errMsg, e); + log.error(errMsg); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body( JsonUtils.jsonKeyValue(ERRSTR, errMsg)); From 7866bb90b1ef532d0fd7eca5e1ed259f0c86cbac Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Mon, 24 Mar 2025 09:10:57 -0600 Subject: [PATCH 28/32] Renamed `determineNodeOffsetPointLLType` to `getNodeOffsetPointLLType` --- ...ravelerMessageFromHumanToAsnConverter.java | 4 +- ...lerMessageFromHumanToAsnConverterTest.java | 72 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 5e2e95a9c..038139a2d 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -665,7 +665,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLat transformedLat = OffsetLLBuilder.offsetLL(latOffset); transformedLong = OffsetLLBuilder.offsetLL(longOffset); if (deltaText.equals("node-LL")) { - deltaText = determineNodeOffsetPointLLType(transformedLat, transformedLong); + deltaText = getNodeOffsetPointLLType(transformedLat, transformedLong); } } else if (NODE_LAT_LON.equals(deltaText)) { transformedLat = LatitudeBuilder.j2735Latitude(latOffset); @@ -706,7 +706,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLat * @throws InvalidNodeLatLonOffsetException if latDelta or lonDelta are outside the permissible range * of -0.8388608 to +0.8388607 degrees. */ - public static String determineNodeOffsetPointLLType(long latDelta, long lonDelta) throws InvalidNodeLatLonOffsetException { + public static String getNodeOffsetPointLLType(long latDelta, long lonDelta) throws InvalidNodeLatLonOffsetException { long absLatDelta = Math.abs(latDelta); long absLonDelta = Math.abs(lonDelta); diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 27aaf3fc9..8ba68f1dc 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -506,196 +506,196 @@ void transformNodeLL_LLTypeNotSpecified() throws JsonUtilsException, TravelerMes long LL_6_MINIMUM_MICRO_DEGREES = TravelerMessageFromHumanToAsnConverter.NODE_LL6_LIMIT * -1; @Test - void determineNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnDetermineNodeLLType1() + void getNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnGetNodeLLType1() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -1500L; // within LL1 constraints long transformedLong = -1500L; // within LL1 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL1", selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnDetermineNodeLLType2() + void getNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_ShouldReturnGetNodeLLType2() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnDetermineNodeLLType2() + void getNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_ShouldReturnGetNodeLLType2() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldReturnDetermineNodeLLType2() + void getNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldReturnGetNodeLLType2() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -6000; // within LL2 constraints long transformedLong = -6000; // within LL2 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL2", selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnDetermineNodeLLType3() + void getNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_ShouldReturnGetNodeLLType3() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnDetermineNodeLLType3() + void getNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_ShouldReturnGetNodeLLType3() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldReturnDetermineNodeLLType3() + void getNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldReturnGetNodeLLType3() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -25000; // within LL3 constraints long transformedLong = -25000; // within LL3 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL3", selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnDetermineNodeLLType4() + void getNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_ShouldReturnGetNodeLLType4() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnDetermineNodeLLType4() + void getNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_ShouldReturnGetNodeLLType4() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldReturnDetermineNodeLLType4() + void getNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldReturnGetNodeLLType4() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -125000; // within LL4 constraints long transformedLong = -125000; // within LL4 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL4", selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnDetermineNodeLLType5() + void getNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_ShouldReturnGetNodeLLType5() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnDetermineNodeLLType5() + void getNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_ShouldReturnGetNodeLLType5() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldReturnDetermineNodeLLType5() + void getNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldReturnGetNodeLLType5() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -2000000L; // within LL5 constraints long transformedLong = -2000000L; // within LL5 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL5", selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnDetermineNodeLLType6() + void getNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_ShouldReturnGetNodeLLType6() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnDetermineNodeLLType6() + void getNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_ShouldReturnGetNodeLLType6() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldReturnDetermineNodeLLType6() + void getNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldReturnGetNodeLLType6() throws TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException { long transformedLat = -8000000L; // within LL6 constraints long transformedLong = -8000000L; // within LL6 constraints - String selection = TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); Assertions.assertEquals("node-LL6", selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); } @Test - void determineNodeOffsetPointLLType_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { + void getNodeOffsetPointLLType_WhenLatOutsideLL6ConstraintAndLonAtLL6Boundary_ShouldThrowException() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints long transformedLong = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary assertThrows(TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException.class, () -> { - TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); }); } @Test - void determineNodeOffsetPointLLType_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { + void getNodeOffsetPointLLType_WhenLonOutsideLL6ConstraintAndLatAtLL6Boundary_ShouldThrowException() { long transformedLat = LL_6_MINIMUM_MICRO_DEGREES; // at LL6 boundary long transformedLong = LL_6_MINIMUM_MICRO_DEGREES - 1; // outside LL6 constraints assertThrows(TravelerMessageFromHumanToAsnConverter.InvalidNodeLatLonOffsetException.class, () -> { - TravelerMessageFromHumanToAsnConverter.determineNodeOffsetPointLLType(transformedLat, transformedLong); + TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); }); } } \ No newline at end of file From 6e6fc8354ebd4bc82ccfbe787ba8658ae6e71a58 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Mon, 24 Mar 2025 09:15:07 -0600 Subject: [PATCH 29/32] Referenced constants instead of using magic strings for nodeLL types --- ...lerMessageFromHumanToAsnConverterTest.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java index 8ba68f1dc..b4a494e8a 100644 --- a/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java +++ b/jpo-ode-plugins/src/test/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverterTest.java @@ -512,7 +512,7 @@ void getNodeOffsetPointLLType_WhenLatLonWithinLL1Constraints_ShouldReturnGetNode long transformedLong = -1500L; // within LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL1", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL1, selection, "Expected node-LL1 for latitude and longitude within LL1 constraints, " + "but got " + selection + " instead."); } @@ -523,7 +523,7 @@ void getNodeOffsetPointLLType_WhenLatOutsideLL1ConstraintAndLonAtLL1Boundary_Sho long transformedLong = LL_1_MINIMUM_MICRO_DEGREES; // at LL1 boundary String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL2, selection, "Expected node-LL2 when latitude exceeds LL1 constraints and longitude is at LL1 boundary, " + "but got " + selection + " instead."); } @@ -534,7 +534,7 @@ void getNodeOffsetPointLLType_WhenLonOutsideLL1ConstraintAndLatAtLL1Boundary_Sho long transformedLong = LL_1_MINIMUM_MICRO_DEGREES - 1; // outside LL1 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL2, selection, "Expected node-LL2 when longitude exceeds LL1 constraints and latitude is at LL1 boundary, " + "but got " + selection + " instead."); } @@ -545,7 +545,7 @@ void getNodeOffsetPointLLType_WhenLatAndLonWithinLL2Constraints_ShouldReturnGetN long transformedLong = -6000; // within LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL2", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL2, selection, "Expected node-LL2 for latitude and longitude within LL2 constraints, " + "but got " + selection + " instead."); } @@ -556,7 +556,7 @@ void getNodeOffsetPointLLType_WhenLatOutsideLL2ConstraintAndLonAtLL2Boundary_Sho long transformedLong = LL_2_MINIMUM_MICRO_DEGREES; // at LL2 boundary String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL3, selection, "Expected node-LL3 when latitude exceeds LL2 constraints and longitude is at LL2 boundary, " + "but got " + selection + " instead."); } @@ -567,7 +567,7 @@ void getNodeOffsetPointLLType_WhenLonOutsideLL2ConstraintAndLatAtLL2Boundary_Sho long transformedLong = LL_2_MINIMUM_MICRO_DEGREES - 1; // outside LL2 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL3, selection, "Expected node-LL3 when longitude exceeds LL2 constraints and latitude is at LL2 boundary, " + "but got " + selection + " instead."); } @@ -578,7 +578,7 @@ void getNodeOffsetPointLLType_WhenLatAndLonWithinLL3Constraints_ShouldReturnGetN long transformedLong = -25000; // within LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL3", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL3, selection, "Expected node-LL3 for latitude and longitude within LL3 constraints, " + "but got " + selection + " instead."); } @@ -589,7 +589,7 @@ void getNodeOffsetPointLLType_WhenLatOutsideLL3ConstraintAndLonAtLL3Boundary_Sho long transformedLong = LL_3_MINIMUM_MICRO_DEGREES; // at LL3 boundary String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL4, selection, "Expected node-LL4 when latitude exceeds LL3 constraints and longitude is at LL3 boundary, " + "but got " + selection + " instead."); } @@ -600,7 +600,7 @@ void getNodeOffsetPointLLType_WhenLonOutsideLL3ConstraintAndLatAtLL3Boundary_Sho long transformedLong = LL_3_MINIMUM_MICRO_DEGREES - 1; // outside LL3 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL4, selection, "Expected node-LL4 when longitude exceeds LL3 constraints and latitude is at LL3 boundary, " + "but got " + selection + " instead."); } @@ -611,7 +611,7 @@ void getNodeOffsetPointLLType_WhenLatAndLonWithinLL4Constraints_ShouldReturnGetN long transformedLong = -125000; // within LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL4", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL4, selection, "Expected node-LL4 for latitude and longitude within LL4 constraints, " + "but got " + selection + " instead."); } @@ -622,7 +622,7 @@ void getNodeOffsetPointLLType_WhenLatOutsideLL4ConstraintAndLonAtLL4Boundary_Sho long transformedLong = LL_4_MINIMUM_MICRO_DEGREES; // at LL4 boundary String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL5, selection, "Expected node-LL5 when latitude exceeds LL4 constraints and longitude is at LL4 boundary, " + "but got " + selection + " instead."); } @@ -633,7 +633,7 @@ void getNodeOffsetPointLLType_WhenLonOutsideLL4ConstraintAndLatAtLL4Boundary_Sho long transformedLong = LL_4_MINIMUM_MICRO_DEGREES - 1; // outside LL4 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL5, selection, "Expected node-LL5 when longitude exceeds LL4 constraints and latitude is at LL4 boundary, " + "but got " + selection + " instead."); } @@ -644,7 +644,7 @@ void getNodeOffsetPointLLType_WhenLatAndLonWithinLL5Constraints_ShouldReturnGetN long transformedLong = -2000000L; // within LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL5", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL5, selection, "Expected node-LL5 for latitude and longitude within LL5 constraints, " + "but got " + selection + " instead."); } @@ -655,7 +655,7 @@ void getNodeOffsetPointLLType_WhenLatOutsideLL5ConstraintAndLonAtLL5Boundary_Sho long transformedLong = LL_5_MINIMUM_MICRO_DEGREES; // at LL5 boundary String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL6, selection, "Expected node-LL6 when latitude exceeds LL5 constraints and longitude is at LL5 boundary, " + "but got " + selection + " instead."); } @@ -666,7 +666,7 @@ void getNodeOffsetPointLLType_WhenLonOutsideLL5ConstraintAndLatAtLL5Boundary_Sho long transformedLong = LL_5_MINIMUM_MICRO_DEGREES - 1; // outside LL5 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL6, selection, "Expected node-LL6 when longitude exceeds LL5 constraints and latitude is at LL5 boundary, " + "but got " + selection + " instead."); } @@ -677,7 +677,7 @@ void getNodeOffsetPointLLType_WhenLatAndLonWithinLL6Constraints_ShouldReturnGetN long transformedLong = -8000000L; // within LL6 constraints String selection = TravelerMessageFromHumanToAsnConverter.getNodeOffsetPointLLType(transformedLat, transformedLong); - Assertions.assertEquals("node-LL6", selection, + Assertions.assertEquals(TravelerMessageFromHumanToAsnConverter.NODE_LL6, selection, "Expected node-LL6 for latitude and longitude within LL6 constraints, " + "but got " + selection + " instead."); } From 41481651b89b5fa7956831ff8537d19f1b5328ba Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Mon, 24 Mar 2025 09:15:24 -0600 Subject: [PATCH 30/32] Changed some accessors to protected instead of public --- ...ravelerMessageFromHumanToAsnConverter.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index 038139a2d..e2b5011c1 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -634,7 +634,7 @@ private static ArrayNode transformNodeSetLL(JsonNode nodes) throws InvalidNodeLa return outputNodeList; } - public static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLatLonOffsetException { + protected static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLatLonOffsetException { //// EXPECTED INPUT: @@ -678,20 +678,20 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLat } // -- Nodes with LL content Span at the equator when using a zoom of one: - public static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node - public static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node - public static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node - public static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node - public static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node - public static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node + protected static final String NODE_LL1 = "node-LL1"; // Node-LL-24B, within ±22.634554 meters of last node + protected static final String NODE_LL2 = "node-LL2"; // Node-LL-28B, within ±90.571389 meters of last node + protected static final String NODE_LL3 = "node-LL3"; // Node-LL-32B, within ±362.31873 meters of last node + protected static final String NODE_LL4 = "node-LL4"; // Node-LL-36B, within ±1.449308 kilometers of last node + protected static final String NODE_LL5 = "node-LL5"; // Node-LL-44B, within ±23.189096 kilometers of last node + protected static final String NODE_LL6 = "node-LL6"; // Node-LL-48B, within ±92.756481 kilometers of last node // -- Limits for each node type - public final static long NODE_LL1_LIMIT = 2047; - public final static long NODE_LL2_LIMIT = 8191; - public final static long NODE_LL3_LIMIT = 32767; - public final static long NODE_LL4_LIMIT = 131071; - public final static long NODE_LL5_LIMIT = 2097151; - public final static long NODE_LL6_LIMIT = 8388607; + protected final static long NODE_LL1_LIMIT = 2047; + protected final static long NODE_LL2_LIMIT = 8191; + protected final static long NODE_LL3_LIMIT = 32767; + protected final static long NODE_LL4_LIMIT = 131071; + protected final static long NODE_LL5_LIMIT = 2097151; + protected final static long NODE_LL6_LIMIT = 8388607; // In J2735, the value -8388608 indicates an unknown value and is considered invalid because it falls outside the acceptable ± range. /** @@ -706,7 +706,7 @@ public static ObjectNode transformNodeLL(JsonNode oldNode) throws InvalidNodeLat * @throws InvalidNodeLatLonOffsetException if latDelta or lonDelta are outside the permissible range * of -0.8388608 to +0.8388607 degrees. */ - public static String getNodeOffsetPointLLType(long latDelta, long lonDelta) throws InvalidNodeLatLonOffsetException { + protected static String getNodeOffsetPointLLType(long latDelta, long lonDelta) throws InvalidNodeLatLonOffsetException { long absLatDelta = Math.abs(latDelta); long absLonDelta = Math.abs(lonDelta); From 24d0a664a68390fb891866e5e6ce0548936d79d1 Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Mon, 24 Mar 2025 09:19:46 -0600 Subject: [PATCH 31/32] Made `nonCompliantFields` list a static instance variable & reformatted the list --- .../TravelerMessageFromHumanToAsnConverter.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java index e2b5011c1..13074328a 100644 --- a/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java +++ b/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java @@ -1203,6 +1203,20 @@ private static String nodeOffsetPointXY(long transformedX, long transformedY) { } } + private static final Set nonCompliantFields = Set.of( + SSP_MSG_CONTENT, + SSP_MSG_TYPES, + SSP_LOCATION_RIGHTS, + SSP_TIM_RIGHTS, + SSP_MSG_RIGHTS_1, + SSP_MSG_RIGHTS_2, + NOT_USED, + NOT_USED_1, + NOT_USED_2, + NOT_USED_3, + DURATON_TIME_MISSPELLED + ); + /** * Ensures compliance with the J2735 2024 standard by checking * for old fields in the given data frame. @@ -1212,9 +1226,6 @@ private static String nodeOffsetPointXY(long transformedX, long transformedY) { */ public static void ensureComplianceWithJ2735Revision2024(ObjectNode dataFrame) throws NoncompliantFieldsException { // Check and throw exception if old fields are found - Set nonCompliantFields = - Set.of(SSP_MSG_CONTENT, SSP_MSG_TYPES, SSP_LOCATION_RIGHTS, SSP_TIM_RIGHTS, SSP_MSG_RIGHTS_1, SSP_MSG_RIGHTS_2, NOT_USED, NOT_USED_1, - NOT_USED_2, NOT_USED_3, DURATON_TIME_MISSPELLED); ArrayList violations = new ArrayList<>(); for (String violationName : nonCompliantFields) { if (dataFrame.has(violationName)) { From 6154bc28964a06d9814719b56288d077a2bb84ed Mon Sep 17 00:00:00 2001 From: dmccoystephenson Date: Mon, 24 Mar 2025 15:23:35 -0600 Subject: [PATCH 32/32] Specified `annotationProcessorPaths` in the root pom.xml --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index 3a04df47f..864cec291 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,13 @@ -Xlint:deprecation + + + org.projectlombok + lombok + 1.18.30 + +