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 79354031e..1c01f69c7 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
@@ -33,7 +33,6 @@
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Import;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
@@ -53,7 +52,6 @@
@RequestMapping("active-tim")
@ApiIgnore
@Slf4j
-@Import(DateTimeHelperImpl.class)
public class ActiveTimController extends BaseController {
private TimDbTables timDbTables;
@@ -72,17 +70,17 @@ public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNull
this.dateTimeHelper = dateTimeHelper;
}
- /**
- * Retrieve active TIMs that are expiring within 24 hours.
- *
- * Note: TIMs with a start time more than 24 hours in the future
- * or an end time less than 24 hours in the future are excluded.
- *
- * @return List of ActiveTim objects
- */
- @RequestMapping(value = "/expiring", method = RequestMethod.GET, produces = "application/json", headers = "Accept=application/json")
- public ResponseEntity> GetExpiringActiveTims() {
- List activeTims = new ArrayList<>();
+ /**
+ * Retrieve active TIMs that are expiring within 24 hours.
+ *
+ * Note: TIMs with a start time more than 24 hours in the future
+ * or an end time less than 24 hours in the future are excluded.
+ *
+ * @return List of ActiveTim objects
+ */
+ @RequestMapping(value = "/expiring", method = RequestMethod.GET, produces = "application/json", headers = "Accept=application/json")
+ 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";
@@ -112,24 +110,14 @@ public ResponseEntity> GetExpiringActiveTims() {
if (!rs.wasNull() && frameTypeValue >= 0 && frameTypeValue < TravelerInfoType.values().length) {
activeTim.setFrameType(TravelerInfoType.values()[frameTypeValue]);
}
- else {
+ 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
- String serializedContent = rs.getString("DF_CONTENT");
- ContentEnum contentType;
- if (serializedContent == null || serializedContent.isEmpty()) {
- contentType = ContentEnum.advisory;
- } else {
- contentType = ContentEnum.fromString(serializedContent);
+ activeTim.getActiveTimId());
+ // assume roadSignage
+ activeTim.setFrameType(TravelerInfoType.roadSignage);
}
- activeTim.setDfContent(contentType);
+ activeTim.setDfContent(ContentEnum.advisory);
activeTims.add(activeTim);
}
} catch (Exception e) {
@@ -163,28 +151,19 @@ public ResponseEntity GetUpdateModelFromActiveTimId(@PathVariabl
// convert to ActiveTim object
while (rs.next()) {
// Active_Tim properties
- activeTim = buildTimUpdateModelFromResultSet(rs);
+ activeTim = buildTimUpdateModelFromResultSet(rs);
int frameTypeValue = rs.getInt("FRAME_TYPE");
if (!rs.wasNull() && frameTypeValue >= 0 && frameTypeValue < TravelerInfoType.values().length) {
activeTim.setFrameType(TravelerInfoType.values()[frameTypeValue]);
}
- else {
+ 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
- String serializedContent = rs.getString("DF_CONTENT");
- ContentEnum contentType;
- if (serializedContent == null || serializedContent.isEmpty()) {
- contentType = ContentEnum.advisory;
- } else {
- contentType = ContentEnum.fromString(serializedContent);
+ // assume roadSignage
+ activeTim.setFrameType(TravelerInfoType.roadSignage);
}
- activeTim.setDfContent(contentType);
+
+ activeTim.setDfContent(ContentEnum.advisory);
}
} catch (Exception e) {
log.error("Error getting active tim", e);
@@ -290,12 +269,11 @@ public ResponseEntity> GetActiveTimIndicesByRsu(@PathVariable Stri
List indices = new ArrayList<>();
- String selectStatement = "select tim_rsu.rsu_index from active_tim";
- selectStatement += " inner join tim on active_tim.tim_id = tim.tim_id";
- selectStatement += " inner join tim_rsu on tim_rsu.tim_id = tim.tim_id";
- selectStatement += " inner join rsu on rsu.rsu_id = tim_rsu.rsu_id";
- selectStatement += " inner join rsu_view on rsu.deviceid = rsu_view.deviceid";
- selectStatement += " where rsu_view.ipv4_address = '" + rsuTarget + "'";
+ String selectStatement = "select tim_rsu.rsu_index from active_tim";
+ selectStatement += " inner join tim on active_tim.tim_id = tim.tim_id";
+ selectStatement += " inner join tim_rsu on tim_rsu.tim_id = tim.tim_id";
+ selectStatement += " inner join rsus on rsus.rsu_id = tim_rsu.rsu_id";
+ selectStatement += " where rsus.ipv4_address = '" + rsuTarget + "'";
try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(selectStatement)) {
// convert to ActiveTim object
@@ -698,12 +676,11 @@ public ResponseEntity> GetActiveRsuTims() {
List results = new ArrayList();
ActiveTim activeTim = null;
- String query = "select active_tim.*, rsu_view.ipv4_address, tim_rsu.rsu_index from active_tim";
+ String query = "select active_tim.*, rsus.ipv4_address, tim_rsu.rsu_index from active_tim";
query += " inner join tim_rsu on active_tim.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 += " inner join rsus on tim_rsu.rsu_id = rsus.rsu_id";
query += " where sat_record_id is null";
- query += " order by rsu_view.ipv4_address, tim_rsu.rsu_index"; // Required by ValidateRsus
+ query += " order by rsus.ipv4_address, tim_rsu.rsu_index"; // Required by ValidateRsus
try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(query)) {
// convert to ActiveTim object
@@ -755,9 +732,9 @@ public ResponseEntity GetActiveRsuTim(@RequestBody ActiveRsuTimQueryM
String query = "select * from active_tim";
query += " inner join tim_rsu on active_tim.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 ipv4_address = '" + artqm.getIpv4() + "' and client_id = '" + artqm.getClientId() + "' and active_tim.direction = '" + artqm.getDirection() + "'";
+ query += " inner join rsus on tim_rsu.rsu_id = rsus.rsu_id";
+ query += " where ipv4_address = '" + artqm.getIpv4() + "' and client_id = '" + artqm.getClientId()
+ + "' and active_tim.direction = '" + artqm.getDirection() + "'";
try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(query)) {
List activeTims = getActiveTimFromRS(rs, false);
@@ -1119,6 +1096,65 @@ private TimUpdateModel buildTimUpdateModelFromResultSet(ResultSet rs) throws SQL
timUpdateModel.setDataFrameId(rs.getInt("DATA_FRAME_ID"));
timUpdateModel.setDurationTime(rs.getInt("DURATION_TIME"));
timUpdateModel.setUrl(rs.getString("URL"));
+
return timUpdateModel;
}
+
+ public TimUpdateModel setPropertiesForActiveTim(ResultSet rs, TimUpdateModel activeTim) throws SQLException {
+ 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.setUrl(rs.getString("URL"));
+ return activeTim;
+ }
}
diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/CdotUpstreamPathController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/CdotUpstreamPathController.java
new file mode 100644
index 000000000..95fb09781
--- /dev/null
+++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/CdotUpstreamPathController.java
@@ -0,0 +1,392 @@
+package com.trihydro.cvdatacontroller.controller;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.trihydro.library.helpers.CdotGisConnector;
+import com.trihydro.library.model.Milepost;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.web.client.RestClientException;
+
+@CrossOrigin
+@RestController
+@RequestMapping("cdot-upstream-path")
+public class CdotUpstreamPathController extends BaseController {
+ private final CdotGisConnector cdotGisService;
+
+ private final Logger logger = LoggerFactory.getLogger(CdotUpstreamPathController.class);
+
+ public CdotUpstreamPathController(CdotGisConnector cdotGisService) {
+ this.cdotGisService = cdotGisService;
+ }
+
+ /**
+ * Retrieves a buffer path of mileposts for a given route and desired distance.
+ *
+ * This method takes a list of path mileposts, a route ID, and a desired distance in miles.
+ * It fetches all mileposts for the specified route and determines the direction of the path.
+ * Then, it traverses the mileposts to create a buffer path that meets the desired distance.
+ *
+ * Note: The current implementation pulls back the entire route linestring in one request.
+ * There is a possibility to optimize this by hitting the geo REST service multiple times
+ * to fetch smaller segments of the route. However, this method will proceed with the current
+ * implementation unless performance issues are observed.
+ *
+ * @param pathMileposts the list of mileposts defining the path
+ * @param routeId the ID of the route
+ * @param desiredDistanceInMiles the desired distance for the buffer path in miles
+ * @return a ResponseEntity containing the buffer path of mileposts or a bad request status if an error occurs
+ * @throws JsonProcessingException if there is an error processing the JSON response from the geo service
+ */
+ @PostMapping(value = "/get-buffer-for-path/{routeId}/{desiredDistanceInMiles:.+}")
+ public ResponseEntity> getBufferForPath(@RequestBody List pathMileposts,
+ @PathVariable String routeId, @PathVariable
+ double desiredDistanceInMiles) throws
+ JsonProcessingException {
+ logger.info("Getting buffer for path with desired distance: {} miles", desiredDistanceInMiles);
+ List allMileposts;
+ try {
+ allMileposts = getMilepostsForRoute(routeId);
+ } catch (RestClientException e) {
+ logger.error("Error getting mileposts for route", e);
+ return ResponseEntity.badRequest().body(null);
+ }
+ if (allMileposts == null || allMileposts.isEmpty()) {
+ logger.warn("No mileposts found for route");
+ return ResponseEntity.badRequest().body(null);
+ }
+ PathDirection direction;
+ try {
+ direction = getPathDirection(pathMileposts, allMileposts);
+ } catch (NotEnoughMilepostsException e) {
+ logger.warn("Not enough mileposts in path", e);
+ return ResponseEntity.badRequest().body(null);
+ } catch (MilepostNotFoundException e) {
+ logger.warn("Milepost not found in route", e);
+ return ResponseEntity.badRequest().body(null);
+ }
+ if (direction == null) {
+ logger.warn("Invalid path direction");
+ return ResponseEntity.badRequest().body(null);
+ }
+ Milepost firstMilepostInPath = pathMileposts.get(0);
+ int startIndex = getIndexOfMilepost(allMileposts, firstMilepostInPath);
+ TraverseContext traverseContext =
+ new TraverseContext(allMileposts, startIndex, desiredDistanceInMiles, direction);
+ if (direction == PathDirection.ASCENDING) {
+ traverseContext.setTraverseStrategy(new DescendingTraverseStrategy());
+ } else {
+ traverseContext.setTraverseStrategy(new AscendingTraverseStrategy());
+ }
+ traverseContext.performTraversal();
+ List buffer = traverseContext.getBuffer();
+ if (buffer.size() < 2) {
+ // at least 2 mileposts are needed to create a valid buffer path
+ logger.warn("Buffer path has less than 2 mileposts");
+ return ResponseEntity.badRequest().body(null);
+ }
+ double distanceInMiles = traverseContext.getDistanceInMiles();
+ if (distanceInMiles < desiredDistanceInMiles) {
+ logger.warn("Buffer path has less distance than desired distance");
+ return ResponseEntity.badRequest().body(null);
+ }
+ logger.info("Distance of buffer path: {} miles", distanceInMiles);
+ if (logger.isDebugEnabled()) {
+ String geojsonString = convertMilepostsToGeojsonString(buffer);
+ logger.debug("Geojson string for buffer: {}", geojsonString);
+ }
+ return ResponseEntity.ok(buffer);
+ }
+
+ /**
+ * Retrieves all mileposts for a given route from the CDOT GIS service.
+ *
+ * This method uses `CdotGisService.getRouteById()` to retrieve the route information
+ * in JSON format. The JSON response contains all the latitude and longitude points
+ * in the route. This information is then extracted into the `Milepost` model and
+ * returned as a list of mileposts.
+ *
+ * @param routeId the ID of the route to retrieve mileposts for
+ * @return a list of `Milepost` objects representing the mileposts in the route
+ * @throws JsonProcessingException if there is an error processing the JSON response
+ * @throws RestClientException if an error occurs while making the request
+ */
+ public List getMilepostsForRoute(String routeId) throws JsonProcessingException,
+ RestClientException {
+ ResponseEntity response = cdotGisService.getRouteById(routeId);
+ String routeJsonString = response.getBody();
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode rootNode = objectMapper.readTree(routeJsonString);
+ JsonNode pathNode = rootNode.path("features").get(0).path("geometry").path("paths").get(0);
+ List mileposts = new ArrayList<>();
+ for (JsonNode node : pathNode) {
+ Milepost milepost = new Milepost();
+ milepost.setCommonName(routeId);
+ BigDecimal latitude = new BigDecimal(node.get(1).asText()).setScale(14, RoundingMode.HALF_UP);
+ BigDecimal longitude =
+ new BigDecimal(node.get(0).asText()).setScale(14, RoundingMode.HALF_UP);
+ milepost.setLatitude(latitude);
+ milepost.setLongitude(longitude);
+ mileposts.add(milepost);
+ }
+ return mileposts;
+ }
+
+ public PathDirection getPathDirection(List pathMileposts, List allMileposts)
+ throws NotEnoughMilepostsException, MilepostNotFoundException {
+ if (pathMileposts.size() < 2) {
+ throw new NotEnoughMilepostsException("Path has less than 2 mileposts");
+ }
+ Milepost firstMilepostInPath = pathMileposts.get(0);
+ Milepost secondMilepostInPath = pathMileposts.get(1);
+ int firstMilepostInPathIndex = getIndexOfMilepost(allMileposts, firstMilepostInPath);
+ if (firstMilepostInPathIndex == -1) {
+ throw new MilepostNotFoundException("First milepost not found in route");
+ }
+ int secondMilepostInPathIndex = getIndexOfMilepost(allMileposts, secondMilepostInPath);
+ if (secondMilepostInPathIndex == -1) {
+ throw new MilepostNotFoundException("Second milepost not found in route");
+ }
+ if (firstMilepostInPathIndex < secondMilepostInPathIndex) {
+ return PathDirection.ASCENDING;
+ } else {
+ return PathDirection.DESCENDING;
+ }
+ }
+
+ private int getIndexOfMilepost(List mileposts, Milepost milepost) {
+ if (milepost.getLatitude() == null || milepost.getLongitude() == null) {
+ logger.warn("Milepost has null latitude or longitude");
+ return -1;
+ }
+ BigDecimal latitude = milepost.getLatitude().setScale(14, RoundingMode.HALF_UP);
+ BigDecimal longitude = milepost.getLongitude().setScale(14, RoundingMode.HALF_UP);
+ // Roughly a 1-mile starting buffer
+ BigDecimal latDifference = new BigDecimal(0.015);
+ BigDecimal lonDifference = new BigDecimal(0.015);
+ int closestIndex = -1;
+ for (int i = 0; i < mileposts.size(); i++) {
+ Milepost currentMilepost = mileposts.get(i);
+ BigDecimal currentLatitude = currentMilepost.getLatitude().setScale(14, RoundingMode.HALF_UP);
+ BigDecimal currentLongitude = currentMilepost.getLongitude().setScale(14,
+ RoundingMode.HALF_UP);
+
+ // If the current milepost is closer, update the closest index
+ if (latDifference.compareTo(latitude.subtract(currentLatitude).abs()) > 0
+ && lonDifference.compareTo(longitude.subtract(currentLongitude).abs()) > 0) {
+ latDifference = latitude.subtract(currentLatitude).abs();
+ lonDifference = longitude.subtract(currentLongitude).abs();
+ closestIndex = i;
+ }
+ }
+ return closestIndex;
+ }
+
+ private String convertMilepostsToGeojsonString(List mileposts) {
+ StringBuilder geojsonStringBuilder = new StringBuilder();
+ geojsonStringBuilder.append(
+ "{ \"type\": \"FeatureCollection\", \"features\": [{ \"type\": \"Feature\", \"geometry\": { \"type\": \"LineString\", \"coordinates\": [");
+ for (int i = 0; i < mileposts.size(); i++) {
+ Milepost milepost = mileposts.get(i);
+ geojsonStringBuilder.append("[");
+ geojsonStringBuilder.append(milepost.getLongitude().toString());
+ geojsonStringBuilder.append(", ");
+ geojsonStringBuilder.append(milepost.getLatitude().toString());
+ geojsonStringBuilder.append("]");
+ if (i < mileposts.size() - 1) {
+ geojsonStringBuilder.append(", ");
+ }
+ }
+ geojsonStringBuilder.append("] }, \"properties\": { \"commonName\": \"");
+ geojsonStringBuilder.append(mileposts.get(0).getCommonName());
+ geojsonStringBuilder.append("\" } }] }");
+ return geojsonStringBuilder.toString();
+ }
+
+ // define path direction enum (ASCENDING, DESCENDING)
+ public enum PathDirection {
+ ASCENDING,
+ DESCENDING
+ }
+
+ public static class NotEnoughMilepostsException extends Exception {
+ public NotEnoughMilepostsException(String message) {
+ super(message);
+ }
+ }
+
+ public static class MilepostNotFoundException extends Exception {
+ public MilepostNotFoundException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Context class for traversing mileposts to get buffer path
+ */
+ public static class TraverseContext {
+ private final List allMileposts;
+ private final int startIndex;
+ private final double desiredDistanceInMiles;
+ private final PathDirection direction;
+
+ private TraverseStrategy traverseStrategy;
+
+ private List buffer;
+ private double distanceInMiles;
+
+ public TraverseContext(List allMileposts, int startIndex,
+ double desiredDistanceInMiles, PathDirection direction) {
+ this.allMileposts = allMileposts;
+ this.startIndex = startIndex;
+ this.desiredDistanceInMiles = desiredDistanceInMiles;
+ this.direction = direction;
+ this.buffer = new ArrayList<>();
+ }
+
+ public void performTraversal() {
+ traverseStrategy.traverse(this);
+ }
+
+ public List getAllMileposts() {
+ return allMileposts;
+ }
+
+ public int getStartIndex() {
+ return startIndex;
+ }
+
+ public double getDesiredDistanceInMiles() {
+ return desiredDistanceInMiles;
+ }
+
+ public PathDirection getDirection() {
+ return direction;
+ }
+
+ public void setTraverseStrategy(TraverseStrategy traverseStrategy) {
+ this.traverseStrategy = traverseStrategy;
+ }
+
+ public List getBuffer() {
+ return buffer;
+ }
+
+ public void setBuffer(List buffer) {
+ this.buffer = buffer;
+ }
+
+ public double getDistanceInMiles() {
+ return distanceInMiles;
+ }
+
+ public void setDistanceInMiles(double distanceInMiles) {
+ this.distanceInMiles = distanceInMiles;
+ }
+ }
+
+ /**
+ * Interface for traverse strategy to get buffer path
+ */
+ public interface TraverseStrategy {
+ void traverse(TraverseContext context);
+ }
+
+ /**
+ * Traverse strategy to get buffer path by traversing the mileposts in ascending
+ * or descending direction from a starting milepost.
+ */
+ public abstract static class AbstractTraverseStrategy implements TraverseStrategy {
+
+ protected abstract int getNextIndex(int currentIndex);
+
+ /**
+ * Traverses the mileposts to create a buffer path.
+ *
+ * This method iterates through the mileposts starting from the given start index
+ * and adds them to the buffer until the desired distance in miles is reached.
+ *
+ * Note: The current implementation recalculates the total distance of the buffer
+ * after adding each milepost, which can be inefficient. If performance issues are
+ * observed, consider optimizing this calculation.
+ *
+ * @param context the context containing the mileposts, start index, desired distance, and direction
+ */
+ @Override
+ public void traverse(TraverseContext context) {
+ List buffer = new ArrayList<>();
+ List allMileposts = context.getAllMileposts();
+ int startIndex = context.getStartIndex();
+ double desiredDistanceInMiles = context.getDesiredDistanceInMiles();
+ double distanceInMiles = 0;
+
+ buffer.add(allMileposts.get(startIndex));
+ for (int i = getNextIndex(startIndex); i >= 0 && i < allMileposts.size(); i = getNextIndex(i)) {
+ distanceInMiles = DistanceCalculator.calculateDistanceInMiles(buffer);
+ if (distanceInMiles >= desiredDistanceInMiles) {
+ break;
+ }
+ buffer.add(allMileposts.get(i));
+ }
+ context.setBuffer(buffer);
+ context.setDistanceInMiles(distanceInMiles);
+ }
+ }
+
+ /**
+ * Traverse strategy to get buffer path by traversing the mileposts in ascending
+ * direction from a starting milepost.
+ */
+ public static class AscendingTraverseStrategy extends AbstractTraverseStrategy {
+
+ @Override
+ protected int getNextIndex(int currentIndex) {
+ return currentIndex + 1;
+ }
+ }
+
+ /**
+ * Traverse strategy to get buffer path by traversing the mileposts in descending
+ * direction from a starting milepost.
+ */
+ public static class DescendingTraverseStrategy extends AbstractTraverseStrategy {
+
+ @Override
+ protected int getNextIndex(int currentIndex) {
+ return currentIndex - 1;
+ }
+ }
+
+ /**
+ * Helper class to calculate distance between two points and total distance of a buffer path
+ */
+ public static class DistanceCalculator {
+ final static int R = 6371000; // Radius of the earth in meters
+
+ public static double calculateDistanceInMiles(List buffer) {
+ double distanceInMiles = 0;
+ for (int i = 0; i < buffer.size() - 1; i++) {
+ Milepost mp1 = buffer.get(i);
+ Milepost mp2 = buffer.get(i + 1);
+ double distanceInMeters = mp1.angularDistanceTo(mp2) * R;
+ distanceInMiles += distanceInMeters / 1609.34;
+ }
+ return distanceInMiles;
+ }
+ }
+}
\ No newline at end of file
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 698f71ef9..9e6e23eaf 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
@@ -115,10 +115,10 @@ public ResponseEntity AddDataFrame(@RequestBody DataFrame dFrame, @PathVar
if (col.equals("TIM_ID")) {
sqlNullHandler.setLongOrNull(preparedStatement, fieldNum, timId);
} else if (col.equals("FRAME_TYPE")) {
- Integer ordinal = null;
- if (dFrame.getFrameType() != null) {
- ordinal = dFrame.getFrameType().ordinal();
- }
+ Integer ordinal = null;
+ if (dFrame.getFrameType() != null) {
+ ordinal = dFrame.getFrameType().ordinal();
+ }
sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, ordinal);
} else if (col.equals("DURATION_TIME")) {
sqlNullHandler.setIntegerOrNull(preparedStatement, fieldNum, dFrame.getDurationTime());
diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/MilepostController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/MilepostController.java
index c1da71f5e..5b9399469 100644
--- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/MilepostController.java
+++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/MilepostController.java
@@ -7,6 +7,7 @@
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
@@ -15,12 +16,12 @@
import com.mapbox.services.commons.geojson.LineString;
import com.mapbox.services.commons.models.Position;
import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
import com.trihydro.cvdatacontroller.services.MilepostService;
import com.trihydro.library.model.Milepost;
import com.trihydro.library.model.MilepostBuffer;
import com.trihydro.library.model.WydotTim;
+import com.trihydro.library.model.SetMilepostCacheRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@@ -40,7 +41,8 @@
@ApiIgnore
public class MilepostController extends BaseController {
- private MilepostService milepostService;
+ private MilepostService milepostService;
+ private final HashMap> milepostCache = new HashMap<>();
@Autowired
public void InjectDependencies(MilepostService _milepostService) {
@@ -126,7 +128,7 @@ public ResponseEntity> getMilepostsCommonName(@PathVariable Strin
mileposts.add(milepost);
}
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(mileposts);
} finally {
try {
@@ -140,7 +142,7 @@ public ResponseEntity> getMilepostsCommonName(@PathVariable Strin
if (rs != null)
rs.close();
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(mileposts);
@@ -182,10 +184,10 @@ public ResponseEntity> getMilepostRange(@PathVariable String dire
}
if (mileposts.size() == 0) {
- log.info("Unable to find mileposts with query: {}", statementStr);
+ log.info("Unable to find mileposts with query: {}", statementStr);
}
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(mileposts);
} finally {
try {
@@ -199,7 +201,7 @@ public ResponseEntity> getMilepostRange(@PathVariable String dire
if (rs != null)
rs.close();
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(mileposts);
@@ -238,7 +240,7 @@ public ResponseEntity> getMilepostRangeNoDirection(@PathVariable
mileposts.add(milepost);
}
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(mileposts);
} finally {
try {
@@ -252,7 +254,7 @@ public ResponseEntity> getMilepostRangeNoDirection(@PathVariable
if (rs != null)
rs.close();
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(mileposts);
@@ -312,6 +314,74 @@ public ResponseEntity>
return ResponseEntity.ok(data);
}
+ @RequestMapping(method = RequestMethod.POST, value="/set-milepost-cache")
+ public ResponseEntity setMilepostCache(@RequestBody SetMilepostCacheRequest milepostCacheBody) {
+
+ if (milepostCacheBody.getMileposts().isEmpty() || milepostCacheBody.getTimID() == null) {
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid Request: please provide a valid milepost list and timID");
+ }
+ if (milepostCache.containsKey(milepostCacheBody.getTimID())) {
+ log.info("Updating milepost cache for timID: {}", milepostCacheBody.getTimID());
+ } else {
+ log.info("Setting milepost cache for timID: {}", milepostCacheBody.getTimID());
+ }
+ milepostCache.put(milepostCacheBody.getTimID(), milepostCacheBody.getMileposts());
+ return ResponseEntity.ok("Milepost cache set successfully for timID: " + milepostCacheBody.getTimID());
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value="/get-milepost-cache/{timID}")
+ public ResponseEntity> getMilepostCacheByTimID(@PathVariable String timID) {
+ List mileposts = new ArrayList<>();
+
+ if (milepostCache.containsKey(timID)) {
+ mileposts = milepostCache.get(timID);
+ log.info("Found {} mileposts in cache for timID: {}", mileposts.size(), timID);
+ return ResponseEntity.ok(milepostCache.get(timID));
+ }
+
+ return ResponseEntity.ok(mileposts);
+ }
+
+ @RequestMapping(method = RequestMethod.DELETE, value="/delete-milepost-cache/{timID}")
+ public ResponseEntity deleteMilepostCache(@PathVariable String timID) {
+ log.info("Deleting milepost cache for timID: {}", timID);
+
+ if (milepostCache.containsKey(timID)) {
+ milepostCache.remove(timID);
+ return ResponseEntity.ok("Milepost cache deleted successfully for timID: " + timID);
+ }
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Milepost cache not found for timID: " + timID);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value="/clear-milepost-cache")
+ public ResponseEntity clearMilepostCache() {
+ log.info("Clearing milepost cache");
+ List clientIDs = new ArrayList<>(milepostCache.keySet());
+ List activeTimClientIds = getActiveTimClientIds();
+ // remove all active TIM IDs from the list of milepost cache TIM IDs
+ clientIDs.removeAll(activeTimClientIds);
+ for (String clientID : clientIDs) {
+ milepostCache.remove(clientID);
+ }
+ return ResponseEntity.ok("Milepost cache cleared successfully");
+ }
+
+ private List getActiveTimClientIds() {
+ List activeTimIds = new ArrayList<>();
+ String sql = "SELECT client_id FROM active_tim WHERE marked_for_deletion = False";
+ try (Connection connection = dbInteractions.getConnectionPool();
+ Statement statement = connection.createStatement();
+ ResultSet rs = statement.executeQuery(sql)) {
+ while (rs.next()) {
+ String timId = rs.getString("CLIENT_ID");
+ activeTimIds.add(timId);
+ }
+ } catch (SQLException e) {
+ log.error("Error retrieving active TIM IDs ", e); // Improved logging
+ }
+ return activeTimIds;
+ }
+
/**
* Rewrite of getMilepostsByStartEndPoint used in testing to cut time on geojson
* creation to test continuity
@@ -405,7 +475,7 @@ public List getMilepostsTest() {
mileposts.add(milepost);
}
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
} finally {
try {
// close prepared statement
@@ -418,7 +488,7 @@ public List getMilepostsTest() {
if (rs != null)
rs.close();
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
}
}
return mileposts;
@@ -467,7 +537,7 @@ public List getMilepostTestRange(@PathVariable String direction, @Path
mileposts.add(milepost);
}
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
} finally {
try {
// close prepared statement
@@ -480,7 +550,7 @@ public List getMilepostTestRange(@PathVariable String direction, @Path
if (rs != null)
rs.close();
} catch (SQLException e) {
- log.error("Exception", e);
+ log.error("Exception", e);
}
}
return mileposts;
diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/RsuController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/RsuController.java
index 6120f124a..f5a30d2ea 100644
--- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/RsuController.java
+++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/RsuController.java
@@ -9,10 +9,10 @@
import java.util.List;
import com.trihydro.library.model.WydotRsu;
-import com.trihydro.library.model.WydotRsuTim;
-
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
+import com.trihydro.library.model.WydotRsuTim;
+
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
@@ -21,15 +21,15 @@
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
-import springfox.documentation.annotations.ApiIgnore;
-
-@CrossOrigin
-@RestController
-@Slf4j
-@ApiIgnore
-public class RsuController extends BaseController {
-
- @RequestMapping(value = "/rsus", method = RequestMethod.GET, headers = "Accept=application/json")
+import springfox.documentation.annotations.ApiIgnore;
+
+@CrossOrigin
+@RestController
+@Slf4j
+@ApiIgnore
+public class RsuController extends BaseController {
+
+ @RequestMapping(value = "/rsus", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity> SelectAllRsus() {
ArrayList rsus = new ArrayList();
Connection connection = null;
@@ -40,9 +40,8 @@ public ResponseEntity> SelectAllRsus() {
connection = dbInteractions.getConnectionPool();
statement = connection.createStatement();
- // select all RSUs from RSU table
- rs = statement.executeQuery(
- "select * from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid order by milepost asc");
+ // select all RSUs from rsus table
+ rs = statement.executeQuery("select rsu_id, ST_X(ST_AsText(geography)) as longitude, ST_Y(ST_AsText(geography)) as latitude, ipv4_address, primary_route, milepost from rsus order by milepost asc");
while (rs.next()) {
WydotRsu rsu = new WydotRsu();
@@ -50,13 +49,13 @@ public ResponseEntity> SelectAllRsus() {
rsu.setRsuTarget(rs.getString("IPV4_ADDRESS"));
rsu.setLatitude(rs.getBigDecimal("LATITUDE"));
rsu.setLongitude(rs.getBigDecimal("LONGITUDE"));
- rsu.setRoute(rs.getString("ROUTE"));
+ rsu.setRoute(rs.getString("PRIMARY_ROUTE"));
rsu.setMilepost(rs.getDouble("MILEPOST"));
rsus.add(rsu);
}
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(rsus);
} finally {
try {
@@ -69,17 +68,17 @@ public ResponseEntity> SelectAllRsus() {
// close result set
if (rs != null)
rs.close();
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(rsus);
}
- @RequestMapping(value = "/selectActiveRSUs", method = RequestMethod.GET, headers = "Accept=application/json")
- public ResponseEntity> SelectActiveRsus() {
- List rsus = new ArrayList();
+ @RequestMapping(method = RequestMethod.GET, value = "/rsus-for-tim/{timId}")
+ public ResponseEntity> GetFullRsusTimIsOn(@PathVariable Long timId) {
+ List rsus = new ArrayList();
Connection connection = null;
ResultSet rs = null;
Statement statement = null;
@@ -88,20 +87,29 @@ public ResponseEntity> SelectActiveRsus() {
connection = dbInteractions.getConnectionPool();
statement = connection.createStatement();
- // select all RSUs that are labeled as 'Existing' in the WYDOT view
rs = statement.executeQuery(
- "select rsu.*, rsu_view.latitude, rsu_view.longitude, rsu_view.ipv4_address from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid where rsu_view.status = 'Existing'");
+ "select rsus.rsu_id, rsu_credentials.username as update_username, " +
+ "rsu_credentials.password as update_password, ST_X(ST_AsText(rsus.geography)) " +
+ "as longitude, ST_Y(ST_AsText(rsus.geography)) as latitude, rsus.ipv4_address, " +
+ "tim_rsu.rsu_index from rsus inner join rsu_credentials on " +
+ "rsu_credentials.credential_id = rsus.credential_id inner join tim_rsu on " +
+ "tim_rsu.rsu_id = rsus.rsu_id where tim_rsu.tim_id = " + timId);
while (rs.next()) {
- WydotRsu rsu = new WydotRsu();
- // rsu.setRsuId(rs.getInt("rsu_id"));
+ WydotRsuTim rsu = new WydotRsuTim();
rsu.setRsuTarget(rs.getString("IPV4_ADDRESS"));
rsu.setLatitude(rs.getBigDecimal("LATITUDE"));
rsu.setLongitude(rs.getBigDecimal("LONGITUDE"));
- rsus.add(rsu);
+ rsu.setIndex(rs.getInt("RSU_INDEX"));
+ rsu.setRsuUsername(rs.getString("UPDATE_USERNAME"));
+ rsu.setRsuPassword(rs.getString("UPDATE_PASSWORD"));
+ // only add unique values in
+ if (!rsus.contains(rsu)) {
+ rsus.add(rsu);
+ }
}
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(rsus);
} finally {
try {
@@ -114,16 +122,16 @@ public ResponseEntity> SelectActiveRsus() {
// close result set
if (rs != null)
rs.close();
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(rsus);
}
- @RequestMapping(method = RequestMethod.GET, produces = "application/json", value = "/rsus-for-tim/{timId}")
- public ResponseEntity> GetFullRsusTimIsOn(@PathVariable Long timId) {
- List rsus = new ArrayList();
+ @RequestMapping(method = RequestMethod.GET, produces = "application/json", value = "/rsus-by-geometry/{geometry}")
+ public ResponseEntity> SelectRsusByGeometry(@PathVariable String geometry) {
+ ArrayList rsus = new ArrayList<>();
Connection connection = null;
ResultSet rs = null;
Statement statement = null;
@@ -132,26 +140,35 @@ public ResponseEntity> GetFullRsusTimIsOn(@PathVariable Long t
connection = dbInteractions.getConnectionPool();
statement = connection.createStatement();
- // select all RSUs that are labeled as 'Existing' in the WYDOT view
+ // select all RSUs from RSU table
rs = statement.executeQuery(
- "select rsu.*, tim_rsu.rsu_index, rsu_view.latitude, rsu_view.longitude, rsu_view.ipv4_address from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid inner join tim_rsu on tim_rsu.rsu_id = rsu.rsu_id where tim_rsu.tim_id = "
- + timId);
+ "SELECT rsu_id, ST_X(ST_AsText(geography)) as longitude, " +
+ "ST_Y(ST_AsText(geography)) as latitude, primary_route, milepost, ipv4_address, sc.username, sc.password " +
+ "FROM rsus " +
+ "JOIN snmp_credentials AS sc ON rsus.snmp_credential_id = sc.snmp_credential_id " +
+ "WHERE rsu_id NOT IN (" +
+ "SELECT rsu_id " +
+ "FROM rsu_organization AS ro " +
+ "JOIN organizations AS o ON ro.organization_id = o.organization_id " +
+ "WHERE o.name = 'Region 1') " +
+ "AND ST_Intersects(" +
+ "ST_Buffer(ST_GeomFromText('" + geometry + "'), 1), geography)"
+ );
while (rs.next()) {
- WydotRsuTim rsu = new WydotRsuTim();
+ WydotRsu rsu = new WydotRsu();
+ rsu.setRsuId(rs.getInt("RSU_ID"));
rsu.setRsuTarget(rs.getString("IPV4_ADDRESS"));
rsu.setLatitude(rs.getBigDecimal("LATITUDE"));
rsu.setLongitude(rs.getBigDecimal("LONGITUDE"));
- rsu.setIndex(rs.getInt("RSU_INDEX"));
- rsu.setRsuUsername(rs.getString("UPDATE_USERNAME"));
- rsu.setRsuPassword(rs.getString("UPDATE_PASSWORD"));
- // only add unique values in
- if (!rsus.contains(rsu)) {
- rsus.add(rsu);
- }
+ rsu.setRoute(rs.getString("PRIMARY_ROUTE"));
+ rsu.setMilepost(rs.getDouble("MILEPOST"));
+ rsu.setRsuUsername(rs.getString("USERNAME"));
+ rsu.setRsuPassword(rs.getString("PASSWORD"));
+ rsus.add(rsu);
}
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(rsus);
} finally {
try {
@@ -164,8 +181,8 @@ public ResponseEntity> GetFullRsusTimIsOn(@PathVariable Long t
// close result set
if (rs != null)
rs.close();
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(rsus);
@@ -184,8 +201,7 @@ public ResponseEntity> SelectRsusByRoute(@PathVariable Strin
// select all RSUs from RSU table
rs = statement.executeQuery(
- "select * from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid where rsu_view.route like '%"
- + route + "%' and rsu_view.status = 'Existing' order by milepost asc");
+ "select rsu_id, ST_X(ST_AsText(geography)) as longitude, ST_Y(ST_AsText(geography)) as latitude, ipv4_address, primary_route, milepost from rsus where primary_route like '%" + route + "%'");
while (rs.next()) {
WydotRsu rsu = new WydotRsu();
@@ -197,8 +213,8 @@ public ResponseEntity> SelectRsusByRoute(@PathVariable Strin
rsu.setMilepost(rs.getDouble("MILEPOST"));
rsus.add(rsu);
}
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(rsus);
} finally {
try {
@@ -211,8 +227,8 @@ public ResponseEntity> SelectRsusByRoute(@PathVariable Strin
// close result set
if (rs != null)
rs.close();
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(rsus);
@@ -240,8 +256,8 @@ public ResponseEntity> GetActiveRsuTimIndexes(@PathVariable Intege
while (rs.next()) {
indexes.add(rs.getInt("RSU_INDEX"));
}
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(indexes);
} finally {
try {
@@ -254,10 +270,10 @@ public ResponseEntity> GetActiveRsuTimIndexes(@PathVariable Intege
// close result set
if (rs != null)
rs.close();
- } catch (SQLException e) {
- log.error("Exception", e);
+ } catch (SQLException e) {
+ log.error("Exception", e);
}
}
return ResponseEntity.ok(indexes);
}
-}
+}
\ No newline at end of file
diff --git a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/model/DataControllerConfigProperties.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/model/DataControllerConfigProperties.java
index 6ffb2b0a3..ed557432e 100644
--- a/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/model/DataControllerConfigProperties.java
+++ b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/model/DataControllerConfigProperties.java
@@ -1,5 +1,6 @@
package com.trihydro.cvdatacontroller.model;
+import com.trihydro.library.helpers.CdotGisConnector;
import com.trihydro.library.helpers.DbInteractions;
import com.trihydro.library.helpers.EmailHelper;
import com.trihydro.library.helpers.JavaMailSenderImplProvider;
@@ -7,6 +8,7 @@
import com.trihydro.library.helpers.Utility;
import com.trihydro.library.model.DbInteractionsProps;
import com.trihydro.library.model.EmailProps;
+import com.trihydro.library.service.RestTemplateProvider;
import com.trihydro.library.tables.LoggingTables;
import com.trihydro.library.tables.TimDbTables;
import lombok.Data;
@@ -18,7 +20,8 @@
@ConfigurationProperties("config")
@Data
@Import({ TimDbTables.class, SQLNullHandler.class, Utility.class, EmailHelper.class,
- JavaMailSenderImplProvider.class, LoggingTables.class, DbInteractions.class })
+ JavaMailSenderImplProvider.class, LoggingTables.class, DbInteractions.class,
+ CdotGisConnector.class, RestTemplateProvider.class })
public class DataControllerConfigProperties implements DbInteractionsProps, EmailProps {
private String dbUrl;
private String dbUsername;
diff --git a/cv-data-controller/src/main/resources/application.properties b/cv-data-controller/src/main/resources/application.properties
index fe2e64b06..7230c04a7 100644
--- a/cv-data-controller/src/main/resources/application.properties
+++ b/cv-data-controller/src/main/resources/application.properties
@@ -20,4 +20,6 @@ spring.data.neo4j.uri=bolt://host.docker.internal:6687
# server.ssl.key-store: classpath:keystore.jks
# server.ssl.key-store-password: store-password
# server.ssl.keyStoreType: JKS
-# server.ssl.keyAlias: some-alias
\ No newline at end of file
+# server.ssl.keyAlias: some-alias
+
+logging.level.root=INFO
\ No newline at end of file
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 ce82d01dc..f9badb77f 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
@@ -34,6 +34,8 @@
import org.testcontainers.junit.jupiter.Testcontainers;
import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType;
+import org.springframework.web.client.HttpServerErrorException;
+
public class ActiveTimControllerTest extends TestBase {
@Spy
private TimDbTables mockTimDbTables = new TimDbTables();
@@ -55,7 +57,7 @@ private void setupPreparedStatement() {
public void GetExpiringActiveTims_SUCCESS() throws SQLException {
// Arrange
// we only set one property to verify its returned
- when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999l);
+ when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999L);
when(mockRs.getInt(any())).thenReturn(0);
when(mockRs.getInt("FRAME_TYPE")).thenReturn(FrameType.TravelerInfoType.advisory.ordinal());
String selectStatement = "SELECT atim.*, tt.type as tim_type_name, tt.description as tim_type_description";
@@ -106,8 +108,7 @@ public void GetExpiringActiveTims_FAIL() throws SQLException {
public void GetExpiringActiveTims_CorrectContentType() throws SQLException {
// Arrange
when(mockRs.getString(any())).thenReturn("");
- when(mockRs.getString("DF_CONTENT")).thenReturn("workZone");
- when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999l);
+ when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999L);
// Act
ResponseEntity> tums = uut.GetExpiringActiveTims();
@@ -115,16 +116,16 @@ public void GetExpiringActiveTims_CorrectContentType() throws SQLException {
// Assert
Assertions.assertEquals(HttpStatus.OK, tums.getStatusCode());
Assertions.assertEquals(1, tums.getBody().size());
- Assertions.assertEquals(ContentEnum.workZone, tums.getBody().get(0).getDfContent());
+ Assertions.assertEquals(ContentEnum.advisory, tums.getBody().get(0).getDfContent());
}
@Test
public void GetUpdateModelFromActiveTimId_SUCCESS() throws SQLException {
// Arrange
// we only set one property to verify its returned
- when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999l);
+ when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999L);
when(mockRs.getInt(any())).thenReturn(0);
- when(mockRs.getInt("FRAME_TYPE")).thenReturn(FrameType.TravelerInfoType.advisory.ordinal());
+ when(mockRs.getInt("FRAME_TYPE")).thenReturn(FrameType.TravelerInfoType.roadSignage.ordinal());
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";
@@ -138,16 +139,16 @@ public void GetUpdateModelFromActiveTimId_SUCCESS() throws SQLException {
selectStatement += " LEFT JOIN data_frame df on atim.tim_id = df.tim_id";
selectStatement += " LEFT JOIN region r on df.data_frame_id = r.data_frame_id";
selectStatement += " LEFT JOIN tim_type tt ON atim.tim_type_id = tt.tim_type_id";
- selectStatement += " WHERE atim.active_tim_id = " + 999l;
+ selectStatement += " WHERE atim.active_tim_id = " + 999L;
// Act
- ResponseEntity tum = uut.GetUpdateModelFromActiveTimId(999l);
+ ResponseEntity tum = uut.GetUpdateModelFromActiveTimId(999L);
// Assert
Assertions.assertEquals(HttpStatus.OK, tum.getStatusCode());
Assertions.assertNotNull(tum.getBody());
Assertions.assertEquals(Long.valueOf(999), tum.getBody().getActiveTimId());
- Assertions.assertEquals(FrameType.TravelerInfoType.advisory, tum.getBody().getFrameType());
+ Assertions.assertEquals(FrameType.TravelerInfoType.roadSignage, tum.getBody().getFrameType());
verify(mockStatement).executeQuery(selectStatement);
}
@@ -157,7 +158,7 @@ public void GetUpdateModelFromActiveTimId_FAIL() throws SQLException {
when(mockRs.getLong("ACTIVE_TIM_ID")).thenThrow(new SQLException());
// Act
- ResponseEntity tum = uut.GetUpdateModelFromActiveTimId(999l);
+ ResponseEntity tum = uut.GetUpdateModelFromActiveTimId(999L);
// Assert
Assertions.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, tum.getStatusCode());
@@ -170,16 +171,15 @@ public void GetUpdateModelFromActiveTimId_FAIL() throws SQLException {
public void GetUpdateModelFromActiveTimId_CorrectContentType() throws SQLException {
// Arrange
when(mockRs.getString(any())).thenReturn("");
- when(mockRs.getString("DF_CONTENT")).thenReturn("workZone");
- when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999l);
+ when(mockRs.getLong("ACTIVE_TIM_ID")).thenReturn(999L);
// Act
- ResponseEntity tum = uut.GetUpdateModelFromActiveTimId(999l);
+ ResponseEntity tum = uut.GetUpdateModelFromActiveTimId(999L);
// Assert
Assertions.assertEquals(HttpStatus.OK, tum.getStatusCode());
Assertions.assertNotNull(tum.getBody());
- Assertions.assertEquals(ContentEnum.workZone, tum.getBody().getDfContent());
+ Assertions.assertEquals(ContentEnum.advisory, tum.getBody().getDfContent());
}
@Test
@@ -189,7 +189,7 @@ public void UpdateActiveTim_SatRecordId_FAIL() {
doReturn(false).when(mockDbInteractions).updateOrDelete(mockPreparedStatement);
// Act
- ResponseEntity success = uut.updateActiveTim_SatRecordId(-1l, "asdf");
+ ResponseEntity success = uut.updateActiveTim_SatRecordId(-1L, "asdf");
// Assert
Assertions.assertFalse(success.getBody(), "UpdateActiveTim_SatRecordId succeeded when it should have failed");
@@ -202,7 +202,7 @@ public void UpdateActiveTim_SatRecordId_SUCCESS() {
doReturn(true).when(mockDbInteractions).updateOrDelete(mockPreparedStatement);
// Act
- ResponseEntity success = uut.updateActiveTim_SatRecordId(-1l, "asdf");
+ ResponseEntity success = uut.updateActiveTim_SatRecordId(-1L, "asdf");
// Assert
Assertions.assertTrue(success.getBody(), "UpdateActiveTim_SatRecordId failed when it should have succeeded");
@@ -214,7 +214,7 @@ public void UpdateActiveTim_SatRecordId_EXCEPTION() throws SQLException {
doThrow(new SQLException()).when(mockDbInteractions).getConnectionPool();
// Act
- ResponseEntity success = uut.updateActiveTim_SatRecordId(-1l, "asdf");
+ ResponseEntity success = uut.updateActiveTim_SatRecordId(-1L, "asdf");
// Assert
Assertions.assertFalse(success.getBody(), "UpdateActiveTim_SatRecordId was successful during an error");
@@ -386,9 +386,8 @@ public void GetActiveTimIndicesByRsu_SUCCESS() throws SQLException {
String selectStatement = "select tim_rsu.rsu_index from active_tim";
selectStatement += " inner join tim on active_tim.tim_id = tim.tim_id";
selectStatement += " inner join tim_rsu on tim_rsu.tim_id = tim.tim_id";
- selectStatement += " inner join rsu on rsu.rsu_id = tim_rsu.rsu_id";
- selectStatement += " inner join rsu_view on rsu.deviceid = rsu_view.deviceid";
- selectStatement += " where rsu_view.ipv4_address = '" + rsuTarget + "'";
+ selectStatement += " inner join rsus on rsus.rsu_id = tim_rsu.rsu_id";
+ selectStatement += " where rsus.ipv4_address = '" + rsuTarget + "'";
// Act
ResponseEntity> data = uut.GetActiveTimIndicesByRsu(rsuTarget);
@@ -409,9 +408,8 @@ public void GetActiveTimIndicesByRsu_FAIL() throws SQLException {
String selectStatement = "select tim_rsu.rsu_index from active_tim";
selectStatement += " inner join tim on active_tim.tim_id = tim.tim_id";
selectStatement += " inner join tim_rsu on tim_rsu.tim_id = tim.tim_id";
- selectStatement += " inner join rsu on rsu.rsu_id = tim_rsu.rsu_id";
- selectStatement += " inner join rsu_view on rsu.deviceid = rsu_view.deviceid";
- selectStatement += " where rsu_view.ipv4_address = '" + rsuTarget + "'";
+ selectStatement += " inner join rsus on rsus.rsu_id = tim_rsu.rsu_id";
+ selectStatement += " where rsus.ipv4_address = '" + rsuTarget + "'";
doThrow(new SQLException()).when(mockRs).getInt("RSU_INDEX");
// Act
@@ -489,6 +487,9 @@ public void getActiveTimsByClientIdDirection_FAIL() throws SQLException {
public void GetBufferTimsByClientId_SUCCESS() throws SQLException {
// Arrange
String clientId = "clientId";
+ String selectStatement = "select * from active_tim where CLIENT_ID like '" + clientId
+ + "\\%BUFF-%' ESCAPE '\\'";
+
// Act
ResponseEntity> data = uut.GetBufferTimsByClientId(clientId);
@@ -535,7 +536,7 @@ public void GetBufferTimsByClientId_FAIL() throws SQLException {
@Test
public void GetItisCodesForActiveTim_SUCCESS() throws SQLException {
// Arrange
- Long activeTimId = -1l;
+ Long activeTimId = -1L;
String selectStatement = "select itis_code from active_tim ";
selectStatement += "inner join tim on tim.tim_id = active_tim.tim_id ";
selectStatement += "inner join data_frame on tim.tim_id = data_frame.tim_id ";
@@ -559,7 +560,7 @@ public void GetItisCodesForActiveTim_SUCCESS() throws SQLException {
@Test
public void GetItisCodesForActiveTim_FAIL() throws SQLException {
// Arrange
- Long activeTimId = -1l;
+ Long activeTimId = -1L;
String selectStatement =
"select itis_code from active_tim inner join tim on tim.tim_id = active_tim.tim_id inner join data_frame on tim.tim_id = data_frame.tim_id inner join data_frame_itis_code on data_frame_itis_code.data_frame_id = data_frame.data_frame_id inner join itis_code on data_frame_itis_code.itis_code_id = itis_code.itis_code_id where active_tim_id = " +
activeTimId + " order by data_frame_itis_code.position asc";
@@ -579,7 +580,7 @@ public void GetItisCodesForActiveTim_FAIL() throws SQLException {
@Test
public void DeleteActiveTim_SUCCESS() throws SQLException {
// Arrange
- Long activeTimId = -1l;
+ Long activeTimId = -1L;
// Act
ResponseEntity data = uut.DeleteActiveTim(activeTimId);
@@ -595,7 +596,7 @@ public void DeleteActiveTim_SUCCESS() throws SQLException {
@Test
public void DeleteActiveTim_FAIL() throws SQLException {
// Arrange
- Long activeTimId = -1l;
+ Long activeTimId = -1L;
doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, activeTimId);
// Act
@@ -623,7 +624,7 @@ public void deleteActiveTimsById_SUCCESS() throws SQLException {
Assertions.assertEquals(HttpStatus.OK, data.getStatusCode());
Assertions.assertTrue(data.getBody(), "Fail return on success");
verify(mockConnection).prepareStatement("DELETE FROM ACTIVE_TIM WHERE ACTIVE_TIM_ID in (?)");
- verify(mockPreparedStatement).setLong(1, -1l);
+ verify(mockPreparedStatement).setLong(1, -1L);
verify(mockPreparedStatement).close();
verify(mockConnection).close();
}
@@ -633,7 +634,7 @@ public void deleteActiveTimsById_FAIL() throws SQLException {
// Arrange
List activeTimIds = new ArrayList<>();
activeTimIds.add(Long.valueOf(-1));
- doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, -1l);
+ doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, -1L);
// Act
ResponseEntity data = uut.deleteActiveTimsById(activeTimIds);
@@ -670,7 +671,7 @@ public void GetActiveTimsByIds_SUCCESS() throws SQLException {
String query = "select * from active_tim where active_tim_id in (?, ?)";
// Act
- var response = uut.GetActiveTimsByIds(Arrays.asList(-1l, -2l));
+ var response = uut.GetActiveTimsByIds(Arrays.asList(-1L, -2L));
// Assert
Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
@@ -683,10 +684,10 @@ public void GetActiveTimsByIds_SUCCESS() throws SQLException {
public void GetActiveTimsByIds_FAIL() throws SQLException {
// Arrange
String query = "select * from active_tim where active_tim_id in (?, ?)";
- doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, -1l);
+ doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, -1L);
// Act
- var response = uut.GetActiveTimsByIds(Arrays.asList(-1l, -2l));
+ var response = uut.GetActiveTimsByIds(Arrays.asList(-1L, -2L));
// Assert
Assertions.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
@@ -714,7 +715,7 @@ public void GetActiveTimsByWydotTim_SUCCESS() throws SQLException {
wydotTim.setClientId("clientId");
wydotTim.setDirection("westward");
wydotTims.add(wydotTim);
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String query = "select * from active_tim where TIM_TYPE_ID = ? and ((CLIENT_ID like ? and DIRECTION = ?))";
// Act
@@ -752,7 +753,7 @@ public void GetActiveTimsByWydotTim_BothDirections() throws SQLException {
wydotTim.setClientId("clientId");
wydotTim.setDirection("B");
wydotTims.add(wydotTim);
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String query = "select * from active_tim where TIM_TYPE_ID = ? and ((CLIENT_ID like ?))";
// Act
@@ -789,7 +790,7 @@ public void GetActiveTimsByWydotTim_FAIL() throws SQLException {
wydotTim.setClientId("clientId");
wydotTim.setDirection("westward");
wydotTims.add(wydotTim);
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String query = "select * from active_tim where TIM_TYPE_ID = ? and ((CLIENT_ID like ? and DIRECTION = ?))";
doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, timTypeId);
@@ -807,7 +808,7 @@ public void GetActiveTimsByWydotTim_FAIL() throws SQLException {
@Test
public void GetActivesTimByType_SUCCESS() throws SQLException {
// Arrange
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String query = "select * from active_tim where TIM_TYPE_ID = " + timTypeId;
// Act
@@ -839,7 +840,7 @@ public void GetActivesTimByType_SUCCESS() throws SQLException {
@Test
public void GetActivesTimByType_FAIL() throws SQLException {
// Arrange
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String query = "select * from active_tim where TIM_TYPE_ID = " + timTypeId;
doThrow(new SQLException()).when(mockRs).getLong("ACTIVE_TIM_ID");
@@ -945,8 +946,7 @@ public void GetActiveRsuTim_SUCCESS() throws SQLException {
String ipv4Address = "10.0.0.1";
String query = "select * from active_tim";
query += " inner join tim_rsu on active_tim.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 += " inner join rsus on tim_rsu.rsu_id = rsus.rsu_id";
query += " where ipv4_address = '" + ipv4Address + "' and client_id = '" + clientId;
query += "' and active_tim.direction = '" + direction + "'";
@@ -984,8 +984,7 @@ public void GetActiveRsuTim_FAIL() throws SQLException {
String ipv4Address = "10.0.0.1";
String query = "select * from active_tim";
query += " inner join tim_rsu on active_tim.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 += " inner join rsus on tim_rsu.rsu_id = rsus.rsu_id";
query += " where ipv4_address = '" + ipv4Address + "' and client_id = '" + clientId;
query += "' and active_tim.direction = '" + direction + "'";
doThrow(new SQLException()).when(mockStatement).executeQuery(query);
@@ -1206,7 +1205,7 @@ public void ResetExpirationDate_SUCCESS() throws SQLException {
Assertions.assertEquals(HttpStatus.OK, data.getStatusCode());
Assertions.assertTrue(data.getBody(), "Fail return on success");
verify(mockConnection).prepareStatement("UPDATE ACTIVE_TIM SET EXPIRATION_DATE = NULL WHERE ACTIVE_TIM_ID IN (?)");
- verify(mockPreparedStatement).setLong(1, -1l);
+ verify(mockPreparedStatement).setLong(1, -1L);
verify(mockPreparedStatement).close();
verify(mockConnection).close();
}
@@ -1256,7 +1255,7 @@ public void ResetExpirationDate_FAIL() throws SQLException {
// Arrange
List activeTimIds = new ArrayList<>();
activeTimIds.add(Long.valueOf(-1));
- doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, -1l);
+ doThrow(new SQLException()).when(mockPreparedStatement).setLong(1, -1L);
// Act
ResponseEntity data = uut.ResetExpirationDate(activeTimIds);
diff --git a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/CdotUpstreamPathControllerTest.java b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/CdotUpstreamPathControllerTest.java
new file mode 100644
index 000000000..73a7caf36
--- /dev/null
+++ b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/CdotUpstreamPathControllerTest.java
@@ -0,0 +1,312 @@
+package com.trihydro.cvdatacontroller.controller;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.trihydro.cvdatacontroller.controller.CdotUpstreamPathController.DistanceCalculator;
+import com.trihydro.cvdatacontroller.controller.CdotUpstreamPathController.PathDirection;
+import com.trihydro.library.helpers.CdotGisConnector;
+import com.trihydro.library.model.Milepost;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+class CdotUpstreamPathControllerTest {
+ private final String ROUTE_ID = "025A"; // I-25
+ private final String PATH_TO_ROUTE_JSON_TEST_DATA =
+ "src/test/resources/com/trihydro/cvdatacontroller/controller/cdotRouteResponseForI25_First30Mileposts.json";
+
+ @Mock
+ CdotGisConnector cdotGisService = Mockito.mock(CdotGisConnector.class);
+
+ @InjectMocks
+ CdotUpstreamPathController uut;
+
+ List getMockMileposts() throws IOException {
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode rootNode = objectMapper.readTree(routeJsonString);
+ JsonNode pathNode = rootNode.path("features").get(0).path("geometry").path("paths").get(0);
+ List mileposts = new ArrayList<>();
+ for (JsonNode node : pathNode) {
+ Milepost milepost = new Milepost();
+ milepost.setCommonName(ROUTE_ID);
+ BigDecimal latitude = new BigDecimal(node.get(1).asText()).setScale(14, RoundingMode.HALF_UP);
+ BigDecimal longitude =
+ new BigDecimal(node.get(0).asText()).setScale(14, RoundingMode.HALF_UP);
+ milepost.setLatitude(latitude);
+ milepost.setLongitude(longitude);
+ mileposts.add(milepost);
+ }
+ return mileposts;
+ }
+
+ @BeforeEach
+ void setUp() {
+ uut = new CdotUpstreamPathController(cdotGisService);
+ }
+
+ @Test
+ void testGetMilepostsForRoute() throws IOException {
+ // prepare
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ResponseEntity mockResponse = new ResponseEntity<>(routeJsonString, HttpStatus.OK);
+ when(cdotGisService.getRouteById(ROUTE_ID)).thenReturn(mockResponse);
+ List expectedMileposts = getMockMileposts();
+
+ // execute
+ List mileposts = uut.getMilepostsForRoute(ROUTE_ID);
+
+ // verify
+ verify(cdotGisService).getRouteById(ROUTE_ID);
+ Assertions.assertEquals(expectedMileposts.size(), mileposts.size());
+ for (int i = 0; i < expectedMileposts.size(); i++) {
+ Milepost expected = expectedMileposts.get(i);
+ Milepost actual = mileposts.get(i);
+ Assertions.assertEquals(expected.getCommonName(), actual.getCommonName());
+ Assertions.assertNull(actual.getMilepost());
+ Assertions.assertNull(actual.getDirection());
+ Assertions.assertEquals(expected.getLatitude(), actual.getLatitude());
+ Assertions.assertEquals(expected.getLongitude(), actual.getLongitude());
+ }
+ }
+
+ @Test
+ void testGetPathDirection_ASCENDING()
+ throws IOException, CdotUpstreamPathController.MilepostNotFoundException,
+ CdotUpstreamPathController.NotEnoughMilepostsException {
+ // prepare
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(0);
+ Milepost mp2 = allMileposts.get(1);
+ List pathMileposts = List.of(mp1, mp2);
+
+ // execute
+ PathDirection direction = uut.getPathDirection(pathMileposts, allMileposts);
+
+ // verify
+ Assertions.assertEquals(PathDirection.ASCENDING, direction);
+ }
+
+ @Test
+ void testGetPathDirection_DESCENDING()
+ throws IOException, CdotUpstreamPathController.MilepostNotFoundException,
+ CdotUpstreamPathController.NotEnoughMilepostsException {
+ // prepare
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(1);
+ Milepost mp2 = allMileposts.get(0);
+ List pathMileposts = List.of(mp1, mp2);
+
+ // execute
+ PathDirection direction = uut.getPathDirection(pathMileposts, allMileposts);
+
+ // verify
+ Assertions.assertEquals(PathDirection.DESCENDING, direction);
+ }
+
+ @Test
+ void testGetPathDirection_NOT_ENOUGH_MILEPOSTS()
+ throws IOException {
+ // prepare
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(0);
+ List pathMileposts = List.of(mp1);
+
+ // execute
+ assertThrows(CdotUpstreamPathController.NotEnoughMilepostsException.class, () -> {
+ uut.getPathDirection(pathMileposts, allMileposts);
+ });
+ }
+
+ @Test
+ void testGetPathDirection_FirstMilepostOfPathNotInAllMileposts()
+ throws IOException {
+ // prepare
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = new Milepost();
+ mp1.setCommonName(ROUTE_ID);
+ mp1.setLatitude(new BigDecimal("30.12").setScale(14, RoundingMode.HALF_UP));
+ mp1.setLongitude(new BigDecimal("-100.34").setScale(14, RoundingMode.HALF_UP));
+ Milepost mp2 = allMileposts.get(1);
+ List pathMileposts = List.of(mp1, mp2);
+
+ // execute
+ assertThrows(CdotUpstreamPathController.MilepostNotFoundException.class, () -> {
+ uut.getPathDirection(pathMileposts, allMileposts);
+ });
+ }
+
+ @Test
+ void testGetPathDirection_SecondMilepostOfPathNotInAllMileposts()
+ throws IOException {
+ // prepare
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(0);
+ Milepost mp2 = new Milepost();
+ mp2.setCommonName(ROUTE_ID);
+ mp1.setLatitude(new BigDecimal("30.12").setScale(14, RoundingMode.HALF_UP));
+ mp1.setLongitude(new BigDecimal("-100.34").setScale(14, RoundingMode.HALF_UP));
+ List pathMileposts = List.of(mp1, mp2);
+
+ // execute
+ assertThrows(CdotUpstreamPathController.MilepostNotFoundException.class, () -> {
+ uut.getPathDirection(pathMileposts, allMileposts);
+ });
+ }
+
+ @Test
+ void testGetBufferForPath_Ascending_Success() throws IOException {
+ // prepare
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ResponseEntity mockResponse = new ResponseEntity<>(routeJsonString, HttpStatus.OK);
+ when(cdotGisService.getRouteById(ROUTE_ID)).thenReturn(mockResponse);
+
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(20);
+ Milepost mp2 = allMileposts.get(21);
+ List pathMileposts = List.of(mp1, mp2);
+
+ double desiredDistanceInMiles = 0.5;
+
+ // execute
+ ResponseEntity> response =
+ uut.getBufferForPath(pathMileposts, ROUTE_ID, desiredDistanceInMiles);
+
+ // verify
+ List buffer = response.getBody();
+ assert buffer != null;
+ Assertions.assertFalse(buffer.isEmpty());
+ double distanceInMiles = getDistanceInMiles(buffer);
+ Assertions.assertTrue(distanceInMiles >=
+ desiredDistanceInMiles); // buffer should be at least as long as desired distance
+ Assertions.assertTrue(distanceInMiles <=
+ desiredDistanceInMiles + 1); // buffer should not be much longer than desired distance
+ }
+
+ @Test
+ void testGetBufferForPath_Ascending_Failure_EndOfAllMilepostsReached() throws IOException {
+ // prepare
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ResponseEntity mockResponse = new ResponseEntity<>(routeJsonString, HttpStatus.OK);
+ when(cdotGisService.getRouteById(ROUTE_ID)).thenReturn(mockResponse);
+
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(1);
+ Milepost mp2 = allMileposts.get(2);
+ List pathMileposts = List.of(mp1, mp2);
+
+ double desiredDistanceInMiles = 5.0;
+
+ // execute
+ ResponseEntity> response =
+ uut.getBufferForPath(pathMileposts, ROUTE_ID, desiredDistanceInMiles);
+
+ // verify
+ List buffer = response.getBody();
+ Assertions.assertNull(buffer);
+ }
+
+ @Test
+ void testGetBufferForPath_Descending_Success() throws IOException {
+ // prepare
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ResponseEntity mockResponse = new ResponseEntity<>(routeJsonString, HttpStatus.OK);
+ when(cdotGisService.getRouteById(ROUTE_ID)).thenReturn(mockResponse);
+
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(1);
+ Milepost mp2 = allMileposts.get(0);
+ List pathMileposts = List.of(mp1, mp2);
+
+ double desiredDistanceInMiles = 0.5;
+
+ // execute
+ ResponseEntity> response =
+ uut.getBufferForPath(pathMileposts, ROUTE_ID, desiredDistanceInMiles);
+
+ // verify
+ List buffer = response.getBody();
+ assert buffer != null;
+ Assertions.assertFalse(buffer.isEmpty());
+ double distanceInMiles = getDistanceInMiles(buffer);
+ Assertions.assertTrue(distanceInMiles >=
+ desiredDistanceInMiles); // buffer should be at least as long as desired distance
+ Assertions.assertTrue(distanceInMiles <=
+ desiredDistanceInMiles + 1); // buffer should not be much longer than desired distance
+ }
+
+ @Test
+ void testGetBufferForPath_Descending_Failure_EndOfAllMilepostsReached() throws IOException {
+ // prepare
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ResponseEntity mockResponse = new ResponseEntity<>(routeJsonString, HttpStatus.OK);
+ when(cdotGisService.getRouteById(ROUTE_ID)).thenReturn(mockResponse);
+
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(28);
+ Milepost mp2 = allMileposts.get(27);
+ List pathMileposts = List.of(mp1, mp2);
+
+ double desiredDistanceInMiles = 5.0;
+
+ // execute
+ ResponseEntity> response =
+ uut.getBufferForPath(pathMileposts, ROUTE_ID, desiredDistanceInMiles);
+
+ // verify
+ List buffer = response.getBody();
+ Assertions.assertNull(buffer);
+ }
+
+ @Test
+ void testGetBufferForPath_PathDirectionIsNull() throws IOException {
+ // prepare
+ String routeJsonString =
+ new String(Files.readAllBytes(Paths.get(PATH_TO_ROUTE_JSON_TEST_DATA)));
+ ResponseEntity mockResponse = new ResponseEntity<>(routeJsonString, HttpStatus.OK);
+ when(cdotGisService.getRouteById(ROUTE_ID)).thenReturn(mockResponse);
+
+ List allMileposts = getMockMileposts();
+ Milepost mp1 = allMileposts.get(0);
+ List pathMileposts = List.of(mp1);
+
+ int desiredDistanceInMiles = 5;
+
+ // execute
+ ResponseEntity> response =
+ uut.getBufferForPath(pathMileposts, ROUTE_ID, desiredDistanceInMiles);
+
+ // verify
+ List buffer = response.getBody();
+ Assertions.assertNull(buffer);
+ }
+
+ private double getDistanceInMiles(List buffer) {
+ return DistanceCalculator.calculateDistanceInMiles(buffer);
+ }
+
+}
\ No newline at end of file
diff --git a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/RsuControllerTest.java b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/RsuControllerTest.java
index 0eaeaa6a6..e220dc46e 100644
--- a/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/RsuControllerTest.java
+++ b/cv-data-controller/src/test/java/com/trihydro/cvdatacontroller/controller/RsuControllerTest.java
@@ -1,27 +1,26 @@
package com.trihydro.cvdatacontroller.controller;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
-import com.trihydro.library.model.WydotRsu;
-import com.trihydro.library.model.WydotRsuTim;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import com.trihydro.library.model.WydotRsu;
+import com.trihydro.library.model.WydotRsuTim;
+
public class RsuControllerTest extends TestBase {
@Test
public void SelectAllRsus_SUCCESS() throws SQLException {
// Arrange
- String selectStatement = "select * from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid order by milepost asc";
+ String selectStatement = "select rsu_id, ST_X(ST_AsText(geography)) as longitude, ST_Y(ST_AsText(geography)) as latitude, ipv4_address, primary_route, milepost from rsus order by milepost asc";
// Act
ResponseEntity> data = uut.SelectAllRsus();
@@ -33,7 +32,7 @@ public void SelectAllRsus_SUCCESS() throws SQLException {
verify(mockRs).getString("IPV4_ADDRESS");
verify(mockRs).getBigDecimal("LATITUDE");
verify(mockRs).getBigDecimal("LONGITUDE");
- verify(mockRs).getString("ROUTE");
+ verify(mockRs).getString("PRIMARY_ROUTE");
verify(mockRs).getDouble("MILEPOST");
verify(mockStatement).close();
verify(mockConnection).close();
@@ -43,7 +42,7 @@ public void SelectAllRsus_SUCCESS() throws SQLException {
@Test
public void SelectAllRsus_FAIL() throws SQLException {
// Arrange
- String selectStatement = "select * from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid order by milepost asc";
+ String selectStatement = "select rsu_id, ST_X(ST_AsText(geography)) as longitude, ST_Y(ST_AsText(geography)) as latitude, ipv4_address, primary_route, milepost from rsus order by milepost asc";
doThrow(new SQLException()).when(mockRs).getInt("RSU_ID");
// Act
ResponseEntity> data = uut.SelectAllRsus();
@@ -56,49 +55,15 @@ public void SelectAllRsus_FAIL() throws SQLException {
verify(mockRs).close();
}
- @Test
- public void SelectActiveRsus_SUCCESS() throws SQLException {
- // Arrange
- String selectStatement = "select rsu.*, rsu_view.latitude, rsu_view.longitude, rsu_view.ipv4_address from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid where rsu_view.status = 'Existing'";
-
- // Act
- ResponseEntity> data = uut.SelectActiveRsus();
-
- // Assert
- Assertions.assertEquals(HttpStatus.OK, data.getStatusCode());
- verify(mockStatement).executeQuery(selectStatement);
- verify(mockRs).getString("IPV4_ADDRESS");
- verify(mockRs).getBigDecimal("LATITUDE");
- verify(mockRs).getBigDecimal("LONGITUDE");
- verify(mockStatement).close();
- verify(mockConnection).close();
- verify(mockRs).close();
- }
-
- @Test
- public void SelectActiveRsus_FAIL() throws SQLException {
- // Arrange
- String selectStatement = "select rsu.*, rsu_view.latitude, rsu_view.longitude, rsu_view.ipv4_address from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid where rsu_view.status = 'Existing'";
- doThrow(new SQLException()).when(mockRs).getString("IPV4_ADDRESS");
-
- // Act
- ResponseEntity> data = uut.SelectActiveRsus();
-
- // Assert
- Assertions.assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, data.getStatusCode());
- verify(mockStatement).executeQuery(selectStatement);
- verify(mockStatement).close();
- verify(mockConnection).close();
- verify(mockRs).close();
- }
-
@Test
public void GetFullRsusTimIsOn_SUCCESS() throws SQLException {
// Arrange
Long timId = -1l;
- String selectStatement = "select rsu.*, tim_rsu.rsu_index, rsu_view.latitude, rsu_view.longitude, rsu_view.ipv4_address ";
- selectStatement += "from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid ";
- selectStatement += "inner join tim_rsu on tim_rsu.rsu_id = rsu.rsu_id where tim_rsu.tim_id = " + timId;
+ String selectStatement = "select rsus.rsu_id, rsu_credentials.username as update_username, " +
+ "rsu_credentials.password as update_password, ST_X(ST_AsText(rsus.geography)) as longitude, " +
+ "ST_Y(ST_AsText(rsus.geography)) as latitude, rsus.ipv4_address, tim_rsu.rsu_index from rsus " +
+ "inner join rsu_credentials on rsu_credentials.credential_id = rsus.credential_id inner join " +
+ "tim_rsu on tim_rsu.rsu_id = rsus.rsu_id where tim_rsu.tim_id = " + timId;
// Act
ResponseEntity> data = uut.GetFullRsusTimIsOn(timId);
@@ -121,8 +86,11 @@ public void GetFullRsusTimIsOn_SUCCESS() throws SQLException {
public void GetFullRsusTimIsOn_FAIL() throws SQLException {
// Arrange
Long timId = -1l;
- String selectStatement = "select rsu.*, tim_rsu.rsu_index, rsu_view.latitude, rsu_view.longitude, rsu_view.ipv4_address from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid inner join tim_rsu on tim_rsu.rsu_id = rsu.rsu_id where tim_rsu.tim_id = "
- + timId;
+ String selectStatement = "select rsus.rsu_id, rsu_credentials.username as update_username, " +
+ "rsu_credentials.password as update_password, ST_X(ST_AsText(rsus.geography)) as longitude, " +
+ "ST_Y(ST_AsText(rsus.geography)) as latitude, rsus.ipv4_address, tim_rsu.rsu_index from rsus " +
+ "inner join rsu_credentials on rsu_credentials.credential_id = rsus.credential_id inner join " +
+ "tim_rsu on tim_rsu.rsu_id = rsus.rsu_id where tim_rsu.tim_id = " + timId;
doThrow(new SQLException()).when(mockRs).getString("IPV4_ADDRESS");
// Act
@@ -140,8 +108,9 @@ public void GetFullRsusTimIsOn_FAIL() throws SQLException {
public void SelectRsusByRoute_SUCCESS() throws SQLException {
// Arrange
String route = "I80";
- String selectStatement = "select * from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid where rsu_view.route like '%"
- + route + "%' and rsu_view.status = 'Existing' order by milepost asc";
+ String selectStatement = "select rsu_id, ST_X(ST_AsText(geography)) as longitude, " +
+ "ST_Y(ST_AsText(geography)) as latitude, ipv4_address, primary_route, milepost from rsus " +
+ "where primary_route like '%" + route + "%'";
// Act
ResponseEntity> data = uut.SelectRsusByRoute(route);
@@ -163,8 +132,9 @@ public void SelectRsusByRoute_SUCCESS() throws SQLException {
public void SelectRsusByRoute_FAIL() throws SQLException {
// Arrange
String route = "I80";
- String selectStatement = "select * from rsu inner join rsu_view on rsu.deviceid = rsu_view.deviceid where rsu_view.route like '%"
- + route + "%' and rsu_view.status = 'Existing' order by milepost asc";
+ String selectStatement = "select rsu_id, ST_X(ST_AsText(geography)) as longitude, " +
+ "ST_Y(ST_AsText(geography)) as latitude, ipv4_address, primary_route, milepost from rsus " +
+ "where primary_route like '%" + route + "%'";
doThrow(new SQLException()).when(mockRs).getInt("RSU_ID");
// Act
ResponseEntity> data = uut.SelectRsusByRoute(route);
diff --git a/cv-data-controller/src/test/resources/com/trihydro/cvdatacontroller/controller/cdotRouteResponseForI25_First30Mileposts.json b/cv-data-controller/src/test/resources/com/trihydro/cvdatacontroller/controller/cdotRouteResponseForI25_First30Mileposts.json
new file mode 100644
index 000000000..7306d9b14
--- /dev/null
+++ b/cv-data-controller/src/test/resources/com/trihydro/cvdatacontroller/controller/cdotRouteResponseForI25_First30Mileposts.json
@@ -0,0 +1,180 @@
+{
+ "displayFieldName": "",
+ "fieldAliases": {
+ "OBJECTID": "OBJECTID",
+ "Route": "Route",
+ "MMin": "MMin",
+ "MMax": "MMax",
+ "SHAPE_Length": "SHAPE_Length"
+ },
+ "geometryType": "esriGeometryPolyline",
+ "spatialReference": {
+ "wkid": 4326,
+ "latestWkid": 4326
+ },
+ "fields": [
+ {
+ "name": "OBJECTID",
+ "type": "esriFieldTypeOID",
+ "alias": "OBJECTID"
+ },
+ {
+ "name": "Route",
+ "type": "esriFieldTypeString",
+ "alias": "Route",
+ "length": 90
+ },
+ {
+ "name": "MMin",
+ "type": "esriFieldTypeDouble",
+ "alias": "MMin"
+ },
+ {
+ "name": "MMax",
+ "type": "esriFieldTypeDouble",
+ "alias": "MMax"
+ },
+ {
+ "name": "SHAPE_Length",
+ "type": "esriFieldTypeDouble",
+ "alias": "SHAPE_Length"
+ }
+ ],
+ "features": [
+ {
+ "attributes": {
+ "OBJECTID": 1,
+ "Route": "025A",
+ "MMin": -0,
+ "MMax": 298.87900000000002,
+ "SHAPE_Length": 4.4977027441765571
+ },
+ "geometry": {
+ "paths": [
+ [
+ [
+ -104.48045588599996,
+ 36.993878229000074
+ ],
+ [
+ -104.48050318099996,
+ 36.994486232000042
+ ],
+ [
+ -104.48065092399997,
+ 36.995038290000025
+ ],
+ [
+ -104.48070509599995,
+ 36.99524070700005
+ ],
+ [
+ -104.48080757499997,
+ 36.995446935000075
+ ],
+ [
+ -104.48084011699996,
+ 36.995512422000047
+ ],
+ [
+ -104.48109407099997,
+ 36.995913712000061
+ ],
+ [
+ -104.48129848999997,
+ 36.996175908000055
+ ],
+ [
+ -104.48187755499998,
+ 36.996844846000045
+ ],
+ [
+ -104.48219789199999,
+ 36.99729805000004
+ ],
+ [
+ -104.48243650499995,
+ 36.997797080000055
+ ],
+ [
+ -104.48248663299995,
+ 36.997977548000051
+ ],
+ [
+ -104.48255274299999,
+ 36.998345181000047
+ ],
+ [
+ -104.48256583299997,
+ 36.998729557000047
+ ],
+ [
+ -104.48252486699994,
+ 36.999069289000033
+ ],
+ [
+ -104.48251842099995,
+ 36.999122742000054
+ ],
+ [
+ -104.48241381599996,
+ 36.999516043000028
+ ],
+ [
+ -104.48041568299999,
+ 37.005994416000078
+ ],
+ [
+ -104.48016812399999,
+ 37.006796975000043
+ ],
+ [
+ -104.48006938599997,
+ 37.007213985000078
+ ],
+ [
+ -104.48000987099999,
+ 37.007636323000042
+ ],
+ [
+ -104.48000904399998,
+ 37.007642192000048
+ ],
+ [
+ -104.47999405199994,
+ 37.00807076600006
+ ],
+ [
+ -104.48002256199999,
+ 37.008504324000057
+ ],
+ [
+ -104.48009628499995,
+ 37.008939769000051
+ ],
+ [
+ -104.48021678199996,
+ 37.009374874000059
+ ],
+ [
+ -104.48030103699995,
+ 37.009608998000033
+ ],
+ [
+ -104.48237161199995,
+ 37.015362141000026
+ ],
+ [
+ -104.48260622599997,
+ 37.01598049100005
+ ],
+ [
+ -104.48277556599999,
+ 37.016368185000033
+ ]
+ ]
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/factory/KafkaFactory.java b/cv-data-service-library/src/main/java/com/trihydro/library/factory/KafkaFactory.java
index ce8add417..4667f9186 100644
--- a/cv-data-service-library/src/main/java/com/trihydro/library/factory/KafkaFactory.java
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/factory/KafkaFactory.java
@@ -4,17 +4,35 @@
import java.util.List;
import java.util.Properties;
+import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
+import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Slf4j
+@ConfigurationProperties("data-service-library.kafka")
public class KafkaFactory {
+ private String kafkaType;
+ private String confluentKey;
+ private String confluentSecret;
+ private final Properties kafkaProperties;
+
+ public KafkaFactory() throws IllegalArgumentException {
+
+ kafkaType = getKafkaType();
+
+ if ("CONFLUENT".equalsIgnoreCase(kafkaType)) {
+ kafkaProperties = addConfluentProperties(new Properties());
+ } else {
+ kafkaProperties = new Properties();
+ }
+ }
/**
* Creates a Kafka consumer that has a key.deserializer and value.deserializer
@@ -102,6 +120,8 @@ public Consumer createStringConsumer(String host, String consume
props.put("max.poll.records", maxPollRecords.intValue());
}
+ props.putAll(kafkaProperties);
+
var consumer = new KafkaConsumer(props);
consumer.subscribe(topics);
@@ -124,6 +144,51 @@ public Producer createStringProducer(String host) {
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
- return new KafkaProducer(props);
+ props.putAll(kafkaProperties);
+
+ return new KafkaProducer<>(props);
+ }
+
+ Properties addConfluentProperties(Properties props) {
+ String username = getConfluentKey();
+ String password = getConfluentSecret();
+
+ if (Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(password)) {
+ throw new IllegalArgumentException("CONFLUENT_KEY and CONFLUENT_SECRET must be set in the environment");
+ }
+
+ String auth = "org.apache.kafka.common.security.plain.PlainLoginModule required " +
+ "username=\"" + username + "\" " +
+ "password=\"" + password + "\";";
+ props.put("sasl.jaas.config", auth);
+ props.put("ssl.endpoint.identification.algorithm", "https");
+ props.put("security.protocol", "SASL_SSL");
+ props.put("sasl.mechanism", "PLAIN");
+
+ return props;
+ }
+
+ final String getKafkaType() {
+ return kafkaType;
+ }
+
+ public String getConfluentKey() {
+ return confluentKey;
+ }
+
+ public void setConfluentKey(String confluentKey) {
+ this.confluentKey = confluentKey;
+ }
+
+ public String getConfluentSecret() {
+ return confluentSecret;
+ }
+
+ public void setConfluentSecret(String confluentSecret) {
+ this.confluentSecret = confluentSecret;
+ }
+
+ public void setKafkaType(String kafkaType) {
+ this.kafkaType = kafkaType;
}
}
\ No newline at end of file
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CdotGisConnector.java b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CdotGisConnector.java
new file mode 100644
index 000000000..9271ad75f
--- /dev/null
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/helpers/CdotGisConnector.java
@@ -0,0 +1,54 @@
+package com.trihydro.library.helpers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+
+import com.trihydro.library.service.RestTemplateProvider;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestClientException;
+
+@Component
+public class CdotGisConnector {
+ private final String baseUrl = "https://dtdapps.coloradodot.info/arcgis/rest/services/LRS/Routes_withDEC/MapServer/exts/CdotLrsAccessRounded";
+
+ private final RestTemplateProvider restTemplateProvider;
+
+ private final Logger logger = LoggerFactory.getLogger(CdotGisConnector.class);
+
+ public CdotGisConnector(RestTemplateProvider _restTemplateProvider) {
+ this.restTemplateProvider = _restTemplateProvider;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ public RestTemplateProvider getRestTemplateProvider() {
+ return restTemplateProvider;
+ }
+
+ /**
+ * Retrieves the route information from the CDOT GIS service by route ID.
+ *
+ * This method sends a GET request to the CDOT GIS service to retrieve the route information
+ * in JSON format. The JSON response includes every latitude and longitude point associated
+ * with the specified route, such as I-25.
+ *
+ * @param routeId the ID of the route to retrieve
+ * @return a ResponseEntity containing the JSON response from the CDOT GIS service
+ * @throws RestClientException if an error occurs while making the request
+ */
+ public ResponseEntity getRouteById(String routeId) throws RestClientException {
+ String targetUrl = baseUrl + "/Route";
+ logger.info("Getting route with ID {} from CDOT GIS service at: {}", routeId, targetUrl);
+ String params = "?routeId=" + routeId + "&outSR=4326&f=json";
+ HttpHeaders headers = new HttpHeaders();
+ headers.set("Accept", "application/json");
+ HttpEntity entity = new HttpEntity<>(headers);
+ return restTemplateProvider.GetRestTemplate().exchange(targetUrl + params, HttpMethod.GET, entity, String.class);
+ }
+}
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 a920b31a4..e8c9bd52a 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
@@ -24,10 +24,8 @@
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.MsgId;
-import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.RoadSignID;
import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.NodeXY;
import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType.TravelerInfoType;
-import us.dot.its.jpo.ode.plugin.j2735.timstorage.MutcdCode.MutcdCodeEnum;
@Component
@Slf4j
@@ -45,15 +43,15 @@ public void InjectDependencies(Utility _utility) {
*
* @param wydotTim The WydotTim object containing the data for the TIM.
* @param genProps The TimGenerationProps object containing the generation properties.
- * @param content The ContentEnum object representing the content of the TIM.
- * @param frameType The TravelerInfoType object representing the frame type of the TIM.
* @param allMileposts The list of Milepost objects representing all mileposts.
* @param reducedMileposts The list of Milepost objects representing reduced mileposts.
* @param anchor The Milepost object representing the anchor milepost.
* @return The WydotTravelerInputData object containing the built TIM.
*/
- public WydotTravelerInputData buildTim(WydotTim wydotTim, TimGenerationProps genProps, ContentEnum content,
- TravelerInfoType frameType, List allMileposts, List reducedMileposts, Milepost anchor) {
+ public WydotTravelerInputData buildTim(WydotTim wydotTim, TimGenerationProps genProps,
+ List allMileposts, List reducedMileposts, Milepost anchor) {
+
+ ContentEnum content = ContentEnum.advisory;
// build TIM object with data
WydotTravelerInputData timToSend = new WydotTravelerInputData();
@@ -75,18 +73,18 @@ public WydotTravelerInputData buildTim(WydotTim wydotTim, TimGenerationProps gen
dataFrame.setPriority(5);
dataFrame.setContent(content.getStringValue());
- dataFrame.setFrameType(frameType);
+ // Per CTW, FrameType should be set to roadSignage when state or local deployment agency is generating the message
+ // which is all messages coming through the TIMM so always set to roadSignage
+ dataFrame.setFrameType(TravelerInfoType.roadSignage);
dataFrame.setUrl("null");
// add itis codes to tim
dataFrame.setItems(wydotTim.getItisCodes().toArray(new String[wydotTim.getItisCodes().size()]));
- // create anchor for the msgId
- OdePosition3D anchorPosition = new OdePosition3D();
- anchorPosition.setLatitude(anchor.getLatitude());
- anchorPosition.setLongitude(anchor.getLongitude());
-
- // build msgId
- MsgId msgId = buildMsgId(anchorPosition, content, frameType);
+ // Per CTW guidance, msgId must be populated using furtherInfoID (not roadSignID)
+ // Per SAE J2735 (DE_FurtherInfoID), this field is defined as an OCTET STRING (SIZE(2)).
+ // Since furtherInfoID is not used, set it to two zero bytes (0000) to indicate "unknown or not present"
+ MsgId msgId = new MsgId();
+ msgId.setFurtherInfoID("0000");
dataFrame.setMsgId(msgId);
// set regions. note that we now support multiple regions in a single TIM package
@@ -198,7 +196,7 @@ protected OdeTravelerInformationMessage.DataFrame.Region buildSingleRegion(BigDe
region.setDirection(directionString); // heading slice
// set path nodes
- if (reducedMileposts != null && reducedMileposts.size() > 0) {
+ if (reducedMileposts != null && !reducedMileposts.isEmpty()) {
OdeTravelerInformationMessage.NodeXY[] nodes = buildNodePathFromMileposts(reducedMileposts, anchor);
OdeTravelerInformationMessage.DataFrame.Region.Path path = new OdeTravelerInformationMessage.DataFrame.Region.Path();
path.setScale(0);
@@ -246,7 +244,7 @@ public String buildHeadingSliceFromMileposts(List allMileposts, OdePos
int timDirection = 0;
// this is a regular tim, so we need to set the direction normally
// path list - change later
- if (allMileposts != null && allMileposts.size() > 0) {
+ if (allMileposts != null && !allMileposts.isEmpty()) {
double startLat = anchorPosition.getLatitude().doubleValue();
double startLon = anchorPosition.getLongitude().doubleValue();
for (int j = 0; j < allMileposts.size(); j++) {
@@ -269,30 +267,4 @@ public String buildHeadingSliceFromMileposts(List allMileposts, OdePos
headingSliceString = StringUtils.reverse(headingSliceString);
return headingSliceString;
}
-
- /**
- * Builds a message ID based on the provided anchor position, content, and frame type.
- *
- * @param anchorPosition The anchor position for the road sign.
- * @param content The content of the message.
- * @param frameType The type of the frame.
- * @return The built message ID.
- */
- protected MsgId buildMsgId(OdePosition3D anchorPosition, ContentEnum content, TravelerInfoType frameType) {
- MsgId msgId = new MsgId();
- RoadSignID roadSignID = new RoadSignID();
- roadSignID.setPosition(anchorPosition);
-
- // if we are coming in with content=speedLimit and frameType=roadSignage,
- // we need to set the mutcdCode to regulatory to display the regulatory signage
- if (content == ContentEnum.speedLimit && frameType == TravelerInfoType.roadSignage) {
- roadSignID.setMutcdCode(MutcdCodeEnum.regulatory);
- } else {
- roadSignID.setMutcdCode(MutcdCodeEnum.warning);
- }
- // set view angle to 360 degrees
- roadSignID.setViewAngle("1111111111111111");
- msgId.setRoadSignID(roadSignID);
- return msgId;
- }
}
\ 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 8ffcad458..f9341bcf6 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
@@ -11,9 +11,10 @@
import java.util.List;
import java.util.Map;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
+import lombok.extern.slf4j.Slf4j;
+
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
@@ -56,7 +57,7 @@ public OdeLogMetadata convertTimMetadataJsonToJava(String value) {
// check for null rxSource for Distress Notifications
if (receivedMessageDetailsNode != null) {
String rxSource = mapper.treeToValue(receivedMessageDetailsNode.get("rxSource"), String.class);
- if (rxSource.equals("")) {
+ if (rxSource.isEmpty()) {
((ObjectNode) receivedMessageDetailsNode).remove("rxSource");
((ObjectNode) metaDataNode).replace("receivedMessageDetails", receivedMessageDetailsNode);
}
@@ -253,16 +254,16 @@ public OdeTimPayload convertTimPayloadJsonToJava(String value) {
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());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.exitService.getStringValue())) {
sequenceArrNode = contentNode.get(ContentEnum.exitService.getStringValue()).get("SEQUENCE");
- dataFrame.setContent(ContentEnum.exitService.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.genericSign.getStringValue())) {
sequenceArrNode = contentNode.get(ContentEnum.genericSign.getStringValue()).get("SEQUENCE");
- dataFrame.setContent(ContentEnum.genericSign.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.workZone.getStringValue())) {
sequenceArrNode = contentNode.get(ContentEnum.workZone.getStringValue()).get("SEQUENCE");
- dataFrame.setContent(ContentEnum.workZone.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
}
LocalDate now = LocalDate.now();
@@ -460,7 +461,7 @@ public OdeTimPayload convertTmcTimTopicJsonToJava(String value) {
JsonNode timeStampNode = timNode.get("timeStamp");
if (timeStampNode != null) {
LocalDateTime timeStampDate = firstDay.atStartOfDay().plus(timeStampNode.asInt(), ChronoUnit.MINUTES);
- tim.setTimeStamp(timeStampDate.toString() + "Z");
+ tim.setTimeStamp(timeStampDate + "Z");
}
JsonNode travelerDataFrameArray = timNode.findValue("dataFrames");
@@ -472,56 +473,50 @@ public OdeTimPayload convertTmcTimTopicJsonToJava(String value) {
dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.speedLimit.getStringValue())) {
sequenceArrNode = contentNode.get("speedLimit");
- dataFrame.setContent(ContentEnum.speedLimit.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.exitService.getStringValue())) {
sequenceArrNode = contentNode.get("exitService");
- dataFrame.setContent(ContentEnum.exitService.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.genericSign.getStringValue())) {
sequenceArrNode = contentNode.get("genericSign");
- dataFrame.setContent(ContentEnum.genericSign.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.getStringValue());
} else if (contentNode.has(ContentEnum.workZone.getStringValue())) {
sequenceArrNode = contentNode.get("workZone");
- dataFrame.setContent(ContentEnum.workZone.getStringValue());
+ dataFrame.setContent(ContentEnum.advisory.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) {
+ 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) {
+ 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)) {
+ if (!itemsList.contains(item))
itemsList.add(item);
- }
}
}
// ADD NON ARRAY ELEMENT
if (sequenceArrNode != null && !sequenceArrNode.isArray()) {
- if (sequenceArrNode.get("item").get("itis") != null) {
+ 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) {
+ 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");
- }
itemsList.add(item);
}
// 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);
+ if (frameTypeNode != null) {
+ if (frameTypeNode.fieldNames().hasNext()) {
+ TravelerInfoType frameType = TravelerInfoType.valueOf(frameTypeNode.fieldNames().next());
+ if (frameType != null) {
+ dataFrame.setFrameType(frameType);
+ }
+ }
}
JsonNode startTimeNode = travelerDataFrame.get("startTime");
@@ -530,9 +525,10 @@ public OdeTimPayload convertTmcTimTopicJsonToJava(String value) {
LocalDateTime startDate = firstDay.atStartOfDay().plus(startTimeNode.asInt(), ChronoUnit.MINUTES);
- dataFrame.setStartDateTime(startDate.toString() + "Z");
+ dataFrame.setStartDateTime(startDate + "Z");
dataFrame.setDurationTime(durationNode.asInt());
dataFrame.setPriority(priorityNode.asInt());
+ dataFrame.setFrameType(TravelerInfoType.roadSignage);
String[] items = new String[itemsList.size()];
items = itemsList.toArray(items);
@@ -543,7 +539,9 @@ public OdeTimPayload convertTmcTimTopicJsonToJava(String value) {
// it as a region
if (geographicalPathNode.isObject()) {
// single region
- regions.add(getRegion(geographicalPathNode));
+ JsonNode regionNode = geographicalPathNode;
+ Region region = getRegion(regionNode);
+ regions.add(region);
} else if (geographicalPathNode.isArray()) {
// multiple regions
for (final JsonNode regionNode : geographicalPathNode) {
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 36404bb40..2efd8262b 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
@@ -20,7 +20,6 @@
import com.trihydro.library.model.ActiveTimError;
import com.trihydro.library.model.ActiveTimHolding;
import com.trihydro.library.model.ActiveTimValidationResult;
-import com.trihydro.library.model.ContentEnum;
import com.trihydro.library.model.Coordinate;
import com.trihydro.library.model.Milepost;
import com.trihydro.library.model.MilepostBuffer;
@@ -57,10 +56,7 @@
import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.MsgId;
import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.Region;
import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.Region.Path;
-import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame.RoadSignID;
import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.NodeXY;
-import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType.TravelerInfoType;
-import us.dot.its.jpo.ode.plugin.j2735.timstorage.MutcdCode.MutcdCodeEnum;
@Component
@Slf4j
@@ -353,13 +349,22 @@ private WydotTim getWydotTimFromTum(TimUpdateModel tum) {
}
private List getAllMps(WydotTim wydotTim) {
- List allMps;
+ List allMps = new ArrayList<>();
log.info("Fetching mileposts for regular TIM with client id: {}", wydotTim.getClientId());
if (wydotTim.getEndPoint() != null) {
- allMps = milepostService.getMilepostsByStartEndPointDirection(wydotTim);
- log.info("Found {} mileposts between {} and {}", allMps.size(),
- gson.toJson(wydotTim.getStartPoint()), gson.toJson(wydotTim.getEndPoint()));
+ if (wydotTim.getGeometry() != null && wydotTim.getGeometry().size() > 1) {
+ allMps.addAll(wydotTim.toMileposts());
+ milepostService.setMilepostCache(allMps, wydotTim.getClientId());
+ } else {
+ // Check to see if milepost array exists in cache
+ allMps = milepostService.getMilepostCache(wydotTim.getClientId());
+ if (allMps.isEmpty()) {
+ allMps = milepostService.getMilepostsByStartEndPointDirection(wydotTim);
+ }
+ }
+ log.info("Found {} mileposts between {} and {}", allMps.size(),
+ gson.toJson(wydotTim.getStartPoint()), gson.toJson(wydotTim.getEndPoint()));
} else {
// point incident
MilepostBuffer mpb = new MilepostBuffer();
@@ -799,7 +804,7 @@ private OdeTravelerInformationMessage getTim(TimUpdateModel aTim, List
boolean resetStartTimes,
boolean resetExpirationTime) {
String nowAsISO = Instant.now().toString();
- DataFrame dataFrame = getDataFrame(aTim, anchor, resetStartTimes, resetExpirationTime);
+ DataFrame dataFrame = getDataFrame(aTim, resetStartTimes, resetExpirationTime);
// check to see if we have any itis codes
// if not, just continue on
if (dataFrame.getItems() == null || dataFrame.getItems().length == 0) {
@@ -904,7 +909,7 @@ private List sendTim(WydotTravelerInputData timToSend, Tim
log.trace("Checking if active TIM is not a SAT TIM and along route with RSUs");
if (StringUtils.isBlank(tum.getSatRecordId()) && Arrays.asList(config.getRsuRoutes()).contains(tum.getRoute())) {
log.debug("Sending active TIM with client id {} to RSU", tum.getClientId());
- var exMsg = updateAndSendRSU(timToSend, tum);
+ var exMsg = updateAndSendRSU(timToSend, tum, reduced_mps);
if (StringUtils.isNotBlank(exMsg)) {
exceptions.add(new ResubmitTimException(activeTimId, exMsg));
}
@@ -937,25 +942,12 @@ protected int getNextMessageCount(int currentCount) {
return ++currentCount;
}
- private DataFrame getDataFrame(TimUpdateModel aTim, Milepost anchor, boolean resetStartTimes,
+ private DataFrame getDataFrame(TimUpdateModel aTim, boolean resetStartTimes,
boolean resetExpirationTime) {
- // RoadSignID
- RoadSignID rsid = new RoadSignID();
- rsid.setPosition(getAnchorPosition(anchor));
- rsid.setViewAngle("1111111111111111");
-
- // if we are coming in with content=speedLimit and frameType=roadSignage,
- // we need to set the mutcdCode to regulatory to display the regulatory signage
- if (aTim.getDfContent() == ContentEnum.speedLimit &&
- aTim.getFrameType() == TravelerInfoType.roadSignage) {
- rsid.setMutcdCode(MutcdCodeEnum.regulatory);
- } else {
- rsid.setMutcdCode(MutcdCodeEnum.warning);
- }
// MsgId
MsgId msgId = new MsgId();
- msgId.setRoadSignID(rsid);
+ msgId.setFurtherInfoID("0000");
// DataFrame
DataFrame df = new DataFrame();
@@ -1125,15 +1117,24 @@ private String getBaseRegionName(TimUpdateModel aTim, String middle) {
return regionName;
}
- private String updateAndSendRSU(WydotTravelerInputData timToSend, TimUpdateModel aTim) {
+ private String updateAndSendRSU(WydotTravelerInputData timToSend, TimUpdateModel aTim, List mileposts) {
String exMsg = "";
List wydotRsus = rsuService.getFullRsusTimIsOn(aTim.getTimId());
List dbRsus = new ArrayList();
if (wydotRsus == null || wydotRsus.size() <= 0) {
log.info("No RSUs found for active_tim_id {}", aTim.getActiveTimId());
- dbRsus = rsuService.getRsusByLatLong(aTim.getDirection(), aTim.getStartPoint(),
- aTim.getEndPoint(), aTim.getRoute());
+ if (mileposts != null && mileposts.size() > 0) {
+ // use milepost geometry to find RSUs
+ List coords = new ArrayList();
+ for (Milepost mp : mileposts) {
+ coords.add(new Coordinate(mp.getLatitude(), mp.getLongitude()));
+ }
+ dbRsus = rsuService.getRsusByGeometry(coords);
+ } else {
+ dbRsus = rsuService.getRsusByLatLong(aTim.getDirection(), aTim.getStartPoint(), aTim.getEndPoint(),
+ aTim.getRoute());
+ }
// if no RSUs found
if (dbRsus.isEmpty()) {
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/model/SetMilepostCacheRequest.java b/cv-data-service-library/src/main/java/com/trihydro/library/model/SetMilepostCacheRequest.java
new file mode 100644
index 000000000..bda604c15
--- /dev/null
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/model/SetMilepostCacheRequest.java
@@ -0,0 +1,19 @@
+package com.trihydro.library.model;
+
+import java.util.List;
+
+public class SetMilepostCacheRequest {
+ private final List mileposts;
+ private final String timID;
+
+ public SetMilepostCacheRequest(List mileposts, String timID) {
+ this.mileposts = mileposts;
+ this.timID = timID;
+ }
+ public List getMileposts() {
+ return mileposts;
+ }
+ public String getTimID() {
+ return timID;
+ }
+}
\ No newline at end of file
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 36103fe2f..beb78832a 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
@@ -43,7 +43,6 @@ public class TimUpdateModel extends ActiveTim {
public BigDecimal getLaneWidth() {
return laneWidth;
- // DataFrame df;df.setFrameType(frameType);
}
public String getRegionDirection() {
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/model/WydotTim.java b/cv-data-service-library/src/main/java/com/trihydro/library/model/WydotTim.java
index 1f72a5bbe..700988d3c 100644
--- a/cv-data-service-library/src/main/java/com/trihydro/library/model/WydotTim.java
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/model/WydotTim.java
@@ -7,38 +7,48 @@
public class WydotTim {
- @ApiModelProperty(value = "Expected values are I, D, B", required = true)
- private String direction;
- @ApiModelProperty(required = true)
- private Coordinate startPoint;
- @ApiModelProperty(required = true)
- private Coordinate endPoint;
- @ApiModelProperty(value = "The common name for the selected route", required = true)
- private String route;
- @ApiModelProperty(required = true)
- private List itisCodes;
- @ApiModelProperty(required = true)
- private String clientId;
+ @ApiModelProperty(value = "Expected values are I, D, B", required = true)
+ private String direction;
+ @ApiModelProperty(required = false)
+ private Coordinate startPoint;
+ @ApiModelProperty(required = false)
+ private Coordinate endPoint;
+ @ApiModelProperty(value = "The common name for the selected route", required = true)
+ private String route;
+ @ApiModelProperty(required = true)
+ private List itisCodes;
+ @ApiModelProperty(required = true)
+ private String clientId;
+ @ApiModelProperty(required = false)
+ private List geometry;
+ @ApiModelProperty(required = false)
+ private Integer bearing;
public WydotTim() {
}
- public WydotTim(WydotTim o) {
- this.direction = o.direction;
- if (o.startPoint != null) {
- this.startPoint =
- new Coordinate(o.startPoint.getLatitude(), o.startPoint.getLongitude());
- }
- if (o.endPoint != null) {
- this.endPoint = new Coordinate(o.endPoint.getLatitude(), o.endPoint.getLongitude());
- }
- this.route = o.route;
- if (o.itisCodes != null) {
- this.itisCodes = new ArrayList<>(o.itisCodes);
- }
- this.clientId = o.clientId;
- }
+ public WydotTim(WydotTim o) {
+ this.direction = o.direction;
+ if (o.startPoint != null)
+ this.startPoint = new Coordinate(o.startPoint.getLatitude(), o.startPoint.getLongitude());
+ if (o.endPoint != null)
+ this.endPoint = new Coordinate(o.endPoint.getLatitude(), o.endPoint.getLongitude());
+ this.route = o.route;
+ if (o.itisCodes != null)
+ this.itisCodes = new ArrayList<>(o.itisCodes);
+ this.clientId = o.clientId;
+ if (o.geometry != null) {
+ this.geometry = new ArrayList<>(o.geometry);
+ // If geometry is present and has more than one point, set start and end points
+ if (o.geometry.size() > 1) {
+ this.startPoint = new Coordinate(o.geometry.get(0).getLatitude(), o.geometry.get(0).getLongitude());
+ this.endPoint = new Coordinate(o.geometry.get(o.geometry.size() - 1).getLatitude(), o.geometry.get(o.geometry.size() - 1).getLongitude());
+ }
+ }
+ if (o.bearing != null)
+ this.bearing = o.bearing;
+ }
public WydotTim(TimUpdateModel aTim) {
setClientId(aTim.getClientId());
@@ -96,7 +106,52 @@ public String getRoute() {
return this.route;
}
- public void setRoute(String route) {
- this.route = route;
- }
+ public void setRoute(String route) {
+ this.route = route;
+ }
+
+ public List getGeometry() {
+ return this.geometry;
+ }
+
+ public void setGeometry(List geometry) {
+ this.geometry = geometry;
+ }
+
+ public Integer getBearing() {
+ return this.bearing;
+ }
+
+ public void setBearing(Integer bearing) {
+ this.bearing = bearing;
+ }
+
+ public boolean isGeometryValid() {
+ if (this.geometry != null && this.getGeometry().size() > 1) { // must have 2 or more points to be valid
+ for (Coordinate coord : this.geometry) {
+ if (!coord.isValid()) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public List toMileposts() {
+ var mileposts = new ArrayList();
+ if (isGeometryValid()) {
+ for (Coordinate coordinate : this.getGeometry()) {
+ Milepost milepost = new Milepost();
+ milepost.setLatitude(coordinate.getLatitude());
+ milepost.setLongitude(coordinate.getLongitude());
+ milepost.setDirection(this.getDirection());
+ milepost.setCommonName(this.getRoute());
+ milepost.setMilepost(0.0);
+ mileposts.add(milepost);
+ }
+ }
+ return mileposts;
+ }
}
\ No newline at end of file
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 7818f5eff..73de74097 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
@@ -212,15 +212,15 @@ public String getMinExpiration(String packetID, String expDate) {
public TimUpdateModel getUpdateModelFromActiveTimId(Long activeTimId) {
String url = String.format("%s/active-tim/update-model/%d", config.getCvRestService(), activeTimId);
log.debug("Getting update model for active TIM ID: {} from URL: {}", activeTimId, url);
- TimUpdateModel timUpdateModel = null;
- try {
- ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(url, TimUpdateModel.class);
- timUpdateModel = response.getBody();
- } catch (Exception e) {
- log.error("Error getting update model for active TIM ID: {} from URL: {}", activeTimId, url, e);
- }
- log.debug("Update model found: {}", timUpdateModel);
- return timUpdateModel;
+ TimUpdateModel timUpdateModel = null;
+ try {
+ ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(url, TimUpdateModel.class);
+ timUpdateModel = response.getBody();
+ } catch (Exception e) {
+ log.error("Error getting update model for active TIM ID: {} from URL: {}", activeTimId, url, e);
+ }
+ log.debug("Update model found: {}", timUpdateModel);
+ return timUpdateModel;
}
public boolean resetActiveTimsExpirationDate(List activeTimIds) {
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/service/MilepostService.java b/cv-data-service-library/src/main/java/com/trihydro/library/service/MilepostService.java
index 15de8a472..2867998b7 100644
--- a/cv-data-service-library/src/main/java/com/trihydro/library/service/MilepostService.java
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/service/MilepostService.java
@@ -5,6 +5,7 @@
import com.trihydro.library.model.Milepost;
import com.trihydro.library.model.MilepostBuffer;
import com.trihydro.library.model.WydotTim;
+import com.trihydro.library.model.SetMilepostCacheRequest;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
@@ -40,4 +41,65 @@ public List getMilepostsByPointWithBuffer(MilepostBuffer milepostBuffe
entity, responseType);
return response.getBody();
}
+
+ public String setMilepostCache(List mileposts, String timID) {
+ String url = String.format("%s/set-milepost-cache", config.getCvRestService());
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ SetMilepostCacheRequest body = new SetMilepostCacheRequest(mileposts, timID);
+ HttpEntity entity = new HttpEntity(body, headers);
+ ResponseEntity response = restTemplateProvider.GetRestTemplate().exchange(url, HttpMethod.POST, entity,
+ String.class);
+ return response.getBody();
+ }
+
+ public List getMilepostCache(String timID) {
+ String url = String.format("%s/get-milepost-cache/%s", config.getCvRestService(), timID);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity entity = new HttpEntity(null, headers);
+ ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {};
+ ResponseEntity> response = restTemplateProvider.GetRestTemplate().exchange(url, HttpMethod.GET,
+ entity, responseType);
+ return response.getBody();
+ }
+
+ public String deleteMilepostCache(String timID) {
+ String url = String.format("%s/delete-milepost-cache/%s", config.getCvRestService(), timID);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity entity = new HttpEntity(null, headers);
+ ResponseEntity response = restTemplateProvider.GetRestTemplate().exchange(url, HttpMethod.DELETE, entity,
+ String.class);
+ return response.getBody();
+ }
+
+ public void clearMilepostCache() {
+ String url = String.format("%s/clear-milepost-cache/", config.getCvRestService());
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity entity = new HttpEntity(null, headers);
+ ParameterizedTypeReference responseType = new ParameterizedTypeReference() {};
+ restTemplateProvider.GetRestTemplate().exchange(url, HttpMethod.GET, entity, responseType);
+ }
+
+ /**
+ * Retrieves a buffer of mileposts for a given path from the CDOT upstream service.
+ *
+ * @param routeId the ID of the route for which the buffer is to be retrieved
+ * @param desiredDistanceInMiles the desired distance in miles for the buffer
+ * @param pathMileposts the list of mileposts representing the path
+ * @return a list of mileposts representing the buffer for the given path
+ */
+ public List getBufferForPath(String routeId, double desiredDistanceInMiles, List pathMileposts) {
+ String url = String.format("%s/cdot-upstream-path/get-buffer-for-path/%s/%s", config.getCvRestService(), routeId, desiredDistanceInMiles);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity> entity = new HttpEntity<>(pathMileposts, headers);
+ ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {
+ };
+ ResponseEntity> response = restTemplateProvider.GetRestTemplate().exchange(url, HttpMethod.POST,
+ entity, responseType);
+ return response.getBody();
+ }
}
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/service/RsuService.java b/cv-data-service-library/src/main/java/com/trihydro/library/service/RsuService.java
index c03a9f140..420cb54b0 100644
--- a/cv-data-service-library/src/main/java/com/trihydro/library/service/RsuService.java
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/service/RsuService.java
@@ -6,32 +6,23 @@
import java.util.List;
import java.util.stream.Collectors;
-import com.trihydro.library.helpers.Utility;
-import com.trihydro.library.model.Coordinate;
-import com.trihydro.library.model.WydotRsu;
-import com.trihydro.library.model.WydotRsuTim;
-
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
+import com.trihydro.library.model.Coordinate;
+import com.trihydro.library.model.WydotRsu;
+import com.trihydro.library.model.WydotRsuTim;
+
@Component
public class RsuService extends CvDataServiceLibrary {
private final Logger logger = LoggerFactory.getLogger(RsuService.class);
- private Utility utility;
-
- @Autowired
- public void InjectDependencies(Utility _utility) {
- this.utility = _utility;
- }
-
public List selectAll() {
String url = String.format("%s/rsus", config.getCvRestService());
ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(url,
@@ -55,6 +46,13 @@ public List selectRsusByRoute(String route) {
return Arrays.asList(rsus);
}
+ public List selectRsusByGeometry(String geometry) {
+ String url = String.format("%s/rsus-by-geometry/%s", config.getCvRestService(), geometry);
+ ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(url,
+ WydotRsu[].class);
+ return Arrays.asList(response.getBody());
+ }
+
public List getFullRsusTimIsOn(Long timId) {
String url = String.format("%s/rsus-for-tim/%d", config.getCvRestService(), timId);
logger.debug("Getting RSUs for TIM: {} from URL: {}", timId, url);
@@ -87,10 +85,10 @@ public List getRsusByLatLong(String direction, Coordinate startPoint,
// if there are no rsus on this route
List mainRsus = getRsusByRouteWithRetryAndTimeout(route);
- if (mainRsus.size() == 0) {
+ if (mainRsus.size() == 0) {
logger.info("No RSUs found for route {}", route);
return rsus;
- } else {
+ } else {
logger.info("Found {} RSUs for route {}", mainRsus.size(), route);
}
@@ -166,7 +164,7 @@ public List getRsusByLatLong(String direction, Coordinate startPoint,
}
}
- if (rsusHigher.size() == 0) {
+ if (rsusHigher.size() == 0) {
logger.info("No RSUs found higher than 'low' point");
}
@@ -223,6 +221,23 @@ public List getRsusByLatLong(String direction, Coordinate startPoint,
return rsus;
}
+ public List getRsusByGeometry(List geometry) {
+ var coordinateBuilder = new StringBuilder("LINESTRING(");
+
+ for (Coordinate coordinate : geometry) {
+ coordinateBuilder.append(coordinate.getLongitude()).append(" ").append(coordinate.getLatitude()).append(",");
+ }
+ coordinateBuilder.deleteCharAt(coordinateBuilder.length() - 1);
+ coordinateBuilder.append(")");
+
+ List rsus = selectRsusByGeometry(coordinateBuilder.toString());
+ for (WydotRsu rsu : rsus) {
+ rsu.setRsuRetries(3);
+ rsu.setRsuTimeout(5000);
+ }
+ return rsus;
+ }
+
private List getRsusByRouteWithRetryAndTimeout(String route) {
List rsus = selectRsusByRoute(route);
for (WydotRsu rsu : rsus) {
diff --git a/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java b/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java
index 0a41d28d7..56271c9c5 100644
--- a/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java
+++ b/cv-data-service-library/src/main/java/com/trihydro/library/service/WydotTimService.java
@@ -30,7 +30,6 @@
import com.trihydro.library.model.ActiveRsuTimQueryModel;
import com.trihydro.library.model.ActiveTim;
import com.trihydro.library.model.ActiveTimHolding;
-import com.trihydro.library.model.ContentEnum;
import com.trihydro.library.model.Coordinate;
import com.trihydro.library.model.EmailProps;
import com.trihydro.library.model.Milepost;
@@ -53,7 +52,6 @@
import us.dot.its.jpo.ode.plugin.j2735.OdeGeoRegion;
import us.dot.its.jpo.ode.plugin.j2735.OdePosition3D;
import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.DataFrame;
-import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType.TravelerInfoType;
@Component
@Slf4j
@@ -115,11 +113,11 @@ public void InjectDependencies(EmailProps _emailProps, OdeProps _odeProps, TimGe
DateTimeFormatter utcformatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
public WydotTravelerInputData createTim(WydotTim wydotTim, String timTypeStr, String startDateTime,
- String endDateTime, ContentEnum content, TravelerInfoType frameType, List allMileposts,
- List reducedMileposts, Milepost anchor) {
+ String endDateTime, List allMileposts,
+ List reducedMileposts, Milepost anchor, String dotGnisId) {
// build base TIM
- WydotTravelerInputData timToSend = createBaseTimUtil.buildTim(wydotTim, genProps, content, frameType,
+ WydotTravelerInputData timToSend = createBaseTimUtil.buildTim(wydotTim, genProps,
allMileposts, reducedMileposts, anchor);
if (timToSend == null) {
@@ -149,21 +147,36 @@ public WydotTravelerInputData createTim(WydotTim wydotTim, String timTypeStr, St
timToSend.getTim().getDataframes()[0].setDurationTime(120);
}
- // set PacketId to a random 18 character hex value
+ // Set PacketId as an 18-character hex string: DOT GNIS ID + random hex suffix
Random rand = new Random();
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
+ if (dotGnisId.equals("000000")) {
+ throw new IllegalStateException("DOT GNIS ID is set to default value of 000000. This is not a valid GNIS ID and should be changed in the configuration.");
+ }
+ sb.append(dotGnisId);
while (sb.length() < 18) {
sb.append(Integer.toHexString(rand.nextInt()));
}
- timToSend.getTim().setPacketID(sb.toString().substring(0, 18).toUpperCase());
+ timToSend.getTim().setPacketID(sb.substring(0, 18).toUpperCase());
return timToSend;
}
public List getAllMilepostsForTim(WydotTim wydotTim) {
- List milepostsAll = new ArrayList<>();
+ List milepostsAll;
+
+ // get mileposts from cache if they exist
+ milepostsAll = milepostService.getMilepostCache(wydotTim.getClientId());
+ if (milepostsAll != null && !milepostsAll.isEmpty()) {
+ return milepostsAll;
+ }
- if (wydotTim.getEndPoint() != null && wydotTim.getEndPoint().getLatitude() != null
+ if (wydotTim.isGeometryValid()) {
+ if (milepostsAll == null) {
+ milepostsAll = new ArrayList<>();
+ }
+ milepostsAll.addAll(wydotTim.toMileposts());
+ } else if (wydotTim.getEndPoint() != null && wydotTim.getEndPoint().getLatitude() != null
&& wydotTim.getEndPoint().getLongitude() != null) {
milepostsAll = milepostService.getMilepostsByStartEndPointDirection(wydotTim);
} else {
@@ -176,6 +189,11 @@ public List getAllMilepostsForTim(WydotTim wydotTim) {
milepostsAll = milepostService.getMilepostsByPointWithBuffer(mpb);
}
+ // cache mileposts
+ if (milepostsAll != null && !milepostsAll.isEmpty()) {
+ milepostService.setMilepostCache(milepostsAll, wydotTim.getClientId());
+ }
+
return milepostsAll;
}
@@ -244,11 +262,20 @@ public void sendTimToRsus(WydotTim wydotTim, WydotTravelerInputData timToSend, S
TimType timType, Integer pk, String endDateTime, Coordinate endPoint, String desiredEndDateTime) {
// FIND ALL RSUS TO SEND TO
// TODO: should this query a graph db instead to follow with milepost?
- List rsus = rsuService.getRsusByLatLong(wydotTim.getDirection(), wydotTim.getStartPoint(), endPoint,
+
+ // if geometry exists, use it to find RSUs
+ List rsus = new ArrayList<>();
+
+ if (wydotTim.isGeometryValid()) {
+ rsus = rsuService.getRsusByGeometry(wydotTim.getGeometry());
+ log.info("Found {} RSUs by geometry", rsus.size());
+ } else {
+ rsus = rsuService.getRsusByLatLong(wydotTim.getDirection(), wydotTim.getStartPoint(), endPoint,
wydotTim.getRoute());
+ }
// if no RSUs found
- if (rsus.size() == 0) {
+ if (rsus.isEmpty()) {
log.info("No RSUs found to place TIM on, returning");
return;
}
@@ -261,7 +288,14 @@ public void sendTimToRsus(WydotTim wydotTim, WydotTravelerInputData timToSend, S
odeRsu.setRsuIndex(rsu.getRsuIndex());
odeRsu.setRsuTarget(rsu.getRsuTarget());
- // rsuUsername, rsuPassword will take ODE defaults.
+
+ if (rsu.getRsuUsername() != null) {
+ odeRsu.setRsuUsername(rsu.getRsuUsername());
+ }
+ if (rsu.getRsuPassword() != null) {
+ odeRsu.setRsuPassword(rsu.getRsuPassword());
+ }
+
odeRsu.setRsuRetries(rsu.getRsuRetries());
odeRsu.setRsuTimeout(rsu.getRsuTimeout());
@@ -396,6 +430,7 @@ public TimDeleteSummary deleteTimsFromRsusAndSdx(List activeTims) {
}
// delete active tim
if (activeTimService.deleteActiveTim(activeTim.getActiveTimId())) {
+ milepostService.deleteMilepostCache(activeTim.getClientId());
log.debug("Successfully deleted active TIM with ID: {}", activeTim.getActiveTimId());
returnValue.addSuccessfulRsuDeletions(activeTim.getActiveTimId());
} else {
diff --git a/cv-data-service-library/src/main/resources/application.properties b/cv-data-service-library/src/main/resources/application.properties
new file mode 100644
index 000000000..352a7edc2
--- /dev/null
+++ b/cv-data-service-library/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+data-service-library.kafka.confluentKey=someKey
+data-service-library.kafka.confluentSecret=someSecret
+data-service-library.kafka.kafkaType=LOCAL
\ No newline at end of file
diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/factory/KafkaFactoryTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/factory/KafkaFactoryTest.java
new file mode 100644
index 000000000..01a8c2c06
--- /dev/null
+++ b/cv-data-service-library/src/test/java/com/trihydro/library/factory/KafkaFactoryTest.java
@@ -0,0 +1,117 @@
+package com.trihydro.library.factory;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.kafka.clients.consumer.Consumer;
+import org.apache.kafka.clients.producer.Producer;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+
+@ExtendWith(MockitoExtension.class)
+public class KafkaFactoryTest {
+
+ @InjectMocks
+ private KafkaFactory kafkaFactory;
+
+ @Test
+ public void testCreateStringConsumerLocal() {
+ String host = "localhost:9092";
+ String consumerGroup = "testGroup";
+ String topic = "testTopic";
+
+ Consumer consumer = kafkaFactory.createStringConsumer(host, consumerGroup, topic);
+
+ assertNotNull(consumer);
+ }
+
+ @Test
+ public void testKafkaFactoryConstructorConfluentException() throws Exception {
+ KafkaFactory kafkaFactoryTest = new KafkaFactory();
+ assertThrows(IllegalArgumentException.class, () -> {
+ kafkaFactoryTest.addConfluentProperties(new Properties());
+ });
+ }
+
+ @Test
+ public void testKafkaFactoryConstructorConfluent() {
+ // Create a spy of KafkaFactory
+ KafkaFactory spyKafkaFactory = spy(new KafkaFactory());
+
+ // Mock the getKafka() method
+ doReturn("testKey").when(spyKafkaFactory).getConfluentKey();
+ doReturn("testSecret").when(spyKafkaFactory).getConfluentSecret();
+
+ Properties props = spyKafkaFactory.addConfluentProperties(new Properties());
+
+ assertNotNull(props);
+ assertEquals("org.apache.kafka.common.security.plain.PlainLoginModule required username=\"testKey\" password=\"testSecret\";", props.getProperty("sasl.jaas.config"));
+ assertEquals("https", props.getProperty("ssl.endpoint.identification.algorithm"));
+ assertEquals("SASL_SSL", props.getProperty("security.protocol"));
+ assertEquals("PLAIN", props.getProperty("sasl.mechanism"));
+ }
+
+ @Test
+ public void testCreateStringConsumerWithProperties() {
+ String host = "localhost:9092";
+ String consumerGroup = "testGroup";
+ List topics = Arrays.asList("testTopic1", "testTopic2");
+ Integer maxPollInterval = 300000;
+ Integer maxPollRecords = 500;
+
+ Consumer consumer = kafkaFactory.createStringConsumer(host, consumerGroup, topics, maxPollInterval, maxPollRecords);
+
+ assertNotNull(consumer);
+ }
+
+ @Test
+ public void testCreateStringProducerLocal() {
+ String host = "localhost:9092";
+
+ Producer producer = kafkaFactory.createStringProducer(host);
+
+ assertNotNull(producer);
+ }
+
+ @Test
+ public void testCreateStringConsumerLocalWithInvalidHost() {
+ String host = "";
+ String consumerGroup = "testGroup";
+ String topic = "testTopic";
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ kafkaFactory.createStringConsumer(host, consumerGroup, topic);
+ });
+ }
+
+ @Test
+ public void testCreateStringConsumerWithInvalidConsumerGroup() {
+ String host = "localhost:9092";
+ String consumerGroup = "";
+ String topic = "testTopic";
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ kafkaFactory.createStringConsumer(host, consumerGroup, topic);
+ });
+ }
+
+ @Test
+ public void testCreateStringConsumerWithInvalidTopics() {
+ String host = "localhost:9092";
+ String consumerGroup = "testGroup";
+ List topics = Arrays.asList();
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ kafkaFactory.createStringConsumer(host, consumerGroup, topics);
+ });
+ }
+}
\ No newline at end of file
diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CdotGisConnectorTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CdotGisConnectorTest.java
new file mode 100644
index 000000000..b0338c758
--- /dev/null
+++ b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CdotGisConnectorTest.java
@@ -0,0 +1,52 @@
+package com.trihydro.library.helpers;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+
+import com.trihydro.library.service.BaseServiceTest;
+
+class CdotGisConnectorTest extends BaseServiceTest {
+
+ @InjectMocks
+ private CdotGisConnector uut;
+
+ private final String expectedBaseUrl = "https://dtdapps.coloradodot.info/arcgis/rest/services/LRS/Routes_withDEC/MapServer/exts/CdotLrsAccessRounded";
+
+ @Test
+ void testGetBaseUrl() {
+ Assertions.assertEquals(expectedBaseUrl, uut.getBaseUrl());
+ }
+
+ @Test
+ void testGetRouteById() {
+ // prepare
+ String expectedTargetUrl = expectedBaseUrl + "/Route";
+ String routeId = "025A";
+ int outSR = 4326;
+ String f = "json";
+ String expectedParams = "?routeId=" + routeId + "&outSR=" + outSR + "&f=" + f;
+ HttpHeaders mockHeaders = new HttpHeaders();
+ mockHeaders.set("Accept", "application/json");
+ HttpEntity mockEntity = new HttpEntity<>(mockHeaders);
+ String mockResponseString = "mockResponseString";
+ ResponseEntity mockResponse = ResponseEntity.ok(mockResponseString);
+ when(mockRestTemplate.exchange(expectedTargetUrl + expectedParams, HttpMethod.GET, mockEntity, String.class)).thenReturn(mockResponse);
+
+ // execute
+ ResponseEntity response = uut.getRouteById(routeId);
+
+ // verify
+ Assertions.assertEquals(mockResponse.getStatusCode(), response.getStatusCode());
+ Assertions.assertEquals(mockResponseString, response.getBody());
+ verify(mockRestTemplate).exchange(expectedTargetUrl + expectedParams, HttpMethod.GET, mockEntity, String.class);
+ }
+
+}
\ No newline at end of file
diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CreateBaseTimUtilTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CreateBaseTimUtilTest.java
index a505bbe01..2128cd886 100644
--- a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CreateBaseTimUtilTest.java
+++ b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/CreateBaseTimUtilTest.java
@@ -4,7 +4,6 @@
import java.util.ArrayList;
import java.util.List;
-import com.trihydro.library.model.ContentEnum;
import com.trihydro.library.model.Coordinate;
import com.trihydro.library.model.Milepost;
import com.trihydro.library.model.WydotTim;
@@ -106,11 +105,8 @@ public void buildTim_EndpointSUCCESS() {
wydotTim.setItisCodes(itisCodes);
wydotTim.setClientId("testclientid");
- var content = ContentEnum.advisory;
- var frameType = TravelerInfoType.advisory;
-
// Act
- var data = uut.buildTim(wydotTim, genProps, content, frameType, allMileposts, milepostsReduced, anchor);
+ var data = uut.buildTim(wydotTim, genProps, allMileposts, milepostsReduced, anchor);
// Assert
// validate dataFrame
@@ -118,6 +114,9 @@ public void buildTim_EndpointSUCCESS() {
Assertions.assertNotNull(dataFrame);
Assertions.assertEquals("advisory", dataFrame.getContent());
Assertions.assertEquals(32000, dataFrame.getDurationTime());
+ Assertions.assertEquals("0000", dataFrame.getMsgId().getFurtherInfoID());
+ Assertions.assertEquals(TravelerInfoType.roadSignage, dataFrame.getFrameType());
+ Assertions.assertNull(dataFrame.getMsgId().getRoadSignID());
var region = dataFrame.getRegions()[0];
Assertions.assertNotNull(region);
@@ -125,8 +124,6 @@ public void buildTim_EndpointSUCCESS() {
// validate anchor
var anchor = region.getAnchorPosition();
Assertions.assertNotNull(anchor);
- Assertions.assertEquals(anchor.getLatitude(), anchor.getLatitude());
- Assertions.assertEquals(anchor.getLongitude(), anchor.getLongitude());
// validate path
var path = region.getPath();
@@ -155,11 +152,8 @@ public void buildTim_singlePointSUCCESS() {
wydotTim.setItisCodes(itisCodes);
wydotTim.setClientId("testclientid");
- var content = ContentEnum.advisory;
- var frameType = TravelerInfoType.advisory;
-
// Act
- var data = uut.buildTim(wydotTim, genProps, content, frameType, allMileposts, milepostsReduced, anchor);
+ var data = uut.buildTim(wydotTim, genProps, allMileposts, milepostsReduced, anchor);
// Assert
// validate dataFrame
@@ -167,6 +161,9 @@ public void buildTim_singlePointSUCCESS() {
Assertions.assertNotNull(dataFrame);
Assertions.assertEquals("advisory", dataFrame.getContent());
Assertions.assertEquals(32000, dataFrame.getDurationTime());
+ Assertions.assertEquals("0000", dataFrame.getMsgId().getFurtherInfoID());
+ Assertions.assertEquals(TravelerInfoType.roadSignage, dataFrame.getFrameType());
+ Assertions.assertNull(dataFrame.getMsgId().getRoadSignID());
var region = dataFrame.getRegions()[0];
Assertions.assertNotNull(region);
@@ -174,8 +171,6 @@ public void buildTim_singlePointSUCCESS() {
// validate anchor
var anchor = region.getAnchorPosition();
Assertions.assertNotNull(anchor);
- Assertions.assertEquals(anchor.getLatitude(), anchor.getLatitude());
- Assertions.assertEquals(anchor.getLongitude(), anchor.getLongitude());
// validate path
var path = region.getPath();
@@ -204,11 +199,8 @@ public void buildTim_singleRegion_SUCCESS() {
wydotTim.setItisCodes(itisCodes);
wydotTim.setClientId("testclientid");
- var content = ContentEnum.advisory;
- var frameType = TravelerInfoType.advisory;
-
// Act
- var data = uut.buildTim(wydotTim, genProps, content, frameType, allMileposts, milepostsReduced, anchor);
+ var data = uut.buildTim(wydotTim, genProps, allMileposts, milepostsReduced, anchor);
// Assert
Assertions.assertEquals(1, data.getTim().getDataframes()[0].getRegions().length);
@@ -235,11 +227,8 @@ public void buildTim_twoRegions_SUCCESS() {
wydotTim.setItisCodes(itisCodes);
wydotTim.setClientId("testclientid");
- var content = ContentEnum.advisory;
- var frameType = TravelerInfoType.advisory;
-
// Act
- var data = uut.buildTim(wydotTim, genProps, content, frameType, allMileposts, milepostsReduced, anchor);
+ var data = uut.buildTim(wydotTim, genProps, allMileposts, milepostsReduced, anchor);
// Assert
Assertions.assertEquals(2, data.getTim().getDataframes()[0].getRegions().length);
@@ -278,11 +267,8 @@ public void buildTim_threeRegions_SUCCESS() {
wydotTim.setItisCodes(itisCodes);
wydotTim.setClientId("testclientid");
- var content = ContentEnum.advisory;
- var frameType = TravelerInfoType.advisory;
-
// Act
- var data = uut.buildTim(wydotTim, genProps, content, frameType, allMileposts, milepostsReduced, anchor);
+ var data = uut.buildTim(wydotTim, genProps, allMileposts, milepostsReduced, anchor);
// Assert
Assertions.assertEquals(3, data.getTim().getDataframes()[0].getRegions().length);
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 6c1c86627..ab4b9fb0a 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
@@ -255,7 +255,7 @@ public void TestConvertTimPayloadJsonToJava_SpeedLimit() throws IOException, URI
// Assert
Assertions.assertNotNull(odeTimPayloadTest);
Assertions.assertTrue(getTim(odeTimPayloadTest).getDataframes()[0].getItems().length > 0);
- Assertions.assertEquals("speedLimit", getTim(odeTimPayloadTest).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(odeTimPayloadTest).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "13609", "268", "12554", "8720" },
getTim(odeTimPayloadTest).getDataframes()[0].getItems());
}
@@ -391,7 +391,7 @@ public void TestConvertTmcTimTopicJsonToJava_HandlesVslContentType() throws IOEx
// Assert
Assertions.assertNotNull(tim_vsl);
- Assertions.assertEquals("speedLimit", getTim(tim_vsl).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(tim_vsl).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "268", "12604", "8720" },
getTim(tim_vsl).getDataframes()[0].getItems());
@@ -409,7 +409,7 @@ public void TestConvertTmcTimTopicJsonToJava_HandlesVslContentType_MultipleRegio
// Assert
Assertions.assertNotNull(tim_vsl);
- Assertions.assertEquals("speedLimit", getTim(tim_vsl).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(tim_vsl).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "268", "12604", "8720" },
getTim(tim_vsl).getDataframes()[0].getItems());
@@ -427,7 +427,7 @@ public void TestConvertTmcTimTopicJsonToJava_HandlesParkingContentType() throws
// Assert
Assertions.assertNotNull(tim_parking);
- Assertions.assertEquals("exitService", getTim(tim_parking).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(tim_parking).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "4104", "11794", "345" },
getTim(tim_parking).getDataframes()[0].getItems());
@@ -445,7 +445,7 @@ public void TestConvertTmcTimTopicJsonToJava_HandlesParkingContentType_MultipleR
// Assert
Assertions.assertNotNull(tim_parking);
- Assertions.assertEquals("exitService", getTim(tim_parking).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(tim_parking).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "4104", "11794", "345" },
getTim(tim_parking).getDataframes()[0].getItems());
@@ -464,7 +464,7 @@ public void TestConvertTmcTimTopicJsonToJava_HandlesConstructionContentType() th
// Assert
Assertions.assertNotNull(tim_construction);
- Assertions.assertEquals("workZone", getTim(tim_construction).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(tim_construction).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "1537", "12554", "8728" },
getTim(tim_construction).getDataframes()[0].getItems());
@@ -483,7 +483,7 @@ public void TestConvertTmcTimTopicJsonToJava_HandlesConstructionContentType_Mult
// Assert
Assertions.assertNotNull(tim_construction);
- Assertions.assertEquals("workZone", getTim(tim_construction).getDataframes()[0].getContent());
+ Assertions.assertEquals("advisory", getTim(tim_construction).getDataframes()[0].getContent());
Assertions.assertArrayEquals(new String[] { "1537", "12554", "8728" },
getTim(tim_construction).getDataframes()[0].getItems());
diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/TimGenerationHelperTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/TimGenerationHelperTest.java
index cfe66882f..0e475ec0c 100644
--- a/cv-data-service-library/src/test/java/com/trihydro/library/helpers/TimGenerationHelperTest.java
+++ b/cv-data-service-library/src/test/java/com/trihydro/library/helpers/TimGenerationHelperTest.java
@@ -175,6 +175,7 @@ public void resubmitToOde_NoMileposts() {
verifyNoInteractions(mockDataFrameService, mockPathNodeXYService, mockRegionService,
mockRsuService, mockOdeService, mockActiveTimHoldingService, mockSdwService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction);
}
@@ -209,6 +210,7 @@ public void resubmitToOde_DataFrameException() throws Utility.IdenticalPointsExc
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
+ verify(mockMilepostService).getMilepostCache(any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService);
}
@@ -220,12 +222,11 @@ public void resubmitToOde_RsuException() throws Utility.IdenticalPointsException
setupActiveTimModel();
setupMilepostReturn();
tum.setRoute("I 80");
+ setupRoutes(tum.getRoute());
List mps = new ArrayList<>();
mps.add(new Milepost());
doReturn(mps).when(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- String[] rsuRoutes = new String[] {"I 80"};
- doReturn(rsuRoutes).when(mockConfig).getRsuRoutes();
doReturn(new String[] {"1234"}).when(mockDataFrameService)
.getItisCodesForDataFrameId(any());
@@ -243,15 +244,15 @@ public void resubmitToOde_RsuException() throws Utility.IdenticalPointsException
Assertions.assertEquals(new ResubmitTimException(activeTimId, exMsg), ex);
verify(mockRsuService).getFullRsusTimIsOn(any());
- verify(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
+ verify(mockRsuService).getRsusByGeometry(any());
verify(mockDataFrameService).getItisCodesForDataFrameId(any());
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockOdeService,
mockActiveTimHoldingService, mockSdwService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
- mockRsuService);
+ verify(mockMilepostService).getMilepostCache(any());
+ verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService, mockRsuService);
}
@Test
@@ -262,12 +263,11 @@ public void resubmitToOde_RsuExistingSuccess() throws Utility.IdenticalPointsExc
setupActiveTimModel();
setupMilepostReturn();
tum.setRoute("I 80");
+ setupRoutes(tum.getRoute());
List mps = new ArrayList<>();
mps.add(new Milepost());
doReturn(mps).when(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- String[] rsuRoutes = new String[] {"I 80"};
- doReturn(rsuRoutes).when(mockConfig).getRsuRoutes();
List wydotRsus = new ArrayList<>();
var wydotRsuTim = new WydotRsuTim();
@@ -294,8 +294,9 @@ public void resubmitToOde_RsuExistingSuccess() throws Utility.IdenticalPointsExc
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
- mockRsuService, mockOdeService);
+ verify(mockMilepostService).getMilepostCache(any());
+ verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService, mockRsuService,
+ mockOdeService);
}
@Test
@@ -306,12 +307,11 @@ public void resubmitToOde_RsuNewFailTimQuery() throws Utility.IdenticalPointsExc
setupActiveTimModel();
setupMilepostReturn();
tum.setRoute("I 80");
+ setupRoutes(tum.getRoute());
List mps = new ArrayList<>();
mps.add(new Milepost());
doReturn(mps).when(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- String[] rsuRoutes = new String[] {"I 80"};
- doReturn(rsuRoutes).when(mockConfig).getRsuRoutes();
doReturn(new Coordinate(BigDecimal.valueOf(1), BigDecimal.valueOf(2))).when(mockUtility)
.calculateAnchorCoordinate(any(), any());
@@ -320,11 +320,9 @@ public void resubmitToOde_RsuNewFailTimQuery() throws Utility.IdenticalPointsExc
var rsu = new WydotRsu();
rsu.setRsuTarget("10.10.10.10");
dbRsus.add(rsu);
- doReturn(dbRsus).when(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
- doReturn(new String[] {"1234"}).when(mockDataFrameService)
- .getItisCodesForDataFrameId(any());
- when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(
- null);
+ doReturn(dbRsus).when(mockRsuService).getRsusByGeometry(any());
+ doReturn(new String[] { "1234" }).when(mockDataFrameService).getItisCodesForDataFrameId(any());
+ when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(null);
// Act
var exceptions = uut.resubmitToOde(activeTimIds);
@@ -339,15 +337,15 @@ public void resubmitToOde_RsuNewFailTimQuery() throws Utility.IdenticalPointsExc
Assertions.assertEquals(new ResubmitTimException(activeTimId, exMsg), ex);
verify(mockRsuService).getFullRsusTimIsOn(any());
- verify(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
verify(mockDataFrameService).getItisCodesForDataFrameId(any());
verify(mockOdeService).submitTimQuery(isA(WydotRsu.class), isA(Integer.class));
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
- mockRsuService, mockOdeService, mockActiveTimHoldingService);
+ verify(mockMilepostService).getMilepostCache(any());
+ verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService, mockRsuService,
+ mockOdeService, mockActiveTimHoldingService);
}
@Test
@@ -358,22 +356,19 @@ public void resubmitToOde_RsuNewFailIndices() throws Utility.IdenticalPointsExce
setupActiveTimModel();
setupMilepostReturn();
tum.setRoute("I 80");
+ setupRoutes(tum.getRoute());
List mps = new ArrayList<>();
mps.add(new Milepost());
doReturn(mps).when(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- String[] rsuRoutes = new String[] {"I 80"};
- doReturn(rsuRoutes).when(mockConfig).getRsuRoutes();
List dbRsus = new ArrayList<>();
var rsu = new WydotRsu();
rsu.setRsuTarget("10.10.10.10");
dbRsus.add(rsu);
- doReturn(dbRsus).when(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
- doReturn(new String[] {"1234"}).when(mockDataFrameService)
- .getItisCodesForDataFrameId(any());
- when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(
- new TimQuery());
+ doReturn(dbRsus).when(mockRsuService).getRsusByGeometry(any());
+ doReturn(new String[] { "1234" }).when(mockDataFrameService).getItisCodesForDataFrameId(any());
+ when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(new TimQuery());
when(mockOdeService.findFirstAvailableIndexWithRsuIndex(any())).thenReturn(null);
doReturn(new Coordinate(BigDecimal.valueOf(1), BigDecimal.valueOf(2))).when(mockUtility)
@@ -391,13 +386,14 @@ public void resubmitToOde_RsuNewFailIndices() throws Utility.IdenticalPointsExce
Assertions.assertEquals(new ResubmitTimException(activeTimId, exMsg), ex);
verify(mockRsuService).getFullRsusTimIsOn(any());
- verify(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
+ verify(mockRsuService).getRsusByGeometry(any());
verify(mockRsuService).getActiveRsuTimIndexes(any());
verify(mockDataFrameService).getItisCodesForDataFrameId(any());
verify(mockOdeService).submitTimQuery(isA(WydotRsu.class), isA(Integer.class));
verify(mockActiveTimHoldingService).getActiveTimHoldingForRsu(any());
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
@@ -412,22 +408,19 @@ public void resubmitToOde_RsuNewInsertFail() throws Utility.IdenticalPointsExcep
setupActiveTimModel();
setupMilepostReturn();
tum.setRoute("I 80");
+ setupRoutes(tum.getRoute());
List