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 a5a35e9be..842c734db 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
@@ -66,17 +66,17 @@ public void InjectDependencies(TimDbTables _timDbTables, SQLNullHandler _sqlNull
sqlNullHandler = _sqlNullHandler;
}
- /**
- * 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";
@@ -113,17 +113,7 @@ public ResponseEntity> GetExpiringActiveTims() {
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.setDfContent(contentType);
-
+ activeTim.setDfContent(ContentEnum.advisory);
activeTims.add(activeTim);
}
} catch (Exception e) {
@@ -169,16 +159,7 @@ public ResponseEntity GetUpdateModelFromActiveTimId(@PathVariabl
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.setDfContent(contentType);
+ activeTim.setDfContent(ContentEnum.advisory);
}
} catch (Exception e) {
log.error("Error getting active tim", e);
@@ -284,12 +265,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
@@ -332,7 +312,8 @@ public ResponseEntity> GetActiveTimsByClientIdDirection(@PathVar
public ResponseEntity> GetBufferTimsByClientId(@PathVariable String clientId) {
List activeTims = new ArrayList<>();
- String query = "select * from active_tim where CLIENT_ID like '" + clientId + "\\%BUFF_-%' ESCAPE '\\'";
+ String query = "select * from active_tim where CLIENT_ID like '" + clientId
+ + "\\%BUFF-%' ESCAPE '\\'";
try (Connection connection = dbInteractions.getConnectionPool(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(query)) {
activeTims = getActiveTimFromRS(rs, false);
@@ -671,12 +652,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
@@ -728,9 +708,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);
@@ -1082,4 +1062,62 @@ private TimUpdateModel buildTimUpdateModelFromResultSet(ResultSet rs) throws SQL
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/MilepostController.java b/cv-data-controller/src/main/java/com/trihydro/cvdatacontroller/controller/MilepostController.java
index 5207aa539..55837bbc7 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;
@@ -18,6 +19,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.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@@ -37,6 +39,7 @@
public class MilepostController extends BaseController {
private MilepostService milepostService;
+ private final HashMap> milepostCache = new HashMap<>();
@Autowired
public void InjectDependencies(MilepostService _milepostService) {
@@ -308,6 +311,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())) {
+ utility.logWithDate("Updating milepost cache for timID: " + milepostCacheBody.getTimID());
+ } else {
+ utility.logWithDate("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);
+ utility.logWithDate("Found " + mileposts.size() + " mileposts in cache for timID: " + 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) {
+ utility.logWithDate("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() {
+ utility.logWithDate("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) {
+ utility.logWithDate("Error retrieving active TIM IDs " + e.toString()); // Improved logging
+ }
+ return activeTimIds;
+ }
+
/**
* Rewrite of getMilepostsByStartEndPoint used in testing to cut time on geojson
* creation to test continuity
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 c4a9fe3b5..a238506e1 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
@@ -37,9 +37,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();
@@ -47,7 +46,7 @@ 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);
}
@@ -74,9 +73,9 @@ public ResponseEntity> SelectAllRsus() {
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;
@@ -85,17 +84,26 @@ 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) {
e.printStackTrace();
@@ -118,9 +126,9 @@ public ResponseEntity> SelectActiveRsus() {
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;
@@ -129,23 +137,32 @@ 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) {
e.printStackTrace();
@@ -181,8 +198,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();
@@ -257,4 +273,4 @@ public ResponseEntity> GetActiveRsuTimIndexes(@PathVariable Intege
}
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 10eca26b1..7dbc5278a 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,9 +1,6 @@
package com.trihydro.cvdatacontroller.model;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Import;
-import org.springframework.stereotype.Component;
-
+import com.trihydro.library.helpers.CdotGisConnector;
import com.trihydro.library.helpers.DbInteractions;
import com.trihydro.library.helpers.EmailHelper;
import com.trihydro.library.helpers.JavaMailSenderImplProvider;
@@ -11,13 +8,19 @@
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 org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Import;
+import org.springframework.stereotype.Component;
+
@Component
@ConfigurationProperties("config")
@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 b52ca03fb..bf3a2cb49 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
@@ -57,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";
@@ -108,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();
@@ -117,14 +116,14 @@ 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());
@@ -140,10 +139,10 @@ 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());
@@ -159,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());
@@ -172,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
@@ -191,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");
@@ -204,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");
@@ -216,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");
@@ -388,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);
@@ -411,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
@@ -431,7 +427,7 @@ public void GetActiveTimIndicesByRsu_FAIL() throws SQLException {
public void GetActiveTimsByClientIdDirection_SUCCESS() throws SQLException {
// Arrange
String clientId = "clientId";
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String direction = "eastward";
String selectStatement = "select * from active_tim where CLIENT_ID like '" + clientId + "' and TIM_TYPE_ID = " + timTypeId;
selectStatement += " and DIRECTION = '" + direction + "'";
@@ -465,7 +461,7 @@ public void GetActiveTimsByClientIdDirection_SUCCESS() throws SQLException {
public void GetActiveTimsByClientIdDirection_FAIL() throws SQLException {
// Arrange
String clientId = "clientId";
- Long timTypeId = -1l;
+ Long timTypeId = -1L;
String direction = "eastward";
String selectStatement = "select * from active_tim where CLIENT_ID like '" + clientId + "' and TIM_TYPE_ID = " + timTypeId;
selectStatement += " and DIRECTION = '" + direction + "'";
@@ -487,7 +483,8 @@ 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 '\\'";
+ String selectStatement = "select * from active_tim where CLIENT_ID like '" + clientId
+ + "\\%BUFF-%' ESCAPE '\\'";
// Act
ResponseEntity> data = uut.GetBufferTimsByClientId(clientId);
@@ -518,7 +515,8 @@ public void GetBufferTimsByClientId_FAIL() throws SQLException {
// Arrange
String clientId = "clientId";
- String selectStatement = "select * from active_tim where CLIENT_ID like '" + clientId + "\\%BUFF_-%' ESCAPE '\\'";
+ String selectStatement = "select * from active_tim where CLIENT_ID like '" + clientId
+ + "\\%BUFF-%' ESCAPE '\\'";
doThrow(new SQLException()).when(mockRs).getLong("ACTIVE_TIM_ID");
@@ -536,7 +534,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 ";
@@ -560,7 +558,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";
@@ -580,7 +578,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);
@@ -596,7 +594,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
@@ -624,7 +622,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();
}
@@ -634,7 +632,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);
@@ -653,7 +651,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());
@@ -666,10 +664,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());
@@ -697,7 +695,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
@@ -735,7 +733,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
@@ -772,7 +770,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);
@@ -790,7 +788,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
@@ -822,7 +820,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");
@@ -928,8 +926,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 + "'";
@@ -967,8 +964,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);
@@ -1189,7 +1185,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();
}
@@ -1239,7 +1235,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 b8d1c1a79..b7d19ebb7 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,23 +4,35 @@
import java.util.List;
import java.util.Properties;
-import com.trihydro.library.helpers.Utility;
-
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.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
+import com.google.common.base.Strings;
+import com.trihydro.library.helpers.Utility;
+
@Component
+@ConfigurationProperties("data-service-library.kafka")
public class KafkaFactory {
- private Utility utility;
+ private final Utility utility;
+ private String kafkaType;
+ private String confluentKey;
+ private String confluentSecret;
+ private final Properties kafkaProperties;
- @Autowired
- public KafkaFactory(Utility _utility) {
+ public KafkaFactory(Utility _utility) throws IllegalArgumentException {
utility = _utility;
+ kafkaType = getKafkaType();
+
+ if ("CONFLUENT".equalsIgnoreCase(kafkaType)) {
+ kafkaProperties = addConfluentProperties(new Properties());
+ } else {
+ kafkaProperties = new Properties();
+ }
}
/**
@@ -109,6 +121,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);
@@ -131,6 +145,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 52174c1f5..eab962ed8 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
@@ -22,10 +22,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
public class CreateBaseTimUtil {
@@ -42,16 +40,17 @@ 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,
+ public WydotTravelerInputData buildTim(WydotTim wydotTim, TimGenerationProps genProps,
TravelerInfoType frameType, List allMileposts, List reducedMileposts, Milepost anchor) {
+ ContentEnum content = ContentEnum.advisory;
+
// build TIM object with data
WydotTravelerInputData timToSend = new WydotTravelerInputData();
OdeTravelerInformationMessage tim = new OdeTravelerInformationMessage();
@@ -77,13 +76,10 @@ public WydotTravelerInputData buildTim(WydotTim wydotTim, TimGenerationProps gen
// 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)
+ // Since furtherInfoID is not used, set it to the default value of 0
+ MsgId msgId = new MsgId();
+ msgId.setFurtherInfoID("0");
dataFrame.setMsgId(msgId);
// set regions. note that we now support multiple regions in a single TIM package
@@ -195,7 +191,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);
@@ -243,7 +239,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++) {
@@ -266,30 +262,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 1709b3751..f7b545a90 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;
@@ -256,16 +257,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();
@@ -475,56 +476,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");
@@ -546,7 +541,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 f88afdebd..9a4c4c103 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
@@ -11,7 +11,6 @@
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
@@ -20,7 +19,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;
@@ -56,10 +54,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;
+import us.dot.its.jpo.ode.plugin.j2735.OdeTravelerInformationMessage.NodeXY;;
@Component
@Slf4j
@@ -352,13 +347,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);
+ }
+ }
+ utility.logWithDate(String.format("Found %d mileposts between %s and %s", allMps.size(),
+ gson.toJson(wydotTim.getStartPoint()), gson.toJson(wydotTim.getEndPoint())));
} else {
// point incident
MilepostBuffer mpb = new MilepostBuffer();
@@ -691,7 +695,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) {
@@ -792,9 +796,8 @@ private List sendTim(WydotTravelerInputData timToSend, Tim
Long activeTimId, List reduced_mps) {
List exceptions = new ArrayList<>();
// try to send to RSU if not a sat TIM and along route with RSUs
- if (StringUtils.isBlank(tum.getSatRecordId()) &&
- Arrays.asList(config.getRsuRoutes()).contains(tum.getRoute())) {
- var exMsg = updateAndSendRSU(timToSend, tum);
+ if (StringUtils.isBlank(tum.getSatRecordId())) {
+ var exMsg = updateAndSendRSU(timToSend, tum, reduced_mps);
if (StringUtils.isNotBlank(exMsg)) {
exceptions.add(new ResubmitTimException(activeTimId, exMsg));
}
@@ -824,25 +827,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("0");
// DataFrame
DataFrame df = new DataFrame();
@@ -1010,15 +1000,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/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/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 99bc6977a..590518595 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,11 +6,6 @@
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;
@@ -19,6 +14,11 @@
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
+import com.trihydro.library.helpers.Utility;
+import com.trihydro.library.model.Coordinate;
+import com.trihydro.library.model.WydotRsu;
+import com.trihydro.library.model.WydotRsuTim;
+
@Component
public class RsuService extends CvDataServiceLibrary {
@@ -43,6 +43,13 @@ public List selectRsusByRoute(String route) {
return Arrays.asList(response.getBody());
}
+ 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);
ResponseEntity response = restTemplateProvider.GetRestTemplate().getForEntity(url,
@@ -202,6 +209,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 f1ab3b7ca..120d4829e 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
@@ -11,6 +11,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
@@ -29,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;
@@ -55,6 +55,7 @@
import us.dot.its.jpo.ode.plugin.j2735.timstorage.FrameType.TravelerInfoType;
@Component
+@Slf4j
public class WydotTimService {
protected EmailProps emailProps;
@@ -113,11 +114,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, TravelerInfoType frameType, 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, frameType,
allMileposts, reducedMileposts, anchor);
if (timToSend == null) {
@@ -147,21 +148,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 {
@@ -174,6 +190,11 @@ public List getAllMilepostsForTim(WydotTim wydotTim) {
milepostsAll = milepostService.getMilepostsByPointWithBuffer(mpb);
}
+ // cache mileposts
+ if (milepostsAll != null && !milepostsAll.isEmpty()) {
+ milepostService.setMilepostCache(milepostsAll, wydotTim.getClientId());
+ }
+
return milepostsAll;
}
@@ -242,11 +263,20 @@ public void sendTimToRsus(WydotTim wydotTim, WydotTravelerInputData timToSend, S
TimType timType, Integer pk, String endDateTime, Coordinate endPoint) {
// 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());
+ utility.logWithDate("Found " + rsus.size() + " RSUs by geometry");
+ } else {
+ rsus = rsuService.getRsusByLatLong(wydotTim.getDirection(), wydotTim.getStartPoint(), endPoint,
wydotTim.getRoute());
+ }
// if no RSUs found
- if (rsus.size() == 0) {
+ if (rsus.isEmpty()) {
utility.logWithDate("No RSUs found to place TIM on, returning");
return;
}
@@ -259,7 +289,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());
@@ -381,7 +418,7 @@ public TimDeleteSummary deleteTimsFromRsusAndSdx(List activeTims) {
List timRsus = timRsuService.getTimRsusByTimId(activeTim.getTimId());
// get full RSU
- if (timRsus.size() > 0) {
+ if (!timRsus.isEmpty()) {
for (TimRsu timRsu : timRsus) {
rsu = getRsu(timRsu.getRsuId());
// delete tim off rsu
@@ -393,13 +430,14 @@ public TimDeleteSummary deleteTimsFromRsusAndSdx(List activeTims) {
}
// delete active tim
if (activeTimService.deleteActiveTim(activeTim.getActiveTimId())) {
+ milepostService.deleteMilepostCache(activeTim.getClientId());
returnValue.addSuccessfulRsuDeletions(activeTim.getActiveTimId());
} else {
returnValue.addFailedActiveTimDeletions(activeTim.getActiveTimId());
}
}
- if (satTims != null && satTims.size() > 0) {
+ if (satTims != null && !satTims.isEmpty()) {
// Get the sat_record_id values and active_tim_id values
List satRecordIds = satTims.stream().map(ActiveTim::getSatRecordId).collect(Collectors.toList());
List activeSatTimIds = satTims.stream().map(ActiveTim::getActiveTimId).collect(Collectors.toList());
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..1e23a36e6
--- /dev/null
+++ b/cv-data-service-library/src/test/java/com/trihydro/library/factory/KafkaFactoryTest.java
@@ -0,0 +1,127 @@
+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 static org.mockito.ArgumentMatchers.anyString;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import com.trihydro.library.helpers.Utility;
+
+
+@ExtendWith(MockitoExtension.class)
+public class KafkaFactoryTest {
+
+ @Mock
+ private Utility utility;
+
+ @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);
+ verify(utility).logWithDate(anyString());
+ }
+
+ @Test
+ public void testKafkaFactoryConstructorConfluentException() throws Exception {
+ KafkaFactory kafkaFactoryTest = new KafkaFactory(utility);
+ assertThrows(IllegalArgumentException.class, () -> {
+ kafkaFactoryTest.addConfluentProperties(new Properties());
+ });
+ }
+
+ @Test
+ public void testKafkaFactoryConstructorConfluent() {
+ // Create a spy of KafkaFactory
+ KafkaFactory spyKafkaFactory = spy(new KafkaFactory(utility));
+
+ // 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);
+ verify(utility).logWithDate(anyString());
+ }
+
+ @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 1a445ef04..d90f2e878 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,10 @@ 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, frameType, allMileposts, milepostsReduced, anchor);
// Assert
// validate dataFrame
@@ -118,6 +116,8 @@ public void buildTim_EndpointSUCCESS() {
Assertions.assertNotNull(dataFrame);
Assertions.assertEquals("advisory", dataFrame.getContent());
Assertions.assertEquals(32000, dataFrame.getDurationTime());
+ Assertions.assertEquals("0", dataFrame.getMsgId().getFurtherInfoID());
+ Assertions.assertNull(dataFrame.getMsgId().getRoadSignID());
var region = dataFrame.getRegions()[0];
Assertions.assertNotNull(region);
@@ -155,11 +155,10 @@ 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, frameType, allMileposts, milepostsReduced, anchor);
// Assert
// validate dataFrame
@@ -167,6 +166,8 @@ public void buildTim_singlePointSUCCESS() {
Assertions.assertNotNull(dataFrame);
Assertions.assertEquals("advisory", dataFrame.getContent());
Assertions.assertEquals(32000, dataFrame.getDurationTime());
+ Assertions.assertEquals("0", dataFrame.getMsgId().getFurtherInfoID());
+ Assertions.assertNull(dataFrame.getMsgId().getRoadSignID());
var region = dataFrame.getRegions()[0];
Assertions.assertNotNull(region);
@@ -204,11 +205,10 @@ 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, frameType, allMileposts, milepostsReduced, anchor);
// Assert
Assertions.assertEquals(1, data.getTim().getDataframes()[0].getRegions().length);
@@ -235,11 +235,10 @@ 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, frameType, allMileposts, milepostsReduced, anchor);
// Assert
Assertions.assertEquals(2, data.getTim().getDataframes()[0].getRegions().length);
@@ -278,11 +277,10 @@ 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, frameType, 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 e89ca7501..9a36e171d 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
@@ -252,7 +252,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());
}
@@ -388,7 +388,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());
@@ -406,7 +406,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());
@@ -424,7 +424,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());
@@ -442,7 +442,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());
@@ -461,7 +461,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());
@@ -480,7 +480,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 3f65b8a7d..8de027e45 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);
}
@@ -224,8 +226,6 @@ public void resubmitToOde_RsuException() throws Utility.IdenticalPointsException
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 +243,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
@@ -266,8 +266,6 @@ public void resubmitToOde_RsuExistingSuccess() throws Utility.IdenticalPointsExc
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 +292,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
@@ -310,8 +309,6 @@ public void resubmitToOde_RsuNewFailTimQuery() throws Utility.IdenticalPointsExc
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 +317,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 +334,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
@@ -362,18 +357,14 @@ public void resubmitToOde_RsuNewFailIndices() throws Utility.IdenticalPointsExce
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 +382,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,
@@ -416,18 +408,14 @@ public void resubmitToOde_RsuNewInsertFail() throws Utility.IdenticalPointsExcep
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(1);
doReturn("exception").when(mockOdeService).sendNewTimToRsu(any());
@@ -445,7 +433,7 @@ public void resubmitToOde_RsuNewInsertFail() throws Utility.IdenticalPointsExcep
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));
@@ -454,6 +442,7 @@ public void resubmitToOde_RsuNewInsertFail() throws Utility.IdenticalPointsExcep
verify(mockOdeService).sendNewTimToRsu(any());
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
@@ -472,18 +461,14 @@ public void resubmitToOde_RsuNewSuccess() throws Utility.IdenticalPointsExceptio
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(1);
doReturn(new Coordinate(BigDecimal.valueOf(1), BigDecimal.valueOf(2))).when(mockUtility)
@@ -495,7 +480,7 @@ public void resubmitToOde_RsuNewSuccess() throws Utility.IdenticalPointsExceptio
// Assert
Assertions.assertEquals(0, exceptions.size());
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));
@@ -504,6 +489,7 @@ public void resubmitToOde_RsuNewSuccess() throws Utility.IdenticalPointsExceptio
verify(mockOdeService).sendNewTimToRsu(any());
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
@@ -541,6 +527,7 @@ public void resubmitToOde_SdxNewFail() throws Utility.IdenticalPointsException {
verify(mockActiveTimHoldingService).insertActiveTimHolding(any());
verifyNoInteractions(mockPathNodeXYService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -576,6 +563,7 @@ public void resubmitToOde_SdxNewSuccess() throws Utility.IdenticalPointsExceptio
verify(mockOdeService).updateTimOnSdw(any());
verify(mockActiveTimHoldingService).insertActiveTimHolding(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -741,8 +729,9 @@ public void resubmitToOde_SdxExistingFail() throws Utility.IdenticalPointsExcept
verify(mockActiveTimHoldingService).insertActiveTimHolding(any());
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
@@ -774,6 +763,7 @@ public void resubmitToOde_SdxExistingSuccess() throws Utility.IdenticalPointsExc
verifyNoInteractions(mockPathNodeXYService);
verify(mockActiveTimHoldingService).insertActiveTimHolding(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -812,7 +802,7 @@ public void resubmitToOde_IdenticalPointsException_SuccessfulRecovery() throws U
verify(mockActiveTimHoldingService).insertActiveTimHolding(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
- verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
+ verifyNoMoreInteractions(mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
}
@@ -837,7 +827,7 @@ public void resubmitToOde_IdenticalPointsException_FailureToRecover() throws Uti
var ex = exceptions.get(0);
Assertions.assertEquals(new ResubmitTimException(activeTimId, String.format("Unable to resubmit TIM, identical points found while calculating anchor point for Active_Tim %d", activeTimId)), ex);
verifyNoInteractions(mockPathNodeXYService);
- verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
+ verifyNoMoreInteractions(mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
}
@@ -909,6 +899,7 @@ public void updateAndResubmitToOde_noMileposts() {
verifyNoInteractions(mockDataFrameService, mockPathNodeXYService, mockRegionService,
mockRsuService, mockOdeService, mockActiveTimHoldingService, mockSdwService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction);
}
@@ -949,6 +940,7 @@ public void updateAndResubmitToOde_RsuNewTimFail_EndPointMps()
Assertions.assertEquals(new ResubmitTimException(activeTimId, exMsg), ex);
verify(mockDataFrameService).getItisCodesForDataFrameId(any());
verify(mockMilepostService, times(2)).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService, times(2)).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService);
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService,
@@ -987,6 +979,7 @@ public void updateAndResubmitToOde_RsuNewTimFail_EndTimeParse()
Assertions.assertEquals(new ResubmitTimException(activeTimId, exMsg), ex);
verify(mockDataFrameService).getItisCodesForDataFrameId(any());
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService);
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService,
@@ -1030,6 +1023,7 @@ public void updateAndResubmitToOde_RsuNewTimFail_StartPointMps()
Assertions.assertEquals(new ResubmitTimException(activeTimId, exMsg), ex);
verify(mockDataFrameService).getItisCodesForDataFrameId(any());
verify(mockMilepostService, times(2)).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService, times(2)).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService);
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService,
@@ -1047,10 +1041,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_StartPoint()
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());
+ doReturn(new String[] { "1234" }).when(mockDataFrameService).getItisCodesForDataFrameId(any());
doReturn(new Coordinate(BigDecimal.valueOf(1), BigDecimal.valueOf(2))).when(mockUtility)
.calculateAnchorCoordinate(any(), any());
@@ -1066,9 +1057,8 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_StartPoint()
var rsu = new WydotRsu();
rsu.setRsuTarget("10.10.10.10");
dbRsus.add(rsu);
- doReturn(dbRsus).when(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
- when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(
- new TimQuery());
+ doReturn(dbRsus).when(mockRsuService).getRsusByGeometry(any());
+ when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(new TimQuery());
when(mockOdeService.findFirstAvailableIndexWithRsuIndex(any())).thenReturn(1);
// Act
@@ -1077,7 +1067,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_StartPoint()
// Assert
Assertions.assertEquals(0, exceptions.size());
verify(mockRsuService).getFullRsusTimIsOn(any());
- verify(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
+ verify(mockRsuService).getRsusByGeometry(any());
verify(mockRsuService).getActiveRsuTimIndexes(any());
verify(mockDataFrameService, times(2)).getItisCodesForDataFrameId(any());
verify(mockOdeService).submitTimQuery(isA(WydotRsu.class), isA(Integer.class));
@@ -1087,6 +1077,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_StartPoint()
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
verify(mockMilepostService, times(2)).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService, times(2)).getMilepostCache(any());
verify(mockMilepostReduction, times(2)).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -1103,10 +1094,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndPoint()
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());
+ doReturn(new String[] { "1234" }).when(mockDataFrameService).getItisCodesForDataFrameId(any());
var validationResults = getValidationResults();
var errors = new ArrayList();
@@ -1119,9 +1107,8 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndPoint()
var rsu = new WydotRsu();
rsu.setRsuTarget("10.10.10.10");
dbRsus.add(rsu);
- doReturn(dbRsus).when(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
- when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(
- new TimQuery());
+ doReturn(dbRsus).when(mockRsuService).getRsusByGeometry(any());
+ when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(new TimQuery());
when(mockOdeService.findFirstAvailableIndexWithRsuIndex(any())).thenReturn(1);
doReturn(new Coordinate(BigDecimal.valueOf(1), BigDecimal.valueOf(2))).when(mockUtility)
@@ -1133,7 +1120,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndPoint()
// Assert
Assertions.assertEquals(0, exceptions.size());
verify(mockRsuService).getFullRsusTimIsOn(any());
- verify(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
+ verify(mockRsuService).getRsusByGeometry(any());
verify(mockRsuService).getActiveRsuTimIndexes(any());
verify(mockDataFrameService, times(2)).getItisCodesForDataFrameId(any());
verify(mockOdeService).submitTimQuery(isA(WydotRsu.class), isA(Integer.class));
@@ -1143,6 +1130,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndPoint()
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
verify(mockMilepostService, times(2)).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService, times(2)).getMilepostCache(any());
verify(mockMilepostReduction, times(2)).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -1159,10 +1147,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndTime()
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());
+ doReturn(new String[] { "1234" }).when(mockDataFrameService).getItisCodesForDataFrameId(any());
var validationResults = getValidationResults();
var errors = new ArrayList();
@@ -1174,9 +1159,8 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndTime()
var rsu = new WydotRsu();
rsu.setRsuTarget("10.10.10.10");
dbRsus.add(rsu);
- doReturn(dbRsus).when(mockRsuService).getRsusByLatLong(any(), any(), any(), any());
- when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(
- new TimQuery());
+ doReturn(dbRsus).when(mockRsuService).getRsusByGeometry(any());
+ when(mockOdeService.submitTimQuery(isA(WydotRsu.class), isA(Integer.class))).thenReturn(new TimQuery());
when(mockOdeService.findFirstAvailableIndexWithRsuIndex(any())).thenReturn(1);
doReturn(new Coordinate(BigDecimal.valueOf(1), BigDecimal.valueOf(2))).when(mockUtility)
@@ -1188,7 +1172,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndTime()
// Assert
Assertions.assertEquals(0, exceptions.size());
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));
@@ -1198,6 +1182,7 @@ public void updateAndResubmitToOde_RsuNewTimSuccess_EndTime()
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -1214,10 +1199,7 @@ public void updateAndResubmitToOde_RsuUpdateTimSuccess_ItisCodes()
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());
+ doReturn(new String[] { "1234" }).when(mockDataFrameService).getItisCodesForDataFrameId(any());
var validationResults = getValidationResults();
var errors = new ArrayList();
@@ -1245,6 +1227,7 @@ public void updateAndResubmitToOde_RsuUpdateTimSuccess_ItisCodes()
verifyNoInteractions(mockPathNodeXYService, mockRegionService, mockSdwService);
verify(mockMilepostService).getMilepostsByStartEndPointDirection(any());
+ verify(mockMilepostService).getMilepostCache(any());
verify(mockMilepostReduction).applyMilepostReductionAlgorithm(any(), any());
verifyNoMoreInteractions(mockMilepostService, mockMilepostReduction, mockDataFrameService,
mockRsuService, mockOdeService, mockActiveTimHoldingService);
@@ -1407,4 +1390,4 @@ private ActiveTim getActiveTim() {
tim.setActiveTimId(-1L);
return tim;
}
-}
\ No newline at end of file
+}
diff --git a/cv-data-service-library/src/test/java/com/trihydro/library/service/MilepostServiceTest.java b/cv-data-service-library/src/test/java/com/trihydro/library/service/MilepostServiceTest.java
index a668e816e..aed55ab2a 100644
--- a/cv-data-service-library/src/test/java/com/trihydro/library/service/MilepostServiceTest.java
+++ b/cv-data-service-library/src/test/java/com/trihydro/library/service/MilepostServiceTest.java
@@ -19,7 +19,9 @@
import org.mockito.Mock;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
public class MilepostServiceTest extends BaseServiceTest {
@@ -89,4 +91,65 @@ public void getMilepostsByPointWithBuffer() {
Assertions.assertEquals(1, data.size());
Assertions.assertEquals(milepost, data.get(0));
}
-}
\ No newline at end of file
+
+ @Test
+ public void getBufferForPath_Success() {
+ // prepare
+ String routeId = "routeId";
+ double desiredDistanceInMiles = 10.0;
+ Milepost milepost1 = new Milepost();
+ Milepost milepost2 = new Milepost();
+ List pathMileposts = new ArrayList<>();
+ pathMileposts.add(milepost1);
+ pathMileposts.add(milepost2);
+ Milepost bufferMilepost1 = new Milepost();
+ Milepost bufferMilepost2 = new Milepost();
+ List bufferMileposts = new ArrayList<>();
+ bufferMileposts.add(bufferMilepost1);
+ bufferMileposts.add(bufferMilepost2);
+ when(mockRespMilepostList.getBody()).thenReturn(bufferMileposts);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity> entity = new HttpEntity<>(pathMileposts, headers);
+ String url = String.format("%s/cdot-upstream-path/get-buffer-for-path/%s/%s", baseUrl, routeId, desiredDistanceInMiles);
+ ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() {
+ };
+ when(mockRestTemplate.exchange(url, HttpMethod.POST, entity, responseType)).thenReturn(mockRespMilepostList);
+
+ // execute
+ List data = uut.getBufferForPath(routeId, desiredDistanceInMiles, pathMileposts);
+
+ // verify
+ verify(mockRestTemplate).exchange(url, HttpMethod.POST, entity, responseType);
+ Assertions.assertEquals(2, data.size());
+ Assertions.assertEquals(bufferMilepost1, data.get(0));
+ Assertions.assertEquals(bufferMilepost2, data.get(1));
+ }
+
+ @Test
+ public void getBufferForPath_Failure_ResponseBodyNull() {
+ // prepare
+ String routeId = "routeId";
+ double desiredDistanceInMiles = 10.0;
+ Milepost milepost1 = new Milepost();
+ Milepost milepost2 = new Milepost();
+ List pathMileposts = new ArrayList<>();
+ pathMileposts.add(milepost1);
+ pathMileposts.add(milepost2);
+ when(mockRespMilepostList.getBody()).thenReturn(null);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity> entity = new HttpEntity<>(pathMileposts, headers);
+ String url = String.format("%s/cdot-upstream-path/get-buffer-for-path/%s/%s", baseUrl, routeId, desiredDistanceInMiles);
+ ParameterizedTypeReference