diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java b/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java index f1ab3b7ca..5fae641f9 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java @@ -114,7 +114,7 @@ public void InjectDependencies(EmailProps _emailProps, OdeProps _odeProps, TimGe public WydotTravelerInputData createTim(WydotTim wydotTim, String timTypeStr, String startDateTime, String endDateTime, ContentEnum content, TravelerInfoType frameType, List allMileposts, - List reducedMileposts, Milepost anchor) { + List reducedMileposts, Milepost anchor, String dotGnisId) { // build base TIM WydotTravelerInputData timToSend = createBaseTimUtil.buildTim(wydotTim, genProps, content, frameType, @@ -147,13 +147,17 @@ public WydotTravelerInputData createTim(WydotTim wydotTim, String timTypeStr, St timToSend.getTim().getDataframes()[0].setDurationTime(120); } - // set PacketId to a random 18 character hex value + // Set PacketId as an 18-character hex string: DOT GNIS ID + random hex suffix Random rand = new Random(); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); + if (dotGnisId.equals("000000")) { + throw new IllegalStateException("DOT GNIS ID is set to default value of 000000. This is not a valid GNIS ID and should be changed in the configuration."); + } + sb.append(dotGnisId); while (sb.length() < 18) { sb.append(Integer.toHexString(rand.nextInt())); } - timToSend.getTim().setPacketID(sb.toString().substring(0, 18).toUpperCase()); + timToSend.getTim().setPacketID(sb.substring(0, 18).toUpperCase()); return timToSend; } diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/service/WydotTimServiceTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/service/WydotTimServiceTest.java index e14436a2f..3dd2765ee 100644 --- a/cv-data-service-library/src/test/java/com/trihydro/library/service/WydotTimServiceTest.java +++ b/cv-data-service-library/src/test/java/com/trihydro/library/service/WydotTimServiceTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -17,7 +18,6 @@ import java.io.IOException; import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; @@ -235,11 +235,12 @@ public void createTim_ReturnsNull_WhenBuildTimReturnsNull() { List allMileposts = new ArrayList<>(); List reducedMileposts = new ArrayList<>(); Milepost anchor = new Milepost(); + String dotGnisId = "1B2843"; when(mockCreateBaseTimUtil.buildTim(any(), any(), any(), any(), any(), any(), any())).thenReturn(null); // Act - WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor); + WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor, dotGnisId); // Assert assertNull(result); @@ -256,13 +257,14 @@ public void createTim_SetsStartDateTime_WhenProvided() { List allMileposts = new ArrayList<>(); List reducedMileposts = new ArrayList<>(); Milepost anchor = new Milepost(); + String dotGnisId = "1B2843"; WydotTravelerInputData timToSend = getMockWydotTravelerInputDataWithDataFrame(); when(mockCreateBaseTimUtil.buildTim(any(), any(), any(), any(), any(), any(), any())).thenReturn(timToSend); // Act - WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor); + WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor, dotGnisId); // Assert assertEquals(startDateTime, result.getTim().getDataframes()[0].getStartDateTime()); @@ -279,6 +281,7 @@ public void createTim_SetsDurationTime_WhenEndDateTimeProvided() { List allMileposts = new ArrayList<>(); List reducedMileposts = new ArrayList<>(); Milepost anchor = new Milepost(); + String dotGnisId = "1B2843"; WydotTravelerInputData timToSend = getMockWydotTravelerInputDataWithDataFrame(); @@ -286,7 +289,7 @@ public void createTim_SetsDurationTime_WhenEndDateTimeProvided() { when(mockUtility.getMinutesDurationBetweenTwoDates(anyString(), anyString())).thenReturn(60); // Act - WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor); + WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor, dotGnisId); // Assert assertEquals(60, result.getTim().getDataframes()[0].getDurationTime()); @@ -303,20 +306,21 @@ public void createTim_SetsDurationTimeTo120_ForParkingTim() { List allMileposts = new ArrayList<>(); List reducedMileposts = new ArrayList<>(); Milepost anchor = new Milepost(); + String dotGnisId = "1B2843"; WydotTravelerInputData timToSend = getMockWydotTravelerInputDataWithDataFrame(); when(mockCreateBaseTimUtil.buildTim(any(), any(), any(), any(), any(), any(), any())).thenReturn(timToSend); // Act - WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor); + WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor, dotGnisId); // Assert assertEquals(120, result.getTim().getDataframes()[0].getDurationTime()); } @Test - public void createTim_SetsRandomPacketId() { + public void createTim_SetsRandomPacketIdWithGnisIdPrefix() { // Arrange String timTypeStr = "A"; String startDateTime = "2023-01-01T00:00:00.000Z"; @@ -326,18 +330,43 @@ public void createTim_SetsRandomPacketId() { List allMileposts = new ArrayList<>(); List reducedMileposts = new ArrayList<>(); Milepost anchor = new Milepost(); + String dotGnisId = "1B2843"; WydotTravelerInputData timToSend = getMockWydotTravelerInputDataWithDataFrame(); when(mockCreateBaseTimUtil.buildTim(any(), any(), any(), any(), any(), any(), any())).thenReturn(timToSend); // Act - WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor); + WydotTravelerInputData result = uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor, dotGnisId); // Assert assertNotNull(result.getTim().getPacketID()); assertEquals(18, result.getTim().getPacketID().length()); assertTrue(result.getTim().getPacketID().matches("[0-9A-F]+")); + assertTrue(result.getTim().getPacketID().startsWith("1B2843")); + } + + @Test + public void createTim_ThrowsExceptionPacketIdUnsetGNISId() { + // Arrange + String timTypeStr = "A"; + String startDateTime = "2023-01-01T00:00:00.000Z"; + String endDateTime = "2023-01-01T01:00:00.000Z"; + ContentEnum content = ContentEnum.workZone; + TravelerInfoType frameType = TravelerInfoType.advisory; + List allMileposts = new ArrayList<>(); + List reducedMileposts = new ArrayList<>(); + Milepost anchor = new Milepost(); + String dotGnisId = "000000"; + + WydotTravelerInputData timToSend = getMockWydotTravelerInputDataWithDataFrame(); + + when(mockCreateBaseTimUtil.buildTim(any(), any(), any(), any(), any(), any(), any())).thenReturn(timToSend); + + // Act & Assert + assertThrows(IllegalStateException.class, () -> { + uut.createTim(new WydotTim(), timTypeStr, startDateTime, endDateTime, content, frameType, allMileposts, reducedMileposts, anchor, dotGnisId); + }); } @Test diff --git a/docker-compose.yml b/docker-compose.yml index f067bf275..b992df864 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: CONFIG_MAXIMUM_POOL_SIZE: ${WRAPPER_CONFIG_MAXIMUM_POOL_SIZE} CONFIG_CONNECTION_TIMEOUT: ${WRAPPER_CONFIG_CONNECTION_TIMEOUT} CONFIG_ENV: ${WRAPPER_CONFIG_ENV} + CONFIG_DB_DOT_GNIS_ID: ${WRAPPER_CONFIG_DOT_GNIS_ID} CONFIG_SDW_TTL: ${WRAPPER_CONFIG_SDW_TTL} CONFIG_SDW_REST_URL: ${SDW_REST_URL} CONFIG_SDW_API_KEY: ${SDW_API_KEY} diff --git a/ode-wrapper/README.md b/ode-wrapper/README.md index 43cd69116..7b4b2454f 100644 --- a/ode-wrapper/README.md +++ b/ode-wrapper/README.md @@ -110,21 +110,22 @@ You may configure these values in `ode-wrapper/src/main/resources/application.pr **IMPORTANT** When using the env file method, you must You must rename or duplicate the `sample.env` file to `.env`. If using the application.properties method, you must pass in the name of the environment to use with the `--spring.profiles.active` parameter. -| Environment Variable | Variable name in `sample.env` | Property name in `application.properties` | Description | Example Value | -| -------------------- | ------------------------------ | ----------------------------------------- | ----------------------------------------- | -------------------------------------------------------------- | -| SERVER_PORT | WRAPPER_SERVER_PORT | server.port | Server port to run on | 7777 | -| CONFIG_ODE_URL | WRAPPER_CONFIG_ODE_URL | config.odeUrl | URL pointing to the ODE | https://example.com:8443 | -| CONFIG_DB_URL | WRAPPER_CONFIG_DB_URL | config.dbUrl | Database URL | jdbc:postgresql://example.com:5432/dbname | -| CONFIG_DB_USERNAME | WRAPPER_CONFIG_DB_USERNAME | config.dbUsername | Database username | dbuser | -| CONFIG_DB_PASSWORD | WRAPPER_CONFIG_DB_PASSWORD | config.dbPassword | Password for database user | dbpassword | -| CONFIG_MAXIMUM_POOL_SIZE | WRAPPER_CONFIG_MAXIMUM_POOL_SIZE | config.maximumPoolSize | Number of threads in ThreadPool | 7 | -| CONFIG_CONNECTION_TIMEOUT | WRAPPER_CONFIG_CONNECTION_TIMEOUT | config.connectionTimeout | Connection timeout in milliseconds | 10000 | -| CONFIG_ENV | WRAPPER_CONFIG_ENV | config.env | Configuration environment | dev | -| CONFIG_SDW_TTL | WRAPPER_CONFIG_SDW_TTL | config.sdwTtl | SDW time to live default | oneday | -| CONFIG_SDW_REST_URL | SDW_REST_URL | config.sdwRestUrl | REST endpoint for SDX | https://sdx-endpoint.com | -| CONFIG_SDW_API_KEY | SDW_API_KEY | config.sdwApiKey | API Key for accessing SDX | asdf | -| CONFIG_ALERT_ADDRESSES | WRAPPER_CONFIG_ALERT_ADDRESSES | config.alertAddresses | List of email addresses to send alerts to | user@example.com,user2@example.com | -| CONFIG_FROM_EMAIL | WRAPPER_CONFIG_FROM_EMAIL | config.fromEmail | Email to send alerts from | support@example.com | +| Environment Variable | Variable name in `sample.env` | Property name in `application.properties` | Description | Example Value | +| -------------------- | ------------------------------ | ----------------------------------------- | ----------------------------------------- | ------------------------------------------------------------- | +| SERVER_PORT | WRAPPER_SERVER_PORT | server.port | Server port to run on | 7777 | +| CONFIG_ODE_URL | WRAPPER_CONFIG_ODE_URL | config.odeUrl | URL pointing to the ODE | https://example.com:8443 | +| CONFIG_DB_URL | WRAPPER_CONFIG_DB_URL | config.dbUrl | Database URL | jdbc:postgresql://example.com:5432/dbname | +| CONFIG_DB_USERNAME | WRAPPER_CONFIG_DB_USERNAME | config.dbUsername | Database username | dbuser | +| CONFIG_DB_PASSWORD | WRAPPER_CONFIG_DB_PASSWORD | config.dbPassword | Password for database user | dbpassword | +| CONFIG_MAXIMUM_POOL_SIZE | WRAPPER_CONFIG_MAXIMUM_POOL_SIZE | config.maximumPoolSize | Number of threads in ThreadPool | 7 | +| CONFIG_CONNECTION_TIMEOUT | WRAPPER_CONFIG_CONNECTION_TIMEOUT | config.connectionTimeout | Connection timeout in milliseconds | 10000 | +| CONFIG_ENV | WRAPPER_CONFIG_ENV | config.env | Configuration environment | dev | +| CONFIG_DOT_GNIS_ID | WRAPPER_CONFIG_DOT_GNIS_ID | config.dotGnisId | GNIS ID of the DOT used for the packetID | CDOT: 1B2843, UDOT: 163775, WYDOT: 1B285F | +| CONFIG_SDW_TTL | WRAPPER_CONFIG_SDW_TTL | config.sdwTtl | SDW time to live default | oneday | +| CONFIG_SDW_REST_URL | SDW_REST_URL | config.sdwRestUrl | REST endpoint for SDX | https://sdx-endpoint.com | +| CONFIG_SDW_API_KEY | SDW_API_KEY | config.sdwApiKey | API Key for accessing SDX | asdf | +| CONFIG_ALERT_ADDRESSES | WRAPPER_CONFIG_ALERT_ADDRESSES | config.alertAddresses | List of email addresses to send alerts to | user@example.com,user2@example.com | +| CONFIG_FROM_EMAIL | WRAPPER_CONFIG_FROM_EMAIL | config.fromEmail | Email to send alerts from | support@example.com | | CONFIG_MAIL_HOST | MAIL_HOST | config.mailHost | IP of mail host | example.com | | CONFIG_MAIL_PORT | MAIL_PORT | config.mailPort | Port for mail host | 25 | | CONFIG_ENVIRONMENT_NAME | ENVIRONMENT_NAME | config.environmentName | Name of environment (for email subject) | DEV | diff --git a/ode-wrapper/src/main/java/com/trihydro/odewrapper/config/BasicConfiguration.java b/ode-wrapper/src/main/java/com/trihydro/odewrapper/config/BasicConfiguration.java index 4b9177252..bc20354c8 100644 --- a/ode-wrapper/src/main/java/com/trihydro/odewrapper/config/BasicConfiguration.java +++ b/ode-wrapper/src/main/java/com/trihydro/odewrapper/config/BasicConfiguration.java @@ -26,6 +26,7 @@ public class BasicConfiguration implements SdwProps, RsuDataServiceProps, TmddPr private String odeUrl; private String sdwRestUrl; private String sdwApiKey; + private String dotGnisId; private String mailHost; private int mailPort; private String[] alertAddresses; @@ -84,6 +85,10 @@ public void setSdwApiKey(String sdwApiKey) { this.sdwApiKey = sdwApiKey; } + public String getDotGnisId() { return dotGnisId; } + + public void setDotGnisId(String dotGnisId) { this.dotGnisId = dotGnisId; } + public int getMailPort() { return mailPort; } diff --git a/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimBaseController.java b/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimBaseController.java index 506eb93ce..422813c5c 100644 --- a/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimBaseController.java +++ b/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimBaseController.java @@ -739,7 +739,7 @@ protected void createSendTims(WydotTim wydotTim, TimType timType, String startDa // create TIM WydotTravelerInputData timToSend = wydotTimService.createTim(wydotTim, timType.getType(), startDateTime, endDateTime, - content, frameType, allMileposts, reducedMileposts, anchor); + content, frameType, allMileposts, reducedMileposts, anchor, configuration.getDotGnisId()); if (timToSend == null) { return; diff --git a/ode-wrapper/src/main/resources/application-dev.properties b/ode-wrapper/src/main/resources/application-dev.properties index efb8a6b36..ac3f25848 100644 --- a/ode-wrapper/src/main/resources/application-dev.properties +++ b/ode-wrapper/src/main/resources/application-dev.properties @@ -13,6 +13,7 @@ config.sdwApiKey= config.alertAddresses=user@example.com,user2@example.com config.fromEmail=support@example.com config.environmentName=DEV +config.dotGnisId=${WRAPPER_CONFIG_DOT_GNIS_ID:000000} config.mailHost=localhost config.mailPort=25 config.defaultLaneWidth=50 diff --git a/sample.env b/sample.env index 610c7b264..3e29e4055 100644 --- a/sample.env +++ b/sample.env @@ -81,6 +81,7 @@ WRAPPER_CONFIG_DB_PASSWORD= WRAPPER_CONFIG_MAXIMUM_POOL_SIZE=7 WRAPPER_CONFIG_CONNECTION_TIMEOUT=300000 WRAPPER_CONFIG_ENV=dev +WRAPPER_CONFIG_DOT_GNIS_ID= WRAPPER_CONFIG_SDW_TTL=oneday WRAPPER_CONFIG_ALERT_ADDRESSES=user@example.com,user2@example.com WRAPPER_CONFIG_FROM_EMAIL=support@example.com