diff --git a/README.md b/README.md index 881066d06..3a3d6157b 100644 --- a/README.md +++ b/README.md @@ -98,28 +98,28 @@ This will create the `target` folder under each module. From here, create a new ``` . ├── cv-data-controller -│ ├── cv-data-controller-1.4.0-SNAPSHOT.jar +│ ├── cv-data-controller-x.x.x.jar │ ├── Dockerfile ├── cv-data-tasks -│ ├── cv-data-tasks-1.4.0-SNAPSHOT.jar +│ ├── cv-data-tasks-x.x.x.jar │ ├── Dockerfile ├── docker-compose.yml ├── ode-data-logger │ ├── Dockerfile -│ ├── ode-data-logger-1.4.0-SNAPSHOT.jar +│ ├── ode-data-logger-x.x.x.jar ├── ode-mongo-logger │ ├── Dockerfile -│ ├── ode-mongo-logger-1.4.0-SNAPSHOT.jar +│ ├── ode-mongo-logger-x.x.x.jar ├── ode-wrapper │ ├── Dockerfile -│ ├── ode-wrapper-1.4.0-SNAPSHOT.jar +│ ├── ode-wrapper-x.x.x.jar ├── ode-wrapper-docs │ └── swagger-ui-master │ ├── Dockerfile │ ├── (swagger folder structure) └── tim-refresh ├── Dockerfile - ├── tim-refresh-1.4.0-SNAPSHOT.jar + ├── tim-refresh-x.x.x.jar ``` diff --git a/cert-expiration/Dockerfile b/cert-expiration/Dockerfile index 04162921f..5a47ec21d 100644 --- a/cert-expiration/Dockerfile +++ b/cert-expiration/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/cert-expiration -CMD java -jar /home/timm/timm_applications/cert-expiration/cert-expiration-1.4.0-SNAPSHOT.jar +CMD java -jar /home/timm/timm_applications/cert-expiration/cert-expiration-2.0.0.jar diff --git a/cert-expiration/pom.xml b/cert-expiration/pom.xml index e58dae7ce..aba120f33 100644 --- a/cert-expiration/pom.xml +++ b/cert-expiration/pom.xml @@ -5,7 +5,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 cert-expiration diff --git a/cv-data-controller/Dockerfile b/cv-data-controller/Dockerfile index 4806f2e76..65dcf933e 100644 --- a/cv-data-controller/Dockerfile +++ b/cv-data-controller/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/cv-data-controller -CMD java --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/timm/timm_applications/cv-data-controller/cv-data-controller-1.4.0-SNAPSHOT.jar +CMD java --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/timm/timm_applications/cv-data-controller/cv-data-controller-2.0.0.jar diff --git a/cv-data-controller/README.md b/cv-data-controller/README.md index dee9f9a1b..c51a56132 100644 --- a/cv-data-controller/README.md +++ b/cv-data-controller/README.md @@ -111,6 +111,10 @@ You may configure these values in `cv-data-controller/src/main/resources/applica | SERVER_SSL_KEY_STORE_TYPE | CONTROLLER_SERVER_SSL_KEY_STORE_TYPE | server.ssl.keyStoreType | **PROD ONLY** Keystore type (JKS) | JKS | | SERVER_SSL_KEY_ALIAS | CONTROLLER_SERVER_SSL_KEY_ALIAS | server.ssl.keyAlias | **PROD ONLY** Alias for Keystore | example.alias | +## Note on Neo4j Database +The system expects a Neo4j database to be running and accessible at the address specified in the `application.properties` file or the `sample.env` file. The +database should be populated with the necessary data for the system to function properly. The database should be running before starting the application. + ## Testing To run the unit tests, follow these steps: 1. Reopen the project in the provided dev container by clicking on the blue button in the bottom left corner of the window and selecting "Reopen in Container" diff --git a/cv-data-controller/pom.xml b/cv-data-controller/pom.xml index 5f80a13e1..c3736e270 100644 --- a/cv-data-controller/pom.xml +++ b/cv-data-controller/pom.xml @@ -7,7 +7,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/ActiveTimController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/ActiveTimController.java index 0693288c7..a5a35e9be 100644 --- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/ActiveTimController.java +++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/ActiveTimController.java @@ -41,6 +41,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpServerErrorException; import springfox.documentation.annotations.ApiIgnore; import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType.TravelerInfoType; @@ -74,9 +75,8 @@ public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNull * @return List of ActiveTim objects */ @RequestMapping(value = "/expiring", method = RequestMethod.GET, produces = "application/json", headers = "Accept=application/json") - public ResponseEntity> GetExpiringActiveTims() throws SQLException { - TimUpdateModel activeTim; - List activeTims = new ArrayList(); + public ResponseEntity> GetExpiringActiveTims() { + List activeTims = new ArrayList<>(); String selectStatement = "SELECT atim.*, tt.type as tim_type_name, tt.description as tim_type_description"; selectStatement += ", t.msg_cnt, t.url_b, t.is_satellite, t.sat_record_id, t.packet_id"; @@ -100,72 +100,18 @@ public ResponseEntity> GetExpiringActiveTims() throws SQLEx try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(selectStatement)) { // convert to ActiveTim object while (rs.next()) { - activeTim = new TimUpdateModel(); - - // Active_Tim properties - activeTim.setActiveTimId(rs.getLong("ACTIVE_TIM_ID")); - activeTim.setTimId(rs.getLong("TIM_ID")); - activeTim.setDirection(rs.getString("DIRECTION")); - activeTim.setStartDateTime(rs.getString("TIM_START")); - activeTim.setEndDateTime(rs.getString("TIM_END")); - activeTim.setExpirationDateTime(rs.getString("EXPIRATION_DATE")); - activeTim.setSatRecordId(rs.getString("SAT_RECORD_ID")); - activeTim.setClientId(rs.getString("CLIENT_ID")); - activeTim.setRoute(rs.getString("ROUTE")); - - Coordinate startPoint = null; - Coordinate endPoint = null; - BigDecimal startLat = rs.getBigDecimal("START_LATITUDE"); - BigDecimal startLon = rs.getBigDecimal("START_LONGITUDE"); - if (!rs.wasNull()) { - startPoint = new Coordinate(startLat, startLon); - } - activeTim.setStartPoint(startPoint); - - BigDecimal endLat = rs.getBigDecimal("END_LATITUDE"); - BigDecimal endLon = rs.getBigDecimal("END_LONGITUDE"); - if (!rs.wasNull()) { - endPoint = new Coordinate(endLat, endLon); - } - activeTim.setEndPoint(endPoint); - - activeTim.setStartDate_Timestamp(rs.getTimestamp("TIM_START", UTCCalendar)); - activeTim.setEndDate_Timestamp(rs.getTimestamp("TIM_END", UTCCalendar)); - - // Tim properties - activeTim.setMsgCnt(rs.getInt("MSG_CNT")); - activeTim.setUrlB(rs.getString("URL_B")); - activeTim.setPacketId(rs.getString("PACKET_ID")); - - // Tim Type properties - activeTim.setTimTypeName(rs.getString("TIM_TYPE_NAME")); - activeTim.setTimTypeDescription(rs.getString("TIM_TYPE_DESCRIPTION")); - - // Region Properties - activeTim.setRegionId(rs.getInt("REGION_ID")); - activeTim.setAnchorLat(rs.getBigDecimal("ANCHOR_LAT")); - activeTim.setAnchorLong(rs.getBigDecimal("ANCHOR_LONG")); - - activeTim.setLaneWidth(rs.getBigDecimal("LANE_WIDTH")); - activeTim.setRegionDirection(rs.getString("REGION_DIRECTION")); - activeTim.setDirectionality(rs.getString("DIRECTIONALITY")); - activeTim.setClosedPath(rs.getBoolean("CLOSED_PATH")); - activeTim.setPathId(rs.getInt("PATH_ID")); - activeTim.setRegionDescription(rs.getString("REGION_DESCRIPTION")); - - // DataFrame properties - activeTim.setDataFrameId(rs.getInt("DATA_FRAME_ID")); - activeTim.setDurationTime(rs.getInt("DURATION_TIME")); - activeTim.setNotUsed1((short) 0); // as of J2735 this should be set to 0 and is ignored - activeTim.setNotUsed((short) 0); // as of J2735 this should be set to 0 and is ignored - activeTim.setNotUsed3((short) 0); // as of J2735 this should be set to 0 and is ignored - activeTim.setNotUsed2((short) 0); // as of J2735 this should be set to 0 and is ignored - activeTim.setUrl(rs.getString("URL")); + var activeTim = buildTimUpdateModelFromResultSet(rs); int frameTypeValue = rs.getInt("FRAME_TYPE"); if (!rs.wasNull() && frameTypeValue >= 0 && frameTypeValue < TravelerInfoType.values().length) { activeTim.setFrameType(TravelerInfoType.values()[frameTypeValue]); } + else { + log.warn("Could not set frame type from value {} for active tim id {}. Assuming Advisory.", frameTypeValue, + activeTim.getActiveTimId()); + // assume advisory + activeTim.setFrameType(TravelerInfoType.advisory); + } // set dataFrame content. it's required for the ODE, so if we didn't record it, // assume Advisory @@ -210,72 +156,18 @@ public ResponseEntity GetUpdateModelFromActiveTimId(@PathVariabl try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(selectStatement)) { // convert to ActiveTim object while (rs.next()) { - activeTim = new TimUpdateModel(); - // Active_Tim properties - activeTim.setActiveTimId(rs.getLong("ACTIVE_TIM_ID")); - activeTim.setTimId(rs.getLong("TIM_ID")); - activeTim.setDirection(rs.getString("DIRECTION")); - activeTim.setStartDateTime(rs.getString("TIM_START")); - activeTim.setEndDateTime(rs.getString("TIM_END")); - activeTim.setExpirationDateTime(rs.getString("EXPIRATION_DATE")); - activeTim.setSatRecordId(rs.getString("SAT_RECORD_ID")); - activeTim.setClientId(rs.getString("CLIENT_ID")); - activeTim.setRoute(rs.getString("ROUTE")); - - Coordinate startPoint = null; - Coordinate endPoint = null; - BigDecimal startLat = rs.getBigDecimal("START_LATITUDE"); - BigDecimal startLon = rs.getBigDecimal("START_LONGITUDE"); - if (!rs.wasNull()) { - startPoint = new Coordinate(startLat, startLon); - } - activeTim.setStartPoint(startPoint); - - BigDecimal endLat = rs.getBigDecimal("END_LATITUDE"); - BigDecimal endLon = rs.getBigDecimal("END_LONGITUDE"); - if (!rs.wasNull()) { - endPoint = new Coordinate(endLat, endLon); - } - activeTim.setEndPoint(endPoint); - - activeTim.setStartDate_Timestamp(rs.getTimestamp("TIM_START", UTCCalendar)); - activeTim.setEndDate_Timestamp(rs.getTimestamp("TIM_END", UTCCalendar)); - - // Tim properties - activeTim.setMsgCnt(rs.getInt("MSG_CNT")); - activeTim.setUrlB(rs.getString("URL_B")); - activeTim.setPacketId(rs.getString("PACKET_ID")); - - // Tim Type properties - activeTim.setTimTypeName(rs.getString("TIM_TYPE_NAME")); - activeTim.setTimTypeDescription(rs.getString("TIM_TYPE_DESCRIPTION")); - - // Region Properties - activeTim.setRegionId(rs.getInt("REGION_ID")); - activeTim.setAnchorLat(rs.getBigDecimal("ANCHOR_LAT")); - activeTim.setAnchorLong(rs.getBigDecimal("ANCHOR_LONG")); - - activeTim.setLaneWidth(rs.getBigDecimal("LANE_WIDTH")); - activeTim.setRegionDirection(rs.getString("REGION_DIRECTION")); - activeTim.setDirectionality(rs.getString("DIRECTIONALITY")); - activeTim.setClosedPath(rs.getBoolean("CLOSED_PATH")); - activeTim.setPathId(rs.getInt("PATH_ID")); - activeTim.setRegionDescription(rs.getString("REGION_DESCRIPTION")); - - // DataFrame properties - activeTim.setDataFrameId(rs.getInt("DATA_FRAME_ID")); - activeTim.setDurationTime(rs.getInt("DURATION_TIME")); - activeTim.setNotUsed1((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - activeTim.setNotUsed((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - activeTim.setNotUsed3((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - activeTim.setNotUsed2((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - activeTim.setUrl(rs.getString("URL")); + activeTim = buildTimUpdateModelFromResultSet(rs); int frameTypeValue = rs.getInt("FRAME_TYPE"); if (!rs.wasNull() && frameTypeValue >= 0 && frameTypeValue < TravelerInfoType.values().length) { activeTim.setFrameType(TravelerInfoType.values()[frameTypeValue]); } + else { + log.warn("Could not set frame type from value {} for active tim id {}. Assuming Advisory.", frameTypeValue, activeTimId); + // assume advisory + activeTim.setFrameType(TravelerInfoType.advisory); + } // set dataFrame content. it's required for the ODE, so if we didn't record it, // assume Advisory @@ -373,22 +265,19 @@ public ResponseEntity> GetActiveTimsNotSent() { return ResponseEntity.ok(activeTims); } - @RequestMapping(value = "/expired", method = RequestMethod.GET) - public ResponseEntity> GetExpiredActiveTims() { - List activeTims = new ArrayList(); - - String selectStatement = "select * from ACTIVE_TIM"; - selectStatement += " WHERE TIM_END <= (NOW() AT TIME ZONE 'UTC')"; - - try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(selectStatement)) { - activeTims = getActiveTimFromRS(rs, false); - } catch (SQLException e) { - log.error("Error getting expired active tims", e); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(activeTims); - } - - return ResponseEntity.ok(activeTims); - } + @RequestMapping(value = "/expired", method = RequestMethod.GET) + public ResponseEntity> GetExpiredActiveTims(@RequestParam(required = false, defaultValue = "100") Integer limit) { + String query = "SELECT * FROM ACTIVE_TIM WHERE TIM_END <= (NOW() AT TIME ZONE 'UTC') LIMIT ?"; + try (Connection connection = dbInteractions.getConnectionPool(); PreparedStatement preparedStatement = connection.prepareStatement(query)) { + preparedStatement.setInt(1, limit); + try (ResultSet rs = preparedStatement.executeQuery()) { + return ResponseEntity.ok(getActiveTimFromRS(rs, false)); + } + } catch (SQLException e) { + log.error("Error retrieving expired active tims", e); + throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving expired active tims"); + } + } @RequestMapping(value = "/indices-rsu/{rsuTarget}", method = RequestMethod.GET) public ResponseEntity> GetActiveTimIndicesByRsu(@PathVariable String rsuTarget) { @@ -1134,4 +1023,63 @@ public ResponseEntity MarkForDeletion(@PathVariable Long activeTimId) { } return ResponseEntity.ok(success); } + + private TimUpdateModel buildTimUpdateModelFromResultSet(ResultSet rs) throws SQLException { + TimUpdateModel timUpdateModel = new TimUpdateModel(); + timUpdateModel.setActiveTimId(rs.getLong("ACTIVE_TIM_ID")); + timUpdateModel.setTimId(rs.getLong("TIM_ID")); + timUpdateModel.setDirection(rs.getString("DIRECTION")); + timUpdateModel.setStartDateTime(rs.getString("TIM_START")); + timUpdateModel.setEndDateTime(rs.getString("TIM_END")); + timUpdateModel.setExpirationDateTime(rs.getString("EXPIRATION_DATE")); + timUpdateModel.setSatRecordId(rs.getString("SAT_RECORD_ID")); + timUpdateModel.setClientId(rs.getString("CLIENT_ID")); + timUpdateModel.setRoute(rs.getString("ROUTE")); + + Coordinate startPoint = null; + Coordinate endPoint = null; + BigDecimal startLat = rs.getBigDecimal("START_LATITUDE"); + BigDecimal startLon = rs.getBigDecimal("START_LONGITUDE"); + if (!rs.wasNull()) { + startPoint = new Coordinate(startLat, startLon); + } + timUpdateModel.setStartPoint(startPoint); + + BigDecimal endLat = rs.getBigDecimal("END_LATITUDE"); + BigDecimal endLon = rs.getBigDecimal("END_LONGITUDE"); + if (!rs.wasNull()) { + endPoint = new Coordinate(endLat, endLon); + } + timUpdateModel.setEndPoint(endPoint); + + timUpdateModel.setStartDate_Timestamp(rs.getTimestamp("TIM_START", UTCCalendar)); + timUpdateModel.setEndDate_Timestamp(rs.getTimestamp("TIM_END", UTCCalendar)); + + // Tim properties + timUpdateModel.setMsgCnt(rs.getInt("MSG_CNT")); + timUpdateModel.setUrlB(rs.getString("URL_B")); + timUpdateModel.setPacketId(rs.getString("PACKET_ID")); + + // Tim Type properties + timUpdateModel.setTimTypeName(rs.getString("TIM_TYPE_NAME")); + timUpdateModel.setTimTypeDescription(rs.getString("TIM_TYPE_DESCRIPTION")); + + // Region Properties + timUpdateModel.setRegionId(rs.getInt("REGION_ID")); + timUpdateModel.setAnchorLat(rs.getBigDecimal("ANCHOR_LAT")); + timUpdateModel.setAnchorLong(rs.getBigDecimal("ANCHOR_LONG")); + + timUpdateModel.setLaneWidth(rs.getBigDecimal("LANE_WIDTH")); + timUpdateModel.setRegionDirection(rs.getString("REGION_DIRECTION")); + timUpdateModel.setDirectionality(rs.getString("DIRECTIONALITY")); + timUpdateModel.setClosedPath(rs.getBoolean("CLOSED_PATH")); + timUpdateModel.setPathId(rs.getInt("PATH_ID")); + timUpdateModel.setRegionDescription(rs.getString("REGION_DESCRIPTION")); + + // DataFrame properties + timUpdateModel.setDataFrameId(rs.getInt("DATA_FRAME_ID")); + timUpdateModel.setDurationTime(rs.getInt("DURATION_TIME")); + timUpdateModel.setUrl(rs.getString("URL")); + return timUpdateModel; + } } diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/DataFrameController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/DataFrameController.java index da9167f51..2c8c3950b 100644 --- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/DataFrameController.java +++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/DataFrameController.java @@ -14,9 +14,6 @@ import java.util.List; import java.util.TimeZone; -import com.trihydro.library.helpers.SQLNullHandler; -import com.trihydro.library.tables.TimDbTables; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -27,6 +24,9 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import com.trihydro.library.helpers.SQLNullHandler; +import com.trihydro.library.tables.TimDbTables; + import springfox.documentation.annotations.ApiIgnore; import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame; @@ -111,8 +111,6 @@ public ResponseEntity AddDataFrame(@RequestBody DataFrame dFrame, @PathVar for (String col : timDbTables.getDataFrameTable()) { if (col.equals("TIM_ID")) { sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, timId); - } else if (col.equals("SSP_TIM_RIGHTS")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed()); } else if (col.equals("FRAME_TYPE")) { Integer ordinal = null; if (dFrame.getFrameType() != null) { @@ -123,12 +121,6 @@ public ResponseEntity AddDataFrame(@RequestBody DataFrame dFrame, @PathVar sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, dFrame.getDurationTime()); } else if (col.equals("PRIORITY")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, dFrame.getPriority()); - } else if (col.equals("SSP_LOCATION_RIGHTS")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed1()); - } else if (col.equals("SSP_MSG_TYPES")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed3()); - } else if (col.equals("SSP_MSG_CONTENT")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed2()); } else if (col.equals("CONTENT")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, dFrame.getContent()); } else if (col.equals("URL")) { diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/NodeXYController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/NodeXYController.java index c65e98ced..9975e45fd 100644 --- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/NodeXYController.java +++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/NodeXYController.java @@ -56,19 +56,19 @@ else if (col.equals("NODE_LAT")) else if (col.equals("NODE_LONG")) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getNodeLong()); else if (col.equals("X")) - sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getX()); + sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getXpos()); else if (col.equals("Y")) - sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getY()); + sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getYpos()); else if (col.equals("ATTRIBUTES_DWIDTH")) if (nodeXY.getAttributes() != null) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, - nodeXY.getAttributes().getdWidth()); + nodeXY.getAttributes().getDwidth()); else preparedStatement.setString(fieldNum, null); else if (col.equals("ATTRIBUTES_DELEVATION")) if (nodeXY.getAttributes() != null) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, - nodeXY.getAttributes().getdElevation()); + nodeXY.getAttributes().getDelevation()); else preparedStatement.setString(fieldNum, null); fieldNum++; diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/PathNodeXYController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/PathNodeXYController.java index a98f6b2bd..3fa1e6a04 100644 --- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/PathNodeXYController.java +++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/PathNodeXYController.java @@ -62,8 +62,8 @@ public ResponseEntity GetNodeXYForPath(@PathVariable int pathId) { nodexy.setDelta(rs.getString("DELTA")); nodexy.setNodeLat(rs.getBigDecimal("NODE_LAT")); nodexy.setNodeLong(rs.getBigDecimal("NODE_LONG")); - nodexy.setX(rs.getBigDecimal("X")); - nodexy.setY(rs.getBigDecimal("Y")); + nodexy.setXpos(rs.getBigDecimal("X")); + nodexy.setYpos(rs.getBigDecimal("Y")); nodeXYs.add(nodexy); } diff --git a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/ActiveTimControllerTest.java b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/ActiveTimControllerTest.java index 1804f1868..b52ca03fb 100644 --- a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/ActiveTimControllerTest.java +++ b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/ActiveTimControllerTest.java @@ -35,6 +35,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpServerErrorException; import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType; public class ActiveTimControllerTest extends TestBase { @@ -337,15 +338,17 @@ public void GetActiveTimsNotSent_FAIL() throws SQLException { @Test public void GetExpiredActiveTims_SUCCESS() throws SQLException { // Arrange - String statementStr = "select * from ACTIVE_TIM"; - statementStr += " WHERE TIM_END <= (NOW() AT TIME ZONE 'UTC')"; + String statementStr = "SELECT * FROM ACTIVE_TIM"; + statementStr += " WHERE TIM_END <= (NOW() AT TIME ZONE 'UTC') LIMIT ?"; // Act - ResponseEntity> aTims = uut.GetExpiredActiveTims(); + ResponseEntity> aTims = uut.GetExpiredActiveTims(500); // Assert Assertions.assertEquals(HttpStatus.OK, aTims.getStatusCode()); - verify(mockStatement).executeQuery(statementStr); + verify(mockConnection).prepareStatement(statementStr); + verify(mockPreparedStatement).setInt(1, 500); + verify(mockPreparedStatement).executeQuery(); verify(mockRs).getLong("ACTIVE_TIM_ID"); verify(mockRs).getLong("TIM_ID"); verify(mockRs).getString("SAT_RECORD_ID"); @@ -356,7 +359,7 @@ public void GetExpiredActiveTims_SUCCESS() throws SQLException { verify(mockRs).getString("CLIENT_ID"); verify(mockRs).getString("ROUTE"); verify(mockRs).getString("DIRECTION"); - verify(mockStatement).close(); + verify(mockPreparedStatement).close(); verify(mockConnection).close(); Assertions.assertEquals(1, aTims.getBody().size()); } @@ -364,19 +367,18 @@ public void GetExpiredActiveTims_SUCCESS() throws SQLException { @Test public void GetExpiredActiveTims_FAIL() throws SQLException { // Arrange - String statementStr = "select * from ACTIVE_TIM"; - statementStr += " WHERE TIM_END <= (NOW() AT TIME ZONE 'UTC')"; - when(mockStatement.executeQuery(isA(String.class))).thenThrow(new SQLException()); + String statementStr = "SELECT * FROM ACTIVE_TIM"; + statementStr += " WHERE TIM_END <= (NOW() AT TIME ZONE 'UTC') LIMIT ?"; + when(mockPreparedStatement.executeQuery()).thenThrow(new SQLException()); // Act - ResponseEntity> aTims = uut.GetExpiredActiveTims(); + Assertions.assertThrows(HttpServerErrorException.class, () -> uut.GetExpiredActiveTims(500)); // Assert - Assertions.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, aTims.getStatusCode()); - verify(mockStatement).executeQuery(statementStr); - verify(mockStatement).close(); + verify(mockConnection).prepareStatement(statementStr); + verify(mockPreparedStatement).executeQuery(); + verify(mockPreparedStatement).close(); verify(mockConnection).close(); - Assertions.assertEquals(0, aTims.getBody().size()); } @Test diff --git a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/NodeXYControllerTest.java b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/NodeXYControllerTest.java index a64953b23..4037489ff 100644 --- a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/NodeXYControllerTest.java +++ b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/NodeXYControllerTest.java @@ -50,11 +50,11 @@ public void AddNodeXY_SUCCESS() throws SQLException { verify(mockSqlNullHandler).setStringOrNull(mockPreparedStatement, 1, nodeXY.getDelta());// DELTA verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 2, nodeXY.getNodeLat());// NODE_LAT verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 3, nodeXY.getNodeLong());// NODE_LONG - verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 4, nodeXY.getX());// X - verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 5, nodeXY.getY());// Y - verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 6, nodeXY.getAttributes().getdWidth());// ATTRIBUTES_DWIDTH + verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 4, nodeXY.getXpos());// X + verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 5, nodeXY.getYpos());// Y + verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 6, nodeXY.getAttributes().getDwidth());// ATTRIBUTES_DWIDTH verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 7, - nodeXY.getAttributes().getdElevation());// ATTRIBUTES_DELEVATION + nodeXY.getAttributes().getDelevation());// ATTRIBUTES_DELEVATION verify(mockPreparedStatement).close(); verify(mockConnection).close(); } diff --git a/cv-data-service-library/pom.xml b/cv-data-service-library/pom.xml index 164f19787..1127a39b3 100644 --- a/cv-data-service-library/pom.xml +++ b/cv-data-service-library/pom.xml @@ -4,7 +4,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 cv-data-service-library diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CreateBaseTimUtil.java b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CreateBaseTimUtil.java index 4b256573c..52174c1f5 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CreateBaseTimUtil.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CreateBaseTimUtil.java @@ -59,10 +59,6 @@ public WydotTravelerInputData buildTim(WydotTim wydotTim, TimGenerationProps gen // set TIM Properties OdeTravelerInformationMessage.DataFrame dataFrame = new OdeTravelerInformationMessage.DataFrame(); - dataFrame.setNotUsed((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - dataFrame.setNotUsed1((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - dataFrame.setNotUsed2((short) 0); // as of J2735 2020 this should be set to 0 and is ignored - dataFrame.setNotUsed3((short) 0); // as of J2735 2020 this should be set to 0 and is ignored // set TIM TimeStamp and StartDateTime to current time in UTC String nowAsISO = Instant.now().toString(); diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/DbInteractions.java b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/DbInteractions.java index 3d540c82b..1877fe2f6 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/DbInteractions.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/DbInteractions.java @@ -10,27 +10,48 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +/** + * The DbInteractions class is responsible for managing database interactions such as + * obtaining connections from a connection pool, executing SQL operations, and logging results. + * It facilitates configurations related to database connectivity and supports email alerts + * in case of operation failures. + *

+ * This class is annotated with {@code @Component} for Spring's component scanning and + * uses HikariCP for connection pooling. It depends on {@link DbInteractionsProps} for + * database configuration properties and {@link EmailHelper} for sending alert emails. + */ @Component +@Slf4j public class DbInteractions { private static HikariDataSource dataSource; - protected DbInteractionsProps dbConfig; - protected Utility utility; - protected EmailHelper emailHelper; + private final DbInteractionsProps dbConfig; + private final EmailHelper emailHelper; @Autowired - public void InjectDependencies(DbInteractionsProps props, Utility _utility, EmailHelper _emailHelper) { - dbConfig = props; - utility = _utility; - emailHelper = _emailHelper; - utility.logWithDate("A new DbInteractions instance has been created.", this.getClass()); + public DbInteractions(DbInteractionsProps props, EmailHelper emailHelper) { + this.dbConfig = props; + this.emailHelper = emailHelper; + log.info("A new DbInteractions instance has been created."); validateDbConfig(); } + /** + * Retrieves a connection from the connection pool. If the connection pool + * has not been initialized, it initializes the primary connection pool + * before retrieving a connection. + *

+ * In case of a failure in obtaining a connection, an email alert is sent + * to the configured alert addresses and a {@link SQLException} is thrown. + * + * @return A {@link Connection} instance from the connection pool. + * @throws SQLException If unable to retrieve a connection from the pool. + */ public Connection getConnectionPool() throws SQLException { // create pool if not already done if (dataSource == null) { @@ -50,82 +71,123 @@ public Connection getConnectionPool() throws SQLException { try { emailHelper.SendEmail(dbConfig.getAlertAddresses(), "Failed To Get Connection", body); } catch (Exception exception) { - utility.logWithDate("Failed to open connection to " + dbConfig.getDbUrl() - + ", then failed to send email"); - exception.printStackTrace(); + log.error("Failed to open connection to {}, then failed to send email", dbConfig.getDbUrl(), exception); } throw ex; } } + /** + * Executes the given PreparedStatement to perform an update or delete operation on the database. + * + * @param preparedStatement the PreparedStatement to execute for the update or delete operation + * @return true if the operation affected at least one row in the database, false otherwise + */ public boolean updateOrDelete(PreparedStatement preparedStatement) { - boolean result = false; - try { if (preparedStatement.executeUpdate() > 0) { result = true; } } catch (SQLException e) { - e.printStackTrace(); + log.error("Error in updateOrDelete", e); } - return result; } + /** + * Executes a delete operation using the provided PreparedStatement. The method + * returns a boolean indicating whether the operation was successful. If an + * exception occurs during execution, it is logged, and the method returns false. + * + * @param preparedStatement the PreparedStatement used to perform the delete operation + * @return true if the delete operation was successful, false if it failed + */ public boolean deleteWithPossibleZero(PreparedStatement preparedStatement) { boolean result = false; try { preparedStatement.executeUpdate(); result = true; } catch (SQLException e) { - e.printStackTrace(); + log.error("Error in deleteWithPossibleZero", e); } - return result; } + /** + * Executes the given prepared statement, logs the generated key if available, and returns the key. + * + * @param preparedStatement the prepared statement to be executed + * @param type the type of operation or entity being logged, for logging purposes + * @return the generated key as a Long if the execution is successful and a key is generated, otherwise null + */ public Long executeAndLog(PreparedStatement preparedStatement, String type) { Long id = null; try { if (preparedStatement.executeUpdate() > 0) { - ResultSet generatedKeys = preparedStatement.getGeneratedKeys(); - try { + try (ResultSet generatedKeys = preparedStatement.getGeneratedKeys()) { if (generatedKeys != null && generatedKeys.next()) { id = generatedKeys.getLong(1); - utility.logWithDate("------ Generated " + type + " " + id + " --------------"); - } - } finally { - try { - generatedKeys.close(); - } catch (Exception e) { - e.printStackTrace(); + log.trace("------ Generated {} {} --------------", type, id); } } } } catch (SQLException e) { - e.printStackTrace(); + log.error("Error in executeAndLog", e); } return id; } + /** + * Validates the database configuration settings and ensures all necessary + * values are defined. If the configuration is invalid or incomplete, the + * application will log an error and terminate. + *

+ * Key actions performed by this method: + * - Checks if the `dataSource` is null, indicating a need to validate the configuration. + * - Sets the default application time zone to "America/Denver." + * - Verifies that all essential database configuration values (`dbUrl`, `dbUsername`, + * `dbPassword`, `maximumPoolSize`, and `connectionTimeout`) are defined and non-zero. + * - Logs an error and exits the program if any required configuration value is missing. + */ private void validateDbConfig() { - if (dataSource == null) { - TimeZone timeZone = TimeZone.getTimeZone("America/Denver"); - TimeZone.setDefault(timeZone); - - // check dbconfig for null values - if (dbConfig.getDbUrl() == null || - dbConfig.getDbUsername() == null || - dbConfig.getDbPassword() == null || - dbConfig.getMaximumPoolSize() == 0 || - dbConfig.getConnectionTimeout() == 0) { - utility.logWithDate("DbInteractions: One or more database configuration values are undefined. Exiting."); - System.exit(1); - } + if (dataSource != null) { + return; + } + TimeZone timeZone = TimeZone.getTimeZone("America/Denver"); + TimeZone.setDefault(timeZone); + + // check dbconfig for null values + if (dbConfig.getDbUrl() == null || + dbConfig.getDbUsername() == null || + dbConfig.getDbPassword() == null || + dbConfig.getMaximumPoolSize() == 0 || + dbConfig.getConnectionTimeout() == 0) { + log.error("One or more database configuration values are undefined. Exiting."); + System.exit(1); } } + /** + * Initializes the primary connection pool using HikariCP for managing database connections. + * Configures the connection pool with properties retrieved from the database configuration. + * Logs the connection pool configuration details during initialization. + * On successful initialization, assigns the configured {@code HikariDataSource} to {@code dataSource}. + *

+ * This method is private and intended only for internal use by the class to create and configure + * the connection pool required for database operations. + *

+ * The connection pool is configured with the following settings: + * - Driver class name + * - JDBC URL + * - Database username + * - Database password + * - Connection timeout + * - Maximum pool size + *

+ * During the initialization process, any logging information regarding the + * pool's configuration is output through the configured logger. + */ private void initializePrimaryConnectionPool() { HikariConfig config = new HikariConfig(); config.setDriverClassName("org.postgresql.Driver"); @@ -136,14 +198,14 @@ private void initializePrimaryConnectionPool() { config.setMaximumPoolSize(dbConfig.getMaximumPoolSize()); // log the configuration of the connection pool - utility.logWithDate("DbInteractions: Creating connection pool with the following configuration:"); - utility.logWithDate("DbInteractions: driverClassName: " + config.getDriverClassName()); - utility.logWithDate("DbInteractions: dbUrl: " + dbConfig.getDbUrl()); - utility.logWithDate("DbInteractions: dbUsername: " + dbConfig.getDbUsername()); - utility.logWithDate("DbInteractions: connectionTimeout: " + config.getConnectionTimeout()); - utility.logWithDate("DbInteractions: maximumPoolSize: " + config.getMaximumPoolSize()); + log.info("Creating connection pool with the following configuration:"); + log.info("driverClassName: {}", config.getDriverClassName()); + log.info("dbUrl: {}", dbConfig.getDbUrl()); + log.info("dbUsername: {}", dbConfig.getDbUsername()); + log.info("connectionTimeout: {}", config.getConnectionTimeout()); + log.info("maximumPoolSize: {}", config.getMaximumPoolSize()); dataSource = new HikariDataSource(config); - utility.logWithDate("DbInteractions: Successfully initialized connection pool"); + log.info("Successfully initialized connection pool"); } } \ No newline at end of file diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/JsonToJavaConverter.java b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/JsonToJavaConverter.java index aefc1fd61..1709b3751 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/JsonToJavaConverter.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/JsonToJavaConverter.java @@ -1,14 +1,18 @@ package com.trihydro.library.helpers; -import static java.time.temporal.TemporalAdjusters.firstDayOfYear; - import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import static java.time.temporal.TemporalAdjusters.firstDayOfYear; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -17,8 +21,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.trihydro.library.model.ContentEnum; -import org.springframework.stereotype.Component; - import us.dot.its.jpo.ode.model.OdeLogMetadata; import us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy; import us.dot.its.jpo.ode.model.OdeRequestMsgMetadata; @@ -28,9 +30,6 @@ import us.dot.its.jpo.ode.plugin.SNMP; import us.dot.its.jpo.ode.plugin.ServiceRequest; import us.dot.its.jpo.ode.plugin.SnmpProtocol; -import us.dot.its.jpo.ode.plugin.j2735.J2735SpecialVehicleExtensions; -import us.dot.its.jpo.ode.plugin.j2735.J2735SupplementalVehicleExtensions; -import us.dot.its.jpo.ode.plugin.j2735.J2735VehicleSafetyExtensions; import us.dot.its.jpo.ode.plugin.j2735.OdePosition3D; import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage; import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.Region; @@ -40,45 +39,15 @@ import us.dot.its.jpo.ode.util.JsonUtils; @Component +@Slf4j public class JsonToJavaConverter { - private ObjectMapper mapper = new ObjectMapper(); + private final ObjectMapper mapper = new ObjectMapper(); public JsonToJavaConverter() { mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } - public J2735SpecialVehicleExtensions convertJ2735SpecialVehicleExtensionsJsonToJava(String value, int i) { - - JsonNode part2Node = getPart2Node(value, i); - J2735SpecialVehicleExtensions spve = null; - try { - spve = mapper.treeToValue(part2Node, J2735SpecialVehicleExtensions.class); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return spve; - } - - public J2735SupplementalVehicleExtensions convertJ2735SupplementalVehicleExtensionsJsonToJava(String value, int i) { - - JsonNode part2Node = getPart2Node(value, i); - J2735SupplementalVehicleExtensions suve = null; - try { - suve = mapper.treeToValue(part2Node, J2735SupplementalVehicleExtensions.class); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return suve; - } - - public JsonNode getPart2Node(String value, int i) { - JsonNode part2 = JsonUtils.getJsonNode(value, "payload").get("data").get("partII"); - if (part2 != null) - return part2.get(i).get("value"); - return null; - } - public OdeLogMetadata convertTimMetadataJsonToJava(String value) { OdeLogMetadata odeTimMetadata = null; @@ -95,13 +64,12 @@ public OdeLogMetadata convertTimMetadataJsonToJava(String value) { ((ObjectNode) metaDataNode).replace("receivedMessageDetails", receivedMessageDetailsNode); } } - // System.out.println(metaDataNode); + log.trace("MetaDataNode: {}", metaDataNode); odeTimMetadata = mapper.treeToValue(metaDataNode, OdeLogMetadata.class); } catch (IOException e) { - System.out.println("IOException"); - System.out.println(e.getStackTrace()); + log.error("An IOException occurred while converting TIM metadata JSON to Java", e); } catch (NullPointerException e) { - System.out.println(e.getMessage()); + log.error("A NullPointerException occurred while converting TIM metadata JSON to Java: {}", e.getMessage()); } return odeTimMetadata; @@ -166,10 +134,10 @@ public OdeRequestMsgMetadata convertBroadcastTimMetadataJsonToJava(String value) } } catch (IOException e) { - System.out.println("IOException"); - System.out.println(e.getStackTrace()); + log.error("An IOException occurred while converting Broadcast TIM metadata JSON to Java", e); } catch (NullPointerException e) { - System.out.println(e.getMessage()); + log.error("A NullPointerException occurred while converting Broadcast TIM metadata JSON to Java: {}", + e.getMessage()); } return odeTimMetadata; } @@ -242,7 +210,14 @@ else if (reverse != null) } if (regionDirectionNode != null) { - region.setDirection(mapper.treeToValue(regionDirectionNode, String.class)); + StringBuilder directionBuilder = new StringBuilder(); + Iterator> fields = regionDirectionNode.fields(); + while (fields.hasNext()) { + Map.Entry field = fields.next(); + boolean directionBool= Boolean.parseBoolean(field.getValue().toString()); + directionBuilder.append(directionBool ? "1" : "0"); + } + region.setDirection(directionBuilder.toString()); } JsonNode descriptionNode = regionNode.get("description"); @@ -266,7 +241,7 @@ public OdeTimPayload convertTimPayloadJsonToJava(String value) { try { OdeTravelerInformationMessage.DataFrame[] dataFrames = new OdeTravelerInformationMessage.DataFrame[1]; OdeTravelerInformationMessage.DataFrame dataFrame = new OdeTravelerInformationMessage.DataFrame(); - List regions = new ArrayList(); + List regions = new ArrayList<>(); // JsonNode payloadNode = JsonUtils.getJsonNode(value, "payload"); JsonNode timNode = JsonUtils.getJsonNode(value, "payload").get("data").get("MessageFrame").get("value") @@ -352,7 +327,7 @@ else if (sequenceArrNode.get("item").get("text") != null) regions.add(region); } } else { - System.out.println("warning: geographicalPathNode is not an object or an array"); + log.warn("geographicalPathNode is not an object or an array"); } dataFrame.setRegions(regions.toArray(new OdeTravelerInformationMessage.DataFrame.Region[regions.size()])); @@ -362,9 +337,9 @@ else if (sequenceArrNode.get("item").get("text") != null) odeTimPayload = new OdeTimPayload(); odeTimPayload.setData(tim); } catch (IOException e) { - System.out.println(e.getStackTrace()); + log.error("An IOException occurred while converting TIM JSON to Java", e); } catch (NullPointerException e) { - System.out.println(e.getMessage()); + log.error("A NullPointerException occurred while converting TIM JSON to Java: {}", e.getMessage()); } return odeTimPayload; @@ -390,10 +365,10 @@ public OdeTravelerInformationMessage.DataFrame.Region.Path GetPathData(JsonNode if (nodesNode == null) return null; - JsonNode nodeXYArrNode = isXy ? nodesNode.get("NodeXY") : nodesNode.get("NodeLL"); + JsonNode nodeXYArrNode = isXy ? nodesNode.get("NodeXY") : nodesNode; OdeTravelerInformationMessage.DataFrame.Region.Path path = new OdeTravelerInformationMessage.DataFrame.Region.Path(); - List nodeXYs = new ArrayList(); - OdeTravelerInformationMessage.NodeXY nodeXY = new OdeTravelerInformationMessage.NodeXY(); + List nodeXYs = new ArrayList<>(); + OdeTravelerInformationMessage.NodeXY nodeXY; if (nodeXYArrNode.isArray()) { for (final JsonNode objNode : nodeXYArrNode) { @@ -470,133 +445,129 @@ public OdeTimPayload convertTmcTimTopicJsonToJava(String value) { OdeTimPayload odeTimPayload = null; try { - OdeTravelerInformationMessage.DataFrame[] dataFrames = new OdeTravelerInformationMessage.DataFrame[1]; + List dataFrames = new ArrayList<>(); OdeTravelerInformationMessage.DataFrame dataFrame = new OdeTravelerInformationMessage.DataFrame(); - List regions = new ArrayList(); - - // JsonNode timNode = JsonUtils.getJsonNode(value, - // "payload").get("data").get("MessageFrame").get("value") - // .get("TravelerInformation"); - JsonNode timNode = JsonUtils.getJsonNode(value, "payload").findValue("TravelerInformation"); - JsonNode travelerDataFrame = timNode.findValue("TravelerDataFrame"); - - JsonNode sequenceArrNode = null; - JsonNode contentNode = travelerDataFrame.get("content"); - if (contentNode.has(ContentEnum.advisory.getStringValue())) { - sequenceArrNode = contentNode.get(ContentEnum.advisory.getStringValue()).get("SEQUENCE"); - dataFrame.setContent(ContentEnum.advisory.getStringValue()); - } else if (contentNode.has(ContentEnum.speedLimit.getStringValue())) { - sequenceArrNode = contentNode.get(ContentEnum.speedLimit.getStringValue()).get("SEQUENCE"); - dataFrame.setContent(ContentEnum.speedLimit.getStringValue()); - } else if (contentNode.has(ContentEnum.exitService.getStringValue())) { - sequenceArrNode = contentNode.get(ContentEnum.exitService.getStringValue()).get("SEQUENCE"); - dataFrame.setContent(ContentEnum.exitService.getStringValue()); - } else if (contentNode.has(ContentEnum.genericSign.getStringValue())) { - sequenceArrNode = contentNode.get(ContentEnum.genericSign.getStringValue()).get("SEQUENCE"); - dataFrame.setContent(ContentEnum.genericSign.getStringValue()); - } else if (contentNode.has(ContentEnum.workZone.getStringValue())) { - sequenceArrNode = contentNode.get(ContentEnum.workZone.getStringValue()).get("SEQUENCE"); - dataFrame.setContent(ContentEnum.workZone.getStringValue()); - } - - List itemsList = new ArrayList(); - String item = null; - if (sequenceArrNode != null && sequenceArrNode.isArray()) { - for (final JsonNode objNode : sequenceArrNode) { - if (objNode.get("item").get("itis") != null) - item = mapper.treeToValue(objNode.get("item").get("itis"), String.class); - else if (objNode.get("item").get("text") != null) - item = mapper.treeToValue(objNode.get("item").get("text"), String.class); - - itemsList.add(item); - } - } - - // ADD NON ARRAY ELEMENT - if (sequenceArrNode != null && !sequenceArrNode.isArray()) { - if (sequenceArrNode.get("item").get("itis") != null) - item = mapper.treeToValue(sequenceArrNode.get("item").get("itis"), String.class); - else if (sequenceArrNode.get("item").get("text") != null) - item = mapper.treeToValue(sequenceArrNode.get("item").get("text"), String.class); + List regions = new ArrayList<>(); - itemsList.add(item); - } - - // TravelerInfoType.valueOf(); - JsonNode frameTypeNode = travelerDataFrame.get("frameType"); - if (frameTypeNode != null) { - if (frameTypeNode.fieldNames().hasNext()) { - TravelerInfoType frameType = TravelerInfoType.valueOf(frameTypeNode.fieldNames().next()); - if (frameType != null) { - dataFrame.setFrameType(frameType); - } - } + OdeTravelerInformationMessage tim = new OdeTravelerInformationMessage(); + JsonNode timNode = JsonUtils.getJsonNode(value, "payload").findValue("data"); + tim.setMsgCnt(timNode.get("msgCnt").asInt()); + JsonNode packetIDNode = timNode.get("packetID"); + if (packetIDNode != null) { + tim.setPacketID(packetIDNode.asText()); } - JsonNode startTimeNode = travelerDataFrame.get("startTime"); - JsonNode durationNode = travelerDataFrame.get("durationTime"); - JsonNode priorityNode = travelerDataFrame.get("priority"); - JsonNode notUsed1Node = travelerDataFrame.get("notUsed1"); - JsonNode notUsedNode = travelerDataFrame.get("notUsed"); - LocalDate now = LocalDate.now(); LocalDate firstDay = now.with(firstDayOfYear()); - OdeTravelerInformationMessage tim = new OdeTravelerInformationMessage(); - JsonNode timeStampNode = timNode.get("timeStamp"); if (timeStampNode != null) { LocalDateTime timeStampDate = firstDay.atStartOfDay().plus(timeStampNode.asInt(), ChronoUnit.MINUTES); tim.setTimeStamp(timeStampDate.toString() + "Z"); } - LocalDateTime startDate = firstDay.atStartOfDay().plus(startTimeNode.asInt(), ChronoUnit.MINUTES); + JsonNode travelerDataFrameArray = timNode.findValue("dataFrames"); + for (final JsonNode travelerDataFrame : travelerDataFrameArray) { + JsonNode sequenceArrNode = null; + JsonNode contentNode = travelerDataFrame.get("content"); + if (contentNode.has(ContentEnum.advisory.getStringValue())) { + sequenceArrNode = contentNode.get("advisory"); + dataFrame.setContent(ContentEnum.advisory.getStringValue()); + } else if (contentNode.has(ContentEnum.speedLimit.getStringValue())) { + sequenceArrNode = contentNode.get("speedLimit"); + dataFrame.setContent(ContentEnum.speedLimit.getStringValue()); + } else if (contentNode.has(ContentEnum.exitService.getStringValue())) { + sequenceArrNode = contentNode.get("exitService"); + dataFrame.setContent(ContentEnum.exitService.getStringValue()); + } else if (contentNode.has(ContentEnum.genericSign.getStringValue())) { + sequenceArrNode = contentNode.get("genericSign"); + dataFrame.setContent(ContentEnum.genericSign.getStringValue()); + } else if (contentNode.has(ContentEnum.workZone.getStringValue())) { + sequenceArrNode = contentNode.get("workZone"); + dataFrame.setContent(ContentEnum.workZone.getStringValue()); + } - dataFrame.setStartDateTime(startDate.toString() + "Z"); - dataFrame.setDurationTime(durationNode.asInt()); - dataFrame.setPriority(priorityNode.asInt()); - dataFrame.setNotUsed1((short) notUsed1Node.asInt()); - dataFrame.setNotUsed((short) notUsedNode.asInt()); + List itemsList = new ArrayList<>(); + String item = null; + if (sequenceArrNode != null && sequenceArrNode.isArray()) { + for (final JsonNode objNode : sequenceArrNode) { + if (objNode.get("item").get("itis") != null) { + item = mapper.treeToValue(objNode.get("item").get("itis"), String.class); + } else if (objNode.get("item").get("text") != null) { + item = mapper.treeToValue(objNode.get("item").get("text"), String.class); + } else { + log.warn("'itis' or 'text' not found in item when converting TMC TIM"); + } + if (!itemsList.contains(item)) { + itemsList.add(item); + } + } + } - tim.setMsgCnt(timNode.get("msgCnt").asInt()); + // ADD NON ARRAY ELEMENT + if (sequenceArrNode != null && !sequenceArrNode.isArray()) { + if (sequenceArrNode.get("item").get("itis") != null) { + item = mapper.treeToValue(sequenceArrNode.get("item").get("itis"), String.class); + } else if (sequenceArrNode.get("item").get("text") != null) { + item = mapper.treeToValue(sequenceArrNode.get("item").get("text"), String.class); + } else { + log.warn("'itis' or 'text' not found in item when converting TMC TIM"); + } - JsonNode packetIDNode = timNode.get("packetID"); - if (packetIDNode != null) { - tim.setPacketID(packetIDNode.asText()); - } + itemsList.add(item); + } - String[] items = new String[itemsList.size()]; - items = itemsList.toArray(items); + // TravelerInfoType.valueOf(); + JsonNode frameTypeNode = travelerDataFrame.get("frameType"); + if (frameTypeNode != null && frameTypeNode.fieldNames().hasNext()) { + TravelerInfoType frameType = TravelerInfoType.valueOf(frameTypeNode.fieldNames().next()); + dataFrame.setFrameType(frameType); + } else { + log.warn("frameType not found in TravelerDataFrame when converting TMC TIM. Defaulting to 'advisory'"); + dataFrame.setFrameType(TravelerInfoType.advisory); + } - JsonNode geographicalPathNode = travelerDataFrame.findValue("GeographicalPath"); + JsonNode startTimeNode = travelerDataFrame.get("startTime"); + JsonNode durationNode = travelerDataFrame.get("durationTime"); + JsonNode priorityNode = travelerDataFrame.get("priority"); - // geographicalPathNode may be an object or an array; if it is an object, treat - // it as a region - if (geographicalPathNode.isObject()) { - // single region - JsonNode regionNode = geographicalPathNode; - Region region = getRegion(regionNode); - regions.add(region); - } else if (geographicalPathNode.isArray()) { - // multiple regions - for (final JsonNode regionNode : geographicalPathNode) { - Region region = getRegion(regionNode); - regions.add(region); + LocalDateTime startDate = firstDay.atStartOfDay().plus(startTimeNode.asInt(), ChronoUnit.MINUTES); + + dataFrame.setStartDateTime(startDate.toString() + "Z"); + dataFrame.setDurationTime(durationNode.asInt()); + dataFrame.setPriority(priorityNode.asInt()); + + String[] items = new String[itemsList.size()]; + items = itemsList.toArray(items); + + JsonNode geographicalPathNode = travelerDataFrame.findValue("regions"); + + // geographicalPathNode may be an object or an array; if it is an object, treat + // it as a region + if (geographicalPathNode.isObject()) { + // single region + regions.add(getRegion(geographicalPathNode)); + } else if (geographicalPathNode.isArray()) { + // multiple regions + for (final JsonNode regionNode : geographicalPathNode) { + Region region = getRegion(regionNode); + regions.add(region); + } + } else { + log.warn("geographicalPathNode is not an object or an array"); } - } else { - System.out.println("warning: geographicalPathNode is not an object or an array"); - } - dataFrame.setRegions(regions.toArray(new OdeTravelerInformationMessage.DataFrame.Region[regions.size()])); - dataFrame.setItems(items); - dataFrames[0] = dataFrame; - tim.setDataframes(dataFrames); + dataFrame.setRegions(regions.toArray(OdeTravelerInformationMessage.DataFrame.Region[]::new)); + dataFrame.setItems(items); + dataFrames.add(dataFrame); + } + tim.setDataframes(dataFrames.toArray(OdeTravelerInformationMessage.DataFrame[]::new)); odeTimPayload = new OdeTimPayload(); odeTimPayload.setData(tim); } catch (IOException e) { - System.out.println(e.getStackTrace()); + log.error("An IOException occurred while converting TMC TIM JSON to Java", e); } catch (NullPointerException e) { - System.out.println(e.getMessage()); + log.error("A NullPointerException occurred while converting TMC TIM JSON to Java: {}", e.getMessage()); } return odeTimPayload; @@ -610,9 +581,9 @@ public OdeTravelerInformationMessage convertBroadcastTimPayloadJsonToJava(String JsonNode timNode = JsonUtils.getJsonNode(value, "payload").get("data"); odeTim = mapper.treeToValue(timNode, OdeTravelerInformationMessage.class); } catch (IOException e) { - System.out.println(e.getStackTrace()); + log.error("An IOException occurred while converting Broadcast TIM JSON to Java", e); } catch (NullPointerException e) { - System.out.println(e.getMessage()); + log.error("A NullPointerException occurred while converting Broadcast TIM JSON to Java: {}", e.getMessage()); } return odeTim; diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/TimGenerationHelper.java b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/TimGenerationHelper.java index 0e9460d92..f88afdebd 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/TimGenerationHelper.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/TimGenerationHelper.java @@ -846,13 +846,9 @@ private DataFrame getDataFrame(TimUpdateModel aTim, Milepost anchor, boolean res // DataFrame DataFrame df = new DataFrame(); - df.setNotUsed(aTim.getNotUsed()); df.setFrameType(aTim.getFrameType()); df.setMsgId(msgId); df.setPriority(5);// 0-7, 0 being least important, 7 being most - df.setNotUsed1(aTim.getNotUsed1()); - df.setNotUsed3(aTim.getNotUsed3()); - df.setNotUsed2(aTim.getNotUsed2()); if (aTim.getDfContent() != null) { df.setContent(aTim.getDfContent().getStringValue()); } diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/model/TimUpdateModel.java b/cv-data-service-library/src/main/java/com/trihydro/library/model/TimUpdateModel.java index dd7b2c727..7333b268e 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/model/TimUpdateModel.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/model/TimUpdateModel.java @@ -32,10 +32,10 @@ public class TimUpdateModel extends ActiveTim { private int dataFrameId; private TravelerInfoType frameType; private int durationTime; - private short notUsed1; - private short notUsed; - private short notUsed3; - private short notUsed2; + private short doNotUse2; + private short doNotUse1; + private short doNotUse4; + private short doNotUse3; private ContentEnum dfContent; private String url; @@ -172,12 +172,12 @@ public void setFrameType(TravelerInfoType frameType) { this.frameType = frameType; } - public short getNotUsed() { - return notUsed; + public short getDoNotUse1() { + return doNotUse1; } - public void setNotUsed(short notUsed) { - this.notUsed = notUsed; + public void setDoNotUse1(short doNotUse1) { + this.doNotUse1 = doNotUse1; } public ContentEnum getDfContent() { @@ -188,28 +188,28 @@ public void setDfContent(ContentEnum dfContent) { this.dfContent = dfContent; } - public short getNotUsed2() { - return notUsed2; + public short getDoNotUse3() { + return doNotUse3; } - public void setNotUsed2(short notUsed2) { - this.notUsed2 = notUsed2; + public void setDoNotUse3(short doNotUse3) { + this.doNotUse3 = doNotUse3; } - public short getNotUsed3() { - return notUsed3; + public short getDoNotUse4() { + return doNotUse4; } - public void setNotUsed3(short notUsed3) { - this.notUsed3 = notUsed3; + public void setDoNotUse4(short doNotUse4) { + this.doNotUse4 = doNotUse4; } - public short getNotUsed1() { - return notUsed1; + public short getDoNotUse2() { + return doNotUse2; } - public void setNotUsed1(short notUsed1) { - this.notUsed1 = notUsed1; + public void setDoNotUse2(short doNotUse2) { + this.doNotUse2 = doNotUse2; } public BigDecimal getAnchorLong() { diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/service/ActiveTimService.java b/cv-data-service-library/src/main/java/com/trihydro/library/service/ActiveTimService.java index 387b6ff8e..3bb89b706 100644 --- a/cv-data-service-library/src/main/java/com/trihydro/library/service/ActiveTimService.java +++ b/cv-data-service-library/src/main/java/com/trihydro/library/service/ActiveTimService.java @@ -92,8 +92,8 @@ public List getBufferTimsByClientId(String clientId) { return Arrays.asList(response.getBody()); } - public List getExpiredActiveTims() { - ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(config.getCvRestService() + "/active-tim/expired", ActiveTim[].class); + public List getExpiredActiveTims(int limit) { + ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(config.getCvRestService() + "/active-tim/expired?limit=" + limit, ActiveTim[].class); return Arrays.asList(response.getBody()); } diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/DbInteractionsTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/DbInteractionsTest.java index 04c143608..89bd4f24a 100644 --- a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/DbInteractionsTest.java +++ b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/DbInteractionsTest.java @@ -3,68 +3,76 @@ import com.trihydro.library.model.DbInteractionsProps; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import org.mockito.MockitoAnnotations; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class DbInteractionsTest { + private DbInteractions uut; @Mock private DbInteractionsProps dbConfig; @Mock - private Utility utility; + private EmailHelper emailHelper; @Mock - private EmailHelper emailHelper; + private PreparedStatement preparedStatement; - @InjectMocks - private DbInteractions dbInteractions; + @Mock + private ResultSet resultSet; @BeforeEach void setUp() { MockitoAnnotations.initMocks(this); + + when(dbConfig.getDbUrl()).thenReturn("jdbc:postgresql://localhost:5432/test"); + when(dbConfig.getDbUsername()).thenReturn("test"); + when(dbConfig.getDbPassword()).thenReturn("test"); + when(dbConfig.getMaximumPoolSize()).thenReturn(10); + when(dbConfig.getConnectionTimeout()).thenReturn(1000); + uut = new DbInteractions(dbConfig, emailHelper); } @Test - void updateOrDelete_executesUpdate() throws SQLException { - PreparedStatement preparedStatement = mock(PreparedStatement.class); + void testUpdateOrDelete_WhenExecuted_ShouldReturnTrue() throws SQLException { when(preparedStatement.executeUpdate()).thenReturn(1); - boolean result = dbInteractions.updateOrDelete(preparedStatement); + boolean result = uut.updateOrDelete(preparedStatement); assertTrue(result); + verify(preparedStatement, times(1)).executeUpdate(); } @Test - void deleteWithPossibleZero_executesUpdate() throws SQLException { - PreparedStatement preparedStatement = mock(PreparedStatement.class); + void testDeleteWithPossibleZero_WhenNoRowsAffected_ShouldReturnTrue() throws SQLException { when(preparedStatement.executeUpdate()).thenReturn(0); - boolean result = dbInteractions.deleteWithPossibleZero(preparedStatement); + boolean result = uut.deleteWithPossibleZero(preparedStatement); assertTrue(result); + verify(preparedStatement, times(1)).executeUpdate(); } @Test - void executeAndLog_generatesKey() throws SQLException { - PreparedStatement preparedStatement = mock(PreparedStatement.class); - ResultSet resultSet = mock(ResultSet.class); + void testExecuteAndLog_WhenKeyGenerated_ShouldReturnGeneratedKey() throws SQLException { when(preparedStatement.executeUpdate()).thenReturn(1); when(preparedStatement.getGeneratedKeys()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true); when(resultSet.getLong(1)).thenReturn(1L); - Long id = dbInteractions.executeAndLog(preparedStatement, "type"); + Long id = uut.executeAndLog(preparedStatement, "type"); assertNotNull(id); assertEquals(1L, id); + verify(preparedStatement, times(1)).executeUpdate(); + verify(preparedStatement, times(1)).getGeneratedKeys(); + verify(resultSet, times(1)).next(); } } \ No newline at end of file diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/JsonToJavaConverterTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/JsonToJavaConverterTest.java index 131c96bc0..e89ca7501 100644 --- a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/JsonToJavaConverterTest.java +++ b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/JsonToJavaConverterTest.java @@ -7,8 +7,6 @@ import java.nio.file.Path; import java.nio.file.Paths; -import com.fasterxml.jackson.databind.JsonNode; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -22,8 +20,6 @@ import us.dot.its.jpo.ode.model.ReceivedMessageDetails; import us.dot.its.jpo.ode.model.RxSource; import us.dot.its.jpo.ode.model.SerialId; -import us.dot.its.jpo.ode.plugin.j2735.J2735SupplementalVehicleExtensions; -import us.dot.its.jpo.ode.plugin.j2735.J2735VehicleSafetyExtensions; import us.dot.its.jpo.ode.plugin.j2735.OdePosition3D; import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage; import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.Region.Circle; diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/service/ActiveTimServiceTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/service/ActiveTimServiceTest.java index 967d6bd09..af222d08b 100644 --- a/cv-data-service-library/src/test/java/com/trihydro/library/service/ActiveTimServiceTest.java +++ b/cv-data-service-library/src/test/java/com/trihydro/library/service/ActiveTimServiceTest.java @@ -254,11 +254,11 @@ public void getBufferTimsByClientId() { public void getExpiredActiveTims() { // Arrange setupActiveTimArrayReturn(); - String url = String.format("%s/active-tim/expired", baseUrl); + String url = String.format("%s/active-tim/expired?limit=500", baseUrl); when(mockRestTemplate.getForEntity(url, ActiveTim[].class)).thenReturn(mockResponseEntityActiveTims); // Act - List data = uut.getExpiredActiveTims(); + List data = uut.getExpiredActiveTims(500); // Assert verify(mockRestTemplate).getForEntity(url, ActiveTim[].class); 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 1c658cf52..e14436a2f 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 @@ -15,7 +15,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +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; import java.util.Arrays; import java.util.HashMap; @@ -142,14 +146,14 @@ private List getActiveTims(boolean isSat) { return activeTims; } - private OdeTravelerInformationMessage getMockOdeTravelerInformationMessage() { - String timJson = "{\"msgCnt\":\"1\",\"timeStamp\":\"2017-08-03T22:25:36.297Z\",\"urlB\":\"null\",\"packetID\":\"EC9C236B0000000000\",\"dataframes\":[{\"startDateTime\":\"2017-08-02T22:25:00.000Z\",\"durationTime\":1,\"sspTimRights\":\"0\",\"frameType\":\"advisory\",\"msgId\":{\"roadSignID\":{\"position\":{\"latitude\":\"41.678473\",\"longitude\":\"-108.782775\",\"elevation\":\"917.1432\"},\"viewAngle\":\"1010101010101010\",\"mutcdCode\":\"warning\",\"crc\":\"0000\"}},\"priority\":\"0\",\"sspLocationRights\":\"3\",\"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.0030982\",\"nodeLat\":\"0.0014562\",\"delta\":\"node-LL3\"},{\"nodeLong\":\"-111.0093847\",\"nodeLat\":\"41.2500807\",\"delta\":\"node-LatLon\"}]},\"direction\":\"0000000000001010\"}],\"sspMsgTypes\":\"2\",\"sspMsgContent\":\"3\",\"content\":\"Advisory\",\"items\":[\"125\",\"some text\",\"250\",\"'98765\"],\"url\":\"null\"}]}"; + private OdeTravelerInformationMessage getMockOdeTravelerInformationMessage() throws IOException { + String timJson = + new String(Files.readAllBytes(Paths.get("src/test/resources/com/trihydro/library/service/mockOdeTravelerInformationMessage.json"))); Gson gson = new Gson(); - OdeTravelerInformationMessage mockOdeTravelerInformationMessage = gson.fromJson(timJson, OdeTravelerInformationMessage.class); - return mockOdeTravelerInformationMessage; + return gson.fromJson(timJson, OdeTravelerInformationMessage.class); } - private WydotOdeTravelerInformationMessage getMockWydotOdeTravelerInformationMessage() { + private WydotOdeTravelerInformationMessage getMockWydotOdeTravelerInformationMessage() throws IOException { OdeTravelerInformationMessage mockOdeTravelerInformationMessage = getMockOdeTravelerInformationMessage(); WydotOdeTravelerInformationMessage mockWydotOdeTravelerInformationMessage = new WydotOdeTravelerInformationMessage(); mockWydotOdeTravelerInformationMessage.setMsgCnt(mockOdeTravelerInformationMessage.getMsgCnt()); @@ -191,7 +195,7 @@ private WydotTim getMockWydotTim() { return wydotTim; } - private WydotTravelerInputData getMockWydotTravelerInputDataWithServiceRequest() { + private WydotTravelerInputData getMockWydotTravelerInputDataWithServiceRequest() throws IOException { WydotTravelerInputData wydotTravelerInputData = new WydotTravelerInputData(); wydotTravelerInputData.setTim(getMockOdeTravelerInformationMessage()); ServiceRequest serviceRequest = new ServiceRequest(); @@ -379,7 +383,7 @@ public void getAllMilepostsForTim_EndPointNull() { } @Test - public void sendTimToSDW_MultipleActiveSatTimsFound() { + public void sendTimToSDW_MultipleActiveSatTimsFound() throws IOException { // Arrange List activeSatTims = getActiveTims(true); when(mockActiveTimService.getActiveTimsByClientIdDirection(any(), any(), any())).thenReturn(activeSatTims); @@ -403,7 +407,7 @@ public void sendTimToSDW_MultipleActiveSatTimsFound() { } @Test - public void sendTimToSDW_NoActiveSatTimsFound() { + public void sendTimToSDW_NoActiveSatTimsFound() throws IOException { // Arrange when(mockActiveTimService.getActiveTimsByClientIdDirection(any(), any(), any())).thenReturn(new ArrayList<>()); WydotTim wydotTim = getMockWydotTim(); @@ -424,7 +428,7 @@ public void sendTimToSDW_NoActiveSatTimsFound() { } @Test - public void sendTimToSDW_SingleActiveSatTimFound() { + public void sendTimToSDW_SingleActiveSatTimFound() throws IOException { // Arrange List activeSatTims = getActiveTims(true).subList(0, 1); when(mockActiveTimService.getActiveTimsByClientIdDirection(any(), any(), any())).thenReturn(activeSatTims); @@ -448,7 +452,7 @@ public void sendTimToSDW_SingleActiveSatTimFound() { } @Test - public void sendTimToRsus_NoRsusFound() { + public void sendTimToRsus_NoRsusFound() throws IOException { // Arrange when(mockRsuService.getRsusByLatLong(any(), any(), any(), any())).thenReturn(new ArrayList<>()); @@ -468,7 +472,7 @@ public void sendTimToRsus_NoRsusFound() { } @Test - public void sendTimToRsus_RsusFound_NoActiveTIMs() { + public void sendTimToRsus_RsusFound_NoActiveTIMs() throws IOException { // Arrange List rsus = new ArrayList<>(); WydotRsu rsu = new WydotRsu(); @@ -499,7 +503,7 @@ public void sendTimToRsus_RsusFound_NoActiveTIMs() { } @Test - public void sendTimToRsus_RsusFound_ActiveTIMsExist() { + public void sendTimToRsus_RsusFound_ActiveTIMsExist() throws IOException { // Arrange List rsus = new ArrayList<>(); WydotRsu rsu = new WydotRsu(); diff --git a/cv-data-service-library/src/test/resources/broadcastTim_OdeOutput.json b/cv-data-service-library/src/test/resources/broadcastTim_OdeOutput.json index 2889ddd83..6558c2134 100644 --- a/cv-data-service-library/src/test/resources/broadcastTim_OdeOutput.json +++ b/cv-data-service-library/src/test/resources/broadcastTim_OdeOutput.json @@ -22,7 +22,7 @@ "urlB": "null", "dataframes": [ { - "notUsed": 1, + "doNotUse1": 0, "frameType": "advisory", "msgId": { "furtherInfoID": "CDEF" @@ -30,7 +30,7 @@ "startDateTime": "2018-03-15T21:18:46.719-07:00", "durationTime": 32000, "priority": 5, - "notUsed1": 1, + "doNotUse2": 0, "regions": [ { "name": "westbound_I80_370.0_365.0_RSU-10.145.1.100_VSL", @@ -179,8 +179,8 @@ } } ], - "notUsed3": 0, - "notUsed2": 1, + "doNotUse4": 0, + "doNotUse3": 0, "content": "Advisory", "items": [ "268", diff --git a/cv-data-service-library/src/test/resources/com/trihydro/library/service/mockOdeTravelerInformationMessage.json b/cv-data-service-library/src/test/resources/com/trihydro/library/service/mockOdeTravelerInformationMessage.json new file mode 100644 index 000000000..828c86c39 --- /dev/null +++ b/cv-data-service-library/src/test/resources/com/trihydro/library/service/mockOdeTravelerInformationMessage.json @@ -0,0 +1,71 @@ +{ + "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": "3", + "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.0030982", + "nodeLat": "0.0014562", + "delta": "node-LL3" + }, + { + "nodeLong": "-111.0093847", + "nodeLat": "41.2500807", + "delta": "node-LatLon" + } + ] + }, + "direction": "0000000000001010" + } + ], + "doNotUse4": "2", + "doNotUse3": "3", + "content": "Advisory", + "items": [ + "125", + "some text", + "250", + "'98765" + ], + "url": "null" + } + ] +} \ No newline at end of file diff --git a/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput.json b/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput.json index f61c08d40..169a60727 100644 --- a/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput.json +++ b/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput.json @@ -82,10 +82,10 @@ } }, "durationTime": 32000, - "notUsed2": 0, - "notUsed3": 0, - "notUsed": 0, - "notUsed1": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "doNotUse2": 0, "frameType": { "roadSignage": "" }, diff --git a/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_Geometry.json b/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_Geometry.json index a0482b36f..cff628b73 100644 --- a/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_Geometry.json +++ b/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_Geometry.json @@ -69,10 +69,10 @@ } }, "durationTime": 32000, - "notUsed2": 0, - "notUsed3": 0, - "notUsed": 0, - "notUsed1": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "doNotUse2": 0, "frameType": { "roadSignage": "" }, diff --git a/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_MultipleRegions.json b/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_MultipleRegions.json index 95472d2c5..1549e6c85 100644 --- a/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_MultipleRegions.json +++ b/cv-data-service-library/src/test/resources/rxMsg_TIM_OdeOutput_MultipleRegions.json @@ -126,10 +126,10 @@ ] }, "durationTime": 32000, - "notUsed2": 0, - "notUsed3": 0, - "notUsed": 0, - "notUsed1": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "doNotUse2": 0, "frameType": { "roadSignage": "" }, diff --git a/cv-data-service-library/src/test/resources/rxMsg_TIM_SpeedLimit.json b/cv-data-service-library/src/test/resources/rxMsg_TIM_SpeedLimit.json index 2e3e5efeb..4692d3167 100644 --- a/cv-data-service-library/src/test/resources/rxMsg_TIM_SpeedLimit.json +++ b/cv-data-service-library/src/test/resources/rxMsg_TIM_SpeedLimit.json @@ -82,10 +82,10 @@ } }, "durationTime": 32000, - "notUsed2": 0, - "notUsed3": 0, - "notUsed": 0, - "notUsed1": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "doNotUse2": 0, "frameType": { "roadSignage": "" }, diff --git a/cv-data-service-library/src/test/resources/sdxDecodeResponse.json b/cv-data-service-library/src/test/resources/sdxDecodeResponse.json index dc4716bd7..0ee50ee8c 100644 --- a/cv-data-service-library/src/test/resources/sdxDecodeResponse.json +++ b/cv-data-service-library/src/test/resources/sdxDecodeResponse.json @@ -1,4 +1,4 @@ { "messageType": "MessageFrame", - "decodedMessage": "3113469004null1414344751-1101051425111111111111111120194690043200051westbound_I80_39.9_53.31_SAT-4035A5DF_RC_LYMI80EGRAD00414344751-11010514253270000000011111100000-1048300445417415787-1101068786414338729-1048297813417401082-1101173822414302517-1048296846417313218-1101278808414263469-1048334156417231472-1101362065414212124-1048363596417151273-1048348231417067803-1101430219414153700-1101515051414095801-1048292665416990008-1101609734414047121-1048303785416903264-1101704290413998478-1048330081416818875-1101798529413950074-1048362115416736381-1048394037416654255-1101901550413914121-1102014424413891332-1048426742416569080-1102126907413868840-1048459137416484285-1102235582413840132-1048492892416400669-1102332568413793094-1048526150416318091-1048559229416236049-1102434259413752451-1102543983413731407-1048592545416153296-1102655116413714865-1048625771416070802-1102767179413702216-1048658799415988821-1102881705413689256-1048694127415905527-1048732305415821992-1102996201413671479-1103105581413647716-1048769216415741004-1103216030413622307-1048806392415659600-1103325763413587617-1048843990415577334-11033794134135705071158955907null" + "decodedMessage": "3113469004null0414344751-1101051425111111111111111120194690043200050westbound_I80_39.9_53.31_SAT-4035A5DF_RC_LYMI80EGRAD00414344751-11010514253270000000011111100000-1048300445417415787-1101068786414338729-1048297813417401082-1101173822414302517-1048296846417313218-1101278808414263469-1048334156417231472-1101362065414212124-1048363596417151273-1048348231417067803-1101430219414153700-1101515051414095801-1048292665416990008-1101609734414047121-1048303785416903264-1101704290413998478-1048330081416818875-1101798529413950074-1048362115416736381-1048394037416654255-1101901550413914121-1102014424413891332-1048426742416569080-1102126907413868840-1048459137416484285-1102235582413840132-1048492892416400669-1102332568413793094-1048526150416318091-1048559229416236049-1102434259413752451-1102543983413731407-1048592545416153296-1102655116413714865-1048625771416070802-1102767179413702216-1048658799415988821-1102881705413689256-1048694127415905527-1048732305415821992-1102996201413671479-1103105581413647716-1048769216415741004-1103216030413622307-1048806392415659600-1103325763413587617-1048843990415577334-11033794134135705070058955907null" } diff --git a/cv-data-service-library/src/test/resources/tim_construction.json b/cv-data-service-library/src/test/resources/tim_construction.json index c47424c2d..8385e897d 100644 --- a/cv-data-service-library/src/test/resources/tim_construction.json +++ b/cv-data-service-library/src/test/resources/tim_construction.json @@ -28,90 +28,116 @@ "odeTimStartDateTime": "2021-03-04T00:00:00.000Z", "odeReceivedAt": "2021-03-23T18:24:18.438Z" }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 117744, - "packetID": "59CE5322A49CED33CB", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": { - "closedPath": { "false": "" }, - "anchor": { "lat": 417732928, "long": -1071000312 }, - "name": "I_I 80_SAT-BC1AC5E4_RW_24869%BUFF0-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, - { - "delta": { - "node-LL4": { "lon": 115529, "lat": -16624 } - } - }, - { - "delta": { - "node-LL4": { "lon": 39044, "lat": 1521 } - } - }, - { - "delta": { - "node-LL4": { "lon": 56228, "lat": 11450 } - } - } - ] - } + "payload": { + "data": { + "msgCnt": 1, + "timeStamp": 117744, + "packetID": "59CE5322A49CED33CB", + "urlB": "null", + "dataFrames": [ + { + "doNotUse1": 0, + "frameType": "advisory", + "msgId": { + "roadSignID": { + "position": { "lat": 417732928, "long": -1071000312 }, + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "warning" + } + }, + "durationTime": 32000, + "startYear": 2021, + "startTime": 89280, + "priority": 5, + "doNotUse2": 0, + "regions": [ + { + "name": "I_I 80_SAT-BC1AC5E4_RW_24869%BUFF0-0", + "id": { + "region": 0, + "id": 0 + }, + "anchor": { "lat": 417732928, "long": -1071000312 }, + "laneWidth": 5000, + "directionality": "both", + "closedPath": false, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + }, + "description": { + "path": { + "scale": 0, + "offset": { + "ll": { + "nodes": [ + { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, + { + "delta": { + "node-LL4": { "lon": 115529, "lat": -16624 } } }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0001100000000000" - } - }, - "durationTime": 32000, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2021, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { "warning": "" }, - "position": { "lat": 417732928, "long": -1071000312 } - } - }, - "priority": 5, - "content": { - "workZone": { - "SEQUENCE": [ - { "item": { "itis": 1537 } }, - { "item": { "itis": 12554 } }, - { "item": { "itis": 8728 } } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { "advisory": "" }, - "startTime": 89280 - } - }, - "msgCnt": 1 - } - } - } - }, - "dataType": "TravelerInformation" - } -} + { + "delta": { + "node-LL4": { "lon": 39044, "lat": 1521 } + } + }, + { + "delta": { + "node-LL4": { "lon": 56228, "lat": 11450 } + } + } + ] + } + } + } + } + } + ], + "doNotUse3": 0, + "doNotUse4": 0, + "content": { + "workZone": [ + { "item": { "itis": 1537 } }, + { "item": { "itis": 12554 } }, + { "item": { "itis": 8728 } } + ] + }, + "url": "null" + } + ] + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" + } +} \ No newline at end of file diff --git a/cv-data-service-library/src/test/resources/tim_construction_MultipleRegions.json b/cv-data-service-library/src/test/resources/tim_construction_MultipleRegions.json index c31beceec..2b0d145ab 100644 --- a/cv-data-service-library/src/test/resources/tim_construction_MultipleRegions.json +++ b/cv-data-service-library/src/test/resources/tim_construction_MultipleRegions.json @@ -1,157 +1,196 @@ { - "metadata": { - "request": { - "ode": { "verb": "POST", "version": 3 }, - "sdw": { - "recordId": "BC1AC5E4", - "serviceRegion": { - "nwCorner": { "latitude": 41.77329283, "longitude": -107.1000312 }, - "seCorner": { "latitude": 41.77163046, "longitude": -107.07895106 } - }, - "ttl": "oneyear" - } - }, - "recordGeneratedBy": "TMC", - "schemaVersion": 6, - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "odePacketID": "59CE5322A49CED33CB", - "serialId": { - "recordId": 0, - "serialNumber": 917, - "streamId": "9fa59341-9cab-403e-8306-6876238e9fda", - "bundleSize": 1, - "bundleId": 917 + "metadata": { + "request": { + "ode": { "verb": "POST", "version": 3 }, + "sdw": { + "recordId": "BC1AC5E4", + "serviceRegion": { + "nwCorner": { "latitude": 41.77329283, "longitude": -107.1000312 }, + "seCorner": { "latitude": 41.77163046, "longitude": -107.07895106 } }, - "sanitized": false, - "recordGeneratedAt": "2021-03-23T18:24:18.410648Z", - "maxDurationTime": 32000, - "odeTimStartDateTime": "2021-03-04T00:00:00.000Z", - "odeReceivedAt": "2021-03-23T18:24:18.438Z" + "ttl": "oneyear" + } + }, + "recordGeneratedBy": "TMC", + "schemaVersion": 6, + "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", + "odePacketID": "59CE5322A49CED33CB", + "serialId": { + "recordId": 0, + "serialNumber": 917, + "streamId": "9fa59341-9cab-403e-8306-6876238e9fda", + "bundleSize": 1, + "bundleId": 917 }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 117744, - "packetID": "59CE5322A49CED33CB", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": [ - { - "closedPath": { "false": "" }, - "anchor": { "lat": 417732928, "long": -1071000312 }, - "name": "I_I 80_SAT-BC1AC5E4_RW_24869%BUFF0-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, - { - "delta": { - "node-LL4": { "lon": 115529, "lat": -16624 } - } - }, - { - "delta": { - "node-LL4": { "lon": 39044, "lat": 1521 } - } - }, - { - "delta": { - "node-LL4": { "lon": 56228, "lat": 11450 } - } - } - ] - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0001100000000000" - }, - { - "closedPath": { "false": "" }, - "anchor": { "lat": 417732928, "long": -1071000312 }, - "name": "I_I 80_SAT-BC1AC5E4_RW_24869%BUFF0-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, - { - "delta": { - "node-LL4": { "lon": 115529, "lat": -16624 } - } - }, - { - "delta": { - "node-LL4": { "lon": 39044, "lat": 1521 } - } - }, - { - "delta": { - "node-LL4": { "lon": 56228, "lat": 11450 } - } - } - ] - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0001100000000000" - } - ] - }, - "durationTime": 32000, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2021, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { "warning": "" }, - "position": { "lat": 417732928, "long": -1071000312 } - } - }, - "priority": 5, - "content": { - "workZone": { - "SEQUENCE": [ - { "item": { "itis": 1537 } }, - { "item": { "itis": 12554 } }, - { "item": { "itis": 8728 } } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { "advisory": "" }, - "startTime": 89280 - } + "sanitized": false, + "recordGeneratedAt": "2021-03-23T18:24:18.410648Z", + "maxDurationTime": 32000, + "odeTimStartDateTime": "2021-03-04T00:00:00.000Z", + "odeReceivedAt": "2021-03-23T18:24:18.438Z" + }, + "payload": { + "data": { + "msgCnt": 1, + "timeStamp": 117744, + "packetID": "59CE5322A49CED33CB", + "urlB": "null", + "dataFrames": [ + { + "doNotUse1": 0, + "frameType": "advisory", + "msgId": { + "roadSignID": { + "position": { "lat": 417732928, "long": -1071000312 }, + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "warning" + } + }, + "durationTime": 32000, + "startYear": 2021, + "startTime": 89280, + "priority": 5, + "doNotUse2": 0, + "regions": [ + { + "closedPath": false, + "anchor": { "lat": 417732928, "long": -1071000312 }, + "name": "I_I 80_SAT-BC1AC5E4_RW_24869%BUFF0-0", + "laneWidth": 5000, + "directionality": "both", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, + { + "delta": { + "node-LL4": { "lon": 115529, "lat": -16624 } + } + }, + { + "delta": { + "node-LL4": { "lon": 39044, "lat": 1521 } + } }, - "msgCnt": 1 + { + "delta": { + "node-LL4": { "lon": 56228, "lat": 11450 } + } + } + ] } + }, + "scale": 0 } + }, + "id": { "id": 0, "region": 0 }, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + } + }, + { + "id": { + "region": 0, + "id": 0 + }, + "anchor": { "lat": 417732928, "long": -1071000312 }, + "name": "I_I 80_SAT-BC1AC5E4_RW_24869%BUFF0-0", + "laneWidth": 5000, + "directionality": "both", + "closedPath": false, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + }, + "description": { + "path": { + "scale": 0, + "offset": { + "ll": { + "nodes": [ + { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, + { + "delta": { + "node-LL4": { "lon": 115529, "lat": -16624 } + } + }, + { + "delta": { + "node-LL4": { "lon": 39044, "lat": 1521 } + } + }, + { + "delta": { + "node-LL4": { "lon": 56228, "lat": 11450 } + } + } + ] + } + } + } + } } - }, - "dataType": "TravelerInformation" - } + ], + "doNotUse3": 0, + "doNotUse4": 0, + "content": { + "workZone": [ + { "item": { "itis": 1537 } }, + { "item": { "itis": 12554 } }, + { "item": { "itis": 8728 } } + ] + }, + "url": "null" + } + ] + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" + } } diff --git a/cv-data-service-library/src/test/resources/tim_parking.json b/cv-data-service-library/src/test/resources/tim_parking.json index be3d8c709..519b60e3b 100644 --- a/cv-data-service-library/src/test/resources/tim_parking.json +++ b/cv-data-service-library/src/test/resources/tim_parking.json @@ -29,84 +29,105 @@ "odeReceivedAt": "2021-03-23T19:20:48.177Z" }, "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 117800, - "packetID": "AE394DB5A033905B26", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": { - "closedPath": { "false": "" }, - "anchor": { "lat": 410985067, "long": -1051331761 }, - "name": "I_I 80_SAT-1AF9F730_P_68-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, - { - "delta": { - "node-LL5": { "lon": 133699, "lat": 163 } - } - }, - { - "delta": { - "node-LL4": { "lon": 56885, "lat": -5703 } - } - } - ] - } - } + "data": { + "msgCnt": 1, + "timeStamp": 117800, + "packetID": "AE394DB5A033905B26", + "urlB": null, + "dataFrames": [ + { + "doNotUse1": 0, + "frameType": "advisory", + "msgId": { + "roadSignID": { + "position": { "lat": 417732928, "long": -1071000312 }, + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "warning" + } + }, + "durationTime": 32000, + "startYear": 2021, + "startTime": 89280, + "priority": 5, + "doNotUse2": 0, + "regions": [ + { + "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", + "id": { + "region": 0, + "id": 0 + }, + "anchor": { "lat": 417732928, "long": -1071000312 }, + "laneWidth": 5000, + "directionality": "both", + "closedPath": false, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + }, + "description": { + "path": { + "scale": 0, + "offset": { + "ll": { + "nodes": [ + { "node-LL1": { "lon": 0, "lat": 0 } }, + { + "node-LL5": { "lon": 133699, "lat": 163 } }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0001100000000000" - } - }, - "durationTime": 120, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2021, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { "warning": "" }, - "position": { "lat": 410985067, "long": -1051331761 } - } - }, - "priority": 5, - "content": { - "exitService": { - "SEQUENCE": [ - { "item": { "itis": 4104 } }, - { "item": { "itis": 11794 } }, - { "item": { "text": 345 } } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { "advisory": "" }, - "startTime": 117800 - } - }, - "msgCnt": 1 - } - } - } - }, - "dataType": "TravelerInformation" - } + { + "node-LL4": { "lon": 56885, "lat": -5703 } + } ] + } + } + } + } + } + ], + "doNotUse3": 0, + "doNotUse4": 0, + "content": { + "exitService": [ + { "item": { "itis": 4104 } }, + { "item": { "itis": 11794 } }, + { "item": { "text": 345 } } + ] + }, + "url": "null" + } + ] + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" + } } diff --git a/cv-data-service-library/src/test/resources/tim_parking_MultipleRegions.json b/cv-data-service-library/src/test/resources/tim_parking_MultipleRegions.json index 2d18e11d7..594adfcc4 100644 --- a/cv-data-service-library/src/test/resources/tim_parking_MultipleRegions.json +++ b/cv-data-service-library/src/test/resources/tim_parking_MultipleRegions.json @@ -1,147 +1,187 @@ { - "metadata": { - "request": { - "ode": { "verb": "POST", "version": 3 }, - "sdw": { - "recordId": "1AF9F730", - "serviceRegion": { - "nwCorner": { "latitude": 41.09852308, "longitude": -105.13317609 }, - "seCorner": { "latitude": 41.09795279, "longitude": -105.11411777 } - }, - "ttl": "oneday" - } - }, - "recordGeneratedBy": "TMC", - "schemaVersion": 6, - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "odePacketID": "AE394DB5A033905B26", - "serialId": { - "recordId": 0, - "serialNumber": 922, - "streamId": "9fa59341-9cab-403e-8306-6876238e9fda", - "bundleSize": 1, - "bundleId": 922 + "metadata": { + "request": { + "ode": { "verb": "POST", "version": 3 }, + "sdw": { + "recordId": "1AF9F730", + "serviceRegion": { + "nwCorner": { "latitude": 41.09852308, "longitude": -105.13317609 }, + "seCorner": { "latitude": 41.09795279, "longitude": -105.11411777 } }, - "sanitized": false, - "recordGeneratedAt": "2021-03-23T19:20:48.130840Z", - "maxDurationTime": 120, - "odeTimStartDateTime": "2021-03-23T19:20:47.118Z", - "odeReceivedAt": "2021-03-23T19:20:48.177Z" + "ttl": "oneday" + } + }, + "recordGeneratedBy": "TMC", + "schemaVersion": 6, + "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", + "odePacketID": "AE394DB5A033905B26", + "serialId": { + "recordId": 0, + "serialNumber": 922, + "streamId": "9fa59341-9cab-403e-8306-6876238e9fda", + "bundleSize": 1, + "bundleId": 922 }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 117800, - "packetID": "AE394DB5A033905B26", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": [ - { - "closedPath": { "false": "" }, - "anchor": { "lat": 410985067, "long": -1051331761 }, - "name": "I_I 80_SAT-1AF9F730_P_68-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, - { - "delta": { - "node-LL5": { "lon": 133699, "lat": 163 } - } - }, - { - "delta": { - "node-LL4": { "lon": 56885, "lat": -5703 } - } - } - ] - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0001100000000000" - }, - { - "closedPath": { "false": "" }, - "anchor": { "lat": 410985067, "long": -1051331761 }, - "name": "I_I 80_SAT-1AF9F730_P_68-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { "delta": { "node-LL1": { "lon": 0, "lat": 0 } } }, - { - "delta": { - "node-LL5": { "lon": 133699, "lat": 163 } - } - }, - { - "delta": { - "node-LL4": { "lon": 56885, "lat": -5703 } - } - } - ] - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0001100000000000" - } - ] - }, - "durationTime": 120, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2021, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { "warning": "" }, - "position": { "lat": 410985067, "long": -1051331761 } - } - }, - "priority": 5, - "content": { - "exitService": { - "SEQUENCE": [ - { "item": { "itis": 4104 } }, - { "item": { "itis": 11794 } }, - { "item": { "text": 345 } } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { "advisory": "" }, - "startTime": 117800 - } - }, - "msgCnt": 1 + "sanitized": false, + "recordGeneratedAt": "2021-03-23T19:20:48.130840Z", + "maxDurationTime": 120, + "odeTimStartDateTime": "2021-03-23T19:20:47.118Z", + "odeReceivedAt": "2021-03-23T19:20:48.177Z" + }, + "payload": { + "data": { + "timeStamp": 117800, + "packetID": "AE394DB5A033905B26", + "urlB": null, + "dataFrames": [ + { + "regions": [ + { + "closedPath": false, + "anchor": { "lat": 410985067, "long": -1051331761 }, + "name": "I_I 80_SAT-1AF9F730_P_68-0", + "laneWidth": 5000, + "directionality": "both", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { + "delta": { "node-LL1": { "lon": 0, "lat": 0 } } + }, + { + "delta": { + "node-LL5": { "lon": 133699, "lat": 163 } + } + }, + { + "delta": { + "node-LL4": { "lon": 56885, "lat": -5703 } + } + } + ] + } + }, + "scale": 0 } + }, + "id": { "id": 0, "region": 0 }, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false } - } - }, - "dataType": "TravelerInformation" - } + }, + { + "closedPath": "false", + "anchor": { "lat": 410985067, "long": -1051331761 }, + "name": "I_I 80_SAT-1AF9F730_P_68-0", + "laneWidth": 5000, + "directionality": "both", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { + "delta": { "node-LL1": { "lon": 0, "lat": 0 } } + }, + { + "delta": { + "node-LL5": { "lon": 133699, "lat": 163 } + } + }, + { + "delta": { + "node-LL4": { "lon": 56885, "lat": -5703 } + } + } + ] + } + }, + "scale": 0 + } + }, + "id": { "id": 0, "region": 0 }, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + } + } + ], + "durationTime": 120, + "doNotUse3": 0, + "doNotUse4": 0, + "startYear": 2021, + "msgId": { + "roadSignID": { + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "warning", + "position": { "lat": 410985067, "long": -1051331761 } + } + }, + "priority": 5, + "content": { + "exitService": [ + { "item": { "itis": 4104 } }, + { "item": { "itis": 11794 } }, + { "item": { "text": 345 } } + ] + }, + "url": "null", + "doNotUse1": 0, + "doNotUse2": 0, + "frameType": "advisory", + "startTime": 117800 + } + ], + "msgCnt": 1 + }, + "dataType": "TravelerInformation" + } } diff --git a/cv-data-service-library/src/test/resources/tim_vsl.json b/cv-data-service-library/src/test/resources/tim_vsl.json index 3621812d5..fde8dd0cb 100644 --- a/cv-data-service-library/src/test/resources/tim_vsl.json +++ b/cv-data-service-library/src/test/resources/tim_vsl.json @@ -1,102 +1,126 @@ { - "metadata": { - "request": { - "ode": { "verb": "POST", "version": 3 }, - "sdw": { - "recordId": "A5FB00B7", - "serviceRegion": { - "nwCorner": { "latitude": 42.8616018, "longitude": -106.3393164 }, - "seCorner": { "latitude": 42.8616018, "longitude": -106.3393164 } - }, - "ttl": "oneyear" - } - }, - "recordGeneratedBy": "TMC", - "schemaVersion": 6, - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "odePacketID": "FCEAC42FC4F3A9E274", - "serialId": { - "recordId": 0, - "serialNumber": 5745, - "streamId": "28dcab17-fb6b-4df5-8139-6cf59e5d64c5", - "bundleSize": 1, - "bundleId": 5745 + "metadata": { + "request": { + "ode": { "verb": "POST", "version": 3 }, + "sdw": { + "recordId": "A5FB00B7", + "serviceRegion": { + "nwCorner": { "latitude": 42.8616018, "longitude": -106.3393164 }, + "seCorner": { "latitude": 42.8616018, "longitude": -106.3393164 } }, - "sanitized": false, - "recordGeneratedAt": "2021-03-22T08:41:37.953583Z", - "maxDurationTime": 32000, - "odeTimStartDateTime": "2021-03-22T08:41:36.848Z", - "odeReceivedAt": "2021-03-22T08:41:38.108Z" + "ttl": "oneyear" + } + }, + "recordGeneratedBy": "TMC", + "schemaVersion": 6, + "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", + "odePacketID": "FCEAC42FC4F3A9E274", + "serialId": { + "recordId": 0, + "serialNumber": 5745, + "streamId": "28dcab17-fb6b-4df5-8139-6cf59e5d64c5", + "bundleSize": 1, + "bundleId": 5745 }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 115721, - "packetID": "FCEAC42FC4F3A9E274", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": { - "closedPath": { "false": "" }, - "anchor": { "lat": 428605724, "long": -1063379489 }, - "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": { - "delta": { "node-LL3": { "lon": -13675, "lat": 10295 } } - } - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0000000000000010" - } - }, - "durationTime": 32000, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2021, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { "regulatory": "" }, - "position": { "lat": 428605724, "long": -1063379489 } - } - }, - "priority": 5, - "content": { - "speedLimit": { - "SEQUENCE": [ - { "item": { "itis": 268 } }, - { "item": { "itis": 12604 } }, - { "item": { "itis": 8720 } } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { "roadSignage": "" }, - "startTime": 115721 - } - }, - "msgCnt": 1 + "sanitized": false, + "recordGeneratedAt": "2021-03-22T08:41:37.953583Z", + "maxDurationTime": 32000, + "odeTimStartDateTime": "2021-03-22T08:41:36.848Z", + "odeReceivedAt": "2021-03-22T08:41:38.108Z" + }, + "payload": { + "data": { + "msgCnt": 1, + "timeStamp": 115721, + "packetID": "FCEAC42FC4F3A9E274", + "urlB": "null", + "dataFrames": [ + { + "doNotUse1": 0, + "frameType": "advisory", + "msgId": { + "roadSignID": { + "position": { "lat": 417732928, "long": -1071000312 }, + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "warning" + } + }, + "durationTime": 32000, + "startYear": 2021, + "startTime": 89280, + "priority": 5, + "doNotUse2": 0, + "regions": [ + { + "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", + "id": { + "region": 0, + "id": 0 + }, + "anchor": { "lat": 417732928, "long": -1071000312 }, + "laneWidth": 5000, + "directionality": "both", + "closedPath": false, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + }, + "description": { + "path": { + "scale": 0, + "offset": { + "ll": { + "nodes": [{ "node-LL3": { "lon": -13675, "lat": 10295 } }] } + } } + } } - }, - "dataType": "TravelerInformation" - } + ], + "doNotUse3": 0, + "doNotUse4": 0, + "content": { + "speedLimit": [ + { "item": { "itis": 268 } }, + { "item": { "itis": 12604 } }, + { "item": { "itis": 8720 } } + ] + }, + "url": "null" + } + ] + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" + } } diff --git a/cv-data-service-library/src/test/resources/tim_vsl_MultipleRegions.json b/cv-data-service-library/src/test/resources/tim_vsl_MultipleRegions.json index c8d6cde06..e8220debf 100644 --- a/cv-data-service-library/src/test/resources/tim_vsl_MultipleRegions.json +++ b/cv-data-service-library/src/test/resources/tim_vsl_MultipleRegions.json @@ -1,127 +1,171 @@ { - "metadata": { - "request": { - "ode": { "verb": "POST", "version": 3 }, - "sdw": { - "recordId": "A5FB00B7", - "serviceRegion": { - "nwCorner": { "latitude": 42.8616018, "longitude": -106.3393164 }, - "seCorner": { "latitude": 42.8616018, "longitude": -106.3393164 } - }, - "ttl": "oneyear" - } - }, - "recordGeneratedBy": "TMC", - "schemaVersion": 6, - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "odePacketID": "FCEAC42FC4F3A9E274", - "serialId": { - "recordId": 0, - "serialNumber": 5745, - "streamId": "28dcab17-fb6b-4df5-8139-6cf59e5d64c5", - "bundleSize": 1, - "bundleId": 5745 + "metadata": { + "request": { + "ode": { "verb": "POST", "version": 3 }, + "sdw": { + "recordId": "A5FB00B7", + "serviceRegion": { + "nwCorner": { "latitude": 42.8616018, "longitude": -106.3393164 }, + "seCorner": { "latitude": 42.8616018, "longitude": -106.3393164 } }, - "sanitized": false, - "recordGeneratedAt": "2021-03-22T08:41:37.953583Z", - "maxDurationTime": 32000, - "odeTimStartDateTime": "2021-03-22T08:41:36.848Z", - "odeReceivedAt": "2021-03-22T08:41:38.108Z" + "ttl": "oneyear" + } }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 115721, - "packetID": "FCEAC42FC4F3A9E274", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": [ - { - "closedPath": { "false": "" }, - "anchor": { "lat": 428605724, "long": -1063379489 }, - "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": { - "delta": { "node-LL3": { "lon": -13675, "lat": 10295 } } - } - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0000000000000010" - }, - { - "closedPath": { "false": "" }, - "anchor": { "lat": 428605724, "long": -1063379489 }, - "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", - "laneWidth": 5000, - "directionality": { "both": "" }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": { - "delta": { "node-LL3": { "lon": -13675, "lat": 10295 } } - } - } - } - }, - "scale": 0 - } - }, - "id": { "id": 0, "region": 0 }, - "direction": "0000000000000010" - } - ] - }, - "durationTime": 32000, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2021, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { "regulatory": "" }, - "position": { "lat": 428605724, "long": -1063379489 } - } - }, - "priority": 5, - "content": { - "speedLimit": { - "SEQUENCE": [ - { "item": { "itis": 268 } }, - { "item": { "itis": 12604 } }, - { "item": { "itis": 8720 } } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { "roadSignage": "" }, - "startTime": 115721 - } - }, - "msgCnt": 1 + "recordGeneratedBy": "TMC", + "schemaVersion": 6, + "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", + "odePacketID": "FCEAC42FC4F3A9E274", + "serialId": { + "recordId": 0, + "serialNumber": 5745, + "streamId": "28dcab17-fb6b-4df5-8139-6cf59e5d64c5", + "bundleSize": 1, + "bundleId": 5745 + }, + "sanitized": false, + "recordGeneratedAt": "2021-03-22T08:41:37.953583Z", + "maxDurationTime": 32000, + "odeTimStartDateTime": "2021-03-22T08:41:36.848Z", + "odeReceivedAt": "2021-03-22T08:41:38.108Z" + }, + "payload": { + "data": { + "timeStamp": 115721, + "packetID": "FCEAC42FC4F3A9E274", + "urlB": "null", + "dataFrames": [ + { + "regions": [ + { + "closedPath": "false", + "anchor": { "lat": 428605724, "long": -1063379489 }, + "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", + "laneWidth": 5000, + "directionality": "both", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { + "delta": { + "node-LL3": { "lon": -13675, "lat": 10295 } + } + } + ] + } + }, + "scale": 0 + } + }, + "id": { "id": 0, "region": 0 }, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": false, + "from090-0to112-5degrees": false, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": false + } + }, + { + "closedPath": "false", + "anchor": { "lat": 428605724, "long": -1063379489 }, + "name": "I_I 25_SAT-A5FB00B7_VSL_V004988-0", + "laneWidth": 5000, + "directionality": "both", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { + "delta": { + "node-LL3": { "lon": -13675, "lat": 10295 } + } + } + ] } + }, + "scale": 0 } + }, + "id": { "id": 0, "region": 0 }, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": false, + "from090-0to112-5degrees": false, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": false + } } - }, - "dataType": "TravelerInformation" - } + ], + "durationTime": 32000, + "doNotUse3": 1, + "doNotUse4": 1, + "startYear": 2021, + "msgId": { + "roadSignID": { + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "regulatory", + "position": { "lat": 428605724, "long": -1063379489 } + } + }, + "priority": 5, + "content": { + "speedLimit": [ + { "item": { "itis": 268 } }, + { "item": { "itis": 12604 } }, + { "item": { "itis": 8720 } } + ] + }, + "url": "null", + "doNotUse1": 0, + "doNotUse2": 0, + "frameType": "roadSignage", + "startTime": 115721 + } + ], + "msgCnt": 1 + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" + } } diff --git a/cv-data-tasks/Dockerfile b/cv-data-tasks/Dockerfile index 243e3c4a8..4fc8fa7a9 100644 --- a/cv-data-tasks/Dockerfile +++ b/cv-data-tasks/Dockerfile @@ -1,5 +1,5 @@ # Required resources for deployment: -# - cv-data-tasks-1.4.0-SNAPSHOT.jar +# - cv-data-tasks-2.0.0.jar FROM maven:3.8-eclipse-temurin-21-alpine @@ -10,4 +10,4 @@ ADD . $install_dir # Uncomment and modify the certificate name on the following line to import a certificate into the Java keystore # RUN keytool -import -alias resdf -storepass changeit -noprompt -cacerts -file ${install_dir}/.cer -CMD java -jar ${install_dir}/cv-data-tasks-1.4.0-SNAPSHOT.jar +CMD java -jar ${install_dir}/cv-data-tasks-2.0.0.jar diff --git a/cv-data-tasks/pom.xml b/cv-data-tasks/pom.xml index 790b3b5b9..5fb8b54e6 100644 --- a/cv-data-tasks/pom.xml +++ b/cv-data-tasks/pom.xml @@ -10,7 +10,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 diff --git a/cv-data-tasks/src/main/java/com/trihydro/tasks/actions/RemoveExpiredActiveTims.java b/cv-data-tasks/src/main/java/com/trihydro/tasks/actions/RemoveExpiredActiveTims.java index 39f0ea520..930818b26 100644 --- a/cv-data-tasks/src/main/java/com/trihydro/tasks/actions/RemoveExpiredActiveTims.java +++ b/cv-data-tasks/src/main/java/com/trihydro/tasks/actions/RemoveExpiredActiveTims.java @@ -9,13 +9,16 @@ import com.trihydro.library.service.RestTemplateProvider; import com.trihydro.tasks.config.DataTasksConfiguration; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; +import org.springframework.web.client.ResourceAccessException; +@Slf4j @Component public class RemoveExpiredActiveTims implements Runnable { private DataTasksConfiguration configuration; @@ -32,36 +35,61 @@ public void InjectDependencies(DataTasksConfiguration configuration, Utility _ut restTemplateProvider = _restTemplateProvider; } + /** + * This method is called by the task scheduler to remove expired Active TIMs in batches. + * + * The rationale for processing batches of expired Active TIMs is to avoid connection timeouts + * when deleting a large number of Active TIMs. If we tried to delete all expired Active TIMs + * in one batch, and it took longer than the configured connection timeout, the task would fail + * and the Active TIMs would not be deleted. + */ public void run() { - utility.logWithDate("Running...", this.getClass()); + log.info("Running..."); - try { - // select active tims - List activeTims = activeTimService.getExpiredActiveTims(); - utility.logWithDate("Found " + activeTims.size() + " expired Active TIMs", this.getClass()); + int batchSize = 500; + int maxBatchCount = 50; + int batchCount = 0; + while (true) { + try { + // select active tims + List activeTims = activeTimService.getExpiredActiveTims(batchSize); + log.info("Retrieved a batch of {} expired Active TIMs", activeTims.size()); + if (activeTims.isEmpty()) { + break; + } - // delete active tims from rsus - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity entity = null; - String activeTimJson; - Gson gson = new Gson(); + // delete active tims from rsus and sdx + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity entity = null; + String activeTimJson; + Gson gson = new Gson(); - // send to tim type endpoint to delete from RSUs and SDWs - for (ActiveTim activeTim : activeTims) { + // send to tim type endpoint to delete from RSUs and SDX + for (ActiveTim activeTim : activeTims) { - activeTimJson = gson.toJson(activeTim); - entity = new HttpEntity(activeTimJson, headers); + activeTimJson = gson.toJson(activeTim); + entity = new HttpEntity(activeTimJson, headers); - utility.logWithDate("Deleting ActiveTim: { activeTimId: " + activeTim.getActiveTimId() + " }", - this.getClass()); - restTemplateProvider.GetRestTemplate().exchange(configuration.getWrapperUrl() + "/delete-tim/", - HttpMethod.DELETE, entity, String.class); + log.info("Attempting to delete ActiveTim: { activeTimId: {} }", activeTim.getActiveTimId()); + restTemplateProvider.GetRestTemplate() + .exchange(configuration.getWrapperUrl() + "/delete-tim/", + HttpMethod.DELETE, entity, String.class); + } + } catch (ResourceAccessException e) { + log.error("Error accessing resource. This indicates that the ODE Wrapper or CV Data Controller is not reachable. No more batches will be processed until the next run.", e); + // the error should not be rethrown, or else the task will not run until the service is restarted + break; + } catch (Exception e) { + log.error("Unexpected error occurred while processing expired Active TIMs", e); + // the error should not be rethrown, or else the task will not run until the service is restarted + } + batchCount++; + if (batchCount >= maxBatchCount) { + log.warn("Maximum batches reached. This indicates either A) repeated failures to delete expired Active TIMs or B) a large number of expired Active TIMs (more than {}). No more batches will be processed until the next run.", maxBatchCount * batchSize); + break; } - } catch (Exception e) { - e.printStackTrace(); - // don't rethrow error, or the task won't be reran until the service is - // restarted. } + log.info("{} attempts were made to process batches of expired Active TIMs", batchCount); } } \ No newline at end of file diff --git a/cv-data-tasks/src/test/java/com/trihydro/tasks/actions/RemoveExpiredActiveTimsTest.java b/cv-data-tasks/src/test/java/com/trihydro/tasks/actions/RemoveExpiredActiveTimsTest.java index 74431e9b1..37351a033 100644 --- a/cv-data-tasks/src/test/java/com/trihydro/tasks/actions/RemoveExpiredActiveTimsTest.java +++ b/cv-data-tasks/src/test/java/com/trihydro/tasks/actions/RemoveExpiredActiveTimsTest.java @@ -48,7 +48,8 @@ public void setup() { List expiredTims = new ArrayList(); expiredTims.add(new ActiveTim()); expiredTims.add(new ActiveTim()); - when(mockActiveTimService.getExpiredActiveTims()).thenReturn(expiredTims); + when(mockActiveTimService.getExpiredActiveTims(500)).thenReturn(expiredTims).thenReturn( + new ArrayList<>()); } @Test diff --git a/developer-tools/geojson-from-ode-tim/sampledata.json b/developer-tools/geojson-from-ode-tim/sampledata.json index e6daa0016..b8ec7a2fc 100644 --- a/developer-tools/geojson-from-ode-tim/sampledata.json +++ b/developer-tools/geojson-from-ode-tim/sampledata.json @@ -21,7 +21,7 @@ "packetID": "24BE29D8A92FDF0930", "dataframes": [ { - "notUsed": 0, + "doNotUse1": 0, "frameType": "advisory", "msgId": { "roadSignID": { @@ -36,7 +36,7 @@ "startDateTime": "2024-10-02T11:00:50.814Z", "durationTime": 32000, "priority": 5, - "notUsed1": 0, + "doNotUse2": 0, "regions": [ { "name": "D_US 14_SAT-D99EEE98_RC_BJUS14EB", @@ -443,8 +443,8 @@ } } ], - "notUsed2": 0, - "notUsed3": 0, + "doNotUse3": 0, + "doNotUse4": 0, "content": "advisory", "items": [ "770", diff --git a/docker-compose.yml b/docker-compose.yml index ebf6bcc90..f067bf275 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -140,6 +140,7 @@ services: SERVER_SSL_KEY_STORE_PASSWORD: ${CONTROLLER_SERVER_SSL_KEY_STORE_PASSWORD} SERVER_SSL_KEY_STORE_TYPE: ${CONTROLLER_SERVER_SSL_KEY_STORE_TYPE} SERVER_SSL_KEY_ALIAS: ${CONTROLLER_SERVER_SSL_KEY_ALIAS} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} volumes: - /home/timmadmin/timm/cv-data-controller:/keystore logging: @@ -160,6 +161,7 @@ services: CONFIG_SNMP_AUTH_PASSPHRASE: ${RSUCONTROLLER_CONFIG_SNMP_AUTH_PASSPHRASE} CONFIG_SNMP_AUTH_PROTOCOL: ${RSUCONTROLLER_CONFIG_SNMP_AUTH_PROTOCOL} CONFIG_SNMP_SECURITY_LEVEL: ${RSUCONTROLLER_CONFIG_SNMP_SECURITY_LEVEL} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -182,6 +184,7 @@ services: MONGOLOGGER_ENVIRONMENT_NAME: ${ENVIRONMENT_NAME} MONGOLOGGER_MAIL_HOST: ${MAIL_HOST} MONGOLOGGER_MAIL_PORT: ${MAIL_PORT} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -204,6 +207,7 @@ services: MONGOLOGGER_ENVIRONMENT_NAME: ${ENVIRONMENT_NAME} MONGOLOGGER_MAIL_HOST: ${MAIL_HOST} MONGOLOGGER_MAIL_PORT: ${MAIL_PORT} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -226,6 +230,7 @@ services: MONGOLOGGER_ENVIRONMENT_NAME: ${ENVIRONMENT_NAME} MONGOLOGGER_MAIL_HOST: ${MAIL_HOST} MONGOLOGGER_MAIL_PORT: ${MAIL_PORT} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -246,6 +251,7 @@ services: CV_REST_SERVICE: ${LOGGER_CV_REST_SERVICE} PRODUCER_TOPIC: ${DBCONSUMER_DEPOSIT_TOPIC} ENV: ${LOGGER_ENV} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -277,25 +283,6 @@ services: max-size: "20m" max-file: "3" - milepost-graph-db: - build: milepost-graph-db - restart: always - ports: - - "6474:7474" - - "6473:7473" - - "6687:7687" - volumes: - - ./milepost-graph-db/neo-data/plugins:/var/lib/neo4j/plugins - - ./milepost-graph-db/neo-data/import:/var/lib/neo4j/import - - ./milepost-graph-db/neo-data/conf:/var/lib/neo4j/conf - - ./milepost-graph-db/neo-data/data:/var/lib/neo4j/data - environment: - NEO4J_AUTH: none - logging: - options: - max-size: "20m" - max-file: "3" - cert-expiration: build: cert-expiration restart: always @@ -311,6 +298,7 @@ services: DEPOSIT_GROUP: ${EXP_GROUP} CV_REST_SERVICE: ${LOGGER_CV_REST_SERVICE} PRODUCER_TOPIC: ${DBCONSUMER_DEPOSIT_TOPIC} + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" diff --git a/local-deployment/docker-compose.yml b/local-deployment/docker-compose.yml index 0d95edc67..d33ed2200 100644 --- a/local-deployment/docker-compose.yml +++ b/local-deployment/docker-compose.yml @@ -23,7 +23,7 @@ services: KAFKA_CFG_LOG_RETENTION_HOURS: 2 logging: options: - max-size: "10m" + max-size: "10m" max-file: "5" kafka_init: @@ -33,10 +33,10 @@ services: condition: service_started volumes: - ./docker-scripts/kafka/kafka_init.sh:/kafka_init.sh - entrypoint: ["/bin/sh", "kafka_init.sh"] - + entrypoint: [ "/bin/sh", "kafka_init.sh" ] + ode: - image: usdotjpoode/jpo-ode:2024-q2 + image: usdotjpoode/jpo-ode:2025-q1 ports: - "8080:8080" - "9090:9090" @@ -52,13 +52,28 @@ services: - "6666:6666/udp" environment: DOCKER_HOST_IP: ${DOCKER_HOST_IP} - ZK: ${DOCKER_HOST_IP}:2181 + ODE_KAFKA_BROKERS: ${DOCKER_HOST_IP}:9092 ODE_SECURITY_SVCS_SIGNATURE_URI: http://notused ODE_RSU_USERNAME: testusername ODE_RSU_PASSWORD: testpassword DATA_SIGNING_ENABLED_RSU: false DATA_SIGNING_ENABLED_SDW: false DEFAULT_SNMP_PROTOCOL: NTCIP1218 + KAFKA_TYPE: local + CONFLUENT_KEY: notused + CONFLUENT_SECRET: notused + KAFKA_LINGER_MS: 1 + KAFKA_ACKS: all + KAFKA_RETRIES: 0 + KAFKA_BATCH_SIZE: 16384 + KAFKA_BUFFER_MEMORY: 33554432 + KAFKA_COMPRESSION_TYPE: zstd + KAFKA_KEY_SERIALIZER: org.apache.kafka.common.serialization.StringSerializer + KAFKA_VALUE_SERIALIZER: org.apache.kafka.common.serialization.StringSerializer + KAFKA_PARTITIONER_CLASS: org.apache.kafka.clients.producer.internals.DefaultPartitioner + ODE_TIM_INGEST_MONITORING_ENABLED: false + ODE_TIM_INGEST_MONITORING_INTERVAL: 10000 + depends_on: - kafka volumes: @@ -68,15 +83,15 @@ services: options: max-size: "10m" max-file: "5" - + adm: - image: usdotjpoode/asn1_codec:2024-q2 + image: usdotjpoode/asn1_codec:2025-q1 environment: DOCKER_HOST_IP: ${DOCKER_HOST_IP} ACM_CONFIG_FILE: adm.properties ACM_LOG_TO_CONSOLE: "true" ACM_LOG_TO_FILE: "false" - ACM_LOG_LEVEL: ERROR + ACM_LOG_LEVEL: ${ACM_LOG_LEVEL} depends_on: - kafka volumes: @@ -88,13 +103,13 @@ services: restart: on-failure aem: - image: usdotjpoode/asn1_codec:2024-q2 + image: usdotjpoode/asn1_codec:2025-q1 environment: DOCKER_HOST_IP: ${DOCKER_HOST_IP} ACM_CONFIG_FILE: aem.properties ACM_LOG_TO_CONSOLE: "true" ACM_LOG_TO_FILE: "false" - ACM_LOG_LEVEL: ERROR + ACM_LOG_LEVEL: ${ACM_LOG_LEVEL} depends_on: - kafka volumes: @@ -107,7 +122,7 @@ services: # Note: the SDX does not accept unsigned data, so this is commented out for now # sdw_depositor: - # image: usdotjpoode/jpo-sdw-depositor:2024-q2 + # image: usdotjpoode/jpo-sdw-depositor:2025-q1 # environment: # DOCKER_HOST_IP: ${DOCKER_HOST_IP} # SDW_EMAIL_LIST: test@gmail.com @@ -154,27 +169,6 @@ services: max-size: '10m' # end of external dependencies ---------------------------------------------- - # internal dependencies ------------------------------------------------------ - milepost-graph-db: - build: ../milepost-graph-db - restart: always - ports: - - "6474:7474" - - "6473:7473" - - "6687:7687" - volumes: - - ../milepost-graph-db/neo-data/plugins:/var/lib/neo4j/plugins - - ../milepost-graph-db/neo-data/import:/var/lib/neo4j/import - - ../milepost-graph-db/neo-data/conf:/var/lib/neo4j/conf - - ../milepost-graph-db/neo-data/data:/var/lib/neo4j/data - environment: - NEO4J_AUTH: none - logging: - options: - max-size: "20m" - max-file: "3" - # end of internal dependencies ------------------------------------------------ - # timm apps -------------------------------------------------------------- cv-data-controller: build: ../cv-data-controller @@ -190,12 +184,13 @@ services: CONFIG_CONNECTION_TIMEOUT: 300000 CONFIG_ODE_URL: http://ode:8080 CONFIG_ENV: local - SPRING_DATA_NEO4J_URI: bolt://milepost-graph-db:7687 + SPRING_DATA_NEO4J_URI: ${NEO4J_URI} CONFIG_ALERT_ADDRESSES: test@gmail.com CONFIG_FROM_EMAIL: test@gmail.com CONFIG_ENVIRONMENT_NAME: local CONFIG_MAIL_HOST: 172.0.0.1 CONFIG_MAIL_PORT: 123 + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -247,6 +242,7 @@ services: CONFIG_SNMP_AUTH_PASSPHRASE: testpassword CONFIG_SNMP_AUTH_PROTOCOL: SHA CONFIG_SNMP_SECURITY_LEVEL: authNoPriv + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -319,6 +315,7 @@ services: CV_REST_SERVICE: http://cv-data-controller:8888 PRODUCER_TOPIC: topic.OracleDataLogger ENV: local + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -362,7 +359,7 @@ services: CONFIG_DEFAULT_LANE_WIDTH: 50 CONFIG_RSU_ROUTES: ${RSU_ROUTES} CONFIG_POINT_INCIDENT_BUFFER_MILES: 1 - CRON_EXPRESSION: "0 0 * * * ?" + CRON_EXPRESSION: ${REFRESH_CRON_EXPRESSION} CONFIG_ENV: local CONFIG_ALERT_ADDRESSES: test@gmail.com CONFIG_FROM_EMAIL: test@gmail.com @@ -389,6 +386,7 @@ services: DEPOSIT_GROUP: certExpirationGroup CV_REST_SERVICE: http://cv-data-controller:8888 PRODUCER_TOPIC: topic.OracleDataLogger + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -411,6 +409,7 @@ services: MONGOLOGGER_ENVIRONMENT_NAME: local MONGOLOGGER_MAIL_HOST: 172.0.0.1 MONGOLOGGER_MAIL_PORT: 123 + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -433,6 +432,7 @@ services: MONGOLOGGER_ENVIRONMENT_NAME: local MONGOLOGGER_MAIL_HOST: 172.0.0.1 MONGOLOGGER_MAIL_PORT: 123 + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -455,6 +455,7 @@ services: MONGOLOGGER_ENVIRONMENT_NAME: local MONGOLOGGER_MAIL_HOST: 172.0.0.1 MONGOLOGGER_MAIL_PORT: 123 + LOGGING_LEVEL_COM_TRIHYDRO: ${LOGGING_LEVEL_COM_TRIHYDRO} logging: options: max-size: "20m" @@ -464,7 +465,7 @@ services: # volumes --------------------------------------------------------------------- volumes: kafka: - {} + { } pgdb: driver: local mongodb_data_container: diff --git a/local-deployment/sample.env b/local-deployment/sample.env index 27c8d91fe..3d2c7497b 100644 --- a/local-deployment/sample.env +++ b/local-deployment/sample.env @@ -10,4 +10,13 @@ MONGO_USER=username MONGO_PASSWORD=password RSU_ROUTES="route1, route2" TASKS_CONFIG_CLEANUP_STALE_ACTIVE_TIM_HOLDING_RECORDS_PERIOD_MINUTES=5 -LOGGING_LEVEL_COM_TRIHYDRO=DEBUG \ No newline at end of file +LOGGING_LEVEL_COM_TRIHYDRO=DEBUG + +# second minute hour day month day-of-week +REFRESH_CRON_EXPRESSION="0 0 1 * * *" + +# URI for the Neo4j database (which is not included in the local deployment) +NEO4J_URI=bolt://${DOCKER_HOST_IP}:6687 + +# log level of asn1_codec instances +ACM_LOG_LEVEL=ERROR \ No newline at end of file diff --git a/logger-kafka-consumer/Dockerfile b/logger-kafka-consumer/Dockerfile index a35b22b8f..123fb5ecc 100644 --- a/logger-kafka-consumer/Dockerfile +++ b/logger-kafka-consumer/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/logger-kafka-consumer -CMD java -jar /home/timm/timm_applications/logger-kafka-consumer/logger-kafka-consumer-1.4.0-SNAPSHOT.jar +CMD java -jar /home/timm/timm_applications/logger-kafka-consumer/logger-kafka-consumer-2.0.0.jar diff --git a/logger-kafka-consumer/pom.xml b/logger-kafka-consumer/pom.xml index d92b71609..811694f23 100644 --- a/logger-kafka-consumer/pom.xml +++ b/logger-kafka-consumer/pom.xml @@ -10,7 +10,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 logger-kafka-consumer diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/LoggerKafkaConsumer.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/LoggerKafkaConsumer.java index b88d0aa94..627195a68 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/LoggerKafkaConsumer.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/LoggerKafkaConsumer.java @@ -1,6 +1,5 @@ package com.trihydro.loggerkafkaconsumer.app; -import java.io.IOException; import java.util.Date; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -18,6 +17,7 @@ import com.trihydro.loggerkafkaconsumer.app.services.TimService; import com.trihydro.loggerkafkaconsumer.config.LoggerConfiguration; +import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.springframework.beans.factory.annotation.Autowired; @@ -26,23 +26,23 @@ import us.dot.its.jpo.ode.model.OdeData; @Component +@Slf4j public class LoggerKafkaConsumer { - private ObjectMapper mapper; - private LoggerConfiguration loggerConfig; - private KafkaFactory kafkaFactory; - private ActiveTimService activeTimService; - private ActiveTimHoldingService activeTimHoldingService; - private TimService timService; - private TimDataConverter timDataConverter; - private Utility utility; - private EmailHelper emailHelper; + private final LoggerConfiguration loggerConfig; + private final KafkaFactory kafkaFactory; + private final ActiveTimService activeTimService; + private final ActiveTimHoldingService activeTimHoldingService; + private final TimService timService; + private final TimDataConverter timDataConverter; + private final Utility utility; + private final EmailHelper emailHelper; @Autowired public LoggerKafkaConsumer(LoggerConfiguration _loggerConfig, KafkaFactory _kafkaFactory, - ActiveTimService _activeTimService, TimService _timService, - TimDataConverter _timDataConverter, Utility _utility, EmailHelper _emailHelper, - ActiveTimHoldingService _activeTimHoldingService) throws IOException, Exception { + ActiveTimService _activeTimService, TimService _timService, + TimDataConverter _timDataConverter, Utility _utility, EmailHelper _emailHelper, + ActiveTimHoldingService _activeTimHoldingService) throws Exception { loggerConfig = _loggerConfig; kafkaFactory = _kafkaFactory; activeTimService = _activeTimService; @@ -52,9 +52,9 @@ public LoggerKafkaConsumer(LoggerConfiguration _loggerConfig, KafkaFactory _kafk emailHelper = _emailHelper; activeTimHoldingService = _activeTimHoldingService; - System.out.println("starting.............."); + log.info("Logger Kafka Consumer starting.............."); - mapper = new ObjectMapper(); + ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); startKafkaConsumer(); } @@ -63,8 +63,8 @@ public void startKafkaConsumer() throws Exception { String endpoint = loggerConfig.getKafkaHostServer() + ":9092"; var stringConsumer = kafkaFactory.createStringConsumer(endpoint, loggerConfig.getDepositGroup(), - loggerConfig.getDepositTopic(), Integer.valueOf(loggerConfig.getMaxPollIntervalMs()), - Integer.valueOf(loggerConfig.getMaxPollRecords())); + loggerConfig.getDepositTopic(), loggerConfig.getMaxPollIntervalMs(), + loggerConfig.getMaxPollRecords()); Gson gson = new Gson(); @@ -75,7 +75,7 @@ public void startKafkaConsumer() throws Exception { ConsumerRecords records = stringConsumer.poll(100); recordCount = records.count(); if (recordCount > 0) { - utility.logWithDate(String.format("Found %d records to parse", recordCount)); + log.info("Found {} records to parse", recordCount); } for (ConsumerRecord record : records) { TopicDataWrapper tdw = null; @@ -83,97 +83,95 @@ public void startKafkaConsumer() throws Exception { tdw = gson.fromJson(record.value(), TopicDataWrapper.class); } catch (Exception e) { // Could be ioException, JsonParseException, JsonMappingException - e.printStackTrace(); + log.error("Failed to parse record: {}", record.value(), e); } if (tdw != null && tdw.getData() != null) { - utility.logWithDate(String.format("Found data for topic: %s", tdw.getTopic())); + log.info("Found data for topic: {}", tdw.getTopic()); switch (tdw.getTopic()) { - case "topic.OdeTimJson": - utility.logWithDate("Before processing JSON: " + tdw.getData()); - odeData = timDataConverter.processTimJson(tdw.getData()); - utility.logWithDate(String.format("Parsed TIM: %s", gson.toJson(odeData))); - if (odeData != null) { - if (odeData.getMetadata() + case "topic.OdeTimJson": + log.trace("Before processing JSON: {}", tdw.getData()); + odeData = timDataConverter.processTimJson(tdw.getData()); + log.trace("After processing JSON: {}", gson.toJson(odeData)); + if (odeData != null) { + if (odeData.getMetadata() .getRecordGeneratedBy() == us.dot.its.jpo.ode.model.OdeMsgMetadata.GeneratedBy.TMC) { - timService.addActiveTimToDatabase(odeData); - } else if (odeData.getMetadata().getRecordGeneratedBy() == null) { - // we shouldn't get here...log it - utility.logWithDate("Failed to get recordGeneratedBy, continuing..."); + timService.addActiveTimToDatabase(odeData); + } else if (odeData.getMetadata().getRecordGeneratedBy() == null) { + // we shouldn't get here...log it + log.error("Failed to get recordGeneratedBy, continuing..."); + } else { + timService.addTimToDatabase(odeData); + } } else { - timService.addTimToDatabase(odeData); + log.error("Failed to parse topic.OdeTimJson, insert fails"); } - } else { - utility.logWithDate("Failed to parse topic.OdeTimJson, insert fails"); - } - break; - - case "topic.OdeTIMCertExpirationTimeJson": - try { - CertExpirationModel certExpirationModel = gson.fromJson(tdw.getData(), + break; + + case "topic.OdeTIMCertExpirationTimeJson": + try { + CertExpirationModel certExpirationModel = gson.fromJson(tdw.getData(), CertExpirationModel.class); - var success = timService.updateActiveTimExpiration(certExpirationModel); - if (success) { - utility.logWithDate("Successfully updated expiration date"); - } else { - // Check for issues - var activeTim = activeTimService + var success = timService.updateActiveTimExpiration(certExpirationModel); + if (success) { + log.info("Successfully updated expiration date"); + } else { + // Check for issues + var activeTim = activeTimService .getActiveTimByPacketId(certExpirationModel.getPacketID()); - // Check if activeTim exists - if (activeTim == null) { - // active_tim not created yet, check active_tim_holding - var ath = activeTimHoldingService + // Check if activeTim exists + if (activeTim == null) { + // active_tim not created yet, check active_tim_holding + var ath = activeTimHoldingService .getActiveTimHoldingByPacketId(certExpirationModel.getPacketID()); - if (ath != null) { - // update ath expiration - success = activeTimHoldingService.updateTimExpiration( + if (ath != null) { + // update ath expiration + success = activeTimHoldingService.updateTimExpiration( certExpirationModel.getPacketID(), certExpirationModel.getExpirationDate()); + } + } else if (messageSuperseded(certExpirationModel.getStartDateTime(), activeTim)) { + // Message superseded + log.info("Unable to update expiration date for Active Tim {} (Packet ID: {}). Message superseded.", + activeTim.getActiveTimId(), certExpirationModel.getPacketID()); } - } else if (messageSuperseded(certExpirationModel.getStartDateTime(), activeTim)) { - // Message superseded - utility.logWithDate(String.format( - "Unable to update expiration date for Active Tim %s (Packet ID: %s). Message superseded.", - activeTim.getActiveTimId(), certExpirationModel.getPacketID())); - } - if (!success) { - // Message either not superseded, or not found in active_tim nor holding tables. error case - utility.logWithDate(String.format("Failed to update expiration for data: %s", - tdw.getData())); + if (!success) { + // Message either not superseded, or not found in active_tim nor holding tables. error case + log.error("Failed to update expiration for data: {}", tdw.getData()); - String body = "logger-kafka-consumer failed attempting to update the expiration for an ActiveTim record"; - body += "
"; - body += "The associated expiration topic record is:
"; - body += tdw.getData(); - emailHelper.SendEmail(loggerConfig.getAlertAddresses(), + String body = "logger-kafka-consumer failed attempting to update the expiration for an ActiveTim record"; + body += "
"; + body += "The associated expiration topic record is:
"; + body += tdw.getData(); + emailHelper.SendEmail(loggerConfig.getAlertAddresses(), "Failed To Update ActiveTim Expiration", body); + } } + } catch (Exception ex) { + log.error("Failed to parse topic.OdeTIMCertExpirationTimeJson, insert fails", ex); } - } catch (Exception ex) { - ex.printStackTrace(); - } - break; + break; } } else { - utility.logWithDate("Logger Kafka Consumer failed to deserialize proper TopicDataWrapper"); + log.error("Logger Kafka Consumer failed to deserialize proper TopicDataWrapper"); if (tdw != null) { - utility.logWithDate(gson.toJson(tdw)); + log.error("Data: {}", tdw.getData()); } } } } } catch (Exception ex) { - utility.logWithDate(ex.getMessage()); + log.error("Error in Kafka Consumer: {}", ex.getMessage()); emailHelper.ContainerRestarted(loggerConfig.getAlertAddresses(), loggerConfig.getMailPort(), - loggerConfig.getMailHost(), loggerConfig.getFromEmail(), "Logger Kafka Consumer"); + loggerConfig.getMailHost(), loggerConfig.getFromEmail(), "Logger Kafka Consumer"); throw ex; } finally { try { stringConsumer.close(); } catch (Exception consumerEx) { - consumerEx.printStackTrace(); + log.error("Failed to close consumer", consumerEx); } } } @@ -193,7 +191,7 @@ private boolean messageSuperseded(String startTime, ActiveTim dbRecord) { // currently processing has been superseded. return expectedStart.getTime() < dbRecord.getStartTimestamp().getTime(); } catch (Exception ex) { - utility.logWithDate("Error while checking if message was superseded: " + ex.getMessage()); + log.error("Error while checking if message was superseded: {}", ex.getMessage()); return false; } } diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimHoldingService.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimHoldingService.java index 70f3ea0dc..18069c563 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimHoldingService.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimHoldingService.java @@ -9,49 +9,35 @@ import com.trihydro.library.model.ActiveTimHolding; import com.trihydro.library.model.Coordinate; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @Component +@Slf4j public class ActiveTimHoldingService extends BaseService { public ActiveTimHolding getRsuActiveTimHolding(String clientId, String direction, String ipv4Address) { ActiveTimHolding activeTimHolding = null; - Connection connection = null; - Statement statement = null; - ResultSet rs = null; - - try { - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - String query = "select * from active_tim_holding"; - query += " where rsu_target = '" + ipv4Address; - if (clientId != null) { - query += "' and client_id = '" + clientId + "'"; - } else { - query += "' and client_id is null"; - } - query += " and direction = '" + direction + "'"; - rs = statement.executeQuery(query); + String query = "select * from active_tim_holding"; + query += " where rsu_target = '" + ipv4Address; + if (clientId != null) { + query += "' and client_id = '" + clientId + "'"; + } else { + query += "' and client_id is null"; + } + query += " and direction = '" + direction + "'"; + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // convert to ActiveTim object activeTimHolding = getSingleActiveTimHoldingFromResultSet(rs); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("SQL Exception while getting RSU ActiveTimHolding with clientId: {}, direction: {}, ipv4Address: {}", + clientId, direction, ipv4Address, e); } return activeTimHolding; @@ -59,42 +45,26 @@ public ActiveTimHolding getRsuActiveTimHolding(String clientId, String direction public ActiveTimHolding getSdxActiveTimHolding(String clientId, String direction, String satRecordId) { ActiveTimHolding activeTimHolding = null; - Connection connection = null; - Statement statement = null; - ResultSet rs = null; - - try { - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - String query = "select * from active_tim_holding"; - query += " where sat_record_id = '" + satRecordId; - if (clientId != null) { - query += "' and client_id = '" + clientId + "'"; - } else { - query += "' and client_id is null"; - } - query += " and direction = '" + direction + "'"; - rs = statement.executeQuery(query); + String query = "select * from active_tim_holding"; + query += " where sat_record_id = '" + satRecordId; + if (clientId != null) { + query += "' and client_id = '" + clientId + "'"; + } else { + query += "' and client_id is null"; + } + query += " and direction = '" + direction + "'"; + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // convert to ActiveTim object activeTimHolding = getSingleActiveTimHoldingFromResultSet(rs); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("SQL Exception while getting SDX ActiveTimHolding with clientId: {}, direction: {}, satRecordId: {}", + clientId, direction, satRecordId, e); } return activeTimHolding; @@ -102,35 +72,19 @@ public ActiveTimHolding getSdxActiveTimHolding(String clientId, String direction public ActiveTimHolding getActiveTimHoldingByPacketId(String packetId) { ActiveTimHolding activeTimHolding = null; - Connection connection = null; - Statement statement = null; - ResultSet rs = null; - try { - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - String query = "select * from active_tim_holding"; - query += " where packet_id = '" + packetId + "'"; - rs = statement.executeQuery(query); + String query = "select * from active_tim_holding"; + query += " where packet_id = '" + packetId + "'"; + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // convert to ActiveTim object activeTimHolding = getSingleActiveTimHoldingFromResultSet(rs); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("SQL Exception while getting ActiveTimHolding with packetId: {}", packetId, e); } return activeTimHolding; @@ -146,9 +100,9 @@ private ActiveTimHolding getSingleActiveTimHoldingFromResultSet(ResultSet rs) th activeTimHolding.setRsuTargetId(rs.getString("RSU_TARGET")); activeTimHolding.setSatRecordId(rs.getString("SAT_RECORD_ID")); activeTimHolding.setStartPoint( - new Coordinate(rs.getBigDecimal("START_LATITUDE"), rs.getBigDecimal("START_LONGITUDE"))); + new Coordinate(rs.getBigDecimal("START_LATITUDE"), rs.getBigDecimal("START_LONGITUDE"))); activeTimHolding - .setEndPoint(new Coordinate(rs.getBigDecimal("END_LATITUDE"), rs.getBigDecimal("END_LONGITUDE"))); + .setEndPoint(new Coordinate(rs.getBigDecimal("END_LATITUDE"), rs.getBigDecimal("END_LONGITUDE"))); int projectKey = rs.getInt("PROJECT_KEY"); if (!rs.wasNull()) { @@ -167,71 +121,46 @@ public Boolean deleteActiveTimHolding(Long activeTimHoldingId) { } String updateTableSQL = "DELETE FROM ACTIVE_TIM_HOLDING WHERE ACTIVE_TIM_HOLDING_ID = ?"; - Connection connection = null; - PreparedStatement preparedStatement = null; - try { - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection.prepareStatement(updateTableSQL); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(updateTableSQL); + ) { preparedStatement.setLong(1, activeTimHoldingId); var success = dbInteractions.updateOrDelete(preparedStatement); if (success) { - utility.logWithDate("Deleted ACTIVE_TIM_HOLDING with ID: " + activeTimHoldingId); + log.info("Deleted ACTIVE_TIM_HOLDING with ID: {}", activeTimHoldingId); } else { - utility.logWithDate("Failed to delete ACTIVE_TIM_HOLDING with ID: " + activeTimHoldingId); + log.error("Failed to delete ACTIVE_TIM_HOLDING with ID: {}", activeTimHoldingId); } return success; } catch (SQLException e) { - e.printStackTrace(); + log.error("SQL Exception while deleting ACTIVE_TIM_HOLDING with ID: {}", activeTimHoldingId, e); return false; - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } } } public boolean updateTimExpiration(String packetID, String expDate) { - Connection connection = null; - PreparedStatement preparedStatement = null; - boolean success = false; + boolean success; String updateStatement = "UPDATE ACTIVE_TIM_HOLDING SET EXPIRATION_DATE = ? WHERE PACKET_ID = ?"; - try { - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection.prepareStatement(updateStatement); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(updateStatement); + ) { preparedStatement.setObject(1, expDate);// expDate comes in as MST from previously called function - // (GetMinExpiration) + // (GetMinExpiration) preparedStatement.setObject(2, packetID); // execute update statement success = dbInteractions.updateOrDelete(preparedStatement); } catch (Exception e) { - e.printStackTrace(); + log.error("Exception while updating ACTIVE_TIM_HOLDING with packetID: {}", packetID, e); return false; - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } } - utility.logWithDate(String.format( - "Called ActiveTimHolding UpdateTimExpiration with packetID: %s, expDate: %s. Successful: %s", packetID, - expDate, success)); + log.info("Called ActiveTimHolding UpdateTimExpiration with packetID: {}, expDate: {}. Successful: {}", packetID, + expDate, success); return success; } diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimService.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimService.java index d24a6cabc..c9f61034b 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimService.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/ActiveTimService.java @@ -19,45 +19,42 @@ import com.trihydro.library.model.Coordinate; import com.trihydro.library.tables.TimDbTables; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component +@Slf4j public class ActiveTimService extends BaseService { private TimDbTables timDbTables; private SQLNullHandler sqlNullHandler; - private Calendar UTCCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + private final Calendar UTCCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); @Autowired - public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNullHandler) { + public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNullHandler) { // TODO: use constructor instead of InjectDependencies timDbTables = _timDbTables; sqlNullHandler = _sqlNullHandler; } public Long insertActiveTim(ActiveTim activeTim) { - Connection connection = null; - PreparedStatement preparedStatement = null; + String insertQueryStatement = timDbTables.buildInsertQueryStatement("active_tim", + timDbTables.getActiveTimTable()); - try { - String insertQueryStatement = timDbTables.buildInsertQueryStatement("active_tim", - timDbTables.getActiveTimTable()); - - // get connection - connection = dbInteractions.getConnectionPool(); - - preparedStatement = connection.prepareStatement(insertQueryStatement, new String[] { "active_tim_id" }); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(insertQueryStatement, new String[] {"active_tim_id"}); + ) { int fieldNum = 1; for (String col : timDbTables.getActiveTimTable()) { - if (col.equals("TIM_ID")) + if (col.equals("TIM_ID")) { sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, activeTim.getTimId()); - else if (col.equals("DIRECTION")) + } else if (col.equals("DIRECTION")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, activeTim.getDirection()); - else if (col.equals("TIM_START")) { - utility.logWithDate( - String.format("Converting %s for TIM_START value", activeTim.getStartDateTime())); + } else if (col.equals("TIM_START")) { + log.info("Converting {} for TIM_START value", activeTim.getStartDateTime()); java.util.Date tim_start_date = utility.convertDate(activeTim.getStartDateTime()); Timestamp ts = new Timestamp(tim_start_date.getTime()); sqlNullHandler.setTimestampOrNull(preparedStatement, fieldNum, ts); @@ -66,8 +63,9 @@ else if (col.equals("TIM_START")) { java.util.Date tim_end_date = utility.convertDate(activeTim.getEndDateTime()); Timestamp ts = new Timestamp(tim_end_date.getTime()); sqlNullHandler.setTimestampOrNull(preparedStatement, fieldNum, ts); - } else + } else { preparedStatement.setNull(fieldNum, java.sql.Types.TIMESTAMP); + } } else if (col.equals("EXPIRATION_DATE")) { if (activeTim.getExpirationDateTime() != null) { java.util.Date tim_exp_date = utility.convertDate(activeTim.getExpirationDateTime()); @@ -76,35 +74,39 @@ else if (col.equals("TIM_START")) { } else { preparedStatement.setNull(fieldNum, java.sql.Types.TIMESTAMP); } - } else if (col.equals("TIM_TYPE_ID")) + } else if (col.equals("TIM_TYPE_ID")) { sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, activeTim.getTimTypeId()); - else if (col.equals("ROUTE")) + } else if (col.equals("ROUTE")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, activeTim.getRoute()); - else if (col.equals("CLIENT_ID")) + } else if (col.equals("CLIENT_ID")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, activeTim.getClientId()); - else if (col.equals("SAT_RECORD_ID")) + } else if (col.equals("SAT_RECORD_ID")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, activeTim.getSatRecordId()); - else if (col.equals("PK")) + } else if (col.equals("PK")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, activeTim.getPk()); - else if (col.equals("START_LATITUDE")) { + } else if (col.equals("START_LATITUDE")) { BigDecimal start_lat = null; - if (activeTim.getStartPoint() != null) + if (activeTim.getStartPoint() != null) { start_lat = activeTim.getStartPoint().getLatitude(); + } sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, start_lat); } else if (col.equals("START_LONGITUDE")) { BigDecimal start_lon = null; - if (activeTim.getStartPoint() != null) + if (activeTim.getStartPoint() != null) { start_lon = activeTim.getStartPoint().getLongitude(); + } sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, start_lon); } else if (col.equals("END_LATITUDE")) { BigDecimal end_lat = null; - if (activeTim.getEndPoint() != null) + if (activeTim.getEndPoint() != null) { end_lat = activeTim.getEndPoint().getLatitude(); + } sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, end_lat); } else if (col.equals("END_LONGITUDE")) { BigDecimal end_lon = null; - if (activeTim.getEndPoint() != null) + if (activeTim.getEndPoint() != null) { end_lon = activeTim.getEndPoint().getLongitude(); + } sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, end_lon); } else if (col.equals("PROJECT_KEY")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, activeTim.getProjectKey()); @@ -113,24 +115,12 @@ else if (col.equals("START_LATITUDE")) { fieldNum++; } - Long activeTimId = dbInteractions.executeAndLog(preparedStatement, "active tim"); - return activeTimId; + return dbInteractions.executeAndLog(preparedStatement, "active tim"); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Error inserting active_tim", e); } - return Long.valueOf(0); + return 0L; } public boolean updateActiveTim(ActiveTim activeTim) { @@ -138,8 +128,6 @@ public boolean updateActiveTim(ActiveTim activeTim) { boolean activeTimIdResult = false; String updateTableSQL = "UPDATE ACTIVE_TIM SET TIM_ID = ?, START_LATITUDE = ?, START_LONGITUDE = ?, END_LATITUDE = ?,"; updateTableSQL += "END_LONGITUDE = ?, TIM_START = ?, TIM_END = ?, PK = ?, PROJECT_KEY = ? WHERE ACTIVE_TIM_ID = ?"; - Connection connection = null; - PreparedStatement preparedStatement = null; BigDecimal start_lat = null; BigDecimal start_lon = null; @@ -153,9 +141,10 @@ public boolean updateActiveTim(ActiveTim activeTim) { end_lat = activeTim.getEndPoint().getLatitude(); end_lon = activeTim.getEndPoint().getLongitude(); } - try { - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection.prepareStatement(updateTableSQL); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(updateTableSQL); + ) { sqlNullHandler.setLongOrNull(preparedStatement, 1, activeTim.getTimId()); sqlNullHandler.setBigDecimalOrNull(preparedStatement, 2, start_lat); sqlNullHandler.setBigDecimalOrNull(preparedStatement, 3, start_lon); @@ -166,9 +155,9 @@ public boolean updateActiveTim(ActiveTim activeTim) { Timestamp ts = new Timestamp(tim_start_date.getTime()); sqlNullHandler.setTimestampOrNull(preparedStatement, 6, ts); - if (activeTim.getEndDateTime() == null) + if (activeTim.getEndDateTime() == null) { preparedStatement.setNull(7, java.sql.Types.TIMESTAMP); - else { + } else { java.util.Date tim_end_date = utility.convertDate(activeTim.getEndDateTime()); Timestamp ts2 = new Timestamp(tim_end_date.getTime()); sqlNullHandler.setTimestampOrNull(preparedStatement, 7, ts2); @@ -178,20 +167,9 @@ public boolean updateActiveTim(ActiveTim activeTim) { sqlNullHandler.setIntegerOrNull(preparedStatement, 9, activeTim.getProjectKey()); sqlNullHandler.setLongOrNull(preparedStatement, 10, activeTim.getActiveTimId()); activeTimIdResult = dbInteractions.updateOrDelete(preparedStatement); - System.out.println("------ Updated active_tim with id: " + activeTim.getActiveTimId() + " --------------"); + log.info("------ Updated active_tim with id: {} --------------", activeTim.getActiveTimId()); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Error updating active_tim with id: {}", activeTim.getActiveTimId(), e); } return activeTimIdResult; @@ -200,18 +178,15 @@ public boolean updateActiveTim(ActiveTim activeTim) { public ActiveTim getActiveSatTim(String satRecordId, String direction) { ActiveTim activeTim = null; - Connection connection = null; - Statement statement = null; - ResultSet rs = null; - try { - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - String query = "select * from active_tim"; - query += " where sat_record_id = '" + satRecordId + "' and active_tim.direction = '" + direction + "'"; - - rs = statement.executeQuery(query); + String query = "select * from active_tim"; + query += " where sat_record_id = '" + satRecordId + "' and active_tim.direction = '" + direction + "'"; + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // convert to ActiveTim object while (rs.next()) { activeTim = new ActiveTim(); @@ -243,21 +218,7 @@ public ActiveTim getActiveSatTim(String satRecordId, String direction) { activeTim.setEndPoint(endPoint); } } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Error getting active_sat_tim with satRecordId: {}, direction: {}", satRecordId, direction, e); } return activeTim; @@ -266,27 +227,23 @@ public ActiveTim getActiveSatTim(String satRecordId, String direction) { public ActiveTim getActiveRsuTim(String clientId, String direction, String ipv4Address) { ActiveTim activeTim = null; - Connection connection = null; - Statement statement = null; - ResultSet rs = null; - - try { - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - // - String query = "select distinct atim.ACTIVE_TIM_ID, atim.TIM_ID, atim.SAT_RECORD_ID,"; - query += " atim.CLIENT_ID, atim.DIRECTION, atim.TIM_END, atim.TIM_START,"; - query += " atim.EXPIRATION_DATE, atim.ROUTE, atim.PK,"; - query += " atim.START_LATITUDE, atim.START_LONGITUDE, atim.END_LATITUDE, atim.END_LONGITUDE"; - query += " from active_tim atim"; - query += " inner join tim_rsu on atim.tim_id = tim_rsu.tim_id"; - query += " inner join rsu on tim_rsu.rsu_id = rsu.rsu_id"; - query += " inner join rsu_view on rsu.deviceid = rsu_view.deviceid"; - query += " where sat_record_id is null and ipv4_address = '" + ipv4Address + "' and client_id = '" - + clientId + "' and atim.direction = '" + direction + "'"; - - rs = statement.executeQuery(query); + String query = "select distinct atim.ACTIVE_TIM_ID, atim.TIM_ID, atim.SAT_RECORD_ID,"; + query += " atim.CLIENT_ID, atim.DIRECTION, atim.TIM_END, atim.TIM_START,"; + query += " atim.EXPIRATION_DATE, atim.ROUTE, atim.PK,"; + query += " atim.START_LATITUDE, atim.START_LONGITUDE, atim.END_LATITUDE, atim.END_LONGITUDE"; + query += " from active_tim atim"; + query += " inner join tim_rsu on atim.tim_id = tim_rsu.tim_id"; + query += " inner join rsu on tim_rsu.rsu_id = rsu.rsu_id"; + query += " inner join rsu_view on rsu.deviceid = rsu_view.deviceid"; + query += " where sat_record_id is null and ipv4_address = '" + ipv4Address + "' and client_id = '" + + clientId + "' and atim.direction = '" + direction + "'"; + + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // convert to ActiveTim object while (rs.next()) { activeTim = new ActiveTim(); @@ -318,21 +275,8 @@ public ActiveTim getActiveRsuTim(String clientId, String direction, String ipv4A activeTim.setEndPoint(endPoint); } } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Error getting active_rsu_tim with clientId: {}, direction: {}, ipv4Address: {}", clientId, + direction, ipv4Address, e); } return activeTim; @@ -340,18 +284,15 @@ public ActiveTim getActiveRsuTim(String clientId, String direction, String ipv4A public ActiveTim getActiveTimByPacketId(String packetID) { ActiveTim activeTim = null; - Connection connection = null; - Statement statement = null; - ResultSet rs = null; - try { - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - String query = "SELECT ACTIVE_TIM.* FROM ACTIVE_TIM JOIN TIM ON ACTIVE_TIM.TIM_ID = TIM.TIM_ID " - + "WHERE TIM.PACKET_ID = '" + packetID + "'"; - - rs = statement.executeQuery(query); + String query = "SELECT ACTIVE_TIM.* FROM ACTIVE_TIM JOIN TIM ON ACTIVE_TIM.TIM_ID = TIM.TIM_ID " + + "WHERE TIM.PACKET_ID = '" + packetID + "'"; + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // convert to ActiveTim object while (rs.next()) { activeTim = new ActiveTim(); @@ -383,30 +324,14 @@ public ActiveTim getActiveTimByPacketId(String packetID) { activeTim.setEndPoint(endPoint); } } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Error getting active_tim by packetId: {}", packetID, e); } return activeTim; } public boolean updateActiveTimExpiration(String packetID, String expDate) { - Connection connection = null; - PreparedStatement preparedStatement = null; - boolean success = false; + boolean success; String query = "SELECT ACTIVE_TIM_ID FROM ACTIVE_TIM atim"; query += " INNER JOIN TIM ON atim.TIM_ID = TIM.TIM_ID"; @@ -416,88 +341,61 @@ public boolean updateActiveTimExpiration(String packetID, String expDate) { updateStatement += query; updateStatement += ")"; - try { - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection.prepareStatement(updateStatement); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(updateStatement); + ) { DateFormat sdf = new SimpleDateFormat("dd-MMM-yy hh.mm.ss.SSS a"); Date dte = sdf.parse(expDate); Timestamp ts = new Timestamp(dte.getTime()); preparedStatement.setTimestamp(1, ts);// expDate comes in as MST from previously called function - // (GetMinExpiration) + // (GetMinExpiration) preparedStatement.setString(2, packetID); // execute update statement success = dbInteractions.updateOrDelete(preparedStatement); } catch (Exception e) { - e.printStackTrace(); + log.error("Error updating active_tim expiration date with packetID: {}, expDate: {}", packetID, expDate, e); return false; - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } } - utility.logWithDate(String.format("Called UpdateExpiration with packetID: %s, expDate: %s. Successful: %s", - packetID, expDate, success)); + log.info("Called UpdateExpiration with packetID: {}, expDate: {}. Successful: {}", packetID, expDate, success); return success; } public String getMinExpiration(String packetID, String expDate) throws ParseException { - Connection connection = null; - Statement statement = null; - ResultSet rs = null; + String targetFormat = "DD-MON-YYYY HH12.MI.SS a"; + String selectTimestamp = String.format("SELECT TO_TIMESTAMP('%s', '%s')", + translateIso8601ToTimestampFormat(expDate), targetFormat); + + String minExpDate = "SELECT MIN(EXPIRATION_DATE) FROM ACTIVE_TIM atim"; + minExpDate += " INNER JOIN TIM ON atim.TIM_ID = TIM.TIM_ID"; + minExpDate += " WHERE TIM.PACKET_ID = '" + packetID + "'"; + + String query = String.format("SELECT LEAST((%s), (COALESCE((%s),(%s)))) minStart", + selectTimestamp, minExpDate, selectTimestamp); String minStart = ""; - try { + try ( + Connection connection = dbInteractions.getConnectionPool(); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery(query); + ) { // Fetch the minimum of passed in expDate and database held // active_tim.expiration_date. To compare like values we convert the expDate // TO_TIMESTAMP. Without this it compares string length. // Also, there are some null values in the db. To get around these, we use the // coalesce function with the expDate passed in value. - connection = dbInteractions.getConnectionPool(); - statement = connection.createStatement(); - String targetFormat = "DD-MON-YYYY HH12.MI.SS a"; - String selectTimestamp = String.format("SELECT TO_TIMESTAMP('%s', '%s')", - translateIso8601ToTimestampFormat(expDate), targetFormat); - - String minExpDate = "SELECT MIN(EXPIRATION_DATE) FROM ACTIVE_TIM atim"; - minExpDate += " INNER JOIN TIM ON atim.TIM_ID = TIM.TIM_ID"; - minExpDate += " WHERE TIM.PACKET_ID = '" + packetID + "'"; - - String query = String.format("SELECT LEAST((%s), (COALESCE((%s),(%s)))) minStart", - selectTimestamp, minExpDate, selectTimestamp); - rs = statement.executeQuery(query); while (rs.next()) { var tmpTs = rs.getTimestamp("MINSTART", UTCCalendar); minStart = utility.timestampFormat.format(tmpTs); } } catch (SQLException e) { - e.printStackTrace(); + log.error("Error getting min expiration date with packetID: {}, expDate: {}", packetID, expDate, e); return null; - } finally { - try { - // close prepared statement - if (statement != null) - statement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - // close result set - if (rs != null) - rs.close(); - } catch (SQLException e) { - e.printStackTrace(); - } } - utility.logWithDate(String.format("Called GetMinExpiration with packetID: %s, expDate: %s. Min start date: %s", - packetID, expDate, minStart)); + log.info("Called GetMinExpiration with packetID: {}, expDate: {}. Min start date: {}", packetID, expDate, + minStart); return minStart; } diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameService.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameService.java index 0a8e34c14..0506ac69c 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameService.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameService.java @@ -10,43 +10,43 @@ import java.util.Date; import java.util.TimeZone; -import com.trihydro.library.helpers.SQLNullHandler; -import com.trihydro.library.tables.TimDbTables; - +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.trihydro.library.helpers.SQLNullHandler; +import com.trihydro.library.tables.TimDbTables; + import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame; @Component +@Slf4j public class DataFrameService extends BaseService { private TimDbTables timDbTables; private SQLNullHandler sqlNullHandler; @Autowired - public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNullHandler) { + public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNullHandler) { // TODO: use constructor instead of InjectDependencies timDbTables = _timDbTables; sqlNullHandler = _sqlNullHandler; } public Long AddDataFrame(DataFrame dFrame, Long timId) { - Connection connection = null; - PreparedStatement preparedStatement = null; - - try { + String insertQueryStatement = timDbTables.buildInsertQueryStatement("data_frame", + timDbTables.getDataFrameTable()); - connection = dbInteractions.getConnectionPool(); - String insertQueryStatement = timDbTables.buildInsertQueryStatement("data_frame", - timDbTables.getDataFrameTable()); - preparedStatement = connection.prepareStatement(insertQueryStatement, new String[] { "data_frame_id" }); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(insertQueryStatement, new String[] {"data_frame_id"}); + ) { int fieldNum = 1; for (String col : timDbTables.getDataFrameTable()) { if (col.equals("TIM_ID")) { sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, timId); } else if (col.equals("SSP_TIM_RIGHTS")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed()); + sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getDoNotUse1()); } else if (col.equals("FRAME_TYPE")) { Integer ordinal = null; if (dFrame.getFrameType() != null) { @@ -58,11 +58,11 @@ public Long AddDataFrame(DataFrame dFrame, Long timId) { } else if (col.equals("PRIORITY")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, dFrame.getPriority()); } else if (col.equals("SSP_LOCATION_RIGHTS")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed1()); + sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getDoNotUse2()); } else if (col.equals("SSP_MSG_TYPES")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed3()); + sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getDoNotUse4()); } else if (col.equals("SSP_MSG_CONTENT")) { - sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getNotUsed2()); + sqlNullHandler.setShortOrNull(preparedStatement, fieldNum, dFrame.getDoNotUse3()); } else if (col.equals("CONTENT")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, dFrame.getContent()); } else if (col.equals("URL")) { @@ -70,18 +70,17 @@ public Long AddDataFrame(DataFrame dFrame, Long timId) { } else if (col.equals("START_DATE_TIME")) { if (dFrame.getStartDateTime() == null) { preparedStatement.setNull(fieldNum, java.sql.Types.TIMESTAMP); - } - else { + } else { Timestamp time = null; try { TimeZone tz = TimeZone.getTimeZone("UTC"); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); // Quoted "Z" to indicate UTC, no - // timezone offset + // timezone offset df.setTimeZone(tz); Date dt = df.parse(dFrame.getStartDateTime()); time = new Timestamp(dt.getTime()); } catch (ParseException ex) { - utility.logWithDate("Unable to parse startdate: " + dFrame.getStartDateTime()); + log.error("Unable to parse startdate: {}", dFrame.getStartDateTime()); } sqlNullHandler.setTimestampOrNull(preparedStatement, fieldNum, time); } @@ -89,23 +88,11 @@ public Long AddDataFrame(DataFrame dFrame, Long timId) { fieldNum++; } - Long dataFrameId = dbInteractions.executeAndLog(preparedStatement, "dataframe"); - return dataFrameId; + return dbInteractions.executeAndLog(preparedStatement, "dataframe"); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Error adding data frame", e); } - return Long.valueOf(0); + return 0L; } } \ No newline at end of file diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeLLService.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeLLService.java index 93d8f05ca..37d49acff 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeLLService.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeLLService.java @@ -45,19 +45,19 @@ else if (col.equals("NODE_LAT")) else if (col.equals("NODE_LONG")) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getNodeLong()); else if (col.equals("X")) - sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getX()); + sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getXpos()); else if (col.equals("Y")) - sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getY()); + sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getYpos()); else if (col.equals("ATTRIBUTES_DWIDTH")) if (nodeXY.getAttributes() != null) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, - nodeXY.getAttributes().getdWidth()); + nodeXY.getAttributes().getDwidth()); else preparedStatement.setNull(fieldNum, java.sql.Types.NUMERIC); else if (col.equals("ATTRIBUTES_DELEVATION")) if (nodeXY.getAttributes() != null) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, - nodeXY.getAttributes().getdElevation()); + nodeXY.getAttributes().getDelevation()); else preparedStatement.setNull(fieldNum, java.sql.Types.NUMERIC); fieldNum++; diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYService.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYService.java index 5409d9c66..c522ac062 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYService.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYService.java @@ -45,19 +45,19 @@ else if (col.equals("NODE_LAT")) else if (col.equals("NODE_LONG")) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getNodeLong()); else if (col.equals("X")) - sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getX()); + sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getXpos()); else if (col.equals("Y")) - sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getY()); + sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, nodeXY.getYpos()); else if (col.equals("ATTRIBUTES_DWIDTH")) if (nodeXY.getAttributes() != null) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, - nodeXY.getAttributes().getdWidth()); + nodeXY.getAttributes().getDwidth()); else preparedStatement.setNull(fieldNum, java.sql.Types.NUMERIC); else if (col.equals("ATTRIBUTES_DELEVATION")) if (nodeXY.getAttributes() != null) sqlNullHandler.setBigDecimalOrNull(preparedStatement, fieldNum, - nodeXY.getAttributes().getdElevation()); + nodeXY.getAttributes().getDelevation()); else preparedStatement.setNull(fieldNum, java.sql.Types.NUMERIC); fieldNum++; diff --git a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/TimService.java b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/TimService.java index 8ae48d686..fc006b924 100644 --- a/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/TimService.java +++ b/logger-kafka-consumer/src/main/java/com/trihydro/loggerkafkaconsumer/app/services/TimService.java @@ -9,7 +9,6 @@ import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; import com.google.gson.Gson; import com.trihydro.library.helpers.SQLNullHandler; @@ -24,6 +23,7 @@ import com.trihydro.library.model.WydotRsu; import com.trihydro.library.tables.TimDbTables; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -44,6 +44,7 @@ import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.Region.Path; @Component +@Slf4j public class TimService extends BaseService { public Gson gson = new Gson(); @@ -67,12 +68,13 @@ public class TimService extends BaseService { @Autowired public void InjectDependencies(ActiveTimService _ats, TimDbTables _timDbTables, - SQLNullHandler _sqlNullHandler, PathService _pathService, RegionService _regionService, - DataFrameService _dataFrameService, RsuService _rsuService, TimTypeService _tts, - ItisCodeService _itisCodesService, TimRsuService _timRsuService, - DataFrameItisCodeService _dataFrameItisCodeService, PathNodeXYService _pathNodeXYService, - NodeXYService _nodeXYService, Utility _utility, ActiveTimHoldingService _athService, - PathNodeLLService _pathNodeLLService, NodeLLService _nodeLLService) { + SQLNullHandler _sqlNullHandler, PathService _pathService, RegionService _regionService, + DataFrameService _dataFrameService, RsuService _rsuService, TimTypeService _tts, + ItisCodeService _itisCodesService, TimRsuService _timRsuService, + DataFrameItisCodeService _dataFrameItisCodeService, PathNodeXYService _pathNodeXYService, + NodeXYService _nodeXYService, Utility _utility, ActiveTimHoldingService _athService, + PathNodeLLService _pathNodeLLService, + NodeLLService _nodeLLService) { // TODO: use constructor instead of InjectDependencies activeTimService = _ats; timDbTables = _timDbTables; sqlNullHandler = _sqlNullHandler; @@ -95,8 +97,7 @@ public void InjectDependencies(ActiveTimService _ats, TimDbTables _timDbTables, public void addTimToDatabase(OdeData odeData) { try { - - utility.logWithDate("Called addTimToDatabase"); + log.info("Called addTimToDatabase"); ReceivedMessageDetails rxMsgDet = null; RecordType recType = null; @@ -111,7 +112,7 @@ public void addTimToDatabase(OdeData odeData) { } Long timId = AddTim(odeData.getMetadata(), rxMsgDet, getTim((OdeTimPayload) odeData.getPayload()), - recType, logFileName, secResCode, null, null); + recType, logFileName, secResCode, null, null); // return if TIM is not inserted if (timId == null) { @@ -120,7 +121,7 @@ public void addTimToDatabase(OdeData odeData) { DataFrame[] dFrames = getTim((OdeTimPayload) odeData.getPayload()).getDataframes(); if (dFrames.length == 0) { - utility.logWithDate("addTimToDatabase - No dataframes found in TIM (tim_id: " + timId + ")"); + log.info("addTimToDatabase - No dataframes found in TIM (tim_id: {})", timId); return; } OdeTravelerInformationMessage.DataFrame firstDataFrame = dFrames[0]; @@ -135,18 +136,15 @@ public void addTimToDatabase(OdeData odeData) { // if this is an RSU TIM if (activeTim != null && activeTim.getRsuTarget() != null) { // save TIM RSU in DB - WydotRsu rsu = rsuService.getRsus().stream() - .filter(x -> x.getRsuTarget().equals(activeTim.getRsuTarget())).findFirst() - .orElse(null); - if (rsu != null) { - timRsuService.AddTimRsu(timId, rsu.getRsuId(), rsu.getRsuIndex()); - } + rsuService.getRsus().stream() + .filter(x -> x.getRsuTarget().equals(activeTim.getRsuTarget())).findFirst() + .ifPresent(rsu -> timRsuService.AddTimRsu(timId, rsu.getRsuId(), rsu.getRsuIndex())); } addDataFrameItis(firstDataFrame, dataFrameId); } catch (NullPointerException e) { - System.out.println("Null pointer exception encountered in TimService.addTimToDatabase() method: " + e.getMessage()); + log.info("Null pointer exception encountered in TimService.addTimToDatabase() method: {}", e.getMessage()); } } @@ -154,34 +152,40 @@ public void addTimToDatabase(OdeData odeData) { * Adds an active TIM to the database. This only handles a single TIM at a time. */ public void addActiveTimToDatabase(OdeData odeData) { - - utility.logWithDate("Called addActiveTimToDatabase", TimService.class); + log.info("Called addActiveTimToDatabase"); ActiveTim activeTim; OdeTimPayload payload = (OdeTimPayload) odeData.getPayload(); - if (payload == null) + if (payload == null) { return; + } OdeTravelerInformationMessage tim = getTim(payload); - if (tim == null) + if (tim == null) { return; + } DataFrame[] dframes = tim.getDataframes(); - if (dframes == null || dframes.length == 0) + if (dframes == null || dframes.length == 0) { return; + } OdeTravelerInformationMessage.DataFrame.Region[] regions = dframes[0].getRegions(); - if (regions == null || regions.length == 0) + if (regions == null || regions.length == 0) { return; + } String firstRegionName = regions[0].getName(); - if (StringUtils.isEmpty(firstRegionName) || StringUtils.isBlank(firstRegionName)) + if (StringUtils.isEmpty(firstRegionName) || StringUtils.isBlank(firstRegionName)) { return; + } OdeRequestMsgMetadata metaData = (OdeRequestMsgMetadata) odeData.getMetadata(); - if (metaData == null) + if (metaData == null) { return; + } // get information from the region name, first check splitname length activeTim = setActiveTimByRegionName(firstRegionName); - if (activeTim == null) + if (activeTim == null) { return; + } String satRecordId = activeTim.getSatRecordId(); @@ -203,31 +207,30 @@ public void addActiveTimToDatabase(OdeData odeData) { addDataFrameItis(dframes[0], dataFrameId); } else { // failed to insert new tim and failed to fetch existing, log and return - utility.logWithDate( - "Failed to insert tim, and failed to fetch existing tim. No data inserted for OdeData: " - + gson.toJson(odeData)); + log.info("Failed to insert tim, and failed to fetch existing tim. No data inserted for OdeData: {}", gson.toJson(odeData)); return; } } else { - utility.logWithDate("TIM already exists, tim_id " + timId); + log.info("TIM already exists, tim_id {}", timId); } // ensure we handle a new satRecordId - if (satRecordId != null && satRecordId != "") { + if (satRecordId != null && !satRecordId.isEmpty()) { updateTimSatRecordId(timId, satRecordId); - utility.logWithDate("Added sat_record_id of " + satRecordId + " to TIM with tim_id " + timId); + log.info("Added sat_record_id of {} to TIM with tim_id {}", satRecordId, timId); } // TODO : Change to loop through RSU array - doing one rsu for now RSU firstRsu = null; if (metaData.getRequest() != null && metaData.getRequest().getRsus() != null - && metaData.getRequest().getRsus().length > 0) { + && metaData.getRequest().getRsus().length > 0) { firstRsu = metaData.getRequest().getRsus()[0]; activeTim.setRsuTarget(firstRsu.getRsuTarget()); } - if (metaData.getRequest() != null && metaData.getRequest().getSdw() != null) + if (metaData.getRequest() != null && metaData.getRequest().getSdw() != null) { activeTim.setSatRecordId(metaData.getRequest().getSdw().getRecordId()); + } // the ODE now parses all dataframes to find the most recent and sets it // to this new OdeTimStartDateTime. We'll take advantage. @@ -236,8 +239,7 @@ public void addActiveTimToDatabase(OdeData odeData) { var stDate = metaData.getOdeTimStartDateTime(); if (StringUtils.isEmpty(stDate)) { stDate = dframes[0].getStartDateTime(); - utility.logWithDate(String.format( - "addActiveTimToDatabase did not find odeTimStartDateTime, setting to dataframe value %s", stDate)); + log.info("addActiveTimToDatabase did not find odeTimStartDateTime, setting to dataframe value {}", stDate); } activeTim.setStartDateTime(stDate); activeTim.setTimId(timId); @@ -248,34 +250,32 @@ public void addActiveTimToDatabase(OdeData odeData) { if (activeTim.getRsuTarget() != null && firstRsu != null) { // save TIM RSU in DB WydotRsu rsu = rsuService.getRsus().stream().filter(x -> x.getRsuTarget().equals(activeTim.getRsuTarget())) - .findFirst().orElse(null); + .findFirst().orElse(null); if (rsu != null) { timRsuService.AddTimRsu(timId, rsu.getRsuId(), rsu.getRsuIndex()); } ath = activeTimHoldingService.getRsuActiveTimHolding(activeTim.getClientId(), activeTim.getDirection(), - activeTim.getRsuTarget()); + activeTim.getRsuTarget()); if (ath == null) { - utility.logWithDate(String.format( - "Could not find active_tim_holding for client_id '%s', direction '%s', rsu_target '%s'", - activeTim.getClientId(), activeTim.getDirection(), activeTim.getRsuTarget())); + log.info("Could not find active_tim_holding for client_id '{}', direction '{}', rsu_target '{}'", + activeTim.getClientId(), activeTim.getDirection(), activeTim.getRsuTarget()); } } else { // SDX tim, fetch holding ath = activeTimHoldingService.getSdxActiveTimHolding(activeTim.getClientId(), activeTim.getDirection(), - activeTim.getSatRecordId()); + activeTim.getSatRecordId()); if (ath == null) { - utility.logWithDate(String.format( - "Could not find active_tim_holding for client_id '%s', direction '%s', sat_record_id '%s'", - activeTim.getClientId(), activeTim.getDirection(), activeTim.getSatRecordId())); + log.info("Could not find active_tim_holding for client_id '{}', direction '{}', sat_record_id '{}'", + activeTim.getClientId(), activeTim.getDirection(), activeTim.getSatRecordId()); } } // set end time if duration is not indefinite if (dframes[0].getDurationTime() != 32000) { ZonedDateTime zdt = ZonedDateTime.parse(dframes[0].getStartDateTime()); - zdt = zdt.plus(dframes[0].getDurationTime(), ChronoUnit.MINUTES); + zdt = zdt.plusMinutes(dframes[0].getDurationTime()); activeTim.setEndDateTime(zdt.toString()); } @@ -300,10 +300,13 @@ public void addActiveTimToDatabase(OdeData odeData) { // if RSU TIM if (activeTim.getRsuTarget() != null) // look for active RSU tim that matches incoming TIM + { activeTimDb = activeTimService.getActiveRsuTim(activeTim.getClientId(), activeTim.getDirection(), - activeTim.getRsuTarget()); - else // else look for active SAT tim that matches incoming TIM + activeTim.getRsuTarget()); + } else // else look for active SAT tim that matches incoming TIM + { activeTimDb = activeTimService.getActiveSatTim(activeTim.getSatRecordId(), activeTim.getDirection()); + } // if there is no active TIM, insert new one if (activeTimDb == null) { @@ -324,7 +327,7 @@ public void addActiveTimToDatabase(OdeData odeData) { } else { // not from WYDOT application // just log for now - utility.logWithDate("Inserting new active_tim, no TimType found - not from WYDOT application"); + log.info("Inserting new active_tim, no TimType found - not from WYDOT application"); activeTimService.insertActiveTim(activeTim); } @@ -335,83 +338,73 @@ public void addActiveTimToDatabase(OdeData odeData) { } public Long getTimId(String packetId, Timestamp timeStamp) { - ResultSet rs = null; - Connection connection = null; - PreparedStatement preparedStatement = null; Long id = null; - try { - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection - .prepareStatement("select tim_id from tim where packet_id = ? and time_stamp = ?"); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection + .prepareStatement("select tim_id from tim where packet_id = ? and time_stamp = ?"); + ) { preparedStatement.setString(1, packetId); preparedStatement.setTimestamp(2, timeStamp); - rs = preparedStatement.executeQuery(); - if (rs.next()) { - id = rs.getLong("tim_id"); + try ( + ResultSet rs = preparedStatement.executeQuery(); + ) { + if (rs.next()) { + id = rs.getLong("tim_id"); + } } } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (preparedStatement != null) - preparedStatement.close(); - - if (connection != null) - connection.close(); - } catch (SQLException ex) { - ex.printStackTrace(); - } + log.error("Failed to get tim_id from database", e); } return id; } public Long AddTim(OdeMsgMetadata odeTimMetadata, ReceivedMessageDetails receivedMessageDetails, - OdeTravelerInformationMessage j2735TravelerInformationMessage, RecordType recordType, String logFileName, - SecurityResultCode securityResultCode, String satRecordId, String regionName) { - PreparedStatement preparedStatement = null; - Connection connection = null; - - try { - - String insertQueryStatement = timDbTables.buildInsertQueryStatement("tim", - timDbTables.getTimTable()); - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection.prepareStatement(insertQueryStatement, new String[] { "tim_id" }); + OdeTravelerInformationMessage j2735TravelerInformationMessage, RecordType recordType, String logFileName, + SecurityResultCode securityResultCode, String satRecordId, String regionName) { + String insertQueryStatement = timDbTables.buildInsertQueryStatement("tim", + timDbTables.getTimTable()); + + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement(insertQueryStatement, new String[] {"tim_id"}); + ) { int fieldNum = 1; for (String col : timDbTables.getTimTable()) { // default to null preparedStatement.setString(fieldNum, null); if (j2735TravelerInformationMessage != null) { - if (col.equals("MSG_CNT")) + if (col.equals("MSG_CNT")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, - j2735TravelerInformationMessage.getMsgCnt()); - else if (col.equals("PACKET_ID")) + j2735TravelerInformationMessage.getMsgCnt()); + } else if (col.equals("PACKET_ID")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, - j2735TravelerInformationMessage.getPacketID()); - else if (col.equals("URL_B")) + j2735TravelerInformationMessage.getPacketID()); + } else if (col.equals("URL_B")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, - j2735TravelerInformationMessage.getUrlB()); - else if (col.equals("TIME_STAMP")) { + j2735TravelerInformationMessage.getUrlB()); + } else if (col.equals("TIME_STAMP")) { String timeStamp = j2735TravelerInformationMessage.getTimeStamp(); java.sql.Timestamp ts = null; if (StringUtils.isNotEmpty(timeStamp) && StringUtils.isNotBlank(timeStamp)) { ts = java.sql.Timestamp - .valueOf(LocalDateTime.parse(timeStamp, DateTimeFormatter.ISO_DATE_TIME)); + .valueOf(LocalDateTime.parse(timeStamp, DateTimeFormatter.ISO_DATE_TIME)); } sqlNullHandler.setTimestampOrNull(preparedStatement, fieldNum, ts); } } if (odeTimMetadata != null) { if (col.equals("RECORD_GENERATED_BY")) { - if (odeTimMetadata.getRecordGeneratedBy() != null) + if (odeTimMetadata.getRecordGeneratedBy() != null) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, - odeTimMetadata.getRecordGeneratedBy().toString()); - else + odeTimMetadata.getRecordGeneratedBy().toString()); + } else { preparedStatement.setString(fieldNum, null); + } } else if (col.equals("RECORD_GENERATED_AT")) { if (odeTimMetadata.getRecordGeneratedAt() != null) { java.util.Date recordGeneratedAtDate = utility.convertDate(odeTimMetadata.getRecordGeneratedAt()); @@ -423,10 +416,11 @@ else if (col.equals("TIME_STAMP")) { } else if (col.equals("SCHEMA_VERSION")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, odeTimMetadata.getSchemaVersion()); } else if (col.equals("SANITIZED")) { - if (odeTimMetadata.isSanitized()) + if (odeTimMetadata.isSanitized()) { preparedStatement.setInt(fieldNum, 1); - else + } else { preparedStatement.setInt(fieldNum, 0); + } } else if (col.equals("PAYLOAD_TYPE")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, odeTimMetadata.getPayloadType()); } else if (col.equals("ODE_RECEIVED_AT")) { @@ -440,68 +434,66 @@ else if (col.equals("TIME_STAMP")) { } if (odeTimMetadata.getSerialId() != null) { - if (col.equals("SERIAL_ID_STREAM_ID")) + if (col.equals("SERIAL_ID_STREAM_ID")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, - odeTimMetadata.getSerialId().getStreamId()); - else if (col.equals("SERIAL_ID_BUNDLE_SIZE")) + odeTimMetadata.getSerialId().getStreamId()); + } else if (col.equals("SERIAL_ID_BUNDLE_SIZE")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, - odeTimMetadata.getSerialId().getBundleSize()); - else if (col.equals("SERIAL_ID_BUNDLE_ID")) + odeTimMetadata.getSerialId().getBundleSize()); + } else if (col.equals("SERIAL_ID_BUNDLE_ID")) { sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, - odeTimMetadata.getSerialId().getBundleId()); - else if (col.equals("SERIAL_ID_RECORD_ID")) + odeTimMetadata.getSerialId().getBundleId()); + } else if (col.equals("SERIAL_ID_RECORD_ID")) { sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, - odeTimMetadata.getSerialId().getRecordId()); - else if (col.equals("SERIAL_ID_SERIAL_NUMBER")) + odeTimMetadata.getSerialId().getRecordId()); + } else if (col.equals("SERIAL_ID_SERIAL_NUMBER")) { sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, - odeTimMetadata.getSerialId().getSerialNumber()); + odeTimMetadata.getSerialId().getSerialNumber()); + } } } if (receivedMessageDetails != null) { if (receivedMessageDetails.getLocationData() != null) { if (col.equals("RMD_LD_ELEVATION")) { sqlNullHandler.setDoubleOrNull(preparedStatement, fieldNum, - Double.parseDouble(receivedMessageDetails.getLocationData().getElevation())); + Double.parseDouble(receivedMessageDetails.getLocationData().getElevation())); } else if (col.equals("RMD_LD_HEADING")) { sqlNullHandler.setDoubleOrNull(preparedStatement, fieldNum, - Double.parseDouble(receivedMessageDetails.getLocationData().getHeading())); + Double.parseDouble(receivedMessageDetails.getLocationData().getHeading())); } else if (col.equals("RMD_LD_LATITUDE")) { sqlNullHandler.setDoubleOrNull(preparedStatement, fieldNum, - Double.parseDouble(receivedMessageDetails.getLocationData().getLatitude())); + Double.parseDouble(receivedMessageDetails.getLocationData().getLatitude())); } else if (col.equals("RMD_LD_LONGITUDE")) { sqlNullHandler.setDoubleOrNull(preparedStatement, fieldNum, - Double.parseDouble(receivedMessageDetails.getLocationData().getLongitude())); + Double.parseDouble(receivedMessageDetails.getLocationData().getLongitude())); } else if (col.equals("RMD_LD_SPEED")) { sqlNullHandler.setDoubleOrNull(preparedStatement, fieldNum, - Double.parseDouble(receivedMessageDetails.getLocationData().getSpeed())); + Double.parseDouble(receivedMessageDetails.getLocationData().getSpeed())); } - } - else { + } else { // location data is null, set all to null (with correct type) if (col.equals("RMD_LD_ELEVATION") || col.equals("RMD_LD_HEADING") || col.equals("RMD_LD_LATITUDE") - || col.equals("RMD_LD_LONGITUDE") || col.equals("RMD_LD_SPEED")) { + || col.equals("RMD_LD_LONGITUDE") || col.equals("RMD_LD_SPEED")) { preparedStatement.setNull(fieldNum, java.sql.Types.NUMERIC); } } if (col.equals("RMD_RX_SOURCE") && receivedMessageDetails.getRxSource() != null) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, - receivedMessageDetails.getRxSource().toString()); + receivedMessageDetails.getRxSource().toString()); } else if (col.equals("SECURITY_RESULT_CODE")) { SecurityResultCodeType securityResultCodeType = GetSecurityResultCodeTypes().stream() - .filter(x -> x.getSecurityResultCodeType().equals(securityResultCode.toString())) - .findFirst().orElse(null); + .filter(x -> x.getSecurityResultCodeType().equals(securityResultCode.toString())) + .findFirst().orElse(null); if (securityResultCodeType != null) { preparedStatement.setInt(fieldNum, securityResultCodeType.getSecurityResultCodeTypeId()); - } - else { + } else { preparedStatement.setNull(fieldNum, java.sql.Types.INTEGER); } } - } - else { + } else { // message details are null, set all to null (with correct type) if (col.equals("RMD_LD_ELEVATION") || col.equals("RMD_LD_HEADING") || col.equals("RMD_LD_LATITUDE") - || col.equals("RMD_LD_LONGITUDE") || col.equals("RMD_LD_SPEED")) { + || col.equals("RMD_LD_LONGITUDE") || col.equals("RMD_LD_SPEED")) { preparedStatement.setNull(fieldNum, java.sql.Types.NUMERIC); } else if (col.equals("RMD_RX_SOURCE")) { preparedStatement.setString(fieldNum, null); @@ -510,11 +502,11 @@ else if (col.equals("SERIAL_ID_SERIAL_NUMBER")) } } - if (col.equals("SAT_RECORD_ID")) + if (col.equals("SAT_RECORD_ID")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, satRecordId); - else if (col.equals("TIM_NAME")) + } else if (col.equals("TIM_NAME")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, regionName); - else if (col.equals("LOG_FILE_NAME")) { + } else if (col.equals("LOG_FILE_NAME")) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, logFileName); } else if (col.equals("RECORD_TYPE") && recordType != null) { sqlNullHandler.setStringOrNull(preparedStatement, fieldNum, recordType.toString()); @@ -522,29 +514,17 @@ else if (col.equals("LOG_FILE_NAME")) { fieldNum++; } // execute insert statement - Long timId = dbInteractions.executeAndLog(preparedStatement, "timID"); - return timId; + return dbInteractions.executeAndLog(preparedStatement, "timID"); } catch (SQLException e) { - e.printStackTrace(); - } finally { - try { - // close prepared statement - if (preparedStatement != null) - preparedStatement.close(); - // return connection back to pool - if (connection != null) - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); - } + log.error("Failed to insert tim into database", e); } - return Long.valueOf(0); + return 0L; } /** * Adds regions to the database for a given DataFrame. - * - * @param dataFrame The DataFrame containing the regions to be added. + * + * @param dataFrame The DataFrame containing the regions to be added. * @param dataFrameId The ID of the DataFrame. */ public void addRegions(DataFrame dataFrame, Long dataFrameId) { @@ -571,18 +551,17 @@ public void addRegions(DataFrame dataFrame, Long dataFrameId) { } else if (geometry != null) { regionService.AddRegion(dataFrameId, null, region); } else { - utility.logWithDate( - "addActiveTimToDatabase - Unable to insert region, no path or geometry found (data_frame_id: " - + dataFrameId + ")"); + log.warn("addActiveTimToDatabase - Unable to insert region, no path or geometry found (data_frame_id: {})", + dataFrameId); } - } + } } public void addDataFrameItis(DataFrame dataFrame, Long dataFrameId) { // save DataFrame ITIS codes String[] items = dataFrame.getItems(); if (items == null || items.length == 0) { - System.out.println("No itis codes found to associate with data_frame " + dataFrameId); + log.warn("No itis codes found to associate with data_frame {}", dataFrameId); return; } for (var i = 0; i < items.length; i++) { @@ -592,9 +571,8 @@ public void addDataFrameItis(DataFrame dataFrame, Long dataFrameId) { String itisCodeId = getItisCodeId(timItisCode); if (itisCodeId != null) { dataFrameItisCodeService.insertDataFrameItisCode(dataFrameId, itisCodeId, i); - } - else { - utility.logWithDate("Could not find corresponding itis code it for " + timItisCode); + } else { + log.warn("Could not find corresponding itis code it for {}", timItisCode); } } else { dataFrameItisCodeService.insertDataFrameItisCode(dataFrameId, timItisCode, i); @@ -603,27 +581,15 @@ public void addDataFrameItis(DataFrame dataFrame, Long dataFrameId) { } public boolean updateTimSatRecordId(Long timId, String satRecordId) { - PreparedStatement preparedStatement = null; - Connection connection = null; - - try { - connection = dbInteractions.getConnectionPool(); - preparedStatement = connection.prepareStatement("update tim set sat_record_id = ? where tim_id = ?"); + try ( + Connection connection = dbInteractions.getConnectionPool(); + PreparedStatement preparedStatement = connection.prepareStatement("update tim set sat_record_id = ? where tim_id = ?"); + ) { preparedStatement.setString(1, satRecordId); preparedStatement.setLong(2, timId); return dbInteractions.updateOrDelete(preparedStatement); } catch (Exception ex) { return false; - } finally { - try { - if (preparedStatement != null) - preparedStatement.close(); - - if (connection != null) - connection.close(); - } catch (Exception e) { - e.printStackTrace(); - } } } @@ -640,8 +606,7 @@ public ActiveTim setActiveTimByRegionName(String regionName) { if (elements.route != null) { activeTim.setRoute(elements.route); - } - else { + } else { return activeTim; } if (elements.rsuOrSat != null) { @@ -654,8 +619,9 @@ public ActiveTim setActiveTimByRegionName(String regionName) { activeTim.setRsuTarget(hyphen_array[1]); } } - } else + } else { return activeTim; + } if (elements.timType != null) { TimType timType = getTimType(elements.timType); if (timType != null) { @@ -668,8 +634,7 @@ public ActiveTim setActiveTimByRegionName(String regionName) { if (elements.timId != null) { activeTim.setClientId(elements.timId); - } - else { + } else { return activeTim; } @@ -687,10 +652,8 @@ public ActiveTim setActiveTimByRegionName(String regionName) { public TimType getTimType(String timTypeName) { - TimType timType = timTypeService.getTimTypes().stream().filter(x -> x.getType().equals(timTypeName)).findFirst() - .orElse(null); - - return timType; + return timTypeService.getTimTypes().stream().filter(x -> x.getType().equals(timTypeName)).findFirst() + .orElse(null); } public String getItisCodeId(String item) { @@ -699,12 +662,13 @@ public String getItisCodeId(String item) { try { ItisCode itisCode = itisCodeService.selectAllItisCodes().stream() - .filter(x -> x.getItisCode().equals(Integer.parseInt(item))).findFirst().orElse(null); - if (itisCode != null) + .filter(x -> x.getItisCode().equals(Integer.parseInt(item))).findFirst().orElse(null); + if (itisCode != null) { itisCodeId = itisCode.getItisCodeId().toString(); + } } catch (Exception ex) { // on rare occasions we see an unparsable Integer - utility.logWithDate("Failed to parse ITIS integer(" + item + "): " + ex.getMessage()); + log.error("Failed to parse ITIS integer({}): {}", item, ex.getMessage()); } return itisCodeId; diff --git a/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/dataConverters/TimDataConverterTest.java b/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/dataConverters/TimDataConverterTest.java index 2600838b3..79405f92f 100644 --- a/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/dataConverters/TimDataConverterTest.java +++ b/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/dataConverters/TimDataConverterTest.java @@ -208,19 +208,6 @@ public void processTimJson_odeTimWithRsus() throws IOException { } - @Test - public void processTimJson_unsigned() throws IOException { - // Arrange - String value = new String(Files.readAllBytes(Paths.get("src/test/resources/TIM_unsigned.json"))); - - // Act - var data = uut.processTimJson(value); - - // Assert - Assertions.assertNotNull(data); - Assertions.assertNotNull(data.getMetadata()); - } - /** * Helper method to get an OdeTravelerInformationMessage object given an OdeTimPayload. */ diff --git a/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameServiceTest.java b/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameServiceTest.java index 658483209..663951b0d 100644 --- a/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameServiceTest.java +++ b/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/DataFrameServiceTest.java @@ -1,8 +1,5 @@ package com.trihydro.loggerkafkaconsumer.app.services; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; - import java.sql.SQLException; import java.sql.Timestamp; import java.text.DateFormat; @@ -11,15 +8,17 @@ import java.util.Date; import java.util.TimeZone; -import com.trihydro.library.helpers.SQLNullHandler; -import com.trihydro.library.tables.TimDbTables; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; import org.mockito.Spy; +import com.trihydro.library.helpers.SQLNullHandler; +import com.trihydro.library.tables.TimDbTables; + import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame; public class DataFrameServiceTest extends TestBase { @@ -51,13 +50,13 @@ public void AddDataFrame_SUCCESS() throws SQLException, ParseException { // Assert Assertions.assertEquals(Long.valueOf(-1), data); verify(mockSqlNullHandler).setLongOrNull(mockPreparedStatement, 1, -1l);// TIM_ID - verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 2, dFrame.getNotUsed());// SSP_TIM_RIGHTS + verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 2, dFrame.getDoNotUse1());// SSP_TIM_RIGHTS & NotUsed verify(mockSqlNullHandler).setIntegerOrNull(mockPreparedStatement, 3, null);// FRAME_TYPE verify(mockSqlNullHandler).setIntegerOrNull(mockPreparedStatement, 4, dFrame.getDurationTime());// DURATION_TIME verify(mockSqlNullHandler).setIntegerOrNull(mockPreparedStatement, 5, dFrame.getPriority());// PRIORITY - verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 6, dFrame.getNotUsed1());// SSP_LOCATION_RIGHTS - verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 7, dFrame.getNotUsed3());// SSP_MSG_TYPES - verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 8, dFrame.getNotUsed2());// SSP_MSG_CONTENT + verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 6, dFrame.getDoNotUse2());// SSP_LOCATION_RIGHTS & NotUsed1 + verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 7, dFrame.getDoNotUse4());// SSP_MSG_TYPES & NotUsed3 + verify(mockSqlNullHandler).setShortOrNull(mockPreparedStatement, 8, dFrame.getDoNotUse3());// SSP_MSG_CONTENT & NotUsed2 verify(mockSqlNullHandler).setStringOrNull(mockPreparedStatement, 9, dFrame.getContent());// CONTENT verify(mockSqlNullHandler).setStringOrNull(mockPreparedStatement, 10, dFrame.getUrl());// URL verify(mockSqlNullHandler).setTimestampOrNull(mockPreparedStatement, 11, time);// START_DATE_TIME diff --git a/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYServiceTest.java b/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYServiceTest.java index 1efffcc5b..7e901a3ee 100644 --- a/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYServiceTest.java +++ b/logger-kafka-consumer/src/test/java/com/trihydro/loggerkafkaconsumer/app/services/NodeXYServiceTest.java @@ -43,11 +43,11 @@ public void AddNodeXY_SUCCESS() throws SQLException { verify(mockSqlNullHandler).setStringOrNull(mockPreparedStatement, 1, nodeXY.getDelta());// DELTA verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 2, nodeXY.getNodeLat());// NODE_LAT verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 3, nodeXY.getNodeLong());// NODE_LONG - verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 4, nodeXY.getX());// X - verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 5, nodeXY.getY());// Y - verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 6, nodeXY.getAttributes().getdWidth());// ATTRIBUTES_DWIDTH + verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 4, nodeXY.getXpos());// X + verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 5, nodeXY.getYpos());// Y + verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 6, nodeXY.getAttributes().getDwidth());// ATTRIBUTES_DWIDTH verify(mockSqlNullHandler).setBigDecimalOrNull(mockPreparedStatement, 7, - nodeXY.getAttributes().getdElevation());// ATTRIBUTES_DELEVATION + nodeXY.getAttributes().getDelevation());// ATTRIBUTES_DELEVATION verify(mockPreparedStatement).close(); verify(mockConnection).close(); } diff --git a/logger-kafka-consumer/src/test/resources/TIM_odeTimStartDateTime.json b/logger-kafka-consumer/src/test/resources/TIM_odeTimStartDateTime.json index 9821975ea..4b66fec03 100644 --- a/logger-kafka-consumer/src/test/resources/TIM_odeTimStartDateTime.json +++ b/logger-kafka-consumer/src/test/resources/TIM_odeTimStartDateTime.json @@ -1,294 +1,309 @@ { - "metadata": { - "request": { - "ode": { - "verb": "POST", - "version": 3 - }, - "sdw": { - "recordId": "047D5D92", - "serviceRegion": { - "nwCorner": { - "latitude": 42.0423655, - "longitude": -110.65625591 - }, - "seCorner": { - "latitude": 41.80934153, - "longitude": -110.53481503 - } - }, - "ttl": "oneyear" - } + "metadata": { + "request": { + "ode": { + "verb": "POST", + "version": 3 + }, + "sdw": { + "recordId": "047D5D92", + "serviceRegion": { + "nwCorner": { + "latitude": 42.0423655, + "longitude": -110.65625591 + }, + "seCorner": { + "latitude": 41.80934153, + "longitude": -110.53481503 + } }, - "recordGeneratedBy": "TMC", - "schemaVersion": 6, - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "odePacketID": "1D6FCDA23022F235E6", - "serialId": { - "recordId": 0, - "serialNumber": 39887, - "streamId": "9a4b7448-d26a-41f9-a80d-97f3ac8c1dd7", - "bundleSize": 1, - "bundleId": 39887 - }, - "sanitized": false, - "recordGeneratedAt": "2020-11-11T07:34:05.151191Z", - "maxDurationTime": 32000, - "odeTimStartDateTime": "2020-11-11T07:36:53.035Z", - "odeReceivedAt": "2020-11-11T07:34:05.220Z" + "ttl": "oneyear" + } + }, + "recordGeneratedBy": "TMC", + "schemaVersion": 6, + "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", + "odePacketID": "1D6FCDA23022F235E6", + "serialId": { + "recordId": 0, + "serialNumber": 39887, + "streamId": "9a4b7448-d26a-41f9-a80d-97f3ac8c1dd7", + "bundleSize": 1, + "bundleId": 39887 }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "timeStamp": 454054, - "packetID": "1D6FCDA23022F235E6", - "urlB": null, - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": { - "closedPath": { - "false": "" - }, - "anchor": { - "lat": 418082518, - "long": -1105341319 - }, - "name": "I_WY 233_SAT-047D5D92_RC_KEMWYO233B", - "laneWidth": 32700, - "directionality": { - "both": "" - }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { - "delta": { - "node-LL3": { - "lon": -8338, - "lat": 10897 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": 1507, - "lat": 169431 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -260004, - "lat": 152391 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -30606, - "lat": 230849 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": -116741, - "lat": 76938 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -237069, - "lat": 63754 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": -110373, - "lat": 80674 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -139739, - "lat": 122423 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -14891, - "lat": 173179 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": -15201, - "lat": 51728 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -207792, - "lat": 174741 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -81993, - "lat": 147705 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": 26456, - "lat": 68121 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": 58918, - "lat": 74751 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": -56248, - "lat": 74095 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -10762, - "lat": 220792 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": -5356, - "lat": 70780 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": 41398, - "lat": 125487 - } - } - }, - { - "delta": { - "node-LL4": { - "lon": 36074, - "lat": 63967 - } - } - }, - { - "delta": { - "node-LL5": { - "lon": -12787, - "lat": 188434 - } - } - } - ] - } - } - }, - "scale": 0 - } - }, - "id": { - "id": 0, - "region": 0 - }, - "direction": 1110000000001111 - } - }, - "durationTime": 32000, - "notUsed2": 1, - "notUsed3": 1, - "startYear": 2020, - "msgId": { - "roadSignID": { - "viewAngle": 1111111111111111, - "mutcdCode": { - "warning": "" - }, - "position": { - "lat": 418082518, - "long": -1105341319 - } - } - }, - "priority": 5, - "content": { - "advisory": { - "SEQUENCE": [ - { - "item": { - "itis": 5906 - } - }, - { - "item": { - "itis": 4868 - } - } - ] - } - }, - "url": null, - "notUsed": 1, - "notUsed1": 1, - "frameType": { - "advisory": "" - }, - "startTime": 454054 + "sanitized": false, + "recordGeneratedAt": "2020-11-11T07:34:05.151191Z", + "maxDurationTime": 32000, + "odeTimStartDateTime": "2020-11-11T07:36:53.035Z", + "odeReceivedAt": "2020-11-11T07:34:05.220Z" + }, + "payload": { + "data": { + "timeStamp": 454054, + "packetID": "1D6FCDA23022F235E6", + "urlB": "null", + "dataFrames": [ + { + "regions": { + "GeographicalPath": { + "closedPath": "false", + "anchor": { + "lat": 418082518, + "long": -1105341319 + }, + "name": "I_WY 233_SAT-047D5D92_RC_KEMWYO233B", + "laneWidth": 32700, + "directionality": "both", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { + "delta": { + "node-LL3": { + "lon": -8338, + "lat": 10897 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": 1507, + "lat": 169431 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -260004, + "lat": 152391 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -30606, + "lat": 230849 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": -116741, + "lat": 76938 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -237069, + "lat": 63754 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": -110373, + "lat": 80674 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -139739, + "lat": 122423 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -14891, + "lat": 173179 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": -15201, + "lat": 51728 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -207792, + "lat": 174741 + } } - }, - "msgCnt": 16 + }, + { + "delta": { + "node-LL5": { + "lon": -81993, + "lat": 147705 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": 26456, + "lat": 68121 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": 58918, + "lat": 74751 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": -56248, + "lat": 74095 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -10762, + "lat": 220792 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": -5356, + "lat": 70780 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": 41398, + "lat": 125487 + } + } + }, + { + "delta": { + "node-LL4": { + "lon": 36074, + "lat": 63967 + } + } + }, + { + "delta": { + "node-LL5": { + "lon": -12787, + "lat": 188434 + } + } + } + ] } + }, + "scale": 0 } + }, + "id": { + "id": 0, + "region": 0 + }, + "direction": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": false, + "from090-0to112-5degrees": false, + "from112-5to135-0degrees": false, + "from135-0to157-5degrees": false, + "from157-5to180-0degrees": false, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + } } - }, - "dataType": "TravelerInformation" + }, + "durationTime": 32000, + "doNotUse3": 0, + "doNotUse4": 0, + "startYear": 2020, + "msgId": { + "roadSignID": { + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + }, + "mutcdCode": "warning", + "position": { + "lat": 418082518, + "long": -1105341319 + } + } + }, + "priority": 5, + "content": { + "advisory": [ + { + "item": { + "itis": 5906 + } + }, + { + "item": { + "itis": 4868 + } + } + ] + }, + "url": null, + "doNotUse1": 0, + "doNotUse2": 0, + "frameType": "advisory", + "startTime": 454054 + } + ], + "msgCnt": 16 } -} \ No newline at end of file + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" +} diff --git a/logger-kafka-consumer/src/test/resources/TIM_odeTim_Rsus.json b/logger-kafka-consumer/src/test/resources/TIM_odeTim_Rsus.json index ef2374a1b..1c0e0c33b 100644 --- a/logger-kafka-consumer/src/test/resources/TIM_odeTim_Rsus.json +++ b/logger-kafka-consumer/src/test/resources/TIM_odeTim_Rsus.json @@ -1,244 +1,259 @@ { - "metadata": { - "maxDurationTime": 32000, - "odePacketID": "257559968DC2308890", - "odeReceivedAt": "2020-12-14T23:36:41.490Z", - "odeTimStartDateTime": "2020-12-14T23:36:40.718Z", - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "recordGeneratedAt": "2020-12-14T23:36:40.965947Z", - "recordGeneratedBy": "TMC", - "request": { - "ode": { - "verb": "PUT", - "version": 3 - }, - "rsus": { - "rsus": { - "rsuIndex": 53, - "rsuRetries": 3, - "rsuTarget": "10.145.12.27", - "rsuTimeout": 5000 - } - }, - "snmp": { - "channel": 178, - "deliverystart": "2020-12-14T23:36:40.718Z", - "deliverystop": "2021-01-06T04:56Z", - "enable": 1, - "interval": 2, - "mode": 1, - "msgid": 31, - "rsuid": 83, - "status": 4 - } - }, - "sanitized": false, - "schemaVersion": 6, - "serialId": { - "bundleId": 2965, - "bundleSize": 1, - "recordId": 0, - "serialNumber": 2965, - "streamId": "78804150-9fa0-4f73-b490-54c507ebc52b" + "metadata": { + "maxDurationTime": 32000, + "odePacketID": "257559968DC2308890", + "odeReceivedAt": "2020-12-14T23:36:41.490Z", + "odeTimStartDateTime": "2020-12-14T23:36:40.718Z", + "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", + "recordGeneratedAt": "2020-12-14T23:36:40.965947Z", + "recordGeneratedBy": "TMC", + "request": { + "ode": { + "verb": "PUT", + "version": 3 + }, + "rsus": { + "rsus": { + "rsuIndex": 53, + "rsuRetries": 3, + "rsuTarget": "10.145.12.27", + "rsuTimeout": 5000 } + }, + "snmp": { + "channel": 178, + "deliverystart": "2020-12-14T23:36:40.718Z", + "deliverystop": "2021-01-06T04:56Z", + "enable": 1, + "interval": 2, + "mode": 1, + "msgid": 31, + "rsuid": 83, + "status": 4 + } }, - "payload": { - "data": { - "MessageFrame": { - "messageId": 31, - "value": { - "TravelerInformation": { - "dataFrames": { - "TravelerDataFrame": { - "content": { - "advisory": { - "SEQUENCE": { - "item": { - "itis": 4871 - } - } - } - }, - "durationTime": 32000, - "frameType": { - "advisory": "" - }, - "msgId": { - "roadSignID": { - "mutcdCode": { - "warning": "" - }, - "position": { - "lat": 412696444, - "long": -1054796709 - }, - "viewAngle": 1111111111111111 - } - }, - "priority": 5, - "regions": { - "GeographicalPath": { - "anchor": { - "lat": 412696444, - "long": -1054796709 - }, - "closedPath": { - "false": "" - }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { - "delta": { - "node-LL3": { - "lat": -10830, - "lon": 12710 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -20785, - "lon": 26578 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -6698, - "lon": 16897 - } - } - }, - { - "delta": { - "node-LL4": { - "lat": -5448, - "lon": 56865 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -14806, - "lon": 32584 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -15537, - "lon": 32086 - } - } - }, - { - "delta": { - "node-LL4": { - "lat": -18878, - "lon": 51470 - } - } - }, - { - "delta": { - "node-LL4": { - "lat": -55342, - "lon": 88538 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -23750, - "lon": 21609 - } - } - }, - { - "delta": { - "node-LL4": { - "lat": -117938, - "lon": 73050 - } - } - }, - { - "delta": { - "node-LL4": { - "lat": -56861, - "lon": 14308 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -28664, - "lon": -2927 - } - } - }, - { - "delta": { - "node-LL4": { - "lat": -41129, - "lon": -17876 - } - } - }, - { - "delta": { - "node-LL3": { - "lat": -14462, - "lon": 667 - } - } - } - ] - } - } - }, - "scale": 0 - } - }, - "direction": "0000111110000000", - "directionality": { - "both": "" - }, - "id": { - "id": 0, - "region": 0 - }, - "laneWidth": 5000, - "name": "I_I 80_RSU-10.145.12.27_RC_test-t-12" - } - }, - "notUsed1": 1, - "notUsed2": 1, - "notUsed3": 1, - "notUsed": 1, - "startTime": 502536, - "startYear": 2020, - "url": null + "sanitized": false, + "schemaVersion": 6, + "serialId": { + "bundleId": 2965, + "bundleSize": 1, + "recordId": 0, + "serialNumber": 2965, + "streamId": "78804150-9fa0-4f73-b490-54c507ebc52b" + } + }, + "payload": { + "data": { + "msgCnt": 2, + "packetID": "257559968DC2308890", + "timeStamp": 502536, + "urlB": "null", + "dataFrames": [ + { + "content": { + "advisory": [ + { + "item": {"itis": 4871} + } + ] + }, + "durationTime": 32000, + "frameType": "advisory", + "msgId": { + "roadSignID": { + "mutcdCode": "warning", + "position": { + "lat": 412696444, + "long": -1054796709 + }, + "viewAngle": { + "from000-0to022-5degrees": true, + "from022-5to045-0degrees": true, + "from045-0to067-5degrees": true, + "from067-5to090-0degrees": true, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": true, + "from202-5to225-0degrees": true, + "from225-0to247-5degrees": true, + "from247-5to270-0degrees": true, + "from270-0to292-5degrees": true, + "from292-5to315-0degrees": true, + "from315-0to337-5degrees": true, + "from337-5to360-0degrees": true + } + } + }, + "priority": 5, + "regions": [ + { + "anchor": { + "lat": 412696444, + "long": -1054796709 + }, + "closedPath": "false", + "description": { + "path": { + "offset": { + "ll": { + "nodes": [ + { + "delta": { + "node-LL3": { + "lat": -10830, + "lon": 12710 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -20785, + "lon": 26578 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -6698, + "lon": 16897 + } + } + }, + { + "delta": { + "node-LL4": { + "lat": -5448, + "lon": 56865 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -14806, + "lon": 32584 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -15537, + "lon": 32086 + } + } + }, + { + "delta": { + "node-LL4": { + "lat": -18878, + "lon": 51470 + } + } + }, + { + "delta": { + "node-LL4": { + "lat": -55342, + "lon": 88538 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -23750, + "lon": 21609 + } + } + }, + { + "delta": { + "node-LL4": { + "lat": -117938, + "lon": 73050 } + } }, - "msgCnt": 2, - "packetID": "257559968DC2308890", - "timeStamp": 502536, - "urlB": null + { + "delta": { + "node-LL4": { + "lat": -56861, + "lon": 14308 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -28664, + "lon": -2927 + } + } + }, + { + "delta": { + "node-LL4": { + "lat": -41129, + "lon": -17876 + } + } + }, + { + "delta": { + "node-LL3": { + "lat": -14462, + "lon": 667 + } + } + } + ] } + }, + "scale": 0 } + }, + "direction": { + "from000-0to022-5degrees": false, + "from022-5to045-0degrees": false, + "from045-0to067-5degrees": false, + "from067-5to090-0degrees": false, + "from090-0to112-5degrees": true, + "from112-5to135-0degrees": true, + "from135-0to157-5degrees": true, + "from157-5to180-0degrees": true, + "from180-0to202-5degrees": false, + "from202-5to225-0degrees": false, + "from225-0to247-5degrees": false, + "from247-5to270-0degrees": false, + "from270-0to292-5degrees": false, + "from292-5to315-0degrees": false, + "from315-0to337-5degrees": false, + "from337-5to360-0degrees": false + }, + "directionality": "both", + "id": { + "id": 0, + "region": 0 + }, + "laneWidth": 5000, + "name": "I_I 80_RSU-10.145.12.27_RC_test-t-12" } - }, - "dataType": "TravelerInformation" + ], + "doNotUse2": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "startTime": 502536, + "startYear": 2020, + "url": "null" + } + ] } -} \ No newline at end of file + }, + "dataType": "us.dot.its.jpo.ode.plugin.j2735.travelerinformation.TravelerInformation" +} diff --git a/logger-kafka-consumer/src/test/resources/TIM_unsigned.json b/logger-kafka-consumer/src/test/resources/TIM_unsigned.json deleted file mode 100644 index 3b3d056d3..000000000 --- a/logger-kafka-consumer/src/test/resources/TIM_unsigned.json +++ /dev/null @@ -1,213 +0,0 @@ -{ - "metadata": { - "request": { - "ode": { - "verb": "POST", - "version": "3" - }, - "sdw": { - "recordId": "60F53BDF", - "serviceRegion": { - "nwCorner": { - "latitude": "44.09328877", - "longitude": "-107.96034055" - }, - "seCorner": { - "latitude": "44.07225981", - "longitude": "-107.95401624" - } - }, - "ttl": "oneyear" - } - }, - "recordGeneratedBy": "TMC", - "schemaVersion": "6", - "payloadType": "us.dot.its.jpo.ode.model.OdeTimPayload", - "odePacketID": "20F6CCABC034423CB3", - "serialId": { - "recordId": "0", - "serialNumber": "76194", - "streamId": "662dd7d9-72d8-4b8a-a25a-4efa45b48936", - "bundleSize": "1", - "bundleId": "76194" - }, - "sanitized": "false", - "recordGeneratedAt": "2022-11-18T17:12:40.652239Z", - "maxDurationTime": "32000", - "odeTimStartDateTime": "2022-09-12T00:00:00.000Z", - "odeReceivedAt": "2022-11-18T17:12:40.682413Z" - }, - "payload": { - "data": { - "AdvisorySituationData": { - "recordID": "60F53BDF", - "timeToLive": "5", - "serviceRegion": { - "nwCorner": { - "lat": "440932888", - "long": "-1079603406" - }, - "seCorner": { - "lat": "440722598", - "long": "-1079540162" - } - }, - "asdmDetails": { - "advisoryMessage": { - "Ieee1609Dot2Data": { - "protocolVersion": "3", - "content": { - "unsecuredData": { - "MessageFrame": { - "messageId": "31", - "value": { - "TravelerInformation": { - "timeStamp": "463272", - "packetID": "20F6CCABC034423CB3", - "urlB": "null", - "dataFrames": { - "TravelerDataFrame": { - "regions": { - "GeographicalPath": { - "closedPath": { - "false": "" - }, - "anchor": { - "lat": "440947086", - "long": "-1079550305" - }, - "name": "D_WY 433_SAT-60F53BDF_RW_39683-0", - "laneWidth": "5000", - "directionality": { - "both": "" - }, - "description": { - "path": { - "offset": { - "ll": { - "nodes": { - "NodeLL": [ - { - "delta": { - "node-LL3": { - "lon": "3768", - "lat": "-14198" - } - } - }, - { - "delta": { - "node-LL3": { - "lon": "6374", - "lat": "-28466" - } - } - }, - { - "delta": { - "node-LL3": { - "lon": "-5520", - "lat": "-28521" - } - } - }, - { - "delta": { - "node-LL4": { - "lon": "-52848", - "lat": "-124572" - } - } - }, - { - "delta": { - "node-LL3": { - "lon": "-4875", - "lat": "-28730" - } - } - } - ] - } - } - }, - "scale": "0" - } - }, - "id": { - "id": "0", - "region": "0" - }, - "direction": "0000000110000000" - } - }, - "durationTime": "32000", - "notUsed2": "1", - "notUsed3": "1", - "startYear": "2022", - "msgId": { - "roadSignID": { - "viewAngle": "1111111111111111", - "mutcdCode": { - "warning": "" - }, - "position": { - "lat": "440947086", - "long": "-1079550305" - } - } - }, - "priority": "5", - "content": { - "workZone": { - "SEQUENCE": { - "item": { - "itis": "1025" - } - } - } - }, - "url": "null", - "notUsed": "1", - "notUsed1": "1", - "frameType": { - "advisory": "" - }, - "startTime": "365760" - } - }, - "msgCnt": "1" - } - } - } - } - } - } - }, - "startTime": { - "month": "0", - "hour": "31", - "year": "0", - "day": "0", - "minute": "60" - }, - "stopTime": { - "month": "0", - "hour": "31", - "year": "0", - "day": "0", - "minute": "60" - }, - "distType": "02", - "asdmType": "2", - "asdmID": "427DA360" - }, - "requestID": "427DA360", - "groupID": "00000000", - "dialogID": "156", - "seqID": "5" - } - }, - "dataType": "TravelerInformation" - } -} \ No newline at end of file diff --git a/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput.json b/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput.json index f61c08d40..169a60727 100644 --- a/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput.json +++ b/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput.json @@ -82,10 +82,10 @@ } }, "durationTime": 32000, - "notUsed2": 0, - "notUsed3": 0, - "notUsed": 0, - "notUsed1": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "doNotUse2": 0, "frameType": { "roadSignage": "" }, diff --git a/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput_NullMetadata.json b/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput_NullMetadata.json index d756c5efd..99c9e6fae 100644 --- a/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput_NullMetadata.json +++ b/logger-kafka-consumer/src/test/resources/rxMsg_TIM_OdeOutput_NullMetadata.json @@ -54,10 +54,10 @@ } }, "durationTime": 32000, - "notUsed2": 0, - "notUsed3": 0, - "notUsed": 0, - "notUsed1": 0, + "doNotUse3": 0, + "doNotUse4": 0, + "doNotUse1": 0, + "doNotUse2": 0, "frameType": { "roadSignage": "" }, diff --git a/milepost-graph-db/Dockerfile b/milepost-graph-db/Dockerfile deleted file mode 100644 index 535a78921..000000000 --- a/milepost-graph-db/Dockerfile +++ /dev/null @@ -1,53 +0,0 @@ -FROM openjdk:8-jre-slim - -ENV NEO4J_SHA256=fb435b11494cde475f748f057a192bcbd8580c7445b380afe9ff52311f334bfe \ - NEO4J_TARBALL=neo4j-community-3.5.14-unix.tar.gz \ - NEO4J_EDITION=community \ - NEO4J_HOME="/var/lib/neo4j" \ - TINI_VERSION="v0.18.0" \ - TINI_SHA256="12d20136605531b09a2c2dac02ccee85e1b874eb322ef6baf7561cd93f93c855" -ARG NEO4J_URI=https://dist.neo4j.org/neo4j-community-3.5.14-unix.tar.gz - -RUN addgroup --system neo4j && adduser --system --no-create-home --home "${NEO4J_HOME}" --ingroup neo4j neo4j - -COPY ./local-package/* /tmp/ - -RUN apt update \ - && apt install -y curl wget gosu jq \ - && curl -L --fail --silent --show-error "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini" > /sbin/tini \ - && echo "${TINI_SHA256} /sbin/tini" | sha256sum -c --strict --quiet \ - && chmod +x /sbin/tini \ - && curl --fail --silent --show-error --location --remote-name ${NEO4J_URI} \ - && echo "${NEO4J_SHA256} ${NEO4J_TARBALL}" | sha256sum -c --strict --quiet \ - && tar --extract --file ${NEO4J_TARBALL} --directory /var/lib \ - && mv /var/lib/neo4j-* "${NEO4J_HOME}" \ - && rm ${NEO4J_TARBALL} \ - && mv "${NEO4J_HOME}"/data /data \ - && mv "${NEO4J_HOME}"/logs /logs \ - && chown -R neo4j:neo4j /data \ - && chmod -R 777 /data \ - && chown -R neo4j:neo4j /logs \ - && chmod -R 777 /logs \ - && chown -R neo4j:neo4j "${NEO4J_HOME}" \ - && chmod -R 777 "${NEO4J_HOME}" \ - && ln -s /data "${NEO4J_HOME}"/data \ - && ln -s /logs "${NEO4J_HOME}"/logs \ - && mv /tmp/neo4jlabs-plugins.json /neo4jlabs-plugins.json \ - && rm -rf /tmp/* \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get -y purge --auto-remove curl - -ENV PATH "${NEO4J_HOME}"/bin:$PATH - -WORKDIR "${NEO4J_HOME}" - -VOLUME /data /logs - -COPY docker-entrypoint.sh /docker-entrypoint.sh - -RUN chmod -R 777 /docker-entrypoint.sh - -EXPOSE 7474 7473 7687 - -ENTRYPOINT ["/sbin/tini", "-g", "--", "/docker-entrypoint.sh"] -CMD ["neo4j"] \ No newline at end of file diff --git a/milepost-graph-db/README.md b/milepost-graph-db/README.md deleted file mode 100644 index 7edca3aac..000000000 --- a/milepost-graph-db/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Milepost Neo4j Database - ---- - -

Dockerized Neo4j database used to efficiently query paths across Wyoming highways -
-

- -## 📝 Table of Contents - -- [About](#about) -- [Getting Started](#getting_started) -- [Deployment](#deployment) -- [Usage](#usage) -- [Built Using](#built_using) -- [TODO](#TODO) - -## 🧐 About - -This is a simple stand-up of a dockerized Neo4j database used to query paths instead of the milepost_vw. It includes several scripts to run to get a version up and running with the Milepost layer. - -## 🏁 Getting Started - -These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See [deployment](#deployment) for notes on how to deploy the project on a live system. - -### Prerequisites - -The only real prerequisite here is to have Docker up and running. The scripts take care of the rest. - -### Installing - -A docker-compose file has been provided here for simplicity to enable running this container individually. To run the container simply execute the following command: - -``` -docker-compose up --build -d -``` - -This will install Neo4j in a docker container without authentication and expose the following ports for access: - -``` -6474: http -6473: https -6687: bolt -``` - -To view the database in browser navigate to http://localhost:6474/browser. - -## 🎈 Usage - -The initial check-in includes the base set of data to avoid having to run the scripts. If you need to update the data in the Neo4j database the following steps may be taken. - -1. Export milepost_vw_new data as .csv from the database (include headers) - ``` - SELECT - * - FROM - milepost_vw_new - ORDER BY - common_name, - milepost - ``` -2. Copy the new export.csv file to the specified [import folder](./neo-data/import) -3. Run [import_commands.cmd](./import_commands.cmd) to import new data. Note that you will need to remove any existing data you are replacing through the browser UI - -## 🚀 Deployment - -Deployment should be very similar to running this locally since everything will be handled in docker. This application can be added to the main docker-compose file in the TIMM applications folder for simplicity. If a different location is desired to store data, specify those locations in the docker-compose.yml file and copy the following folders to the appropriate locations: - -- [conf](./neo-data/conf) - holds custom configuration -- [data/databases](./neo-data/data/databases) - houses the data -- [import](./neo-data/import) - used to import any data -- [plugins](./neo-data/plugins) - holds the APOC and Graph Algorithm jar files used to access data - -## ⛏️ Built Using - -- [Neo4j](https://neo4j.com/) - Database - -## TODO - -The [generate_relationships.sh](./generate_relationships.sh) and [generate_named_relationships.cql](generate_named_relationships.cql) are to be used in conjunction to generate a more efficient and communicative set of import statements to be ran rather than the existing [import.cql](./neo-data/import/import.cql). The existing import scripts run for a substantial time (~12+ hours on dev machine) and do not communicate progress very well. diff --git a/milepost-graph-db/docker-compose.yml b/milepost-graph-db/docker-compose.yml deleted file mode 100644 index 57e10305e..000000000 --- a/milepost-graph-db/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: '3.7' -services: - milepost-graph: - build: . - # image: neo4j:3.5.14 - ports: - - '6474:7474' - - '6473:7473' - - '6687:7687' - volumes: - - type: bind - source: ./neo-data/plugins - target: /var/lib/neo4j/plugins - - type: bind - source: ./neo-data/import - target: /var/lib/neo4j/import - - type: bind - source: ./neo-data/conf - target: /var/lib/neo4j/conf - - type: bind - source: ./neo-data/data - target: /var/lib/neo4j/data - environment: - NEO4J_AUTH: none diff --git a/milepost-graph-db/docker-entrypoint.sh b/milepost-graph-db/docker-entrypoint.sh deleted file mode 100644 index 424b86be6..000000000 --- a/milepost-graph-db/docker-entrypoint.sh +++ /dev/null @@ -1,446 +0,0 @@ -#!/bin/bash -eu - -cmd="$1" - -function running_as_root -{ - test "$(id -u)" = "0" -} - -function secure_mode_enabled -{ - test "${SECURE_FILE_PERMISSIONS:=no}" = "yes" -} - -function containsElement -{ - local e match="$1" - shift - for e; do [[ "$e" == "$match" ]] && return 0; done - return 1 -} - -function is_readable -{ - # this code is fairly ugly but works no matter who this script is running as. - # It would be nice if the writability tests could use this logic somehow. - local _file=${1} - perm=$(stat -c %a "${_file}") - - # everyone permission - if [[ ${perm:2:1} -ge 4 ]]; then - return 0 - fi - # owner permissions - if [[ ${perm:0:1} -ge 4 ]]; then - if [[ "$(stat -c %U ${_file})" = "${userid}" ]] || [[ "$(stat -c %u ${_file})" = "${userid}" ]]; then - return 0 - fi - fi - # group permissions - if [[ ${perm:1:1} -ge 4 ]]; then - if containsElement "$(stat -c %g ${_file})" "${groups[@]}" || containsElement "$(stat -c %G ${_file})" "${groups[@]}" ; then - return 0 - fi - fi - return 1 -} - -function is_writable -{ - # It would be nice if this and the is_readable function could combine somehow - local _file=${1} - perm=$(stat -c %a "${_file}") - - # everyone permission - if containsElement ${perm:2:1} 2 3 6 7; then - return 0 - fi - # owner permissions - if containsElement ${perm:0:1} 2 3 6 7; then - if [[ "$(stat -c %U ${_file})" = "${userid}" ]] || [[ "$(stat -c %u ${_file})" = "${userid}" ]]; then - return 0 - fi - fi - # group permissions - if containsElement ${perm:1:1} 2 3 6 7; then - if containsElement "$(stat -c %g ${_file})" "${groups[@]}" || containsElement "$(stat -c %G ${_file})" "${groups[@]}" ; then - return 0 - fi - fi - return 1 -} - - -function print_permissions_advice_and_fail -{ - _directory=${1} - echo >&2 " -Folder ${_directory} is not accessible for user: ${userid} or group ${groupid} or groups ${groups[@]}, this is commonly a file permissions issue on the mounted folder. - -Hints to solve the issue: -1) Make sure the folder exists before mounting it. Docker will create the folder using root permissions before starting the Neo4j container. The root permissions disallow Neo4j from writing to the mounted folder. -2) Pass the folder owner's user ID and group ID to docker run, so that docker runs as that user. -If the folder is owned by the current user, this can be done by adding this flag to your docker run command: - --user=\$(id -u):\$(id -g) - " - exit 1 -} - -function check_mounted_folder_readable -{ - local _directory=${1} - if ! is_readable "${_directory}"; then - print_permissions_advice_and_fail "${_directory}" - fi -} - -function check_mounted_folder_with_chown -{ -# The /data and /log directory are a bit different because they are very likely to be mounted by the user but not -# necessarily writable. -# This depends on whether a user ID is passed to the container and which folders are mounted. -# -# No user ID passed to container: -# 1) No folders are mounted. -# The /data and /log folder are owned by neo4j by default, so should be writable already. -# 2) Both /log and /data are mounted. -# This means on start up, /data and /logs are owned by an unknown user and we should chown them to neo4j for -# backwards compatibility. -# -# User ID passed to container: -# 1) Both /data and /logs are mounted -# The /data and /logs folders are owned by an unknown user but we *should* have rw permission to them. -# That should be verified and error (helpfully) if not. -# 2) User mounts /data or /logs *but not both* -# The unmounted folder is still owned by neo4j, which should already be writable. The mounted folder should -# have rw permissions through user id. This should be verified. -# 3) No folders are mounted. -# The /data and /log folder are owned by neo4j by default, and these are already writable by the user. -# (This is a very unlikely use case). - - local mountFolder=${1} - if running_as_root; then - if ! is_writable "${mountFolder}" && ! secure_mode_enabled; then - # warn that we're about to chown the folder and then chown it - echo "Warning: Folder mounted to \"${mountFolder}\" is not writable from inside container. Changing folder owner to ${userid}." - chown -R "${userid}":"${groupid}" "${mountFolder}" - fi - else - if [[ ! -w "${mountFolder}" ]] && [[ "$(stat -c %U ${mountFolder})" != "neo4j" ]]; then - print_permissions_advice_and_fail "${mountFolder}" - fi - fi -} - -function load_plugin_from_github -{ - # Load a plugin at runtime. The provided github repository must have a versions.json on the master branch with the - # correct format. - local _plugin_name="${1}" #e.g. apoc, graph-algorithms, graph-ql - - local _plugins_dir="${NEO4J_HOME}/plugins" - if [ -d /plugins ]; then - local _plugins_dir="/plugins" - fi - local _versions_json_url="$(jq --raw-output "with_entries( select(.key==\"${_plugin_name}\") ) | to_entries[] | .value" /neo4jlabs-plugins.json )" - # Using the same name for the plugin irrespective of version ensures we don't end up with different versions of the same plugin - local _destination="${_plugins_dir}/${_plugin_name}.jar" - local _neo4j_version="$(neo4j --version | cut -d' ' -f2)" - - # Now we call out to github to get the versions.json for this plugin and we parse that to find the url for the correct plugin jar for our neo4j version - echo "Fetching versions.json for Plugin '${_plugin_name}' from ${_versions_json_url}" - local _versions_json="$(wget -q --timeout 300 --tries 30 -O - "${_versions_json_url}")" - local _plugin_jar_url="$(echo "${_versions_json}" | jq --raw-output ".[] | select(.neo4j==\"${_neo4j_version}\") | .jar")" - if [[ -z "${_plugin_jar_url}" ]]; then - echo >&2 "No jar URL found for version '${_neo4j_version}' in versions.json from '${_versions_json_url}'" - echo >&2 "${_versions_json}" - fi - echo "Installing Plugin '${_plugin_name}' from ${_plugin_jar_url} to ${_destination} " - wget -q --timeout 300 --tries 30 --output-document="${_destination}" "${_plugin_jar_url}" - - if ! is_readable "${_destination}"; then - echo >&2 "Plugin at '${_destination}' is not readable" - exit 1 - fi -} - -# If we're running as root, then run as the neo4j user. Otherwise -# docker is running with --user and we simply use that user. Note -# that su-exec, despite its name, does not replicate the functionality -# of exec, so we need to use both -if running_as_root; then - userid="neo4j" - groupid="neo4j" - groups=($(id -G neo4j)) - exec_cmd="exec gosu neo4j:neo4j" -else - userid="$(id -u)" - groupid="$(id -g)" - groups=($(id -G)) - exec_cmd="exec" -fi -readonly userid -readonly groupid -readonly groups -readonly exec_cmd - - -# Need to chown the home directory - but a user might have mounted a -# volume here (notably a conf volume). So take care not to chown -# volumes (stuff not owned by neo4j) -if running_as_root; then - # Non-recursive chown for the base directory - chown "${userid}":"${groupid}" "${NEO4J_HOME}" - chmod 700 "${NEO4J_HOME}" - find "${NEO4J_HOME}" -mindepth 1 -maxdepth 1 -user root -type d -exec chown -R ${userid}:${groupid} {} \; - find "${NEO4J_HOME}" -mindepth 1 -maxdepth 1 -user root -type d -exec chmod -R 700 {} \; -fi - -# Only prompt for license agreement if command contains "neo4j" in it -if [[ "${cmd}" == *"neo4j"* ]]; then - if [ "${NEO4J_EDITION}" == "enterprise" ]; then - if [ "${NEO4J_ACCEPT_LICENSE_AGREEMENT:=no}" != "yes" ]; then - echo >&2 " -In order to use Neo4j Enterprise Edition you must accept the license agreement. - -(c) Neo4j Sweden AB. 2019. All Rights Reserved. -Use of this Software without a proper commercial license with Neo4j, -Inc. or its affiliates is prohibited. - -Email inquiries can be directed to: licensing@neo4j.com - -More information is also available at: https://neo4j.com/licensing/ - - -To accept the license agreement set the environment variable -NEO4J_ACCEPT_LICENSE_AGREEMENT=yes - -To do this you can use the following docker argument: - - --env=NEO4J_ACCEPT_LICENSE_AGREEMENT=yes -" - exit 1 - fi - fi -fi - -# Env variable naming convention: -# - prefix NEO4J_ -# - double underscore char '__' instead of single underscore '_' char in the setting name -# - underscore char '_' instead of dot '.' char in the setting name -# Example: -# NEO4J_dbms_tx__log_rotation_retention__policy env variable to set -# dbms.tx_log.rotation.retention_policy setting - -# Backward compatibility - map old hardcoded env variables into new naming convention (if they aren't set already) -# Set some to default values if unset -: ${NEO4J_dbms_tx__log_rotation_retention__policy:=${NEO4J_dbms_txLog_rotation_retentionPolicy:-"100M size"}} -: ${NEO4J_wrapper_java_additional:=${NEO4J_UDC_SOURCE:-"-Dneo4j.ext.udc.source=docker"}} -: ${NEO4J_dbms_unmanaged__extension__classes:=${NEO4J_dbms_unmanagedExtensionClasses:-}} -: ${NEO4J_dbms_allow__format__migration:=${NEO4J_dbms_allowFormatMigration:-}} -: ${NEO4J_dbms_connectors_default__advertised__address:=${NEO4J_dbms_connectors_defaultAdvertisedAddress:-}} - -if [ "${NEO4J_EDITION}" == "enterprise" ]; - then - : ${NEO4J_causal__clustering_expected__core__cluster__size:=${NEO4J_causalClustering_expectedCoreClusterSize:-}} - : ${NEO4J_causal__clustering_initial__discovery__members:=${NEO4J_causalClustering_initialDiscoveryMembers:-}} - : ${NEO4J_causal__clustering_discovery__advertised__address:=${NEO4J_causalClustering_discoveryAdvertisedAddress:-"$(hostname):5000"}} - : ${NEO4J_causal__clustering_transaction__advertised__address:=${NEO4J_causalClustering_transactionAdvertisedAddress:-"$(hostname):6000"}} - : ${NEO4J_causal__clustering_raft__advertised__address:=${NEO4J_causalClustering_raftAdvertisedAddress:-"$(hostname):7000"}} - # Custom settings for dockerized neo4j - : ${NEO4J_causal__clustering_discovery__advertised__address:=$(hostname):5000} - : ${NEO4J_causal__clustering_transaction__advertised__address:=$(hostname):6000} - : ${NEO4J_causal__clustering_raft__advertised__address:=$(hostname):7000} -fi - -# unset old hardcoded unsupported env variables -unset NEO4J_dbms_txLog_rotation_retentionPolicy NEO4J_UDC_SOURCE \ - NEO4J_dbms_unmanagedExtensionClasses NEO4J_dbms_allowFormatMigration \ - NEO4J_dbms_connectors_defaultAdvertisedAddress NEO4J_ha_serverId \ - NEO4J_ha_initialHosts NEO4J_causalClustering_expectedCoreClusterSize \ - NEO4J_causalClustering_initialDiscoveryMembers \ - NEO4J_causalClustering_discoveryListenAddress \ - NEO4J_causalClustering_discoveryAdvertisedAddress \ - NEO4J_causalClustering_transactionListenAddress \ - NEO4J_causalClustering_transactionAdvertisedAddress \ - NEO4J_causalClustering_raftListenAddress \ - NEO4J_causalClustering_raftAdvertisedAddress - -if [ -d /conf ]; then - if secure_mode_enabled; then - check_mounted_folder_readable "/conf" - fi - find /conf -type f -exec cp {} "${NEO4J_HOME}"/conf \; -fi - -if [ -d /ssl ]; then - if secure_mode_enabled; then - check_mounted_folder_readable "/ssl" - fi - : ${NEO4J_dbms_directories_certificates:="/ssl"} -fi - -if [ -d /plugins ]; then - if secure_mode_enabled; then - if [[ ! -z "${NEO4JLABS_PLUGINS:-}" ]]; then - # We need write permissions - check_mounted_folder_with_chown "/plugins" - fi - check_mounted_folder_readable "/plugins" - fi - : ${NEO4J_dbms_directories_plugins:="/plugins"} -fi - -if [ -d /import ]; then - if secure_mode_enabled; then - check_mounted_folder_readable "/import" - fi - : ${NEO4J_dbms_directories_import:="/import"} -fi - -if [ -d /metrics ]; then - if secure_mode_enabled; then - check_mounted_folder_readable "/metrics" - fi - : ${NEO4J_dbms_directories_metrics:="/metrics"} -fi - -if [ -d /logs ]; then - check_mounted_folder_with_chown "/logs" - : ${NEO4J_dbms_directories_logs:="/logs"} -fi - -if [ -d /data ]; then - check_mounted_folder_with_chown "/data" - if [ -d /data/databases ]; then - check_mounted_folder_with_chown "/data/databases" - fi - if [ -d /data/dbms ]; then - check_mounted_folder_with_chown "/data/dbms" - fi -fi - - -# set the neo4j initial password only if you run the database server -if [ "${cmd}" == "neo4j" ]; then - if [ "${NEO4J_AUTH:-}" == "none" ]; then - NEO4J_dbms_security_auth__enabled=false - elif [[ "${NEO4J_AUTH:-}" == neo4j/* ]]; then - password="${NEO4J_AUTH#neo4j/}" - if [ "${password}" == "neo4j" ]; then - echo >&2 "Invalid value for password. It cannot be 'neo4j', which is the default." - exit 1 - fi - - if running_as_root; then - # running set-initial-password as root will create subfolders to /data as root, causing startup fail when neo4j can't read or write the /data/dbms folder - # creating the folder first will avoid that - mkdir -p /data/dbms - chown "${userid}":"${groupid}" /data/dbms - fi - # Will exit with error if users already exist (and print a message explaining that) - # we probably don't want the message though, since it throws an error message on restarting the container. - neo4j-admin set-initial-password "${password}" 2>/dev/null || true - elif [ -n "${NEO4J_AUTH:-}" ]; then - echo >&2 "Invalid value for NEO4J_AUTH: '${NEO4J_AUTH}'" - exit 1 - fi -fi - -declare -A COMMUNITY -declare -A ENTERPRISE - -COMMUNITY=( - [dbms.tx_log.rotation.retention_policy]="100M size" - [dbms.memory.pagecache.size]="2G" - [dbms.memory.heap.initial_size]="2G" - [dbms.memory.heap.max_size]="2G" - [dbms.connectors.default_listen_address]="0.0.0.0" - [dbms.connector.https.listen_address]="0.0.0.0:7473" - [dbms.connector.http.listen_address]="0.0.0.0:7474" - [dbms.connector.bolt.listen_address]="0.0.0.0:7687" -) - -ENTERPRISE=( - [causal_clustering.transaction_listen_address]="0.0.0.0:6000" - [causal_clustering.raft_listen_address]="0.0.0.0:7000" - [causal_clustering.discovery_listen_address]="0.0.0.0:5000" -) - -for conf in ${!COMMUNITY[@]} ; do - - if ! grep -q "^$conf" "${NEO4J_HOME}"/conf/neo4j.conf - then - echo -e "\n"$conf=${COMMUNITY[$conf]} >> "${NEO4J_HOME}"/conf/neo4j.conf - fi -done - -for conf in ${!ENTERPRISE[@]} ; do - - if [ "${NEO4J_EDITION}" == "enterprise" ]; - then - if ! grep -q "^$conf" "${NEO4J_HOME}"/conf/neo4j.conf - then - echo -e "\n"$conf=${ENTERPRISE[$conf]} >> "${NEO4J_HOME}"/conf/neo4j.conf - fi - fi -done - -#The udc.source=tarball should be replaced by udc.source=docker in both dbms.jvm.additional and wrapper.java.additional -#Using sed to replace only this part will allow the custom configs to be added after, separated by a ,. -if grep -q "udc.source=tarball" "${NEO4J_HOME}"/conf/neo4j.conf; then - sed -i -e 's/udc.source=tarball/udc.source=docker/g' "${NEO4J_HOME}"/conf/neo4j.conf -fi -#The udc.source should always be set to docker by default and we have to allow also custom configs to be added after that. -#In this case, this piece of code helps to add the default value and a , to support custom configs after. -if ! grep -q "dbms.jvm.additional=-Dunsupported.dbms.udc.source=docker" "${NEO4J_HOME}"/conf/neo4j.conf; then - sed -i -e 's/dbms.jvm.additional=/dbms.jvm.additional=-Dunsupported.dbms.udc.source=docker,/g' "${NEO4J_HOME}"/conf/neo4j.conf -fi - -# list env variables with prefix NEO4J_ and create settings from them -unset NEO4J_AUTH NEO4J_SHA256 NEO4J_TARBALL -for i in $( set | grep ^NEO4J_ | awk -F'=' '{print $1}' | sort -rn ); do - setting=$(echo ${i} | sed 's|^NEO4J_||' | sed 's|_|.|g' | sed 's|\.\.|_|g') - value=$(echo ${!i}) - # Don't allow settings with no value or settings that start with a number (neo4j converts settings to env variables and you cannot have an env variable that starts with a number) - if [[ -n ${value} ]]; then - if [[ ! "${setting}" =~ ^[0-9]+.*$ ]]; then - if grep -q -F "${setting}=" "${NEO4J_HOME}"/conf/neo4j.conf; then - # Remove any lines containing the setting already - sed --in-place "/^${setting}=.*/d" "${NEO4J_HOME}"/conf/neo4j.conf - fi - # Then always append setting to file - echo "${setting}=${value}" >> "${NEO4J_HOME}"/conf/neo4j.conf - else - echo >&2 "WARNING: ${setting} not written to conf file because settings that start with a number are not permitted" - fi - fi -done - -if [[ ! -z "${NEO4JLABS_PLUGINS:-}" ]]; then - # NEO4JLABS_PLUGINS should be a json array of plugins like '["graph-algorithms", "apoc-procedures", "streams", "graphql"]' - for plugin_name in $(echo "${NEO4JLABS_PLUGINS}" | jq --raw-output '.[]'); do - load_plugin_from_github "${plugin_name}" - done -fi - -[ -f "${EXTENSION_SCRIPT:-}" ] && . ${EXTENSION_SCRIPT} - -if [ "${cmd}" == "dump-config" ]; then - if ! is_writable "/conf"; then - print_permissions_advice_and_fail "/conf" - fi - cp --recursive "${NEO4J_HOME}"/conf/* /conf - echo "Config Dumped" - exit 0 -fi - -# Use su-exec to drop privileges to neo4j user -# Note that su-exec, despite its name, does not replicate the -# functionality of exec, so we need to use both -if [ "${cmd}" == "neo4j" ]; then - ${exec_cmd} neo4j console -else - ${exec_cmd} "$@" -fi \ No newline at end of file diff --git a/milepost-graph-db/generate_named_relationships.cql b/milepost-graph-db/generate_named_relationships.cql deleted file mode 100644 index b4e3be6f2..000000000 --- a/milepost-graph-db/generate_named_relationships.cql +++ /dev/null @@ -1,22 +0,0 @@ -//relationship match, updated -match (n:Milepost{CommonName: "COMMON_NAME"}) -where n.Direction in ["I", "B"] -match (m:Milepost) -where m.CommonName = n.CommonName and m.Milepost > n.Milepost and m.Direction in ["I", "B"] and distance(point({longitude:n.Longitude, latitude:n.Latitude}), point({longitude:m.Longitude, latitude:m.Latitude})) < 804.672 -with n, min(m.Milepost) as minM -match (nxt:Milepost) -where nxt.CommonName = n.CommonName and nxt.Milepost = minM and nxt.Direction in ["I", "B"] and distance(point({longitude:n.Longitude, latitude:n.Latitude}), point({longitude:nxt.Longitude, latitude:nxt.Latitude})) < 804.672 -call apoc.create.relationship(n, replace(n.CommonName, " ", "_")+"_I", {Direction:n.Direction, CommonName:n.CommonName},nxt) yield rel -return rel; - - -//relationship match, updated -match (n:Milepost{CommonName: "COMMON_NAME"}) -where n.Direction in ["D", "B"] -match (m:Milepost) -where m.CommonName = n.CommonName and m.Milepost < n.Milepost and m.Direction in ["D", "B"] and distance(point({longitude:n.Longitude, latitude:n.Latitude}), point({longitude:m.Longitude, latitude:m.Latitude})) < 804.672 -with n, max(m.Milepost) as maxM -match (nxt:Milepost) -where nxt.CommonName = n.CommonName and nxt.Milepost = maxM and nxt.Direction in ["D", "B"] and distance(point({longitude:n.Longitude, latitude:n.Latitude}), point({longitude:nxt.Longitude, latitude:nxt.Latitude})) < 804.672 -call apoc.create.relationship(n, replace(n.CommonName, " ", "_")+"_D", {Direction:n.Direction, CommonName:n.CommonName},nxt) yield rel -return rel; \ No newline at end of file diff --git a/milepost-graph-db/generate_relationships.sh b/milepost-graph-db/generate_relationships.sh deleted file mode 100644 index 6a335d1e2..000000000 --- a/milepost-graph-db/generate_relationships.sh +++ /dev/null @@ -1,4 +0,0 @@ -cat common_names.txt | -while read line; do -sed "s/COMMON_NAME/$line/g" generate_named_relationships.cql >> neo-data/import/tmp.cql -done \ No newline at end of file diff --git a/milepost-graph-db/import_commands.cmd b/milepost-graph-db/import_commands.cmd deleted file mode 100644 index d7bedb3bf..000000000 --- a/milepost-graph-db/import_commands.cmd +++ /dev/null @@ -1 +0,0 @@ -docker exec -it milepost-graph-db_milepost-graph_1 bash -c "cat import/import.cql | bin/cypher-shell" \ No newline at end of file diff --git a/milepost-graph-db/local-package/.sentinel b/milepost-graph-db/local-package/.sentinel deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/local-package/neo4jlabs-plugins.json b/milepost-graph-db/local-package/neo4jlabs-plugins.json deleted file mode 100644 index fa77de243..000000000 --- a/milepost-graph-db/local-package/neo4jlabs-plugins.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "apoc": "https://neo4j-contrib.github.io/neo4j-apoc-procedures/versions.json", - "streams": "https://neo4j-contrib.github.io/neo4j-streams/versions.json", - "graphql": "https://neo4j-graphql.github.io/neo4j-graphql/versions.json", - "graph-algorithms": "https://neo4j-contrib.github.io/neo4j-graph-algorithms/versions.json", - "_testing": "http://host.testcontainers.internal:3000/versions.json" -} diff --git a/milepost-graph-db/neo-data/conf/neo4j.conf b/milepost-graph-db/neo-data/conf/neo4j.conf deleted file mode 100644 index 5a9eb4bc4..000000000 --- a/milepost-graph-db/neo-data/conf/neo4j.conf +++ /dev/null @@ -1,20 +0,0 @@ - -dbms.connector.https.listen_address=0.0.0.0:7473 - -dbms.connectors.default_listen_address=0.0.0.0 - -dbms.connector.http.listen_address=0.0.0.0:7474 - -dbms.connector.bolt.listen_address=0.0.0.0:7687 - -dbms.memory.pagecache.size=2G -dbms.memory.heap.initial_size=2G -dbms.memory.heap.max_size=2G - -dbms.security.procedures.unrestricted=algo.*,apoc.* -wrapper.java.additional=-Dneo4j.ext.udc.source=docker -dbms.tx_log.rotation.retention_policy=100M size -dbms.security.auth_enabled=false -dbms.directories.logs=/logs -HOME=/var/lib/neo4j -EDITION=community diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore b/milepost-graph-db/neo-data/data/databases/graph.db/neostore deleted file mode 100644 index 945fd2cc6..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.counts.db.a b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.counts.db.a deleted file mode 100644 index 42f972e98..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.counts.db.a and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labelscanstore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labelscanstore.db deleted file mode 100644 index 010bd0127..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labelscanstore.db and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.names b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.names deleted file mode 100644 index ce6529796..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.names and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.names.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.names.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.labeltokenstore.db.names.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.labels b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.labels deleted file mode 100644 index df8ce2a58..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.labels and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.labels.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.labels.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.nodestore.db.labels.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.arrays b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.arrays deleted file mode 100644 index d19598d74..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.arrays and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.arrays.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.arrays.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.arrays.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.keys b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.keys deleted file mode 100644 index ce6529796..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.keys and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.keys.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.keys.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.index.keys.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.strings b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.strings deleted file mode 100644 index d19598d74..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.strings and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.strings.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.strings.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.propertystore.db.strings.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipgroupstore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipgroupstore.db deleted file mode 100644 index b72840ef5..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipgroupstore.db and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipgroupstore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipgroupstore.db.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipgroupstore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipstore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipstore.db deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipstore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipstore.db.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshipstore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.id deleted file mode 100644 index 22fd28d4e..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.names b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.names deleted file mode 100644 index ce6529796..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.names and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.names.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.names.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.relationshiptypestore.db.names.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.schemastore.db b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.schemastore.db deleted file mode 100644 index df8ce2a58..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.schemastore.db and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.schemastore.db.id b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.schemastore.db.id deleted file mode 100644 index 60d6e05be..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.schemastore.db.id and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.transaction.db.0 b/milepost-graph-db/neo-data/data/databases/graph.db/neostore.transaction.db.0 deleted file mode 100644 index b1aade4ed..000000000 Binary files a/milepost-graph-db/neo-data/data/databases/graph.db/neostore.transaction.db.0 and /dev/null differ diff --git a/milepost-graph-db/neo-data/data/databases/store_lock b/milepost-graph-db/neo-data/data/databases/store_lock deleted file mode 100644 index e69de29bb..000000000 diff --git a/milepost-graph-db/neo-data/import/export.csv b/milepost-graph-db/neo-data/import/export.csv deleted file mode 100644 index 534884de7..000000000 --- a/milepost-graph-db/neo-data/import/export.csv +++ /dev/null @@ -1,3 +0,0 @@ -"COMMON_NAME","DIRECTION","MILEPOST","LATITUDE","LONGITUDE" -"Example Route","D",0,40.99821606,-104.90694278 -"Example Route","I",0,40.9982158,-104.90666619 \ No newline at end of file diff --git a/milepost-graph-db/neo-data/import/import.cql b/milepost-graph-db/neo-data/import/import.cql deleted file mode 100644 index 3a24451ab..000000000 --- a/milepost-graph-db/neo-data/import/import.cql +++ /dev/null @@ -1,18 +0,0 @@ -load csv with headers from "file:///export.csv" as row -merge (m:Milepost {CommonName:row.COMMON_NAME, Milepost:toFloat(row.MILEPOST), Direction: row.DIRECTION, Latitude:toFloat(row.LATITUDE), Longitude:toFloat(row.LONGITUDE)}); - -//////////////////////////////////////////////////// -match (n:Milepost) -where n.Direction in ["I", "B"] -call apoc.cypher.run('with {n} as n match (m:Milepost) where m.CommonName = n.CommonName and n.Milepost < m.Milepost and m.Direction in ["I","B"] with m, distance(point({longitude:n.Longitude, latitude:n.Latitude}), point({longitude:m.Longitude, latitude:m.Latitude})) as dst where dst < 8046.72 return m order by m.Milepost,dst limit 1', {n:n}) yield value as val -with n, val.m as nxt -call apoc.create.relationship(n, replace(n.CommonName, " ", "_")+"_I", {Direction:n.Direction, CommonName:n.CommonName},nxt) yield rel -return rel; - - -match (n:Milepost) -where n.Direction in ["D", "B"] -call apoc.cypher.run('with {n} as n match (m:Milepost) where m.CommonName = n.CommonName and n.Milepost > m.Milepost and m.Direction in ["D","B"] with m, distance(point({longitude:n.Longitude, latitude:n.Latitude}), point({longitude:m.Longitude, latitude:m.Latitude})) as dst where dst < 8046.72 return m order by m.Milepost desc, dst limit 1', {n:n}) yield value as val -with n, val.m as nxt -call apoc.create.relationship(n, replace(n.CommonName, " ", "_")+"_D", {Direction:n.Direction, CommonName:n.CommonName},nxt) yield rel -return rel; \ No newline at end of file diff --git a/milepost-graph-db/neo-data/plugins/apoc-3.5.0.9.jar b/milepost-graph-db/neo-data/plugins/apoc-3.5.0.9.jar deleted file mode 100644 index 9020b284d..000000000 Binary files a/milepost-graph-db/neo-data/plugins/apoc-3.5.0.9.jar and /dev/null differ diff --git a/milepost-graph-db/neo-data/plugins/graphAlgorithms-3.5.14.0.jar b/milepost-graph-db/neo-data/plugins/graphAlgorithms-3.5.14.0.jar deleted file mode 100644 index 934558518..000000000 Binary files a/milepost-graph-db/neo-data/plugins/graphAlgorithms-3.5.14.0.jar and /dev/null differ diff --git a/ode-data-logger/Dockerfile b/ode-data-logger/Dockerfile index de8e38772..d3c7eb8ff 100644 --- a/ode-data-logger/Dockerfile +++ b/ode-data-logger/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/ode-data-logger -CMD java -jar /home/timm/timm_applications/ode-data-logger/ode-data-logger-1.4.0-SNAPSHOT.jar \ No newline at end of file +CMD java -jar /home/timm/timm_applications/ode-data-logger/ode-data-logger-2.0.0.jar \ No newline at end of file diff --git a/ode-data-logger/pom.xml b/ode-data-logger/pom.xml index 12228871a..6520bd579 100644 --- a/ode-data-logger/pom.xml +++ b/ode-data-logger/pom.xml @@ -5,7 +5,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 ode-data-logger diff --git a/ode-mongo-logger/Dockerfile b/ode-mongo-logger/Dockerfile index e69bf6f03..7784762e8 100644 --- a/ode-mongo-logger/Dockerfile +++ b/ode-mongo-logger/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/ode-mongo-logger -CMD java -jar /home/timm/timm_applications/ode-mongo-logger/ode-mongo-logger-1.4.0-SNAPSHOT.jar +CMD java -jar /home/timm/timm_applications/ode-mongo-logger/ode-mongo-logger-2.0.0.jar diff --git a/ode-mongo-logger/pom.xml b/ode-mongo-logger/pom.xml index 5de24fd94..a4770435f 100644 --- a/ode-mongo-logger/pom.xml +++ b/ode-mongo-logger/pom.xml @@ -4,7 +4,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 diff --git a/ode-wrapper/Dockerfile b/ode-wrapper/Dockerfile index d268f5dcd..e2beb8b2b 100644 --- a/ode-wrapper/Dockerfile +++ b/ode-wrapper/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/ode-wrapper -CMD java -jar /home/timm/timm_applications/ode-wrapper/ode-wrapper-1.4.0-SNAPSHOT.jar +CMD java -jar /home/timm/timm_applications/ode-wrapper/ode-wrapper-2.0.0.jar diff --git a/ode-wrapper/pom.xml b/ode-wrapper/pom.xml index 44bcbb985..7acf07b54 100644 --- a/ode-wrapper/pom.xml +++ b/ode-wrapper/pom.xml @@ -9,7 +9,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 diff --git a/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimIncidentController.java b/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimIncidentController.java index c991a37de..6efd15d6b 100644 --- a/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimIncidentController.java +++ b/ode-wrapper/src/main/java/com/trihydro/odewrapper/controller/WydotTimIncidentController.java @@ -5,7 +5,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.List; import com.trihydro.library.helpers.MilepostReduction; import com.trihydro.library.helpers.TimGenerationHelper; @@ -22,6 +21,7 @@ import com.trihydro.odewrapper.model.TimIncidentList; import com.trihydro.odewrapper.model.WydotTimIncident; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -38,140 +38,114 @@ @CrossOrigin @RestController @Api(description = "Incidents") +@Slf4j public class WydotTimIncidentController extends WydotTimBaseController { - private final String type = "I"; + private final String type = "I"; - @Autowired - public WydotTimIncidentController(BasicConfiguration _basicConfiguration, WydotTimService _wydotTimService, - TimTypeService _timTypeService, SetItisCodes _setItisCodes, ActiveTimService _activeTimService, - RestTemplateProvider _restTemplateProvider, MilepostReduction _milepostReduction, Utility _utility, - TimGenerationHelper _timGenerationHelper, IdenticalPointsExceptionHandler identicalPointsExceptionHandler) { - super(_basicConfiguration, _wydotTimService, _timTypeService, _setItisCodes, _activeTimService, - _restTemplateProvider, _milepostReduction, _utility, _timGenerationHelper, identicalPointsExceptionHandler); - } - - @RequestMapping(value = "/incident-tim", method = RequestMethod.POST, headers = "Accept=application/json") - public ResponseEntity createIncidentTim(@RequestBody TimIncidentList timIncidentList) { - - DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - Date date = new Date(); - - utility.logWithDate(dateFormat.format(date) + " - Create Incident TIM", this.getClass()); - String post = gson.toJson(timIncidentList); - utility.logWithDate(post.toString(), this.getClass()); + @Autowired + public WydotTimIncidentController(BasicConfiguration _basicConfiguration, WydotTimService _wydotTimService, TimTypeService _timTypeService, + SetItisCodes _setItisCodes, ActiveTimService _activeTimService, RestTemplateProvider _restTemplateProvider, + MilepostReduction _milepostReduction, Utility _utility, TimGenerationHelper _timGenerationHelper, IdenticalPointsExceptionHandler identicalPointsExceptionHandler) { + super(_basicConfiguration, _wydotTimService, _timTypeService, _setItisCodes, _activeTimService, _restTemplateProvider, _milepostReduction, + _utility, _timGenerationHelper, identicalPointsExceptionHandler); + } - List timsToSend = new ArrayList(); + @RequestMapping(value = "/incident-tim", method = RequestMethod.POST, headers = "Accept=application/json") + public ResponseEntity createIncidentTim(@RequestBody TimIncidentList timIncidentList) { + log.info("Create Incident TIM"); + String post = gson.toJson(timIncidentList); + log.info(post); - List resultList = new ArrayList(); - ControllerResult resultTim = null; + List timsToSend = new ArrayList<>(); - // build TIM - for (WydotTimIncident wydotTim : timIncidentList.getTimIncidentList()) { + List resultList = new ArrayList<>(); + ControllerResult resultTim; - resultTim = validateInputIncident(wydotTim); + // build TIM + for (WydotTimIncident wydotTim : timIncidentList.getTimIncidentList()) { - if (resultTim.getResultMessages().size() > 0) { - resultList.add(resultTim); - continue; - } + resultTim = validateInputIncident(wydotTim); - // make tims - timsToSend.add(wydotTim); + if (!resultTim.getResultMessages().isEmpty()) { + resultList.add(resultTim); + continue; + } - resultTim.getResultMessages().add("success"); - resultList.add(resultTim); - } + // make tims + timsToSend.add(wydotTim); - makeTimsAsync(timsToSend); - - String responseMessage = gson.toJson(resultList); - return ResponseEntity.status(HttpStatus.OK).body(responseMessage); + resultTim.getResultMessages().add("success"); + resultList.add(resultTim); } - @RequestMapping(value = "/incident-tim", method = RequestMethod.PUT, headers = "Accept=application/json") - public ResponseEntity updateIncidentTim(@RequestBody TimIncidentList timIncidentList) { - - DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - Date date = new Date(); - - utility.logWithDate(dateFormat.format(date) + " - Update Incident TIM", this.getClass()); - String post = gson.toJson(timIncidentList); - utility.logWithDate(post.toString(), this.getClass()); - - List resultList = new ArrayList(); - ControllerResult resultTim = null; - List timsToSend = new ArrayList(); - - // delete TIMs - for (WydotTimIncident wydotTim : timIncidentList.getTimIncidentList()) { - - resultTim = validateInputIncident(wydotTim); - - if (resultTim.getResultMessages().size() > 0) { - resultList.add(resultTim); - continue; - } - - // make tims - timsToSend.add(wydotTim); - - resultTim.getResultMessages().add("success"); - resultList.add(resultTim); - } - if (timsToSend.size() > 0) { - // make tims, expire existing ones, and send them - makeTimsAsync(timsToSend); - } - - String responseMessage = gson.toJson(resultList); - return ResponseEntity.status(HttpStatus.OK).body(responseMessage); + makeTimsAsync(timsToSend); + + String responseMessage = gson.toJson(resultList); + return ResponseEntity.status(HttpStatus.OK).body(responseMessage); + } + + @RequestMapping(value = "/incident-tim", method = RequestMethod.PUT, headers = "Accept=application/json") + public ResponseEntity updateIncidentTim(@RequestBody TimIncidentList timIncidentList) { + log.info("Update Incident TIM"); + String post = gson.toJson(timIncidentList); + log.info(post); + + List resultList = new ArrayList<>(); + ControllerResult resultTim; + List timsToSend = new ArrayList<>(); + + // delete TIMs + for (WydotTimIncident wydotTim : timIncidentList.getTimIncidentList()) { + resultTim = validateInputIncident(wydotTim); + if (!resultTim.getResultMessages().isEmpty()) { + resultList.add(resultTim); + continue; + } + // make tims + timsToSend.add(wydotTim); + resultTim.getResultMessages().add("success"); + resultList.add(resultTim); } - public void makeTimsAsync(List wydotTims) { - - new Thread(new Runnable() { - public void run() { - var startTime = getStartTime(); - for (WydotTimIncident wydotTim : wydotTims) { - // set route - wydotTim.setRoute(wydotTim.getHighway()); - processRequest(wydotTim, getTimType(type), startTime, null, wydotTim.getPk(), ContentEnum.advisory, - TravelerInfoType.advisory); - } - } - }).start(); - } - - @RequestMapping(value = "/incident-tim/{incidentId}", method = RequestMethod.DELETE, headers = "Accept=application/json") - public ResponseEntity deleteIncidentTim(@PathVariable String incidentId) { - - DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - Date date = new Date(); - - utility.logWithDate(dateFormat.format(date) + " - Delete Incident TIM", this.getClass()); - - // expire and clear TIM - wydotTimService.clearTimsById("I", incidentId, null); - - String responseMessage = "success"; - return ResponseEntity.status(HttpStatus.OK).body(responseMessage); - } - - @RequestMapping(value = "/incident-tim", method = RequestMethod.GET, headers = "Accept=application/json") - public Collection getIncidentTims() { - - // get active TIMs - List activeTims = wydotTimService.selectTimsByType("I"); - - return activeTims; - } - - @RequestMapping(value = "/incident-tim/{incidentId}", method = RequestMethod.GET, headers = "Accept=application/json") - public Collection getIncidentTimById(@PathVariable String incidentId) { - - // get active TIMs - List activeTims = wydotTimService.selectTimByClientId("I", incidentId); - return activeTims; + if (!timsToSend.isEmpty()) { + // make tims, expire existing ones, and send them + makeTimsAsync(timsToSend); } + String responseMessage = gson.toJson(resultList); + return ResponseEntity.status(HttpStatus.OK).body(responseMessage); + } + + public void makeTimsAsync(List wydotTims) { + new Thread(() -> { + var startTime = getStartTime(); + for (WydotTimIncident wydotTim : wydotTims) { + // set route + wydotTim.setRoute(wydotTim.getHighway()); + processRequest(wydotTim, getTimType(type), startTime, null, wydotTim.getPk(), ContentEnum.advisory, TravelerInfoType.advisory); + } + }).start(); + } + + @RequestMapping(value = "/incident-tim/{incidentId}", method = RequestMethod.DELETE, headers = "Accept=application/json") + public ResponseEntity deleteIncidentTim(@PathVariable String incidentId) { + log.info("Delete Incident TIM"); + + // expire and clear TIM + wydotTimService.clearTimsById("I", incidentId, null); + String responseMessage = "success"; + return ResponseEntity.status(HttpStatus.OK).body(responseMessage); + } + + @RequestMapping(value = "/incident-tim", method = RequestMethod.GET, headers = "Accept=application/json") + public Collection getIncidentTims() { + // get active TIMs + return wydotTimService.selectTimsByType("I"); + } + + @RequestMapping(value = "/incident-tim/{incidentId}", method = RequestMethod.GET, headers = "Accept=application/json") + public Collection getIncidentTimById(@PathVariable String incidentId) { + // get active TIMs + return wydotTimService.selectTimByClientId("I", incidentId); + } } diff --git a/ode-wrapper/src/main/java/com/trihydro/odewrapper/helpers/SetItisCodes.java b/ode-wrapper/src/main/java/com/trihydro/odewrapper/helpers/SetItisCodes.java index 54b0dca72..062daa1a3 100644 --- a/ode-wrapper/src/main/java/com/trihydro/odewrapper/helpers/SetItisCodes.java +++ b/ode-wrapper/src/main/java/com/trihydro/odewrapper/helpers/SetItisCodes.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; -import com.trihydro.library.helpers.Utility; import com.trihydro.library.model.CustomItisEnum; import com.trihydro.library.model.IncidentChoice; import com.trihydro.library.model.ItisCode; @@ -16,352 +15,351 @@ import com.trihydro.odewrapper.model.WydotTimRc; import com.trihydro.odewrapper.model.WydotTimVsl; -import org.apache.commons.lang3.StringUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component +@Slf4j public class SetItisCodes { - private List incidentProblems; - private List incidentEffects; - private List incidentActions; - private IncidentChoicesService incidentChoicesService; - private ItisCodeService itisCodeService; - private Utility utility; - - private List itisCodes; - - @Autowired - public void InjectDependencies(ItisCodeService _itisCodeService, IncidentChoicesService _incidentChoicesService, - Utility _utility) { - itisCodeService = _itisCodeService; - incidentChoicesService = _incidentChoicesService; - utility = _utility; + private final IncidentChoicesService incidentChoicesService; + private final ItisCodeService itisCodeService; + + private List incidentProblems; + private List incidentEffects; + private List incidentActions; + + private List itisCodes; + + @Autowired + public SetItisCodes(ItisCodeService _itisCodeService, IncidentChoicesService _incidentChoicesService) { + itisCodeService = _itisCodeService; + incidentChoicesService = _incidentChoicesService; + } + + public List getItisCodes() { + if (itisCodes != null) { + return itisCodes; + } else { + itisCodes = itisCodeService.selectAll(); + return itisCodes; } + } - public List getItisCodes() { - if (itisCodes != null) - return itisCodes; - else { - itisCodes = itisCodeService.selectAll(); - return itisCodes; - } - } - - public List setItisCodesFromAdvisoryArray(WydotTimRc wydotTim) { + public List setItisCodesFromAdvisoryArray(WydotTimRc wydotTim) { - // check to see if code exists + // check to see if code exists - List items = new ArrayList(); - for (Integer item : wydotTim.getAdvisory()) { + List items = new ArrayList<>(); + for (Integer item : wydotTim.getAdvisory()) { - ItisCode code = getItisCodes().stream().filter(x -> x.getItisCode().equals(item)).findFirst().orElse(null); + getItisCodes().stream().filter(x -> x.getItisCode().equals(item)).findFirst().ifPresent(code -> items.add(item.toString())); - if (code != null) - items.add(item.toString()); - } - return items; } + return items; + } - public List setItisCodesRc(WydotTimRc wydotTim) { - - List items = new ArrayList(); - - if (wydotTim.getAdvisory() == null) { - return items; - } - - ItisCode code = null; - - for (Integer item : wydotTim.getAdvisory()) { + public List setItisCodesRc(WydotTimRc wydotTim) { - var alphaItis = getCustomAlphabetic(item); - if (alphaItis != null) { - items.add(alphaItis); - continue; - } - // map "closed" itis code - if (item == 769) { - code = getItisCodes().stream().filter(x -> x.getItisCode().equals(770)).findFirst().orElse(null); - } else { - code = getItisCodes().stream().filter(x -> x.getItisCode().equals(item)).findFirst().orElse(null); - } + List items = new ArrayList<>(); - if (code != null) - items.add(code.getItisCode().toString()); - } - - return items; + if (wydotTim.getAdvisory() == null) { + return items; } - public String getCustomAlphabetic(Integer itisCode) { - String text = null; - var en = CustomItisEnum.valueOf(itisCode); - if (en != null) { - text = en.getStringValue(); - } - return text; + ItisCode code; + + for (Integer item : wydotTim.getAdvisory()) { + + var alphaItis = getCustomAlphabetic(item); + if (alphaItis != null) { + items.add(alphaItis); + continue; + } + // map "closed" itis code + if (item == 769) { + code = getItisCodes().stream().filter(x -> x.getItisCode().equals(770)).findFirst().orElse(null); + } else { + code = getItisCodes().stream().filter(x -> x.getItisCode().equals(item)).findFirst().orElse(null); + } + + if (code != null) { + items.add(code.getItisCode().toString()); + } } - public List setItisCodesVsl(WydotTimVsl wydotTim) { + return items; + } - List items = new ArrayList(); - - // speed limit itis code - ItisCode speedLimit = getItisCodes().stream().filter(x -> x.getDescription().equals("speed limit")).findFirst() - .orElse(null); - if (speedLimit != null) { - items.add(speedLimit.getItisCode().toString()); - } - - // number e.g 50, convert to ITIS code - Integer speed = wydotTim.getSpeed() + 12544; - items.add(speed.toString()); - - // mph itis code - ItisCode mph = getItisCodes().stream().filter(x -> x.getDescription().equals("mph")).findFirst().orElse(null); - if (mph != null) { - items.add(mph.getItisCode().toString()); - } - - return items; + public String getCustomAlphabetic(Integer itisCode) { + String text = null; + var en = CustomItisEnum.valueOf(itisCode); + if (en != null) { + text = en.getStringValue(); } + return text; + } - public List setItisCodesParking(WydotTimParking wydotTim) { - - // check to see if code exists - List items = new ArrayList(); - - ItisCode code = getItisCodes().stream().filter(x -> x.getItisCode().equals(wydotTim.getAvailability())) - .findFirst().orElse(null); - - utility.logWithDate("Availablity : " + wydotTim.getAvailability(), this.getClass()); - utility.logWithDate("Exit : " + wydotTim.getExit(), this.getClass()); - - if (code != null) - items.add(wydotTim.getAvailability().toString()); - - // for parking TIM, content=exitService, and includes additional itis codes - // depending on if rest area or exit number - if (wydotTim.getExit() != null) { - // if exit, the exit number should be a text value. - // This has some strange implications as seen here - // https://github.com/usdot-jpo-ode/jpo-ode/blob/540b79f1697f4d6464e8c4b8491666ec9cf08d8d/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java#L337 - // the ODE translates a text value only if we start with a single quote to - // denote this. No ending quote is used - items.add("11794");// Exit Number - if (wydotTim.getExit().toLowerCase().equals("turnout") - || wydotTim.getExit().toLowerCase().equals("parking")) { - items.add("'" + String.valueOf(((int) Math.round(wydotTim.getMileMarker())))); - } else { - items.add("'" + wydotTim.getExit()); - } - } else { - items.add("7986");// Rest Area - utility.logWithDate("rest area", this.getClass()); - } + public List setItisCodesVsl(WydotTimVsl wydotTim) { - return items; - } + List items = new ArrayList<>(); - public List splitExitNumberFromLetter(String exit) { - - List list = new ArrayList(); - String exitNumber = ""; - String exitLetter = ""; - for (int i = 0; i < exit.length(); i++) { - if (StringUtils.isNumeric(String.valueOf(exit.charAt(i)))) { - exitNumber += exit.charAt(i); - } else { - exitLetter += exit.charAt(i); - } - } + // speed limit itis code + getItisCodes().stream().filter(x -> x.getDescription().equals("speed limit")).findFirst() + .ifPresent(speedLimit -> items.add(speedLimit.getItisCode().toString())); - list.add(exitNumber); - if (exitLetter.length() > 0) - list.add(exitLetter); + // number e.g 50, convert to ITIS code + int speed = wydotTim.getSpeed() + 12544; + items.add(Integer.toString(speed)); - return list; - } + // mph itis code + getItisCodes().stream().filter(x -> x.getDescription().equals("mph")).findFirst().ifPresent(mph -> items.add(mph.getItisCode().toString())); - public List setItisCodesFromAvailability(WydotTimParking wydotTim) { + return items; + } - // check to see if code exists - List items = new ArrayList(); + public List setItisCodesParking(WydotTimParking wydotTim) { - utility.logWithDate("availability:" + wydotTim.getAvailability(), this.getClass()); + // check to see if code exists + List items = new ArrayList<>(); - ItisCode code = getItisCodes().stream().filter(x -> x.getItisCode().equals(wydotTim.getAvailability())) - .findFirst().orElse(null); + ItisCode code = getItisCodes().stream().filter(x -> x.getItisCode().equals(wydotTim.getAvailability())).findFirst().orElse(null); - if (code != null) - items.add(wydotTim.getAvailability().toString()); + log.info("Availablity : {}", wydotTim.getAvailability()); + log.info("Exit : {}", wydotTim.getExit()); - if (wydotTim.getExit() != null) { - items.add("11794"); - items.add(wydotTim.getExit()); - } else { - items.add("7986"); - } - - return items; + if (code != null) { + items.add(wydotTim.getAvailability().toString()); } - public List setItisCodesIncident(WydotTimIncident wydotTim) { - List items = new ArrayList(); - - // action - IncidentChoice incidentAction = getIncidentActions().stream() - .filter(x -> x.getCode().equals(wydotTim.getAction())).findFirst().orElse(null); + // for parking TIM, content=exitService, and includes additional itis codes + // depending on if rest area or exit number + if (wydotTim.getExit() != null) { + // if exit, the exit number should be a text value. + // This has some strange implications as seen here + // https://github.com/usdot-jpo-ode/jpo-ode/blob/540b79f1697f4d6464e8c4b8491666ec9cf08d8d/jpo-ode-plugins/src/main/java/us/dot/its/jpo/ode/plugin/j2735/builders/TravelerMessageFromHumanToAsnConverter.java#L337 + // the ODE translates a text value only if we start with a single quote to + // denote this. No ending quote is used + items.add("11794");// Exit Number + if (wydotTim.getExit().equalsIgnoreCase("turnout") || wydotTim.getExit().equalsIgnoreCase("parking")) { + items.add("'" + (int) Math.round(wydotTim.getMileMarker())); + } else { + items.add("'" + wydotTim.getExit()); + } + } else { + items.add("7986");// Rest Area + log.info("rest area"); + } - // if action is not null and action itis code exists - if (incidentAction != null && incidentAction.getItisCodeId() != null) { - ItisCode actionItisCode = getItisCodes().stream() - .filter(x -> x.getItisCodeId().equals(incidentAction.getItisCodeId())).findFirst().orElse(null); - if (actionItisCode != null) { - items.add(actionItisCode.getItisCode().toString()); - } - } + return items; + } - // effect - IncidentChoice incidentEffect = getIncidentEffects().stream() - .filter(x -> x.getCode().equals(wydotTim.getEffect())).findFirst().orElse(null); - - // if effect is not null and effect itis code exists - if (incidentEffect != null && incidentEffect.getItisCodeId() != null) { - ItisCode effectItisCode = getItisCodes().stream() - .filter(x -> x.getItisCodeId().equals(incidentEffect.getItisCodeId())).findFirst().orElse(null); - if (effectItisCode != null) { - items.add(effectItisCode.getItisCode().toString()); - } - } + public List setItisCodesIncident(WydotTimIncident wydotTim) { + List items = new ArrayList<>(); - // problem - IncidentChoice incidentProblem = getIncidentProblems().stream() - .filter(x -> x.getCode().equals(wydotTim.getProblem())).findFirst().orElse(null); - - // if problem is not null and problem itis code exists - if (incidentProblem != null && incidentProblem.getItisCodeId() != null) { - ItisCode problemItisCode = getItisCodes().stream() - .filter(x -> x.getItisCodeId().equals(incidentProblem.getItisCodeId())).findFirst().orElse(null); - if (problemItisCode != null) { - items.add(problemItisCode.getItisCode().toString()); - } - } + // action + IncidentChoice incidentAction = getIncidentActions().stream().filter(x -> x.getCode().equals(wydotTim.getAction())).findFirst().orElse(null); - if (items.size() == 0) - items.add("531");// 531 is "Incident" - - return items; + // if action is not null and action itis code exists + if (incidentAction != null && incidentAction.getItisCodeId() != null) { + getItisCodes().stream().filter(x -> x.getItisCodeId().equals(incidentAction.getItisCodeId())).findFirst() + .ifPresent(actionItisCode -> items.add(actionItisCode.getItisCode().toString())); } - public List getIncidentProblems() { - if (incidentProblems != null) - return incidentProblems; - else { - incidentProblems = incidentChoicesService.selectAllIncidentProblems(); - return incidentProblems; - } - } + // effect + IncidentChoice incidentEffect = getIncidentEffects().stream().filter(x -> x.getCode().equals(wydotTim.getEffect())).findFirst().orElse(null); - public List getIncidentEffects() { - if (incidentEffects != null) - return incidentEffects; - else { - incidentEffects = incidentChoicesService.selectAllIncidentEffects(); - return incidentEffects; - } + // if effect is not null and effect itis code exists + if (incidentEffect != null && incidentEffect.getItisCodeId() != null) { + getItisCodes().stream().filter(x -> x.getItisCodeId().equals(incidentEffect.getItisCodeId())).findFirst() + .ifPresent(effectItisCode -> items.add(effectItisCode.getItisCode().toString())); } - public List getIncidentActions() { - if (incidentActions != null) - return incidentActions; - else { - incidentActions = incidentChoicesService.selectAllIncidentActions(); - return incidentActions; + if (wydotTim.getProblem() != null && !wydotTim.getProblem().equals("other")) { + // Retrieve the matching incident problem based on the provided code + IncidentChoice incidentProblem = + getIncidentProblems().stream().filter(problem -> problem.getCode().equals(wydotTim.getProblem())).findFirst().orElse(null); + + // Add the ITIS code if the incident problem exists and has a valid ITIS code ID + if (incidentProblem != null) { + Integer itisCodeId = incidentProblem.getItisCodeId(); + if (itisCodeId != null) { + getItisCodes().stream().filter(code -> code.getItisCodeId().equals(itisCodeId)).findFirst() + .ifPresent(problemItisCode -> items.add(problemItisCode.getItisCode().toString())); } + } + } else { + items.addAll(handleOtherIncidentProblem(wydotTim)); } - public List setItisCodesRw(WydotTim wydotTim) { - - List items = new ArrayList(); + // If no incident problem is provided, default to "Incident" (ITIS code 531) + if (items.isEmpty()) { + items.add("531"); // 531 is "Incident" + } - items.add("1025"); + return items; + } - return items; + private List handleOtherIncidentProblem(WydotTimIncident wydotTim) { + List items = new ArrayList<>(); + if (wydotTim.getProblemOtherText() == null) { + log.warn("problemOtherText is null for 'other' incident problem"); + return items; } + String problemOtherText = wydotTim.getProblemOtherText(); - public List setItisCodesBowr(WydotTimBowr tim) throws WeightNotSupportedException { - List itisCodes = new ArrayList(); - - int weightInPounds = tim.getData(); + if (!problemOtherText.contains("GVW")) { + log.error("Unsupported problemOtherText: {}", problemOtherText); + return items; + } - itisCodes.add("5127"); // Strong winds - itisCodes.add("2563"); // Truck restriction - itisCodes.add("2569"); // No high profile vehicles - itisCodes.add("7682"); // Below - itisCodes.add("2577"); // Gross-Weight-Limit - itisCodes.add(translateWeightToItisCode(weightInPounds)); // Weight, translated from pounds to ITIS code - itisCodes.add("8739"); // Pounds + // Extract the weight limit from the problemOtherText + String weightLimitInPounds = getWeightLimitFromProblemOtherText(problemOtherText); + if (weightLimitInPounds == null) { + log.warn("Weight limit not found in problemOtherText: {}", problemOtherText); + return items; + } - return itisCodes; + String weightLimitInItisCode = null; + try { + // Convert weight limit to ITIS code + weightLimitInItisCode = translateWeightToItisCode(Integer.parseInt(weightLimitInPounds)); + } catch (WeightNotSupportedException e) { + log.warn("Weight limit not supported: {}", weightLimitInPounds); + return items; } - /** - * This method translates the weight in pounds to its corresponding ITIS code. - * These are large number ITIS codes and do not abide by the standard translations used for other numbers such as mph. - * Supported weights are 20000 to 30000 in increments of 1000 and 30000 to 70000 in increments of 5000 - * @throws WeightNotSupportedException - */ - private String translateWeightToItisCode(int weightInPounds) throws WeightNotSupportedException { - switch(weightInPounds) { - case 20000: - return "11589"; - case 21000: - return "11590"; - case 22000: - return "11591"; - case 23000: - return "11592"; - case 24000: - return "11593"; - case 25000: - return "11594"; - case 26000: - return "11595"; - case 27000: - return "11596"; - case 28000: - return "11597"; - case 29000: - return "11598"; - case 30000: - return "11599"; - case 35000: - return "11600"; - case 40000: - return "11601"; - case 45000: - return "11602"; - case 50000: - return "11603"; - case 55000: - return "11604"; - case 60000: - return "11605"; - case 65000: - return "11606"; - case 70000: - return "11607"; - default: - throw new WeightNotSupportedException("Weight " + weightInPounds + " is not supported"); - } + items.add("2563"); // Truck restriction + items.add("2577"); // Gross-Weight-Limit + items.add(weightLimitInItisCode); // Weight limit in ITIS code + items.add("8739"); // Pounds + + return items; + } + + /** + * Given a problemOtherText string of the format "Weight limit of 60,000 GVW is in effect", + * return the weight limit (60000) in pounds as a string. + */ + private String getWeightLimitFromProblemOtherText(String problemOtherText) { + problemOtherText = problemOtherText.replaceAll(",", ""); + String[] parts = problemOtherText.split(" "); + for (String part : parts) { + if (part.matches("\\d{1,5}")) { // Match a number with 1 to 5 digits + return part; + } } - - public class WeightNotSupportedException extends Exception { - public WeightNotSupportedException(String message) { - super(message); - } + return null; // Return null if no weight limit found + } + + public List getIncidentProblems() { + if (incidentProblems != null) { + return incidentProblems; + } else { + incidentProblems = incidentChoicesService.selectAllIncidentProblems(); + return incidentProblems; + } + } + + public List getIncidentEffects() { + if (incidentEffects != null) { + return incidentEffects; + } else { + incidentEffects = incidentChoicesService.selectAllIncidentEffects(); + return incidentEffects; + } + } + + public List getIncidentActions() { + if (incidentActions != null) { + return incidentActions; + } else { + incidentActions = incidentChoicesService.selectAllIncidentActions(); + return incidentActions; + } + } + + public List setItisCodesRw(WydotTim wydotTim) { + + List items = new ArrayList(); + + items.add("1025"); + + return items; + } + + public List setItisCodesBowr(WydotTimBowr tim) throws WeightNotSupportedException { + List itisCodes = new ArrayList<>(); + + int weightInPounds = tim.getData(); + + itisCodes.add("5127"); // Strong winds + itisCodes.add("2563"); // Truck restriction + itisCodes.add("2569"); // No high profile vehicles + itisCodes.add("7682"); // Below + itisCodes.add("2577"); // Gross-Weight-Limit + itisCodes.add(translateWeightToItisCode(weightInPounds)); // Weight, translated from pounds to ITIS code + itisCodes.add("8739"); // Pounds + + return itisCodes; + } + + /** + * This method translates the weight in pounds to its corresponding ITIS code. + * These are large number ITIS codes and do not abide by the standard translations used for other numbers such as mph. + * Supported weights are 20000 to 30000 in increments of 1000 and 30000 to 70000 in increments of 5000 + * + * @throws WeightNotSupportedException if the weight is not supported + */ + private String translateWeightToItisCode(int weightInPounds) throws WeightNotSupportedException { + switch (weightInPounds) { + case 20000: + return "11589"; + case 21000: + return "11590"; + case 22000: + return "11591"; + case 23000: + return "11592"; + case 24000: + return "11593"; + case 25000: + return "11594"; + case 26000: + return "11595"; + case 27000: + return "11596"; + case 28000: + return "11597"; + case 29000: + return "11598"; + case 30000: + return "11599"; + case 35000: + return "11600"; + case 40000: + return "11601"; + case 45000: + return "11602"; + case 50000: + return "11603"; + case 55000: + return "11604"; + case 60000: + return "11605"; + case 65000: + return "11606"; + case 70000: + return "11607"; + default: + throw new WeightNotSupportedException("Weight " + weightInPounds + " is not supported"); + } + } + + public static class WeightNotSupportedException extends Exception { + public WeightNotSupportedException(String message) { + super(message); } + } } \ No newline at end of file diff --git a/ode-wrapper/src/main/java/com/trihydro/odewrapper/model/WydotTimIncident.java b/ode-wrapper/src/main/java/com/trihydro/odewrapper/model/WydotTimIncident.java index a4e3867d9..a6492f68c 100644 --- a/ode-wrapper/src/main/java/com/trihydro/odewrapper/model/WydotTimIncident.java +++ b/ode-wrapper/src/main/java/com/trihydro/odewrapper/model/WydotTimIncident.java @@ -10,99 +10,114 @@ public class WydotTimIncident extends WydotTim { - @ApiModelProperty(value = "Expected values are mudslide, livestock, avalanche, avalancheControl, landslide, wildfire, signInstall, mowing") - private String problem; - private String effect; - - @ApiModelProperty(value = "Expected values are caution, delays, stop") - private String action; - @ApiModelProperty(required = true) - private String incidentId; - @ApiModelProperty(required = true) - private String highway; - - private Integer pk; - @ApiModelProperty(hidden = true) - private transient String clientId; - @ApiModelProperty(hidden = true) - private transient String route; - @ApiModelProperty(hidden = true) - private transient List itisCodes; - - @ApiModelProperty(value = "Optional. If not provided, a TIM will be generated extending 1 mile upstream from the startPoint", required = false) - private transient Coordinate endPoint; - - public WydotTimIncident() { - + @ApiModelProperty(value = "Expected values are mudslide, livestock, avalanche, avalancheControl, landslide, wildfire, signInstall, mowing") + private String problem; + private String effect; + + @ApiModelProperty(value = "Expected values are caution, delays, stop") + private String action; + @ApiModelProperty(required = true) + private String incidentId; + @ApiModelProperty(required = true) + private String highway; + + private Integer pk; + @ApiModelProperty(hidden = true) + private transient String clientId; + @ApiModelProperty(hidden = true) + private transient String route; + @ApiModelProperty(hidden = true) + private transient List itisCodes; + + @ApiModelProperty(value = "Optional. If not provided, a TIM will be generated extending 1 mile upstream from the startPoint", required = false) + private transient Coordinate endPoint; + + @ApiModelProperty() + private transient String problemOtherText; + + public WydotTimIncident() { + + } + + public WydotTimIncident(WydotTimIncident o) { + super(o); + this.problem = o.problem; + this.effect = o.effect; + this.action = o.action; + this.incidentId = o.incidentId; + this.highway = o.highway; + this.pk = o.pk; + this.clientId = o.clientId; + this.route = o.route; + + if (o.itisCodes != null) { + this.itisCodes = new ArrayList<>(o.itisCodes); } - - public WydotTimIncident(WydotTimIncident o) { - super(o); - this.problem = o.problem; - this.effect = o.effect; - this.action = o.action; - this.incidentId = o.incidentId; - this.highway = o.highway; - this.pk = o.pk; - this.clientId = o.clientId; - this.route = o.route; - - if (o.itisCodes != null) - this.itisCodes = new ArrayList<>(o.itisCodes); - if (o.endPoint != null) - this.endPoint = new Coordinate(o.endPoint.getLatitude(), o.endPoint.getLongitude()); + if (o.endPoint != null) { + this.endPoint = new Coordinate(o.endPoint.getLatitude(), o.endPoint.getLongitude()); } - @Override - public WydotTimIncident copy() { - return new WydotTimIncident(this); - } + this.problemOtherText = o.problemOtherText; + } - public Integer getPk() { - return this.pk; - } + @Override + public WydotTimIncident copy() { + return new WydotTimIncident(this); + } - public void setPk(Integer pk) { - this.pk = pk; - } + public Integer getPk() { + return this.pk; + } - public String getHighway() { - return this.highway; - } + public void setPk(Integer pk) { + this.pk = pk; + } - public void setHighway(String highway) { - this.highway = highway; - } + public String getHighway() { + return this.highway; + } - public String getIncidentId() { - return this.incidentId; - } + public void setHighway(String highway) { + this.highway = highway; + } - public void setIncidentId(String incidentId) { - this.incidentId = incidentId; - } + public String getIncidentId() { + return this.incidentId; + } - public String getProblem() { - return this.problem; - } + public void setIncidentId(String incidentId) { + this.incidentId = incidentId; + } - public void setProblem(String problem) { - this.problem = problem; - } + public String getProblem() { + return this.problem; + } - public String getEffect() { - return this.effect; - } + public void setProblem(String problem) { + this.problem = problem; + } - public void setEffect(String effect) { - this.effect = effect; - } + public String getEffect() { + return this.effect; + } - public String getAction() { - return this.action; - } + public void setEffect(String effect) { + this.effect = effect; + } - public void setAction(String action) { - this.action = action; - } + public String getAction() { + return this.action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getProblemOtherText() { + return this.problemOtherText; + } + + public void setProblemOtherText(String problemOtherText) { + this.problemOtherText = problemOtherText; + } } \ No newline at end of file diff --git a/ode-wrapper/src/test/java/com/trihydro/odewrapper/helpers/SetItisCodesTest.java b/ode-wrapper/src/test/java/com/trihydro/odewrapper/helpers/SetItisCodesTest.java index f8fffa1f4..abbafcb6a 100644 --- a/ode-wrapper/src/test/java/com/trihydro/odewrapper/helpers/SetItisCodesTest.java +++ b/ode-wrapper/src/test/java/com/trihydro/odewrapper/helpers/SetItisCodesTest.java @@ -1,7 +1,10 @@ package com.trihydro.odewrapper.helpers; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; +import com.trihydro.library.model.IncidentChoice; +import com.trihydro.odewrapper.model.WydotTimIncident; import java.util.ArrayList; import java.util.List; @@ -23,135 +26,256 @@ @ExtendWith(MockitoExtension.class) public class SetItisCodesTest { - @Mock - ItisCodeService mockItisCodeService; - @Mock - IncidentChoicesService mockIncidentChoicesService; - - @InjectMocks - SetItisCodes uut; - - public void setup() { - List itisCodes = new ArrayList<>(); - ItisCode code = new ItisCode(); - code.setItisCode(268);// speed limit - itisCodes.add(code); - - code = new ItisCode(); - code.setItisCode(770);// closed - itisCodes.add(code); - - code = new ItisCode(); - code.setItisCode(1309);// rockfall - itisCodes.add(code); - - code = new ItisCode(); - code.setItisCode(3084);// wildfire - itisCodes.add(code); - - code = new ItisCode(); - code.setItisCode(4868); // snow - itisCodes.add(code); - - code = new ItisCode(); - code.setItisCode(770); // closed - itisCodes.add(code); - - doReturn(itisCodes).when(mockItisCodeService).selectAll(); - } - - @Test - public void setItisCodesRc_numeric() { - // Arrange - setup(); - WydotTimRc tim = new WydotTimRc(); - Integer[] itisCodes = new Integer[2]; - itisCodes[0] = 4868; - itisCodes[1] = 1309; - tim.setAdvisory(itisCodes); - // Act - var result = uut.setItisCodesRc(tim); - - // Assert - Assertions.assertEquals(2, result.size()); - } - - @Test - public void setItisCodesRc_nonExistent() { - // Arrange - setup(); - WydotTimRc tim = new WydotTimRc(); - Integer[] itisCodes = new Integer[2]; - itisCodes[0] = 0; - itisCodes[1] = 13; - tim.setAdvisory(itisCodes); - // Act - var result = uut.setItisCodesRc(tim); - - // Assert - Assertions.assertEquals(0, result.size()); - } - - @Test - public void setItisCodesRc_translated() { - // Arrange - setup(); - WydotTimRc tim = new WydotTimRc(); - Integer[] itisCodes = new Integer[2]; - itisCodes[0] = 4868; - itisCodes[1] = 769; - tim.setAdvisory(itisCodes); - // Act - var result = uut.setItisCodesRc(tim); - - // Assert - Assertions.assertEquals(2, result.size()); - Assertions.assertTrue(result.contains("770")); - } - - @Test - public void setItisCodesRc_alphabetic() { - // Arrange - setup(); - WydotTimRc tim = new WydotTimRc(); - Integer[] itisCodes = new Integer[2]; - itisCodes[0] = 4868; - itisCodes[1] = CustomItisEnum.blowOver.getValue(); - tim.setAdvisory(itisCodes); - // Act - var result = uut.setItisCodesRc(tim); - - // Assert - Assertions.assertEquals(2, result.size()); - Assertions.assertTrue(result.contains("Extreme blow over risk")); - } - - @Test - public void setItisCodesBowr_SUCCESS() throws WeightNotSupportedException { - // Arrange - // calling setup() not necessary here - int weightInPounds = 20000; - String weightAsItisCode = "11589"; - WydotTimBowr tim = new WydotTimBowr(); - tim.setData(weightInPounds); - List expectedResult = List.of("5127", "2563", "2569", "7682", "2577", weightAsItisCode, "8739"); - - // Act - List result = uut.setItisCodesBowr(tim); - - // Assert - Assertions.assertEquals(expectedResult, result); - } - - @Test - public void setItisCodesBowr_FAILURE() throws WeightNotSupportedException { - // Arrange - // calling setup() not necessary here - int weightInPounds = 23456; - WydotTimBowr tim = new WydotTimBowr(); - tim.setData(weightInPounds); - - // Act & Assert - Assertions.assertThrows(WeightNotSupportedException.class, () -> uut.setItisCodesBowr(tim)); - } + @Mock + ItisCodeService mockItisCodeService; + @Mock + IncidentChoicesService mockIncidentChoicesService; + + @InjectMocks + SetItisCodes uut; + + public void setup() { + List itisCodes = new ArrayList<>(); + ItisCode code = new ItisCode(); + code.setItisCode(268);// speed limit + itisCodes.add(code); + + code = new ItisCode(); + code.setItisCode(770);// closed + itisCodes.add(code); + + code = new ItisCode(); + code.setItisCode(1309);// rockfall + itisCodes.add(code); + + code = new ItisCode(); + code.setItisCode(3084);// wildfire + itisCodes.add(code); + + code = new ItisCode(); + code.setItisCode(4868); // snow + itisCodes.add(code); + + code = new ItisCode(); + code.setItisCode(770); // closed + itisCodes.add(code); + + doReturn(itisCodes).when(mockItisCodeService).selectAll(); + } + + @Test + public void setItisCodesRc_numeric() { + // Arrange + setup(); + WydotTimRc tim = new WydotTimRc(); + Integer[] itisCodes = new Integer[2]; + itisCodes[0] = 4868; + itisCodes[1] = 1309; + tim.setAdvisory(itisCodes); + // Act + var result = uut.setItisCodesRc(tim); + + // Assert + Assertions.assertEquals(2, result.size()); + } + + @Test + public void setItisCodesRc_nonExistent() { + // Arrange + setup(); + WydotTimRc tim = new WydotTimRc(); + Integer[] itisCodes = new Integer[2]; + itisCodes[0] = 0; + itisCodes[1] = 13; + tim.setAdvisory(itisCodes); + // Act + var result = uut.setItisCodesRc(tim); + + // Assert + Assertions.assertEquals(0, result.size()); + } + + @Test + public void setItisCodesRc_translated() { + // Arrange + setup(); + WydotTimRc tim = new WydotTimRc(); + Integer[] itisCodes = new Integer[2]; + itisCodes[0] = 4868; + itisCodes[1] = 769; + tim.setAdvisory(itisCodes); + // Act + var result = uut.setItisCodesRc(tim); + + // Assert + Assertions.assertEquals(2, result.size()); + Assertions.assertTrue(result.contains("770")); + } + + @Test + public void setItisCodesRc_alphabetic() { + // Arrange + setup(); + WydotTimRc tim = new WydotTimRc(); + Integer[] itisCodes = new Integer[2]; + itisCodes[0] = 4868; + itisCodes[1] = CustomItisEnum.blowOver.getValue(); + tim.setAdvisory(itisCodes); + // Act + var result = uut.setItisCodesRc(tim); + + // Assert + Assertions.assertEquals(2, result.size()); + Assertions.assertTrue(result.contains("Extreme blow over risk")); + } + + @Test + public void setItisCodesBowr_SUCCESS() throws WeightNotSupportedException { + // Arrange + // calling setup() not necessary here + int weightInPounds = 20000; + String weightAsItisCode = "11589"; + WydotTimBowr tim = new WydotTimBowr(); + tim.setData(weightInPounds); + List expectedResult = List.of("5127", "2563", "2569", "7682", "2577", weightAsItisCode, "8739"); + + // Act + List result = uut.setItisCodesBowr(tim); + + // Assert + Assertions.assertEquals(expectedResult, result); + } + + @Test + public void setItisCodesBowr_FAILURE() { + // Arrange + // calling setup() not necessary here + int weightInPounds = 23456; + WydotTimBowr tim = new WydotTimBowr(); + tim.setData(weightInPounds); + + // Act & Assert + Assertions.assertThrows(WeightNotSupportedException.class, () -> uut.setItisCodesBowr(tim)); + } + + @Test + public void testSetItisCodesIncident_ReturnsDefaultIncidentCode() { + // Arrange + WydotTimIncident mockIncident = new WydotTimIncident(); // Mock incident object + List expectedCodes = List.of("531"); // Expected default incident code + + // Act + List result = uut.setItisCodesIncident(mockIncident); + + // Assert + Assertions.assertNotNull(result, "Resulting list should not be null."); + Assertions.assertEquals(expectedCodes, result, "Default incident code should be returned."); + } + + @Test + public void testSetItisCodesIncident_WithExistingProblemItisCode_ShouldReturnExistingItisCode() { + // Arrange + WydotTimIncident incident = new WydotTimIncident(); + incident.setProblem("268"); + List expectedItisCodes = List.of("268"); + + IncidentChoice mockIncidentChoice = new IncidentChoice(); + mockIncidentChoice.setCode("268"); + mockIncidentChoice.setItisCodeId(1); + mockIncidentChoice.setDescription("Speed Limit"); + when(mockIncidentChoicesService.selectAllIncidentProblems()).thenReturn(List.of(mockIncidentChoice)); + + ItisCode mockItisCode = new ItisCode(); + mockItisCode.setItisCode(268); + mockItisCode.setItisCodeId(1); + when(mockItisCodeService.selectAll()).thenReturn(List.of(mockItisCode)); + + // Act + List actualItisCodes = uut.setItisCodesIncident(incident); + + // Assert + Assertions.assertNotNull(actualItisCodes, "Resulting list should not be null."); + Assertions.assertEquals(expectedItisCodes, actualItisCodes, "The ITIS code for the incident problem should be returned."); + } + + @Test + public void testSetItisCodesIncident_OtherProblemGVW_ShouldReturnGVWItisCodes() { + // Arrange + WydotTimIncident incident = new WydotTimIncident(); + incident.setProblem("other"); + incident.setProblemOtherText("Weight limit of 60,000 GVW is in effect"); + List expectedItisCodes = List.of("2563", "2577", "11605", "8739"); + + // Act + List actualItisCodes = uut.setItisCodesIncident(incident); + + // Assert + Assertions.assertNotNull(actualItisCodes, "Resulting list should not be null."); + Assertions.assertEquals(expectedItisCodes, actualItisCodes, "The ITIS codes for a Gross Vehicle Weight restriction (60000 pounds) should be returned."); + } + + @Test + public void testSetItisCodesIncident_OtherProblemNoGVW_ShouldReturnDefaultIncidentCode() { + // Arrange + WydotTimIncident incident = new WydotTimIncident(); + incident.setProblem("other"); + incident.setProblemOtherText("Some other problem"); + List expectedItisCodes = List.of("531"); + + // Act + List actualItisCodes = uut.setItisCodesIncident(incident); + + // Assert + Assertions.assertNotNull(actualItisCodes, "Resulting list should not be null."); + Assertions.assertEquals(expectedItisCodes, actualItisCodes, "The default incident code should be returned."); + } + + @Test + public void testSetItisCodesIncident_OtherProblemNull_ShouldReturnDefaultIncidentCode() { + // Arrange + WydotTimIncident incident = new WydotTimIncident(); + incident.setProblem("other"); + incident.setProblemOtherText(null); + List expectedItisCodes = List.of("531"); + + // Act + List actualItisCodes = uut.setItisCodesIncident(incident); + + // Assert + Assertions.assertNotNull(actualItisCodes, "Resulting list should not be null."); + Assertions.assertEquals(expectedItisCodes, actualItisCodes, "The default incident code should be returned."); + } + + @Test + public void testSetItisCodesIncident_WeightNotFoundInProblemOtherText_ShouldReturnDefaultIncidentCode() { + // Arrange + WydotTimIncident incident = new WydotTimIncident(); + incident.setProblem("other"); + incident.setProblemOtherText("Some GVW weight restriction"); + List expectedItisCodes = List.of("531"); + + // Act + List actualItisCodes = uut.setItisCodesIncident(incident); + + // Assert + Assertions.assertNotNull(actualItisCodes, "Resulting list should not be null."); + Assertions.assertEquals(expectedItisCodes, actualItisCodes, "The default incident code should be returned."); + } + + @Test + public void testSetItisCodesIncident_WeightNotSupported_ShouldReturnDefaultIncidentCode() { + // Arrange + WydotTimIncident incident = new WydotTimIncident(); + incident.setProblem("other"); + incident.setProblemOtherText("Weight limit of 1,000,000 GVW is in effect"); + List expectedItisCodes = List.of("531"); + + // Act + List actualItisCodes = uut.setItisCodesIncident(incident); + + // Assert + Assertions.assertNotNull(actualItisCodes, "Resulting list should not be null."); + Assertions.assertEquals(expectedItisCodes, actualItisCodes, "The default incident code should be returned."); + } + } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0022a177d..d8100f086 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 pom @@ -68,7 +68,7 @@ usdot.jpo.ode jpo-ode-core - 3.0.0 + 4.0.0 * @@ -79,7 +79,7 @@ usdot.jpo.ode jpo-ode-common - 3.0.0 + 4.0.0 * @@ -90,7 +90,7 @@ usdot.jpo.ode jpo-ode-plugins - 3.0.0 + 4.0.0 * @@ -101,7 +101,7 @@ usdot.jpo.ode jpo-ode-svcs - 3.0.0 + 4.0.0 * diff --git a/rsu-data-controller/Dockerfile b/rsu-data-controller/Dockerfile index bcc9a172d..b6dc43322 100644 --- a/rsu-data-controller/Dockerfile +++ b/rsu-data-controller/Dockerfile @@ -10,6 +10,6 @@ RUN apt-get install -y snmp RUN apt-get autoremove -y \ && apt-get clean -y -ADD rsu-data-controller-1.4.0-SNAPSHOT.jar /app/ +ADD rsu-data-controller-2.0.0.jar /app/ -CMD java -jar /app/rsu-data-controller-1.4.0-SNAPSHOT.jar \ No newline at end of file +CMD java -jar /app/rsu-data-controller-2.0.0.jar \ No newline at end of file diff --git a/rsu-data-controller/pom.xml b/rsu-data-controller/pom.xml index 8e23882d3..86478d4d3 100644 --- a/rsu-data-controller/pom.xml +++ b/rsu-data-controller/pom.xml @@ -7,7 +7,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 diff --git a/sample.env b/sample.env index 46450f04c..610c7b264 100644 --- a/sample.env +++ b/sample.env @@ -99,7 +99,9 @@ REFRESH_CONFIG_ODE_URL=http://ode-url:8080 REFRESH_CONFIG_SDW_TTL=oneyear REFRESH_CONFIG_CV_REST_SERVICE=https://ode-url:8888 REFRESH_CONFIG_DEFAULT_LANE_WIDTH=50 -REFRESH_CRON_EXPRESSION=0 0 * * * ? +# Note: If the program runs in a GMT environment, "0 0 1 * * *" will be 1 AM GMT, which corresponds to 7 PM MDT. +# second minute hour day month day-of-week +REFRESH_CRON_EXPRESSION="0 0 1 * * *" REFRESH_CONFIG_ENV=dev REFRESH_CONFIG_RSU_ROUTES=route1, route2 REFRESH_CONFIG_POINT_INCIDENT_BUFFER_MILES=1 diff --git a/tim-refresh/Dockerfile b/tim-refresh/Dockerfile index 4d374067b..d6c4d5564 100644 --- a/tim-refresh/Dockerfile +++ b/tim-refresh/Dockerfile @@ -2,4 +2,4 @@ FROM maven:3.8-eclipse-temurin-21-alpine ADD . /home/timm/timm_applications/tim-refresh -CMD java -jar /home/timm/timm_applications/tim-refresh/tim-refresh-1.4.0-SNAPSHOT.jar +CMD java -jar /home/timm/timm_applications/tim-refresh/tim-refresh-2.0.0.jar diff --git a/tim-refresh/pom.xml b/tim-refresh/pom.xml index a4d52f055..d0525da3b 100644 --- a/tim-refresh/pom.xml +++ b/tim-refresh/pom.xml @@ -6,7 +6,7 @@ com.timm tim-manager - 1.4.0-SNAPSHOT + 2.0.0 diff --git a/tim-refresh/src/main/java/com/trihydro/timrefresh/TimRefreshController.java b/tim-refresh/src/main/java/com/trihydro/timrefresh/TimRefreshController.java index 60d1522fe..bb4109499 100644 --- a/tim-refresh/src/main/java/com/trihydro/timrefresh/TimRefreshController.java +++ b/tim-refresh/src/main/java/com/trihydro/timrefresh/TimRefreshController.java @@ -1,5 +1,6 @@ package com.trihydro.timrefresh; +import com.trihydro.library.model.ActiveTim; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -9,45 +10,49 @@ import com.google.gson.Gson; import com.trihydro.library.helpers.EmailHelper; import com.trihydro.library.helpers.TimGenerationHelper; -import com.trihydro.library.helpers.Utility; import com.trihydro.library.model.Logging_TimUpdateModel; import com.trihydro.library.model.ResubmitTimException; import com.trihydro.library.model.TimUpdateModel; import com.trihydro.library.service.ActiveTimService; import com.trihydro.timrefresh.config.TimRefreshConfiguration; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component +@Slf4j public class TimRefreshController { private final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); public Gson gson = new Gson(); protected TimRefreshConfiguration configuration; - private Utility utility; - private EmailHelper emailHelper; - private ActiveTimService activeTimService; - private TimGenerationHelper timGenerationHelper; + private final EmailHelper emailHelper; + private final ActiveTimService activeTimService; + private final TimGenerationHelper timGenerationHelper; @Autowired - public TimRefreshController(TimRefreshConfiguration configurationRhs, Utility _utility, - ActiveTimService _activeTimService, EmailHelper _emailHelper, TimGenerationHelper _timGenerationHelper) { - configuration = configurationRhs; - utility = _utility; - activeTimService = _activeTimService; - emailHelper = _emailHelper; - timGenerationHelper = _timGenerationHelper; + public TimRefreshController(TimRefreshConfiguration configurationRhs, ActiveTimService activeTimService, EmailHelper emailHelper, + TimGenerationHelper timGenerationHelper) { + this.configuration = configurationRhs; + this.activeTimService = activeTimService; + this.emailHelper = emailHelper; + this.timGenerationHelper = timGenerationHelper; } - @Scheduled(cron = "${cron.expression}") // run at 1:00am every day + /** + * This method is intended to be run once a day, but can be configured to run at + * any time. It will check for Active TIMs that are expiring within 24 hours and + * issue new TIMs to the ODE for those that are expiring. + */ + @Scheduled(cron = "${cron.expression}") public void performTaskUsingCron() { - utility.logWithDate("Regular task performed using Cron at " + dateFormat.format(new Date())); + log.info("Regular task performed using Cron at {}", dateFormat.format(new Date())); // fetch Active_TIM that are expiring within 24 hrs List expiringTims = activeTimService.getExpiringActiveTims(); - utility.logWithDate(expiringTims.size() + " expiring TIMs found"); + log.info("{} expiring TIMs found", expiringTims.size()); List invalidTims = new ArrayList(); List exceptionTims = new ArrayList<>(); List timsToRefresh = new ArrayList(); @@ -68,48 +73,50 @@ public void performTaskUsingCron() { var resetSuccessful = true; // attempt to refresh TIMs and collect any exceptions - if (timsToRefresh.size() > 0) { - var activeTimIds = timsToRefresh.stream().map(x -> x.getActiveTimId()).collect(Collectors.toList()); + if (!timsToRefresh.isEmpty()) { + var activeTimIds = timsToRefresh.stream().map(ActiveTim::getActiveTimId).collect(Collectors.toList()); // Reset expiration dates so they'll be updated after messages are processed. // Success isn't critical to proceed. We'll just end up with redundant resubmissions later on. resetSuccessful = activeTimService.resetActiveTimsExpirationDate(activeTimIds); exceptionTims = timGenerationHelper.resetTimStartTimeAndResubmitToOde(activeTimIds); } - if (invalidTims.size() > 0 || exceptionTims.size() > 0 || !resetSuccessful) { + if (!invalidTims.isEmpty() || !exceptionTims.isEmpty() || !resetSuccessful) { String body = ""; - if(!resetSuccessful) { + if (!resetSuccessful) { body += "An error occurred while resetting the expiration date(s) for the Active TIM(s)"; body += "

"; } - if (invalidTims.size() > 0) { + if (!invalidTims.isEmpty()) { body += "The Tim Refresh application found invalid TIM(s) while attempting to refresh."; body += "
"; body += "The associated ActiveTim records are:
"; + StringBuilder bodyBuilder = new StringBuilder(body); for (Logging_TimUpdateModel timUpdateModel : invalidTims) { - body += gson.toJson(timUpdateModel); - body += "

"; + bodyBuilder.append(gson.toJson(timUpdateModel)); + bodyBuilder.append("

"); } + body = bodyBuilder.toString(); } - if (exceptionTims.size() > 0) { + if (!exceptionTims.isEmpty()) { body += "The TIM Refresh application ran into exceptions while attempting to resubmit TIMs. The following exceptions were found: "; body += "
"; + StringBuilder bodyBuilder = new StringBuilder(body); for (ResubmitTimException rte : exceptionTims) { - body += gson.toJson(rte); - body += "
"; + bodyBuilder.append(gson.toJson(rte)); + bodyBuilder.append("
"); } + body = bodyBuilder.toString(); } try { - utility.logWithDate( - "Sending error email. The following TIM exceptions were found: " + gson.toJson(body)); + log.info("Sending error email. The following TIM exceptions were found: {}", gson.toJson(body)); emailHelper.SendEmail(configuration.getAlertAddresses(), "TIM Refresh Exceptions", body); } catch (Exception e) { - utility.logWithDate("Exception attempting to send email for invalid TIM:"); - e.printStackTrace(); + log.error("Exception attempting to send email for invalid TIM", e); } } } diff --git a/tim-refresh/src/main/resources/application-dev.properties b/tim-refresh/src/main/resources/application-dev.properties index 7cf463dd2..29beca759 100644 --- a/tim-refresh/src/main/resources/application-dev.properties +++ b/tim-refresh/src/main/resources/application-dev.properties @@ -13,4 +13,5 @@ config.environmentName=DEV config.mailHost=localhost config.mailPort=25 -cron.expression=0 0 * * * * \ No newline at end of file +# second minute hour day month day-of-week +cron.expression=0 0 1 * * * \ No newline at end of file