From 693f81df676e7521878eba734d2695987ceaf969 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Thu, 19 Dec 2024 12:44:00 -0800 Subject: [PATCH 1/3] Implemented RoutingResources Controller refactor --- .../opendcs/odcsapi/res/OpenDcsResource.java | 16 +- .../opendcs/odcsapi/res/RoutingResources.java | 512 +++++++++++++++--- .../odcsapi/res/RoutingResourcesTest.java | 240 ++++++++ 3 files changed, 679 insertions(+), 89 deletions(-) create mode 100644 opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/OpenDcsResource.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/OpenDcsResource.java index d5a931a9..eeebd1c2 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/OpenDcsResource.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/OpenDcsResource.java @@ -22,7 +22,10 @@ import javax.ws.rs.core.Context; import decodes.cwms.CwmsDatabaseProvider; +import decodes.db.Database; import decodes.db.DatabaseException; +import decodes.db.DatabaseIO; +import decodes.tsdb.TimeSeriesDb; import decodes.util.DecodesSettings; import opendcs.opentsdb.OpenTsdbProvider; import org.opendcs.database.DatabaseService; @@ -81,7 +84,18 @@ final OpenDcsDatabase createDb() { throw new IllegalStateException("Error connecting to the database via JNDI", ex); } -// throw new IllegalStateException("Error connecting to the database via JNDI", e); } } + + DatabaseIO getLegacyDatabase() + { + return createDb().getLegacyDatabase(Database.class).map(Database::getDbIo) + .orElseThrow(() -> new UnsupportedOperationException("Endpoint is unsupported by the OpenDCS REST API.")); + } + + TimeSeriesDb getLegacyTimeseriesDB() + { + return createDb().getLegacyDatabase(TimeSeriesDb.class) + .orElseThrow(() -> new UnsupportedOperationException("Endpoint is unsupported by the OpenDCS REST API.")); + } } diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java index e7bc268e..935ad66e 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java @@ -15,12 +15,15 @@ package org.opendcs.odcsapi.res; -import java.sql.SQLException; -import java.util.logging.Logger; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; +import java.util.TimeZone; +import java.util.Vector; import javax.annotation.security.RolesAllowed; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -33,19 +36,30 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import decodes.db.DataSource; +import decodes.db.DatabaseException; +import decodes.db.DatabaseIO; +import decodes.db.RoutingSpec; +import decodes.db.RoutingSpecList; +import decodes.db.ScheduleEntry; +import decodes.db.ScheduleEntryStatus; +import decodes.polling.DacqEvent; +import decodes.sql.DbKey; +import decodes.tsdb.DbIoException; +import opendcs.dai.DacqEventDAI; +import opendcs.dai.ScheduleEntryDAI; import org.opendcs.odcsapi.beans.ApiRouting; +import org.opendcs.odcsapi.beans.ApiRoutingExecStatus; +import org.opendcs.odcsapi.beans.ApiRoutingRef; import org.opendcs.odcsapi.beans.ApiScheduleEntry; -import org.opendcs.odcsapi.dao.ApiRoutingDAO; +import org.opendcs.odcsapi.beans.ApiScheduleEntryRef; import org.opendcs.odcsapi.dao.DbException; import org.opendcs.odcsapi.errorhandling.ErrorCodes; import org.opendcs.odcsapi.errorhandling.WebAppException; -import org.opendcs.odcsapi.hydrojson.DbInterface; import org.opendcs.odcsapi.sec.AuthorizationCheck; -import org.opendcs.odcsapi.util.ApiConstants; -import org.opendcs.odcsapi.util.ApiHttpUtil; @Path("/") -public class RoutingResources +public class RoutingResources extends OpenDcsResource { @Context private HttpServletRequest request; @Context private HttpHeaders httpHeaders; @@ -56,12 +70,38 @@ public class RoutingResources @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getRoutingRefs() throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("getRoutingRefs"); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + try { - return ApiHttpUtil.createResponse(dao.getRoutingRefs()); + //TODO: Fix this endpoint. Currently, it is returning an empty list. + DatabaseIO dbio = getLegacyDatabase(); + RoutingSpecList rsList = new RoutingSpecList(); + dbio.readRoutingSpecList(rsList); + return Response.status(HttpServletResponse.SC_OK) + .entity(map(rsList)).build(); } + catch(DatabaseException e) + { + throw new DbException("Unable to retrieve routing reference list", e); + } + } + + static List map(RoutingSpecList rsList) + { + List refs = new ArrayList<>(); + rsList.getList().forEach(rs -> { + ApiRoutingRef ref = new ApiRoutingRef(); + if (rs.getId() != null) + { + ref.setRoutingId(rs.getId().getValue()); + } + else + { + ref.setRoutingId(DbKey.NullKey.getValue()); + } + ref.setName(rs.getName()); + refs.add(ref); + }); + return refs; } @GET @@ -69,19 +109,50 @@ public Response getRoutingRefs() throws DbException @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getRouting(@QueryParam("routingid") Long routingId) - throws WebAppException, DbException, SQLException + throws WebAppException, DbException { - + if (routingId == null) - throw new WebAppException(ErrorCodes.MISSING_ID, - "Missing required routingid parameter."); - - Logger.getLogger(ApiConstants.loggerName).fine("getRouting id=" + routingId); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) { - return ApiHttpUtil.createResponse(dao.getRouting(routingId)); + throw new WebAppException(ErrorCodes.MISSING_ID, + "Missing required routingid parameter."); + } + + try + { + DatabaseIO dbio = getLegacyDatabase(); + RoutingSpec spec = new RoutingSpec(); + spec.setId(DbKey.createDbKey(routingId)); + dbio.readRoutingSpec(spec); + return Response.status(HttpServletResponse.SC_OK) + .entity(map(spec)).build(); + } + catch(DatabaseException e) + { + throw new DbException("Unable to retrieve routing spec by ID", e); + } + } + + static ApiRouting map(RoutingSpec spec) { + ApiRouting routing = new ApiRouting(); + if (spec.getId() != null) + { + routing.setRoutingId(spec.getId().getValue()); + } + else + { + routing.setRoutingId(DbKey.NullKey.getValue()); + } + routing.setName(spec.getName()); + routing.setLastModified(spec.lastModifyTime); + if (spec.outputTimeZone != null) + { + routing.setOutputTZ(spec.outputTimeZone.toZoneId().getId()); } + routing.setNetlistNames(new ArrayList<>(spec.networkListNames)); + routing.setOutputFormat(spec.outputFormat); + routing.setEnableEquations(spec.enableEquations); + return routing; } @POST @@ -90,17 +161,80 @@ public Response getRouting(@QueryParam("routingid") Long routingId) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postRouting(ApiRouting routing) - throws WebAppException, DbException, SQLException + throws DbException + { + try + { + DatabaseIO dbio = getLegacyDatabase(); + RoutingSpec spec = map(routing); + dbio.writeRoutingSpec(spec); + return Response.status(HttpServletResponse.SC_OK).entity(map(spec)).build(); + } + catch(DatabaseException e) + { + throw new DbException("Unable to store routing spec", e); + } + } + + static RoutingSpec map(ApiRouting routing) throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("post routing received routing " + routing.getName() - + " with ID=" + routing.getRoutingId()); - - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + try + { + RoutingSpec spec = new RoutingSpec(); + if (routing.getRoutingId() != null) + { + spec.setId(DbKey.createDbKey(routing.getRoutingId())); + } + else + { + spec.setId(DbKey.NullKey); + } + spec.setName(routing.getName()); + spec.usePerformanceMeasurements = false; + spec.lastModifyTime = routing.getLastModified(); + if (routing.getOutputTZ() != null) + { + spec.outputTimeZoneAbbr = routing.getOutputTZ(); + spec.outputTimeZone = TimeZone.getTimeZone(ZoneId.of(routing.getOutputTZ())); + } + routing.getNetlistNames().forEach(spec::addNetworkListName); + spec.outputFormat = routing.getOutputFormat(); + spec.enableEquations = routing.isEnableEquations(); + spec.presentationGroupName = routing.getPresGroupName(); + spec.isProduction = routing.isProduction(); + spec.consumerArg = routing.getDestinationArg(); + spec.consumerType = routing.getDestinationType(); + if (routing.getSince() != null) + { + spec.sinceTime = routing.getSince(); + } + if (routing.getUntil() != null) + { + spec.untilTime = routing.getUntil(); + } + spec.setProperties(routing.getProperties()); + if (routing.getDataSourceId() != null) + { + DataSource dataSource = new DataSource(); + if (routing.getDataSourceId() != null) + { + dataSource.setId(DbKey.createDbKey(routing.getDataSourceId())); + } + else + { + dataSource.setId(DbKey.NullKey); + } + dataSource.setName(routing.getDataSourceName()); + spec.dataSource = dataSource; + } + spec.networkListNames = new Vector<>(routing.getNetlistNames()); + return spec; + } + catch(DatabaseException e) { - dao.writeRouting(routing); - return ApiHttpUtil.createResponse(routing); + throw new DbException("Unable to map routing spec", e); } + } @DELETE @@ -108,17 +242,26 @@ public Response postRouting(ApiRouting routing) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response deleteRouting(@QueryParam("routingid") Long routingId) - throws WebAppException, DbException, SQLException + throws DbException, WebAppException { - Logger.getLogger(ApiConstants.loggerName) - .fine("DELETE routing received routingId=" + routingId); - - // Use username and password to attempt to connect to the database - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + if (routingId == null) { - dao.deleteRouting(routingId); - return ApiHttpUtil.createResponse("RoutingSpec with ID " + routingId + " deleted"); + throw new WebAppException(HttpServletResponse.SC_BAD_REQUEST, + "Missing required routingid parameter."); + } + + try + { + DatabaseIO dbio = getLegacyDatabase(); + RoutingSpec spec = new RoutingSpec(); + spec.setId(DbKey.createDbKey(routingId)); + dbio.deleteRoutingSpec(spec); + return Response.status(HttpServletResponse.SC_OK) + .entity("RoutingSpec with ID " + routingId + " deleted").build(); + } + catch(DatabaseException e) + { + throw new DbException("Unable to delete routing spec", e); } } @@ -127,33 +270,73 @@ public Response deleteRouting(@QueryParam("routingid") Long routingId) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getScheduleRefs() - throws DbException + throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("getScheduleRefs"); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + + try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) { - return ApiHttpUtil.createResponse(dao.getScheduleRefs()); + List entries = dai.listScheduleEntries(null); + return Response.status(HttpServletResponse.SC_OK) + .entity(map(entries)).build(); } + catch(DbIoException e) + { + throw new DbException("Unable to retrieve schedule entry ref list", e); + } + } + + static List map(List entries) + { + List refs = new ArrayList<>(); + entries.forEach(entry -> { + ApiScheduleEntryRef ref = new ApiScheduleEntryRef(); + if (entry.getId() != null) + { + ref.setSchedEntryId(entry.getId().getValue()); + } + else + { + ref.setSchedEntryId(DbKey.NullKey.getValue()); + } + ref.setEnabled(entry.isEnabled()); + ref.setAppName(entry.getLoadingAppName()); + ref.setName(entry.getName()); + ref.setLastModified(entry.getLastModified()); + ref.setRoutingSpecName(entry.getRoutingSpecName()); + refs.add(ref); + }); + return refs; } @GET @Path("schedule") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) - public Response getSchedule(@QueryParam("scheduleid") Long scheduleId) - throws WebAppException, DbException, SQLException + public Response getSchedule(@QueryParam("scheduleid") Long scheduleId) + throws WebAppException, DbException { if (scheduleId == null) - throw new WebAppException(ErrorCodes.MISSING_ID, - "Missing required scheduleid parameter."); - - Logger.getLogger(ApiConstants.loggerName).fine("getSchedule id=" + scheduleId); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + throw new WebAppException(ErrorCodes.MISSING_ID, + "Missing required scheduleid parameter."); + try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) { - return ApiHttpUtil.createResponse(dao.getSchedule(scheduleId)); + ScheduleEntry entry = new ScheduleEntry(DbKey.createDbKey(scheduleId)); + + // TODO: Add support for schedule retrieval by id in OpenDCS, + // which currently only supports retrieval by name + + // try (DbInterface dbi = new DbInterface(); + // ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + // { + // return ApiHttpUtil.createResponse(dao.getSchedule(scheduleId)); + // } } + // catch(DbIoException e) + // { + // throw new DbException("Unable to retrieve schedule entry by ID", e); + // } + + return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build(); } @POST @@ -162,36 +345,109 @@ public Response getSchedule(@QueryParam("scheduleid") Long scheduleId) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postSchedule(ApiScheduleEntry schedule) - throws WebAppException, DbException, SQLException + throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("post schedule received sched " + schedule.getName() - + " with ID=" + schedule.getSchedEntryId()); - - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) + { + ScheduleEntry entry = map(schedule); + dai.writeScheduleEntry(entry); + return Response.status(HttpServletResponse.SC_OK) + .entity(map(entry)) + .build(); + } + catch (DbIoException e) { - dao.writeSchedule(schedule); - return ApiHttpUtil.createResponse(schedule); + throw new DbException("Unable to store schedule entry", e); } } + static ScheduleEntry map(ApiScheduleEntry schedule) throws DbException + { + try + { + ScheduleEntry entry = new ScheduleEntry(schedule.getName()); + if (schedule.getSchedEntryId() != null) + { + entry.setId(DbKey.createDbKey(schedule.getSchedEntryId())); + } + else + { + entry.setId(DbKey.NullKey); + } + entry.setStartTime(schedule.getStartTime()); + entry.setTimezone(schedule.getTimeZone()); + if (schedule.getAppId() != null) + { + entry.setLoadingAppId(DbKey.createDbKey(schedule.getAppId())); + entry.setLoadingAppName(schedule.getAppName()); + } + if (schedule.getRoutingSpecId() != null) + { + entry.setRoutingSpecId(DbKey.createDbKey(schedule.getRoutingSpecId())); + entry.setRoutingSpecName(schedule.getRoutingSpecName()); + } + entry.setRunInterval(schedule.getRunInterval()); + entry.setLastModified(schedule.getLastModified()); + return entry; + } + catch (DatabaseException e) + { + throw new DbException("Unable to map schedule entry", e); + } + } + + static ApiScheduleEntry map(ScheduleEntry entry) + { + ApiScheduleEntry schedule = new ApiScheduleEntry(); + if (entry.getId() != null) + { + schedule.setSchedEntryId(entry.getId().getValue()); + } + else + { + schedule.setSchedEntryId(DbKey.NullKey.getValue()); + } + schedule.setName(entry.getName()); + schedule.setStartTime(entry.getStartTime()); + schedule.setTimeZone(entry.getTimezone()); + schedule.setEnabled(entry.isEnabled()); + if (entry.getLoadingAppId() != null) + { + schedule.setAppId(entry.getLoadingAppId().getValue()); + schedule.setAppName(entry.getLoadingAppName()); + } + if (entry.getRoutingSpecId() != null) + { + schedule.setRoutingSpecId(entry.getRoutingSpecId().getValue()); + schedule.setRoutingSpecName(entry.getRoutingSpecName()); + } + schedule.setRunInterval(entry.getRunInterval()); + schedule.setLastModified(entry.getLastModified()); + return schedule; + } + @DELETE @Path("schedule") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deleteSchedule(@QueryParam("scheduleid") Long scheduleId) - throws WebAppException, DbException + throws DbException, WebAppException { - Logger.getLogger(ApiConstants.loggerName) - .fine("DELETE schedule received scheduleId=" + scheduleId); - - // Use username and password to attempt to connect to the database - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + if (scheduleId == null) + { + throw new WebAppException(HttpServletResponse.SC_BAD_REQUEST, "missing required scheduleid argument."); + } + try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) + { + ScheduleEntry entry = new ScheduleEntry(DbKey.createDbKey(scheduleId)); + dai.deleteScheduleEntry(entry); + return Response.status(HttpServletResponse.SC_OK) + .entity("Schedule entry with ID " + scheduleId + " deleted").build(); + } + catch (DbIoException e) { - dao.deleteSchedule(scheduleId); - return ApiHttpUtil.createResponse("schedulec with ID " + scheduleId + " deleted"); + throw new DbException(String.format("Unable to delete schedule entry by ID: %s", scheduleId), e); } } @@ -201,48 +457,128 @@ public Response deleteSchedule(@QueryParam("scheduleid") Long scheduleId) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getRoutingStats() - throws WebAppException, DbException + throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("getRoutingStats"); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) { - return ApiHttpUtil.createResponse(dao.getRsStatus()); + return Response.status(HttpServletResponse.SC_OK) + .entity(map(dai.listScheduleEntries(null))).build(); + } + catch (DbIoException e) + { + throw new DbException("Unable to retrieve routing status", e); } } + static ArrayList map(ArrayList entries) + { + ArrayList refs = new ArrayList<>(); + for (ScheduleEntry entry : entries) + { + ApiScheduleEntryRef ref = new ApiScheduleEntryRef(); + ref.setSchedEntryId(entry.getId().getValue()); + ref.setEnabled(entry.isEnabled()); + ref.setAppName(entry.getLoadingAppName()); + ref.setName(entry.getName()); + ref.setLastModified(entry.getLastModified()); + ref.setRoutingSpecName(entry.getRoutingSpecName()); + refs.add(ref); + } + + return refs; + } + @GET @Path("routingexecstatus") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getRoutingExecStatus(@QueryParam("scheduleentryid") Long scheduleEntryId) - throws WebAppException, DbException + throws WebAppException, DbException { if (scheduleEntryId == null) - throw new WebAppException(ErrorCodes.MISSING_ID, "missing required scheduleentryid argument."); - - Logger.getLogger(ApiConstants.loggerName).fine("getRoutingExecStatus"); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) { - return ApiHttpUtil.createResponse(dao.getRoutingExecStatus(scheduleEntryId)); + throw new WebAppException(HttpServletResponse.SC_BAD_REQUEST, "missing required scheduleentryid argument."); + } + + try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) + { + ScheduleEntry entry = new ScheduleEntry(DbKey.createDbKey(scheduleEntryId)); + return Response.status(HttpServletResponse.SC_OK) + .entity(statusMap(dai.readScheduleStatus(entry))).build(); + } + catch (DbIoException e) + { + throw new DbException("Unable to retrieve routing exec status", e); } } + static ArrayList statusMap(ArrayList statuses) + { + ArrayList execStatuses = new ArrayList<>(); + for (ScheduleEntryStatus status : statuses) + { + ApiRoutingExecStatus execStatus = new ApiRoutingExecStatus(); + if (status.getScheduleEntryId() != null) + { + execStatus.setScheduleEntryId(status.getScheduleEntryId().getValue()); + } + else + { + execStatus.setScheduleEntryId(DbKey.NullKey.getValue()); + } + execStatus.setHostname(status.getHostname()); + execStatus.setNumErrors(status.getNumDecodesErrors()); + execStatus.setRunStatus(status.getRunStatus()); + execStatus.setRunStop(status.getRunStop()); + execStatus.setRunStart(status.getRunStart()); + execStatus.setNumPlatforms(status.getNumPlatforms()); + execStatus.setNumMessages(status.getNumMessages()); + execStatus.setLastActivity(status.getLastModified()); + execStatuses.add(execStatus); + } + return execStatuses; + } + @GET @Path("dacqevents") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response getDacqEvents(@QueryParam("appid") Long appId, @QueryParam("routingexecid") Long routingExecId, - @QueryParam("platformid") Long platformId, @QueryParam("backlog") String backlog) - throws DbException + @QueryParam("platformid") Long platformId, @QueryParam("backlog") String backlog) + throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("getDacqEvents"); - try (DbInterface dbi = new DbInterface(); - ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + // TODO: Add support for dacq events retrieval in OpenDCS, which currently only supports retrieval by a few + // of the above parameters independently + + // try (DbInterface dbi = new DbInterface(); + // ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) + // { + // HttpSession session = request.getSession(true); + // return ApiHttpUtil.createResponse(dao.getDacqEvents(appId, routingExecId, platformId, backlog, session)); + // } + + try (DacqEventDAI dai = getLegacyTimeseriesDB().makeDacqEventDAO()) { - HttpSession session = request.getSession(true); - return ApiHttpUtil.createResponse(dao.getDacqEvents(appId, routingExecId, platformId, backlog, session)); + ArrayList platformEvents = new ArrayList<>(); + if (platformId != null) { + dai.readEventsForPlatform(DbKey.createDbKey(platformId), platformEvents); + } + ArrayList routingExecEvents = new ArrayList<>(); + if (routingExecId != null) { + dai.readEventsForScheduleStatus(DbKey.createDbKey(routingExecId), routingExecEvents); + } + + + + // dai.getDacqEvents(appId, routingExecId, platformId, backlog); + // return Response.status(HttpServletResponse.SC_OK) + // .entity(events).build(); } + catch (DbIoException e) + { + throw new DbException("Unable to retrieve dacq events", e); + } + + return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build(); } } diff --git a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java new file mode 100644 index 00000000..484f5b07 --- /dev/null +++ b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java @@ -0,0 +1,240 @@ +package org.opendcs.odcsapi.res; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; +import java.util.Vector; + +import decodes.db.RoutingSpec; +import decodes.db.RoutingSpecList; +import decodes.db.ScheduleEntry; +import decodes.db.ScheduleEntryStatus; +import decodes.sql.DbKey; +import org.junit.jupiter.api.Test; +import org.opendcs.odcsapi.beans.ApiRouting; +import org.opendcs.odcsapi.beans.ApiRoutingExecStatus; +import org.opendcs.odcsapi.beans.ApiRoutingRef; +import org.opendcs.odcsapi.beans.ApiScheduleEntry; +import org.opendcs.odcsapi.beans.ApiScheduleEntryRef; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +import static org.opendcs.odcsapi.res.RoutingResources.map; +import static org.opendcs.odcsapi.res.RoutingResources.statusMap; + +final class RoutingResourcesTest +{ + @Test + void testRoutingRefListMap() throws Exception + { + RoutingSpecList routingSpecList = new RoutingSpecList(); + RoutingSpec routingSpec = buildRoutingSpec(); + routingSpecList.add(routingSpec); + List apiRoutingRefs = map(routingSpecList); + ApiRoutingRef apiRoutingRef = apiRoutingRefs.get(0); + assertNotNull(apiRoutingRef); + assertEquals(apiRoutingRef.getRoutingId(), routingSpec.getId().getValue()); + assertEquals(apiRoutingRef.getName(), routingSpec.getName()); + } + + @Test + void testApiRoutingMap() throws Exception + { + RoutingSpec routingSpec = buildRoutingSpec(); + ApiRouting apiRouting = map(routingSpec); + assertNotNull(apiRouting); + assertEquals(apiRouting.getRoutingId(), routingSpec.getId().getValue()); + assertEquals(apiRouting.getName(), routingSpec.getName()); + assertEquals(apiRouting.getOutputTZ(), routingSpec.outputTimeZone.getID()); + assertEquals(apiRouting.getLastModified(), routingSpec.lastModifyTime); + assertEquals(apiRouting.isEnableEquations(), routingSpec.enableEquations); + assertEquals(new Vector<>(apiRouting.getNetlistNames()), routingSpec.networkListNames); + } + + @Test + void testRoutingSpecMap() throws Exception + { + ApiRouting apiRouting = new ApiRouting(); + apiRouting.setRoutingId(1234L); + apiRouting.setName("TestRoutingSpec"); + RoutingSpec routingSpec = map(apiRouting); + assertNotNull(routingSpec); + assertEquals(routingSpec.getId().getValue(), apiRouting.getRoutingId()); + assertEquals(routingSpec.getName(), apiRouting.getName()); + if (routingSpec.outputTimeZone != null) + { + assertEquals(routingSpec.outputTimeZone.getID(), apiRouting.getOutputTZ()); + } + else if (apiRouting.getOutputTZ() != null) + { + fail("routingSpec.outputTimeZone is null, but apiRouting.getOutputTZ() is not null"); + } + assertEquals(routingSpec.lastModifyTime, apiRouting.getLastModified()); + assertEquals(routingSpec.enableEquations, apiRouting.isEnableEquations()); + assertEquals(routingSpec.networkListNames, new Vector<>(apiRouting.getNetlistNames())); + } + + @Test + void testScheduleEntryRefMap() + { + List scheduleEntries = new ArrayList<>(); + ScheduleEntry scheduleEntry = new ScheduleEntry(DbKey.createDbKey(1234L)); + scheduleEntry.setEnabled(true); + scheduleEntry.setName("TestScheduleEntry"); + scheduleEntry.setRoutingSpecId(DbKey.createDbKey(5678L)); + scheduleEntry.setLastModified(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + scheduleEntry.setLoadingAppName("TestAppName"); + scheduleEntry.setRoutingSpecName("TestRoutingSpec"); + scheduleEntry.setTimezone("UTC"); + scheduleEntry.setStartTime(Date.from(Instant.parse("2021-01-01T00:00:00Z"))); + scheduleEntries.add(scheduleEntry); + List apiScheduleEntryRefs = map(scheduleEntries); + assertNotNull(apiScheduleEntryRefs); + ApiScheduleEntryRef apiScheduleEntryRef = apiScheduleEntryRefs.get(0); + assertNotNull(apiScheduleEntryRef); + assertEquals(apiScheduleEntryRef.getSchedEntryId(), scheduleEntry.getKey().getValue()); + assertEquals(apiScheduleEntryRef.getName(), scheduleEntry.getName()); + assertEquals(apiScheduleEntryRef.getAppName(), scheduleEntry.getLoadingAppName()); + assertEquals(apiScheduleEntryRef.getRoutingSpecName(), scheduleEntry.getRoutingSpecName()); + assertEquals(apiScheduleEntryRef.getLastModified(), scheduleEntry.getLastModified()); + } + + @Test + void testScheduleEntryMap() throws Exception + { + ApiScheduleEntry apiScheduleEntry = new ApiScheduleEntry(); + apiScheduleEntry.setSchedEntryId(1234L); + apiScheduleEntry.setName("TestScheduleEntry"); + apiScheduleEntry.setAppName("TestAppName"); + apiScheduleEntry.setRoutingSpecName("TestRoutingSpec"); + apiScheduleEntry.setLastModified(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + apiScheduleEntry.setAppId(5678L); + apiScheduleEntry.setRoutingSpecId(9012L); + apiScheduleEntry.setStartTime(Date.from(Instant.parse("2021-01-01T00:00:00Z"))); + apiScheduleEntry.setEnabled(true); + apiScheduleEntry.setTimeZone("UTC"); + apiScheduleEntry.setRunInterval("1h"); + ScheduleEntry scheduleEntry = map(apiScheduleEntry); + assertNotNull(scheduleEntry); + assertEquals(scheduleEntry.getKey().getValue(), apiScheduleEntry.getSchedEntryId()); + assertEquals(scheduleEntry.getName(), apiScheduleEntry.getName()); + assertEquals(scheduleEntry.getLoadingAppName(), apiScheduleEntry.getAppName()); + assertEquals(scheduleEntry.getRoutingSpecName(), apiScheduleEntry.getRoutingSpecName()); + assertEquals(scheduleEntry.getLastModified(), apiScheduleEntry.getLastModified()); + assertEquals(scheduleEntry.getLoadingAppId().getValue(), apiScheduleEntry.getAppId()); + assertEquals(scheduleEntry.getRoutingSpecId().getValue(), apiScheduleEntry.getRoutingSpecId()); + assertEquals(scheduleEntry.getStartTime(), apiScheduleEntry.getStartTime()); + assertEquals(scheduleEntry.isEnabled(), apiScheduleEntry.isEnabled()); + assertEquals(scheduleEntry.getTimezone(), apiScheduleEntry.getTimeZone()); + assertEquals(scheduleEntry.getRunInterval(), apiScheduleEntry.getRunInterval()); + } + + @Test + void testApiScheduleEntryListMap() + { + ArrayList scheduleEntries = new ArrayList<>(); + ScheduleEntry scheduleEntry = new ScheduleEntry(DbKey.createDbKey(1234L)); + scheduleEntry.setName("TestScheduleEntry"); + scheduleEntry.setLoadingAppName("TestAppName"); + scheduleEntry.setRoutingSpecName("TestRoutingSpec"); + scheduleEntry.setLastModified(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + scheduleEntry.setLoadingAppId(DbKey.createDbKey(5678L)); + scheduleEntry.setRoutingSpecId(DbKey.createDbKey(9012L)); + scheduleEntry.setStartTime(Date.from(Instant.parse("2021-01-01T00:00:00Z"))); + scheduleEntry.setEnabled(true); + scheduleEntry.setTimezone("UTC"); + scheduleEntry.setRunInterval("1h"); + scheduleEntries.add(scheduleEntry); + + ArrayList results = map(scheduleEntries); + + assertNotNull(results); + assertEquals(1, results.size()); + ApiScheduleEntryRef result = results.get(0); + assertNotNull(result); + assertEquals(scheduleEntry.getKey().getValue(), result.getSchedEntryId()); + assertEquals(scheduleEntry.getName(), result.getName()); + assertEquals(scheduleEntry.getLoadingAppName(), result.getAppName()); + assertEquals(scheduleEntry.getRoutingSpecName(), result.getRoutingSpecName()); + assertEquals(scheduleEntry.getLastModified(), result.getLastModified()); + } + + @Test + void testRoutingStatusMap() + { + ArrayList scheduleEntries = new ArrayList<>(); + ScheduleEntryStatus scheduleEntry = new ScheduleEntryStatus(DbKey.createDbKey(1234L)); + scheduleEntry.setScheduleEntryName("TestScheduleEntry"); + scheduleEntry.setLastModified(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + scheduleEntry.setHostname("TestHost"); + scheduleEntry.setRunStatus("TestStatus"); + scheduleEntry.setNumDecodesErrors(10); + scheduleEntry.setNumMessages(20); + scheduleEntry.setNumPlatforms(30); + scheduleEntry.setRunStop(Date.from(Instant.parse("2021-03-01T00:00:00Z"))); + scheduleEntry.setRunStart(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + scheduleEntry.setLastModified(Date.from(Instant.parse("2021-04-01T00:00:00Z"))); + scheduleEntries.add(scheduleEntry); + + ArrayList results = statusMap(scheduleEntries); + assertNotNull(results); + assertEquals(1, results.size()); + ApiRoutingExecStatus result = results.get(0); + assertNotNull(result); + assertEquals(scheduleEntry.getScheduleEntryId().getValue(), result.getScheduleEntryId()); + assertEquals(scheduleEntry.getHostname(), result.getHostname()); + assertEquals(scheduleEntry.getRunStatus(), result.getRunStatus()); + assertEquals(scheduleEntry.getNumDecodesErrors(), result.getNumErrors()); + assertEquals(scheduleEntry.getNumMessages(), result.getNumMessages()); + assertEquals(scheduleEntry.getNumPlatforms(), result.getNumPlatforms()); + assertEquals(scheduleEntry.getRunStop(), result.getRunStop()); + assertEquals(scheduleEntry.getRunStart(), result.getRunStart()); + assertEquals(scheduleEntry.getLastModified(), result.getLastActivity()); + } + + @Test + void testApiScheduleEntryMap() + { + ScheduleEntry scheduleEntry = new ScheduleEntry(DbKey.createDbKey(1234L)); + scheduleEntry.setName("TestScheduleEntry"); + scheduleEntry.setLoadingAppName("TestAppName"); + scheduleEntry.setRoutingSpecName("TestRoutingSpec"); + scheduleEntry.setLastModified(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + scheduleEntry.setLoadingAppId(DbKey.createDbKey(5678L)); + scheduleEntry.setRoutingSpecId(DbKey.createDbKey(9012L)); + scheduleEntry.setStartTime(Date.from(Instant.parse("2021-01-01T00:00:00Z"))); + scheduleEntry.setEnabled(true); + scheduleEntry.setTimezone("UTC"); + scheduleEntry.setRunInterval("1h"); + + ApiScheduleEntry apiScheduleEntry = map(scheduleEntry); + assertNotNull(apiScheduleEntry); + assertEquals(apiScheduleEntry.getSchedEntryId(), scheduleEntry.getKey().getValue()); + assertEquals(apiScheduleEntry.getName(), scheduleEntry.getName()); + assertEquals(apiScheduleEntry.getAppName(), scheduleEntry.getLoadingAppName()); + assertEquals(apiScheduleEntry.getRoutingSpecName(), scheduleEntry.getRoutingSpecName()); + assertEquals(apiScheduleEntry.getLastModified(), scheduleEntry.getLastModified()); + assertEquals(apiScheduleEntry.getAppId(), scheduleEntry.getLoadingAppId().getValue()); + assertEquals(apiScheduleEntry.getRoutingSpecId(), scheduleEntry.getRoutingSpecId().getValue()); + assertEquals(apiScheduleEntry.getStartTime(), scheduleEntry.getStartTime()); + assertEquals(apiScheduleEntry.isEnabled(), scheduleEntry.isEnabled()); + assertEquals(apiScheduleEntry.getTimeZone(), scheduleEntry.getTimezone()); + assertEquals(apiScheduleEntry.getRunInterval(), scheduleEntry.getRunInterval()); + } + + private RoutingSpec buildRoutingSpec() throws Exception + { + RoutingSpec routingSpec = new RoutingSpec(); + routingSpec.setName("TestRoutingSpec"); + routingSpec.setId(DbKey.createDbKey(1234L)); + routingSpec.outputTimeZone = TimeZone.getTimeZone("UTC"); + routingSpec.lastModifyTime = Date.from(Instant.parse("2021-02-01T00:00:00Z")); + routingSpec.enableEquations = true; + routingSpec.networkListNames = new Vector<>(Arrays.asList("TestNet", "TestNet2")); + return routingSpec; + } +} From d144dc6b3103e57ef1116aaf5855348660844d8b Mon Sep 17 00:00:00 2001 From: zack-rma Date: Fri, 3 Jan 2025 10:19:04 -0800 Subject: [PATCH 2/3] Updated with new OpenDCS Toolkit implementations --- .../opendcs/odcsapi/res/RoutingResources.java | 77 +++++++++---------- .../odcsapi/res/RoutingResourcesTest.java | 31 ++++++++ 2 files changed, 67 insertions(+), 41 deletions(-) diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java index 935ad66e..88c818f6 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java @@ -20,10 +20,12 @@ import java.util.List; import java.util.TimeZone; import java.util.Vector; +import java.util.stream.Collectors; import javax.annotation.security.RolesAllowed; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -46,8 +48,10 @@ import decodes.polling.DacqEvent; import decodes.sql.DbKey; import decodes.tsdb.DbIoException; +import ilex.util.Logger; import opendcs.dai.DacqEventDAI; import opendcs.dai.ScheduleEntryDAI; +import org.opendcs.odcsapi.beans.ApiDacqEvent; import org.opendcs.odcsapi.beans.ApiRouting; import org.opendcs.odcsapi.beans.ApiRoutingExecStatus; import org.opendcs.odcsapi.beans.ApiRoutingRef; @@ -76,6 +80,7 @@ public Response getRoutingRefs() throws DbException DatabaseIO dbio = getLegacyDatabase(); RoutingSpecList rsList = new RoutingSpecList(); dbio.readRoutingSpecList(rsList); + dbio.close(); return Response.status(HttpServletResponse.SC_OK) .entity(map(rsList)).build(); } @@ -124,6 +129,7 @@ public Response getRouting(@QueryParam("routingid") Long routingId) RoutingSpec spec = new RoutingSpec(); spec.setId(DbKey.createDbKey(routingId)); dbio.readRoutingSpec(spec); + dbio.close(); return Response.status(HttpServletResponse.SC_OK) .entity(map(spec)).build(); } @@ -168,6 +174,7 @@ public Response postRouting(ApiRouting routing) DatabaseIO dbio = getLegacyDatabase(); RoutingSpec spec = map(routing); dbio.writeRoutingSpec(spec); + dbio.close(); return Response.status(HttpServletResponse.SC_OK).entity(map(spec)).build(); } catch(DatabaseException e) @@ -256,6 +263,7 @@ public Response deleteRouting(@QueryParam("routingid") Long routingId) RoutingSpec spec = new RoutingSpec(); spec.setId(DbKey.createDbKey(routingId)); dbio.deleteRoutingSpec(spec); + dbio.close(); return Response.status(HttpServletResponse.SC_OK) .entity("RoutingSpec with ID " + routingId + " deleted").build(); } @@ -320,23 +328,15 @@ public Response getSchedule(@QueryParam("scheduleid") Long scheduleId) "Missing required scheduleid parameter."); try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) { - ScheduleEntry entry = new ScheduleEntry(DbKey.createDbKey(scheduleId)); - - // TODO: Add support for schedule retrieval by id in OpenDCS, - // which currently only supports retrieval by name - - // try (DbInterface dbi = new DbInterface(); - // ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) - // { - // return ApiHttpUtil.createResponse(dao.getSchedule(scheduleId)); - // } + ScheduleEntry entry = dai.readScheduleEntry(DbKey.createDbKey(scheduleId)); + return Response.status(HttpServletResponse.SC_OK) + .entity(map(entry)) + .build(); + } + catch(DbIoException e) + { + throw new DbException("Unable to retrieve schedule entry by ID", e); } - // catch(DbIoException e) - // { - // throw new DbException("Unable to retrieve schedule entry by ID", e); - // } - - return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build(); } @POST @@ -547,38 +547,33 @@ public Response getDacqEvents(@QueryParam("appid") Long appId, @QueryParam("rout @QueryParam("platformid") Long platformId, @QueryParam("backlog") String backlog) throws DbException { - // TODO: Add support for dacq events retrieval in OpenDCS, which currently only supports retrieval by a few - // of the above parameters independently - - // try (DbInterface dbi = new DbInterface(); - // ApiRoutingDAO dao = new ApiRoutingDAO(dbi)) - // { - // HttpSession session = request.getSession(true); - // return ApiHttpUtil.createResponse(dao.getDacqEvents(appId, routingExecId, platformId, backlog, session)); - // } - try (DacqEventDAI dai = getLegacyTimeseriesDB().makeDacqEventDAO()) { - ArrayList platformEvents = new ArrayList<>(); - if (platformId != null) { - dai.readEventsForPlatform(DbKey.createDbKey(platformId), platformEvents); - } - ArrayList routingExecEvents = new ArrayList<>(); - if (routingExecId != null) { - dai.readEventsForScheduleStatus(DbKey.createDbKey(routingExecId), routingExecEvents); - } - - - - // dai.getDacqEvents(appId, routingExecId, platformId, backlog); - // return Response.status(HttpServletResponse.SC_OK) - // .entity(events).build(); + HttpSession session = request.getSession(true); + ArrayList events = new ArrayList<>(); + dai.readEvents(events, DbKey.createDbKey(appId), DbKey.createDbKey(routingExecId), + DbKey.createDbKey(platformId), backlog, session); + return Response.status(HttpServletResponse.SC_OK) + .entity(events.stream().map(RoutingResources::map).collect(Collectors.toList())).build(); } catch (DbIoException e) { throw new DbException("Unable to retrieve dacq events", e); } + } - return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build(); + static ApiDacqEvent map(DacqEvent event) + { + ApiDacqEvent apiEvent = new ApiDacqEvent(); + apiEvent.setEventId(event.getDacqEventId().getValue()); + apiEvent.setAppId(event.getAppId().getValue()); + apiEvent.setPlatformId(event.getPlatformId().getValue()); + apiEvent.setRoutingExecId(event.getScheduleEntryStatusId().getValue()); + apiEvent.setPriority(Logger.priorityName[event.getEventPriority()]); + apiEvent.setEventTime(event.getEventTime()); + apiEvent.setEventText(event.getEventText()); + apiEvent.setSubsystem(event.getSubsystem()); + apiEvent.setMsgRecvTime(event.getMsgRecvTime()); + return apiEvent; } } diff --git a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java index 484f5b07..3791567b 100644 --- a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java +++ b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java @@ -12,8 +12,11 @@ import decodes.db.RoutingSpecList; import decodes.db.ScheduleEntry; import decodes.db.ScheduleEntryStatus; +import decodes.polling.DacqEvent; import decodes.sql.DbKey; +import ilex.util.Logger; import org.junit.jupiter.api.Test; +import org.opendcs.odcsapi.beans.ApiDacqEvent; import org.opendcs.odcsapi.beans.ApiRouting; import org.opendcs.odcsapi.beans.ApiRoutingExecStatus; import org.opendcs.odcsapi.beans.ApiRoutingRef; @@ -226,6 +229,34 @@ void testApiScheduleEntryMap() assertEquals(apiScheduleEntry.getRunInterval(), scheduleEntry.getRunInterval()); } + @Test + void testDacqEventMap() + { + DacqEvent dacqEvent = new DacqEvent(); + dacqEvent.setAppId(DbKey.createDbKey(1234L)); + dacqEvent.setDacqEventId(DbKey.createDbKey(5678L)); + dacqEvent.setEventText("TestEvent"); + dacqEvent.setEventTime(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + dacqEvent.setEventPriority(Logger.E_DEBUG1); + dacqEvent.setMsgRecvTime(Date.from(Instant.parse("2021-02-01T12:00:00Z"))); + dacqEvent.setSubsystem("TestSubsystem"); + dacqEvent.setScheduleEntryStatusId(DbKey.createDbKey(9012L)); + dacqEvent.setPlatformId(DbKey.createDbKey(3456L)); + + ApiDacqEvent apiDacqEvent = map(dacqEvent); + + assertNotNull(apiDacqEvent); + assertEquals(apiDacqEvent.getAppId(), dacqEvent.getAppId().getValue()); + assertEquals(apiDacqEvent.getEventId(), dacqEvent.getDacqEventId().getValue()); + assertEquals(apiDacqEvent.getEventText(), dacqEvent.getEventText()); + assertEquals(apiDacqEvent.getEventTime(), dacqEvent.getEventTime()); + assertEquals(apiDacqEvent.getPriority(), Logger.priorityName[dacqEvent.getEventPriority()]); + assertEquals(apiDacqEvent.getMsgRecvTime(), dacqEvent.getMsgRecvTime()); + assertEquals(apiDacqEvent.getSubsystem(), dacqEvent.getSubsystem()); + assertEquals(apiDacqEvent.getRoutingExecId(), dacqEvent.getScheduleEntryStatusId().getValue()); + assertEquals(apiDacqEvent.getPlatformId(), dacqEvent.getPlatformId().getValue()); + } + private RoutingSpec buildRoutingSpec() throws Exception { RoutingSpec routingSpec = new RoutingSpec(); From 9764bc6d7f1aacc1fe261c25b4af1aaaeceda0cd Mon Sep 17 00:00:00 2001 From: zack-rma Date: Fri, 3 Jan 2025 16:04:36 -0800 Subject: [PATCH 3/3] Updated with new OpenDCS Toolkit implementations, mappings --- .../opendcs/odcsapi/res/RoutingResources.java | 114 ++++++++++++++---- .../odcsapi/res/RoutingResourcesTest.java | 53 +++++++- 2 files changed, 145 insertions(+), 22 deletions(-) diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java index 88c818f6..0f14d86c 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/RoutingResources.java @@ -55,10 +55,10 @@ import org.opendcs.odcsapi.beans.ApiRouting; import org.opendcs.odcsapi.beans.ApiRoutingExecStatus; import org.opendcs.odcsapi.beans.ApiRoutingRef; +import org.opendcs.odcsapi.beans.ApiRoutingStatus; import org.opendcs.odcsapi.beans.ApiScheduleEntry; import org.opendcs.odcsapi.beans.ApiScheduleEntryRef; import org.opendcs.odcsapi.dao.DbException; -import org.opendcs.odcsapi.errorhandling.ErrorCodes; import org.opendcs.odcsapi.errorhandling.WebAppException; import org.opendcs.odcsapi.sec.AuthorizationCheck; @@ -67,6 +67,7 @@ public class RoutingResources extends OpenDcsResource { @Context private HttpServletRequest request; @Context private HttpHeaders httpHeaders; + private DatabaseIO dbIo; @GET @Path("routingrefs") @@ -76,11 +77,9 @@ public Response getRoutingRefs() throws DbException { try { - //TODO: Fix this endpoint. Currently, it is returning an empty list. - DatabaseIO dbio = getLegacyDatabase(); + dbIo = getLegacyDatabase(); RoutingSpecList rsList = new RoutingSpecList(); - dbio.readRoutingSpecList(rsList); - dbio.close(); + dbIo.readRoutingSpecList(rsList); return Response.status(HttpServletResponse.SC_OK) .entity(map(rsList)).build(); } @@ -88,10 +87,15 @@ public Response getRoutingRefs() throws DbException { throw new DbException("Unable to retrieve routing reference list", e); } + finally + { + dbIo.close(); + } } static List map(RoutingSpecList rsList) { + // This map does not map the destination value to the ApiRoutingRef object. List refs = new ArrayList<>(); rsList.getList().forEach(rs -> { ApiRoutingRef ref = new ApiRoutingRef(); @@ -104,6 +108,11 @@ static List map(RoutingSpecList rsList) ref.setRoutingId(DbKey.NullKey.getValue()); } ref.setName(rs.getName()); + if (rs.dataSource != null) + { + ref.setDataSourceName(rs.dataSource.getName()); + } + ref.setLastModified(rs.lastModifyTime); refs.add(ref); }); return refs; @@ -119,27 +128,35 @@ public Response getRouting(@QueryParam("routingid") Long routingId) if (routingId == null) { - throw new WebAppException(ErrorCodes.MISSING_ID, + throw new WebAppException(HttpServletResponse.SC_BAD_REQUEST, "Missing required routingid parameter."); } try { - DatabaseIO dbio = getLegacyDatabase(); + dbIo = getLegacyDatabase(); RoutingSpec spec = new RoutingSpec(); spec.setId(DbKey.createDbKey(routingId)); - dbio.readRoutingSpec(spec); - dbio.close(); + dbIo.readRoutingSpec(spec); return Response.status(HttpServletResponse.SC_OK) .entity(map(spec)).build(); } catch(DatabaseException e) { + if (e.getMessage().contains("No RoutingSpec found with id")) + { + return Response.status(HttpServletResponse.SC_NOT_FOUND).build(); + } throw new DbException("Unable to retrieve routing spec by ID", e); } + finally + { + dbIo.close(); + } } static ApiRouting map(RoutingSpec spec) { + // This map does not map the goesSelfTimed value to the ApiRouting object. ApiRouting routing = new ApiRouting(); if (spec.getId() != null) { @@ -151,13 +168,24 @@ static ApiRouting map(RoutingSpec spec) { } routing.setName(spec.getName()); routing.setLastModified(spec.lastModifyTime); - if (spec.outputTimeZone != null) + if (spec.outputTimeZoneAbbr != null) { - routing.setOutputTZ(spec.outputTimeZone.toZoneId().getId()); + routing.setOutputTZ(spec.outputTimeZoneAbbr); } routing.setNetlistNames(new ArrayList<>(spec.networkListNames)); routing.setOutputFormat(spec.outputFormat); routing.setEnableEquations(spec.enableEquations); + if (spec.dataSource != null) + { + routing.setDataSourceId(spec.dataSource.getId().getValue()); + routing.setDataSourceName(spec.dataSource.getName()); + } + routing.setDestinationArg(spec.consumerArg); + routing.setDestinationType(spec.consumerType); + routing.setPresGroupName(spec.presentationGroupName); + routing.setSince(spec.sinceTime); + routing.setUntil(spec.untilTime); + routing.setProperties(spec.getProperties()); return routing; } @@ -171,16 +199,19 @@ public Response postRouting(ApiRouting routing) { try { - DatabaseIO dbio = getLegacyDatabase(); + dbIo = getLegacyDatabase(); RoutingSpec spec = map(routing); - dbio.writeRoutingSpec(spec); - dbio.close(); + dbIo.writeRoutingSpec(spec); return Response.status(HttpServletResponse.SC_OK).entity(map(spec)).build(); } catch(DatabaseException e) { throw new DbException("Unable to store routing spec", e); } + finally + { + dbIo.close(); + } } static RoutingSpec map(ApiRouting routing) throws DbException @@ -248,6 +279,7 @@ static RoutingSpec map(ApiRouting routing) throws DbException @Path("routing") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deleteRouting(@QueryParam("routingid") Long routingId) throws DbException, WebAppException { @@ -259,11 +291,10 @@ public Response deleteRouting(@QueryParam("routingid") Long routingId) try { - DatabaseIO dbio = getLegacyDatabase(); + dbIo = getLegacyDatabase(); RoutingSpec spec = new RoutingSpec(); spec.setId(DbKey.createDbKey(routingId)); - dbio.deleteRoutingSpec(spec); - dbio.close(); + dbIo.deleteRoutingSpec(spec); return Response.status(HttpServletResponse.SC_OK) .entity("RoutingSpec with ID " + routingId + " deleted").build(); } @@ -271,6 +302,10 @@ public Response deleteRouting(@QueryParam("routingid") Long routingId) { throw new DbException("Unable to delete routing spec", e); } + finally + { + dbIo.close(); + } } @GET @@ -324,11 +359,15 @@ public Response getSchedule(@QueryParam("scheduleid") Long scheduleId) throws WebAppException, DbException { if (scheduleId == null) - throw new WebAppException(ErrorCodes.MISSING_ID, + throw new WebAppException(HttpServletResponse.SC_BAD_REQUEST, "Missing required scheduleid parameter."); try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) { ScheduleEntry entry = dai.readScheduleEntry(DbKey.createDbKey(scheduleId)); + if (entry == null) + { + return Response.status(HttpServletResponse.SC_NOT_FOUND).build(); + } return Response.status(HttpServletResponse.SC_OK) .entity(map(entry)) .build(); @@ -462,7 +501,11 @@ public Response getRoutingStats() try (ScheduleEntryDAI dai = getLegacyDatabase().makeScheduleEntryDAO()) { return Response.status(HttpServletResponse.SC_OK) - .entity(map(dai.listScheduleEntries(null))).build(); + .entity(dai.listScheduleEntries(null) + .stream() + .map(RoutingResources::statusMap) + .collect(Collectors.toList())) + .build(); } catch (DbIoException e) { @@ -470,6 +513,33 @@ public Response getRoutingStats() } } + static ApiRoutingStatus statusMap(ScheduleEntry entry) + { + ApiRoutingStatus status = new ApiRoutingStatus(); + if (entry.getId() != null) + { + status.setScheduleEntryId(entry.getId().getValue()); + } + else + { + status.setScheduleEntryId(DbKey.NullKey.getValue()); + } + status.setAppName(entry.getLoadingAppName()); + if (entry.getLoadingAppId() != null) + { + status.setAppId(entry.getLoadingAppId().getValue()); + } + status.setName(entry.getName()); + status.setEnabled(entry.isEnabled()); + if (entry.getRoutingSpecId() != null) + { + status.setRoutingSpecId(entry.getRoutingSpecId().getValue()); + } + status.setRunInterval(entry.getRunInterval()); + status.setLastActivity(entry.getLastModified()); + return status; + } + static ArrayList map(ArrayList entries) { ArrayList refs = new ArrayList<>(); @@ -551,8 +621,10 @@ public Response getDacqEvents(@QueryParam("appid") Long appId, @QueryParam("rout { HttpSession session = request.getSession(true); ArrayList events = new ArrayList<>(); - dai.readEvents(events, DbKey.createDbKey(appId), DbKey.createDbKey(routingExecId), - DbKey.createDbKey(platformId), backlog, session); + dai.readEvents(events, appId != null ? DbKey.createDbKey(appId) : DbKey.NullKey, + routingExecId != null ? DbKey.createDbKey(routingExecId) : DbKey.NullKey, + platformId != null ? DbKey.createDbKey(platformId) : DbKey.NullKey, + backlog, session); return Response.status(HttpServletResponse.SC_OK) .entity(events.stream().map(RoutingResources::map).collect(Collectors.toList())).build(); } diff --git a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java index 3791567b..e5213b56 100644 --- a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java +++ b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/RoutingResourcesTest.java @@ -8,6 +8,7 @@ import java.util.TimeZone; import java.util.Vector; +import decodes.db.DataSource; import decodes.db.RoutingSpec; import decodes.db.RoutingSpecList; import decodes.db.ScheduleEntry; @@ -20,6 +21,7 @@ import org.opendcs.odcsapi.beans.ApiRouting; import org.opendcs.odcsapi.beans.ApiRoutingExecStatus; import org.opendcs.odcsapi.beans.ApiRoutingRef; +import org.opendcs.odcsapi.beans.ApiRoutingStatus; import org.opendcs.odcsapi.beans.ApiScheduleEntry; import org.opendcs.odcsapi.beans.ApiScheduleEntryRef; @@ -42,20 +44,33 @@ void testRoutingRefListMap() throws Exception assertNotNull(apiRoutingRef); assertEquals(apiRoutingRef.getRoutingId(), routingSpec.getId().getValue()); assertEquals(apiRoutingRef.getName(), routingSpec.getName()); + assertEquals(apiRoutingRef.getDataSourceName(), routingSpec.dataSource.getName()); + assertEquals(apiRoutingRef.getLastModified(), routingSpec.lastModifyTime); } @Test void testApiRoutingMap() throws Exception { RoutingSpec routingSpec = buildRoutingSpec(); + ApiRouting apiRouting = map(routingSpec); + assertNotNull(apiRouting); assertEquals(apiRouting.getRoutingId(), routingSpec.getId().getValue()); assertEquals(apiRouting.getName(), routingSpec.getName()); - assertEquals(apiRouting.getOutputTZ(), routingSpec.outputTimeZone.getID()); + assertEquals(apiRouting.getOutputTZ(), routingSpec.outputTimeZoneAbbr); assertEquals(apiRouting.getLastModified(), routingSpec.lastModifyTime); assertEquals(apiRouting.isEnableEquations(), routingSpec.enableEquations); assertEquals(new Vector<>(apiRouting.getNetlistNames()), routingSpec.networkListNames); + assertEquals(apiRouting.getDataSourceName(), routingSpec.dataSource.getName()); + assertEquals(apiRouting.getDestinationType(), routingSpec.consumerType); + assertEquals(apiRouting.getDestinationArg(), routingSpec.consumerArg); + assertEquals(apiRouting.getDataSourceId(), routingSpec.dataSource.getId().getValue()); + assertEquals(apiRouting.getPresGroupName(), routingSpec.presentationGroupName); + assertEquals(apiRouting.getSince(), routingSpec.sinceTime); + assertEquals(apiRouting.getUntil(), routingSpec.untilTime); + assertEquals(apiRouting.getDataSourceId(), routingSpec.dataSource.getId().getValue()); + assertEquals(apiRouting.getProperties(), routingSpec.getProperties()); } @Test @@ -257,6 +272,34 @@ void testDacqEventMap() assertEquals(apiDacqEvent.getPlatformId(), dacqEvent.getPlatformId().getValue()); } + @Test + void testStatusMap() + { + ScheduleEntry scheduleEntry = new ScheduleEntry(DbKey.createDbKey(1234L)); + scheduleEntry.setName("TestScheduleEntry"); + scheduleEntry.setLoadingAppName("TestAppName"); + scheduleEntry.setRoutingSpecName("TestRoutingSpec"); + scheduleEntry.setLastModified(Date.from(Instant.parse("2021-02-01T00:00:00Z"))); + scheduleEntry.setLoadingAppId(DbKey.createDbKey(5678L)); + scheduleEntry.setRoutingSpecId(DbKey.createDbKey(9012L)); + scheduleEntry.setStartTime(Date.from(Instant.parse("2021-01-01T00:00:00Z"))); + scheduleEntry.setEnabled(true); + scheduleEntry.setTimezone("UTC"); + scheduleEntry.setRunInterval("1h"); + + ApiRoutingStatus apiRoutingStatus = statusMap(scheduleEntry); + + assertNotNull(apiRoutingStatus); + assertEquals(apiRoutingStatus.getScheduleEntryId(), scheduleEntry.getKey().getValue()); + assertEquals(apiRoutingStatus.getName(), scheduleEntry.getName()); + assertEquals(apiRoutingStatus.getAppName(), scheduleEntry.getLoadingAppName()); + assertEquals(apiRoutingStatus.getLastActivity(), scheduleEntry.getLastModified()); + assertEquals(apiRoutingStatus.getAppId(), scheduleEntry.getLoadingAppId().getValue()); + assertEquals(apiRoutingStatus.getRoutingSpecId(), scheduleEntry.getRoutingSpecId().getValue()); + assertEquals(apiRoutingStatus.isEnabled(), scheduleEntry.isEnabled()); + assertEquals(apiRoutingStatus.getRunInterval(), scheduleEntry.getRunInterval()); + } + private RoutingSpec buildRoutingSpec() throws Exception { RoutingSpec routingSpec = new RoutingSpec(); @@ -265,7 +308,15 @@ private RoutingSpec buildRoutingSpec() throws Exception routingSpec.outputTimeZone = TimeZone.getTimeZone("UTC"); routingSpec.lastModifyTime = Date.from(Instant.parse("2021-02-01T00:00:00Z")); routingSpec.enableEquations = true; + DataSource dataSource = new DataSource(); + dataSource.setName("TestDataSource"); + routingSpec.dataSource = dataSource; + routingSpec.consumerType = "TestConsumerType"; + routingSpec.consumerArg = "TestConsumerArg"; routingSpec.networkListNames = new Vector<>(Arrays.asList("TestNet", "TestNet2")); + routingSpec.presentationGroupName = "TestPresGroup"; + routingSpec.sinceTime = "2021-01-01T00:00:00Z"; + routingSpec.untilTime ="2021-02-01T00:00:00Z"; return routingSpec; } }