From f0b22a7feea58d3cfaba0700a5bef93b581a8452 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 3 Dec 2024 11:53:52 -0800 Subject: [PATCH 1/8] SiteResources controller updated to use new DAI --- .../org/opendcs/odcsapi/dao/DbException.java | 5 + .../odcsapi/opendcs_dep/TsdbManager.java | 61 +++++++++ .../odcsapi/res/AlgorithmResources.java | 12 +- .../opendcs/odcsapi/res/SiteResources.java | 122 ++++++++++++++---- .../odcsapi/res/SiteResourcesTest.java | 99 ++++++++++++++ .../odcsapi/res/it/SiteResourcesIT.java | 37 ++++++ 6 files changed, 305 insertions(+), 31 deletions(-) create mode 100644 opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java create mode 100644 opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/SiteResourcesTest.java create mode 100644 opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/it/SiteResourcesIT.java diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/dao/DbException.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/dao/DbException.java index 398f14eba..46e35c379 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/dao/DbException.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/dao/DbException.java @@ -32,4 +32,9 @@ public DbException(String message, Exception cause) { super(message, cause); } + + public DbException(String message) + { + super(message); + } } diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java new file mode 100644 index 000000000..4014cb384 --- /dev/null +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java @@ -0,0 +1,61 @@ + +/* + * Copyright 2024 OpenDCS Consortium and its Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opendcs.odcsapi.opendcs_dep; + +import decodes.db.DatabaseException; +import decodes.tsdb.TimeSeriesDb; +import org.opendcs.database.DatabaseService; +import org.opendcs.odcsapi.dao.DbException; +import org.opendcs.odcsapi.hydrojson.DbInterface; + +/** + * A few operations require using the openDCS TimeSeriesDb subclasses. + * This class instantiates and manages those classes given a connection + * provided by the web container. + * + * @author mmaloney + * + */ +public class TsdbManager +{ + /** + * Make an appropriate TimeSeriesDb subclass depending on the database type (CWMS, + * HDB, or OpenTSDB). + * Note: Currently the tsdb is provided with the one connection being used by this + * session, created by the web container. So don't close the connection because + * the container is managing this. + * @param dbi + * @return + * @throws DbException + * @deprecated access DAI objects through OpenDcsDatabase::getDao + */ + @Deprecated + public static TimeSeriesDb makeTsdb(DbInterface dbi) + throws DbException + { + try + { + return DatabaseService.getDatabaseFor(DbInterface.getDataSource()) + .getLegacyDatabase(TimeSeriesDb.class) + .orElseThrow(() -> new DbException("No TimeSeriesDb available")); + } + catch(DatabaseException ex) + { + throw new DbException("", ex); + } + } +} \ No newline at end of file diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java index cdc3fd071..bbef67e8d 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java @@ -61,7 +61,8 @@ public class AlgorithmResources extends OpenDcsResource @RolesAllowed(AuthorizationCheck.ODCS_API_GUEST) public Response getAlgorithmRefs() throws DbIoException { - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { List algorithmRefs = dai.listAlgorithmsForGui() .stream() @@ -96,7 +97,8 @@ public Response getAlgorithm(@QueryParam("algorithmid") Long algoId) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required algorithmid parameter."); } - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { ApiAlgorithm apiAlgorithm = map(dai.getAlgorithmById(DbKey.createDbKey(algoId))); return Response.status(HttpServletResponse.SC_OK) @@ -156,7 +158,8 @@ private static ApiAlgoParm map(DbAlgoParm parameter) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postAlgorithm(ApiAlgorithm algo) throws DbIoException { - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { dai.writeAlgorithm(map(algo)); return Response.status(HttpServletResponse.SC_CREATED) @@ -192,7 +195,8 @@ private static DbCompAlgorithmScript map(ApiAlgorithmScript script, DbCompAlgori @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deletAlgorithm(@QueryParam("algorithmid") Long algorithmId) throws TsdbException { - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { dai.deleteAlgorithm(DbKey.createDbKey(algorithmId)); return Response.status(HttpServletResponse.SC_NO_CONTENT) diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java index 03a94a1a7..f3d8cec65 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java @@ -15,9 +15,13 @@ package org.opendcs.odcsapi.res; -import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import javax.annotation.security.RolesAllowed; +import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -30,18 +34,24 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import decodes.db.DatabaseException; +import decodes.db.Site; +import decodes.db.SiteList; +import decodes.db.SiteName; +import decodes.sql.DbKey; +import decodes.tsdb.DbIoException; +import decodes.tsdb.NoSuchObjectException; +import opendcs.dai.SiteDAI; import org.opendcs.odcsapi.beans.ApiSite; -import org.opendcs.odcsapi.dao.ApiSiteDAO; +import org.opendcs.odcsapi.beans.ApiSiteRef; 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 SiteResources +public class SiteResources extends OpenDcsResource { @Context HttpHeaders httpHeaders; @@ -52,14 +62,42 @@ public class SiteResources public Response geSiteRefs() throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("getSiteRefs"); - try (DbInterface dbi = new DbInterface(); - ApiSiteDAO dao = new ApiSiteDAO(dbi)) + try (SiteDAI dai = createDb().getDao(SiteDAI.class) + .orElseThrow(() -> new DbException("No SiteDAI available"))) { - return ApiHttpUtil.createResponse(dao.getSiteRefs()); + SiteList sites = new SiteList(); + dai.read(sites); + List siteRefs = map(sites); + return Response.status(HttpServletResponse.SC_OK).entity(siteRefs).build(); + } + catch (DbIoException ex) + { + throw new DbException("Unable to retrieve sites", ex); } } + static List map(SiteList sites) + { + List retList = new ArrayList<>(); + for(Iterator it = sites.iterator(); it.hasNext(); ) + { + final Site site = it.next(); + ApiSiteRef siteRef = new ApiSiteRef(); + siteRef.setSiteId(site.getId().getValue()); + siteRef.setPublicName(site.getPublicName()); + siteRef.setDescription(site.getDescription()); + HashMap siteNames = new HashMap<>(); + for(Iterator iter = site.getNames(); iter.hasNext(); ) + { + final SiteName sn = iter.next(); + siteNames.put(sn.getNameType(), sn.getNameValue()); + } + siteRef.setSitenames(siteNames); + retList.add(siteRef); + } + return retList; + } + @GET @Path("site") @Produces(MediaType.APPLICATION_JSON) @@ -71,11 +109,15 @@ public Response geSiteFull(@QueryParam("siteid") Long siteId) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required siteid parameter."); - Logger.getLogger(ApiConstants.loggerName).fine("getSite id=" + siteId); - try (DbInterface dbi = new DbInterface(); - ApiSiteDAO dao = new ApiSiteDAO(dbi)) + try (SiteDAI dai = createDb().getDao(SiteDAI.class) + .orElseThrow(() -> new DbException("No SiteDAI available"))) + { + return Response.status(HttpServletResponse.SC_OK) + .entity(dai.getSiteById(DbKey.createDbKey(siteId))).build(); + } + catch(DbIoException | NoSuchObjectException e) { - return ApiHttpUtil.createResponse(dao.getSite(siteId)); + throw new DbException("Unable to retrieve site by ID", e); } } @@ -85,16 +127,15 @@ public Response geSiteFull(@QueryParam("siteid") Long siteId) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postSite(ApiSite site) - throws WebAppException, DbException + throws DbException { - Logger.getLogger(ApiConstants.loggerName) - .fine("POST site received site id=" + site.getSiteId()); - + // Use username and password to attempt to connect to the database - try (DbInterface dbi = new DbInterface(); - ApiSiteDAO dao = new ApiSiteDAO(dbi)) + try (SiteDAI dai = createDb().getDao(SiteDAI.class) + .orElseThrow(() -> new DbException("No SiteDAI available"))) { - dao.writeSite(site); + + dai.writeSite(map(site)); String sitePubName = site.getPublicName(); if (sitePubName == null) { @@ -103,6 +144,32 @@ public Response postSite(ApiSite site) String resp = String.format("{\"status\": 200, \"message\": \"The site (%s) has been saved successfully.\"}", sitePubName); return ApiHttpUtil.createResponse(resp); } + catch(DatabaseException | DbIoException e) + { + throw new DbException("Unable to store site", e); + } + } + + static Site map(ApiSite site) throws DatabaseException + { + Site returnSite = new Site(); + if (site.getSiteId() != null) + { + returnSite.setId(DbKey.createDbKey(site.getSiteId())); + } + returnSite.setLocationType(site.getLocationType()); + returnSite.setElevation(site.getElevation()); + returnSite.setPublicName(site.getPublicName()); + returnSite.setElevationUnits(site.getElevUnits()); + returnSite.setActive(site.isActive()); + returnSite.setDescription(site.getDescription()); + returnSite.setLastModifyTime(site.getLastModified()); + for (String name : site.getProperties().stringPropertyNames()) + { + SiteName sn = new SiteName(returnSite, name); + returnSite.addName(sn); + } + return returnSite; } @DELETE @@ -110,18 +177,19 @@ public Response postSite(ApiSite site) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) - public Response deleteSite(@QueryParam("siteid") Long siteId) throws WebAppException, DbException + public Response deleteSite(@QueryParam("siteid") Long siteId) throws DbException { - Logger.getLogger(ApiConstants.loggerName) - .fine("DELETE site received site id=" + siteId); - // Use username and password to attempt to connect to the database - try (DbInterface dbi = new DbInterface(); - ApiSiteDAO siteDAO = new ApiSiteDAO(dbi)) + try (SiteDAI dai = createDb().getDao(SiteDAI.class) + .orElseThrow(() -> new DbException("No SiteDAI available"))) { - siteDAO.deleteSite(siteId); + dai.deleteSite(DbKey.createDbKey(siteId)); return ApiHttpUtil.createResponse("ID " + siteId + " deleted"); } + catch(DbIoException e) + { + throw new DbException("Unable to delete site", e); + } } diff --git a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/SiteResourcesTest.java b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/SiteResourcesTest.java new file mode 100644 index 000000000..172f2b404 --- /dev/null +++ b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/SiteResourcesTest.java @@ -0,0 +1,99 @@ +package org.opendcs.odcsapi.res; + +import java.time.Instant; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import decodes.db.Site; +import decodes.db.SiteList; +import decodes.db.SiteName; +import org.junit.jupiter.api.Test; +import org.opendcs.odcsapi.beans.ApiSite; +import org.opendcs.odcsapi.beans.ApiSiteRef; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.opendcs.odcsapi.res.SiteResources.map; + +final class SiteResourcesTest +{ + @Test + void testMapSiteList() + { + SiteList sl = new SiteList(); + Site site1 = siteBuilder("Albuquerque"); + Site site2 = siteBuilder("Santa Fe"); + sl.addSite(site1); + sl.addSite(site2); + List siteRefs = map(sl); + + assertNotNull(siteRefs); + assertNotNull(siteRefs.get(0)); + assertNotNull(siteRefs.get(1)); + + // Site 1 + assertEquals(site1.getDescription(), siteRefs.get(0).getDescription()); + assertEquals(site1.getPublicName(), siteRefs.get(0).getPublicName()); + assertEquals(site1.getId().getValue(), siteRefs.get(0).getSiteId()); + for(Iterator it = site1.getNames(); it.hasNext(); ) + { + final SiteName sn = it.next(); + assertTrue(siteRefs.get(0).getSitenames().containsKey(sn.getNameType())); + assertEquals(sn.getNameType(), siteRefs.get(0).getSitenames().get(sn.getNameType())); + } + + // Site 2 + assertEquals(site2.getDescription(), siteRefs.get(1).getDescription()); + assertEquals(site2.getPublicName(), siteRefs.get(1).getPublicName()); + assertEquals(site2.getId().getValue(), siteRefs.get(1).getSiteId()); + for(Iterator it = site2.getNames(); it.hasNext(); ) + { + final SiteName sn = it.next(); + assertTrue(siteRefs.get(1).getSitenames().containsKey(sn.getNameType())); + assertEquals(sn.getNameType(), siteRefs.get(1).getSitenames().get(sn.getNameType())); + } + } + + @Test + void testMapSite() throws Exception + { + ApiSite apiSite = new ApiSite(); + apiSite.setActive(true); + apiSite.setSiteId(1234L); + apiSite.setCountry("USA"); + apiSite.setDescription("This is a test pump site"); + apiSite.setElevation(10.0); + apiSite.setElevUnits("m"); + apiSite.setPublicName("Albuquerque"); + Site result = map(apiSite); + + assertNotNull(result); + assertEquals(apiSite.getDescription(), result.getDescription()); + assertEquals(apiSite.getPublicName(), result.getPublicName()); + assertEquals(apiSite.getElevation(), result.getElevation()); + assertEquals(apiSite.getElevUnits(), result.getElevationUnits()); + assertEquals(apiSite.isActive(), result.isActive()); + assertEquals(apiSite.getSiteId(), result.getId().getValue()); + for (Map.Entry entry : apiSite.getSitenames().entrySet()) + { + assertEquals(entry.getValue(), result.getName(entry.getKey()).getNameValue()); + } + } + + private static Site siteBuilder(String name) + { + Site site = new Site(); + site.setActive(true); + site.setDescription("This is a test pump site"); + site.setElevation(10.0 * name.length()); + site.setPublicName(name); + site.setElevationUnits("m"); + site.setLocationType("PUMP"); + site.setLastModifyTime(Date.from(Instant.now())); + return site; + } + +} diff --git a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/it/SiteResourcesIT.java b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/it/SiteResourcesIT.java new file mode 100644 index 000000000..6bfa6e02a --- /dev/null +++ b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/it/SiteResourcesIT.java @@ -0,0 +1,37 @@ +package org.opendcs.odcsapi.res.it; + +import javax.servlet.http.HttpServletResponse; + +import io.restassured.filter.log.LogDetail; +import io.restassured.filter.session.SessionFilter; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; +import org.opendcs.odcsapi.fixtures.DatabaseContextProvider; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; + +@Tag("integration") +@ExtendWith(DatabaseContextProvider.class) +final class SiteResourcesIT +{ + @TestTemplate + void testRoundTrip() + { + SessionFilter sessionFilter = new SessionFilter(); + given() + .log().ifValidationFails(LogDetail.ALL, true) + .accept("application/json") + .filter(sessionFilter) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("siterefs") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + ; + } +} From cdd42ba56d3877d67c33e7ef409fee7bd35f8ed0 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 3 Dec 2024 14:12:44 -0800 Subject: [PATCH 2/8] Fixed errors created in rebase --- .../odcsapi/opendcs_dep/TsdbManager.java | 61 ------------------- .../odcsapi/res/AlgorithmResources.java | 12 ++-- 2 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java deleted file mode 100644 index 4014cb384..000000000 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java +++ /dev/null @@ -1,61 +0,0 @@ - -/* - * Copyright 2024 OpenDCS Consortium and its Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.opendcs.odcsapi.opendcs_dep; - -import decodes.db.DatabaseException; -import decodes.tsdb.TimeSeriesDb; -import org.opendcs.database.DatabaseService; -import org.opendcs.odcsapi.dao.DbException; -import org.opendcs.odcsapi.hydrojson.DbInterface; - -/** - * A few operations require using the openDCS TimeSeriesDb subclasses. - * This class instantiates and manages those classes given a connection - * provided by the web container. - * - * @author mmaloney - * - */ -public class TsdbManager -{ - /** - * Make an appropriate TimeSeriesDb subclass depending on the database type (CWMS, - * HDB, or OpenTSDB). - * Note: Currently the tsdb is provided with the one connection being used by this - * session, created by the web container. So don't close the connection because - * the container is managing this. - * @param dbi - * @return - * @throws DbException - * @deprecated access DAI objects through OpenDcsDatabase::getDao - */ - @Deprecated - public static TimeSeriesDb makeTsdb(DbInterface dbi) - throws DbException - { - try - { - return DatabaseService.getDatabaseFor(DbInterface.getDataSource()) - .getLegacyDatabase(TimeSeriesDb.class) - .orElseThrow(() -> new DbException("No TimeSeriesDb available")); - } - catch(DatabaseException ex) - { - throw new DbException("", ex); - } - } -} \ No newline at end of file diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java index bbef67e8d..cdc3fd071 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java @@ -61,8 +61,7 @@ public class AlgorithmResources extends OpenDcsResource @RolesAllowed(AuthorizationCheck.ODCS_API_GUEST) public Response getAlgorithmRefs() throws DbIoException { - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { List algorithmRefs = dai.listAlgorithmsForGui() .stream() @@ -97,8 +96,7 @@ public Response getAlgorithm(@QueryParam("algorithmid") Long algoId) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required algorithmid parameter."); } - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { ApiAlgorithm apiAlgorithm = map(dai.getAlgorithmById(DbKey.createDbKey(algoId))); return Response.status(HttpServletResponse.SC_OK) @@ -158,8 +156,7 @@ private static ApiAlgoParm map(DbAlgoParm parameter) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postAlgorithm(ApiAlgorithm algo) throws DbIoException { - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { dai.writeAlgorithm(map(algo)); return Response.status(HttpServletResponse.SC_CREATED) @@ -195,8 +192,7 @@ private static DbCompAlgorithmScript map(ApiAlgorithmScript script, DbCompAlgori @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deletAlgorithm(@QueryParam("algorithmid") Long algorithmId) throws TsdbException { - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { dai.deleteAlgorithm(DbKey.createDbKey(algorithmId)); return Response.status(HttpServletResponse.SC_NO_CONTENT) From 6c90f94f2d8f96951537facebc8d339da3a6630f Mon Sep 17 00:00:00 2001 From: zack-rma Date: Thu, 5 Dec 2024 08:49:13 -0800 Subject: [PATCH 3/8] Updated responses --- .../opendcs/odcsapi/res/SiteResources.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java index f3d8cec65..0ef92317f 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java @@ -48,12 +48,12 @@ import org.opendcs.odcsapi.errorhandling.ErrorCodes; import org.opendcs.odcsapi.errorhandling.WebAppException; import org.opendcs.odcsapi.sec.AuthorizationCheck; -import org.opendcs.odcsapi.util.ApiHttpUtil; @Path("/") public class SiteResources extends OpenDcsResource { @Context HttpHeaders httpHeaders; + private static final String NO_SITE_DAI = "No SiteDAI available"; @GET @Path("siterefs") @@ -63,7 +63,7 @@ public Response geSiteRefs() throws DbException { try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException("No SiteDAI available"))) + .orElseThrow(() -> new DbException(NO_SITE_DAI))) { SiteList sites = new SiteList(); dai.read(sites); @@ -110,7 +110,7 @@ public Response geSiteFull(@QueryParam("siteid") Long siteId) "Missing required siteid parameter."); try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException("No SiteDAI available"))) + .orElseThrow(() -> new DbException(NO_SITE_DAI))) { return Response.status(HttpServletResponse.SC_OK) .entity(dai.getSiteById(DbKey.createDbKey(siteId))).build(); @@ -129,10 +129,8 @@ public Response geSiteFull(@QueryParam("siteid") Long siteId) public Response postSite(ApiSite site) throws DbException { - - // Use username and password to attempt to connect to the database try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException("No SiteDAI available"))) + .orElseThrow(() -> new DbException(NO_SITE_DAI))) { dai.writeSite(map(site)); @@ -141,8 +139,9 @@ public Response postSite(ApiSite site) { sitePubName = ""; } - String resp = String.format("{\"status\": 200, \"message\": \"The site (%s) has been saved successfully.\"}", sitePubName); - return ApiHttpUtil.createResponse(resp); + return Response.status(HttpServletResponse.SC_OK) + .entity(String.format("{\"status\": 200, \"message\": \"The site (%s) has been saved successfully.\"}", + sitePubName)).build(); } catch(DatabaseException | DbIoException e) { @@ -181,10 +180,11 @@ public Response deleteSite(@QueryParam("siteid") Long siteId) throws DbException { // Use username and password to attempt to connect to the database try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException("No SiteDAI available"))) + .orElseThrow(() -> new DbException(NO_SITE_DAI))) { dai.deleteSite(DbKey.createDbKey(siteId)); - return ApiHttpUtil.createResponse("ID " + siteId + " deleted"); + return Response.status(HttpServletResponse.SC_OK) + .entity("ID " + siteId + " deleted").build(); } catch(DbIoException e) { From 1f861810824045bf443fa00b7597bb17aba94eb6 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 10 Dec 2024 12:56:04 -0800 Subject: [PATCH 4/8] Updated SiteResources to utilize Legacy DB DAI retrieval --- .../org/opendcs/odcsapi/res/OpenDcsResource.java | 15 +++++++++++++++ .../org/opendcs/odcsapi/res/SiteResources.java | 15 ++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) 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 d5a931a9d..01334059b 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,9 +22,12 @@ import javax.ws.rs.core.Context; import decodes.cwms.CwmsDatabaseProvider; +import decodes.db.Database; import decodes.db.DatabaseException; import decodes.util.DecodesSettings; import opendcs.opentsdb.OpenTsdbProvider; +import decodes.db.DatabaseIO; +import decodes.tsdb.TimeSeriesDb; import org.opendcs.database.DatabaseService; import org.opendcs.database.api.OpenDcsDao; import org.opendcs.database.api.OpenDcsDatabase; @@ -84,4 +87,16 @@ final OpenDcsDatabase createDb() // 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/SiteResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java index 0ef92317f..2eee24c4d 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/SiteResources.java @@ -53,7 +53,6 @@ public class SiteResources extends OpenDcsResource { @Context HttpHeaders httpHeaders; - private static final String NO_SITE_DAI = "No SiteDAI available"; @GET @Path("siterefs") @@ -62,8 +61,7 @@ public class SiteResources extends OpenDcsResource public Response geSiteRefs() throws DbException { - try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException(NO_SITE_DAI))) + try (SiteDAI dai = getLegacyTimeseriesDB().makeSiteDAO()) { SiteList sites = new SiteList(); dai.read(sites); @@ -109,8 +107,7 @@ public Response geSiteFull(@QueryParam("siteid") Long siteId) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required siteid parameter."); - try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException(NO_SITE_DAI))) + try (SiteDAI dai = getLegacyTimeseriesDB().makeSiteDAO()) { return Response.status(HttpServletResponse.SC_OK) .entity(dai.getSiteById(DbKey.createDbKey(siteId))).build(); @@ -129,10 +126,8 @@ public Response geSiteFull(@QueryParam("siteid") Long siteId) public Response postSite(ApiSite site) throws DbException { - try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException(NO_SITE_DAI))) + try (SiteDAI dai = getLegacyTimeseriesDB().makeSiteDAO()) { - dai.writeSite(map(site)); String sitePubName = site.getPublicName(); if (sitePubName == null) @@ -178,9 +173,7 @@ static Site map(ApiSite site) throws DatabaseException @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deleteSite(@QueryParam("siteid") Long siteId) throws DbException { - // Use username and password to attempt to connect to the database - try (SiteDAI dai = createDb().getDao(SiteDAI.class) - .orElseThrow(() -> new DbException(NO_SITE_DAI))) + try (SiteDAI dai = getLegacyTimeseriesDB().makeSiteDAO()) { dai.deleteSite(DbKey.createDbKey(siteId)); return Response.status(HttpServletResponse.SC_OK) From 5fc58d211d5c42d06d2d70ec842b12aec3e32d47 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 3 Dec 2024 11:53:52 -0800 Subject: [PATCH 5/8] SiteResources controller updated to use new DAI --- .../odcsapi/opendcs_dep/TsdbManager.java | 61 +++++++++++++++++++ .../odcsapi/res/AlgorithmResources.java | 12 ++-- 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java new file mode 100644 index 000000000..4014cb384 --- /dev/null +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java @@ -0,0 +1,61 @@ + +/* + * Copyright 2024 OpenDCS Consortium and its Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opendcs.odcsapi.opendcs_dep; + +import decodes.db.DatabaseException; +import decodes.tsdb.TimeSeriesDb; +import org.opendcs.database.DatabaseService; +import org.opendcs.odcsapi.dao.DbException; +import org.opendcs.odcsapi.hydrojson.DbInterface; + +/** + * A few operations require using the openDCS TimeSeriesDb subclasses. + * This class instantiates and manages those classes given a connection + * provided by the web container. + * + * @author mmaloney + * + */ +public class TsdbManager +{ + /** + * Make an appropriate TimeSeriesDb subclass depending on the database type (CWMS, + * HDB, or OpenTSDB). + * Note: Currently the tsdb is provided with the one connection being used by this + * session, created by the web container. So don't close the connection because + * the container is managing this. + * @param dbi + * @return + * @throws DbException + * @deprecated access DAI objects through OpenDcsDatabase::getDao + */ + @Deprecated + public static TimeSeriesDb makeTsdb(DbInterface dbi) + throws DbException + { + try + { + return DatabaseService.getDatabaseFor(DbInterface.getDataSource()) + .getLegacyDatabase(TimeSeriesDb.class) + .orElseThrow(() -> new DbException("No TimeSeriesDb available")); + } + catch(DatabaseException ex) + { + throw new DbException("", ex); + } + } +} \ No newline at end of file diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java index cdc3fd071..bbef67e8d 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java @@ -61,7 +61,8 @@ public class AlgorithmResources extends OpenDcsResource @RolesAllowed(AuthorizationCheck.ODCS_API_GUEST) public Response getAlgorithmRefs() throws DbIoException { - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { List algorithmRefs = dai.listAlgorithmsForGui() .stream() @@ -96,7 +97,8 @@ public Response getAlgorithm(@QueryParam("algorithmid") Long algoId) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required algorithmid parameter."); } - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { ApiAlgorithm apiAlgorithm = map(dai.getAlgorithmById(DbKey.createDbKey(algoId))); return Response.status(HttpServletResponse.SC_OK) @@ -156,7 +158,8 @@ private static ApiAlgoParm map(DbAlgoParm parameter) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postAlgorithm(ApiAlgorithm algo) throws DbIoException { - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { dai.writeAlgorithm(map(algo)); return Response.status(HttpServletResponse.SC_CREATED) @@ -192,7 +195,8 @@ private static DbCompAlgorithmScript map(ApiAlgorithmScript script, DbCompAlgori @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deletAlgorithm(@QueryParam("algorithmid") Long algorithmId) throws TsdbException { - try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) + try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) + .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) { dai.deleteAlgorithm(DbKey.createDbKey(algorithmId)); return Response.status(HttpServletResponse.SC_NO_CONTENT) From 1409a1d20ddae4e60932d970d49a5efeff3149c3 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 3 Dec 2024 14:12:44 -0800 Subject: [PATCH 6/8] Fixed errors created in rebase --- .../odcsapi/opendcs_dep/TsdbManager.java | 61 ------------------- .../odcsapi/res/AlgorithmResources.java | 12 ++-- 2 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java deleted file mode 100644 index 4014cb384..000000000 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/opendcs_dep/TsdbManager.java +++ /dev/null @@ -1,61 +0,0 @@ - -/* - * Copyright 2024 OpenDCS Consortium and its Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.opendcs.odcsapi.opendcs_dep; - -import decodes.db.DatabaseException; -import decodes.tsdb.TimeSeriesDb; -import org.opendcs.database.DatabaseService; -import org.opendcs.odcsapi.dao.DbException; -import org.opendcs.odcsapi.hydrojson.DbInterface; - -/** - * A few operations require using the openDCS TimeSeriesDb subclasses. - * This class instantiates and manages those classes given a connection - * provided by the web container. - * - * @author mmaloney - * - */ -public class TsdbManager -{ - /** - * Make an appropriate TimeSeriesDb subclass depending on the database type (CWMS, - * HDB, or OpenTSDB). - * Note: Currently the tsdb is provided with the one connection being used by this - * session, created by the web container. So don't close the connection because - * the container is managing this. - * @param dbi - * @return - * @throws DbException - * @deprecated access DAI objects through OpenDcsDatabase::getDao - */ - @Deprecated - public static TimeSeriesDb makeTsdb(DbInterface dbi) - throws DbException - { - try - { - return DatabaseService.getDatabaseFor(DbInterface.getDataSource()) - .getLegacyDatabase(TimeSeriesDb.class) - .orElseThrow(() -> new DbException("No TimeSeriesDb available")); - } - catch(DatabaseException ex) - { - throw new DbException("", ex); - } - } -} \ No newline at end of file diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java index bbef67e8d..cdc3fd071 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/AlgorithmResources.java @@ -61,8 +61,7 @@ public class AlgorithmResources extends OpenDcsResource @RolesAllowed(AuthorizationCheck.ODCS_API_GUEST) public Response getAlgorithmRefs() throws DbIoException { - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { List algorithmRefs = dai.listAlgorithmsForGui() .stream() @@ -97,8 +96,7 @@ public Response getAlgorithm(@QueryParam("algorithmid") Long algoId) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required algorithmid parameter."); } - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { ApiAlgorithm apiAlgorithm = map(dai.getAlgorithmById(DbKey.createDbKey(algoId))); return Response.status(HttpServletResponse.SC_OK) @@ -158,8 +156,7 @@ private static ApiAlgoParm map(DbAlgoParm parameter) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response postAlgorithm(ApiAlgorithm algo) throws DbIoException { - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { dai.writeAlgorithm(map(algo)); return Response.status(HttpServletResponse.SC_CREATED) @@ -195,8 +192,7 @@ private static DbCompAlgorithmScript map(ApiAlgorithmScript script, DbCompAlgori @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deletAlgorithm(@QueryParam("algorithmid") Long algorithmId) throws TsdbException { - try(AlgorithmDAI dai = createDb().getDao(AlgorithmDAI.class) - .orElseThrow(() -> new DatabaseException("No AlgorithmDAI available."))) + try(AlgorithmDAI dai = getDao(AlgorithmDAI.class)) { dai.deleteAlgorithm(DbKey.createDbKey(algorithmId)); return Response.status(HttpServletResponse.SC_NO_CONTENT) From 88ad0959adc0c12e389c5fbcdd326d35f3c00861 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 10 Dec 2024 10:37:30 -0800 Subject: [PATCH 7/8] Updated PresentationResources to utilize OpenDCS DAI implementations --- .../odcsapi/res/PresentationResources.java | 184 ++++++++++++++---- .../res/PresentationResourcesTest.java | 133 +++++++++++++ 2 files changed, 281 insertions(+), 36 deletions(-) create mode 100644 opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/PresentationResourcesTest.java diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java index ae33d9143..202d73f84 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java @@ -16,9 +16,11 @@ package org.opendcs.odcsapi.res; import java.sql.SQLException; -import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Vector; import javax.annotation.security.RolesAllowed; +import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -31,15 +33,20 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import decodes.db.DataPresentation; +import decodes.db.DataType; +import decodes.db.DatabaseException; +import decodes.db.PresentationGroup; +import decodes.db.PresentationGroupList; +import decodes.sql.DbKey; +import decodes.sql.PresentationGroupListIO; +import org.opendcs.odcsapi.beans.ApiPresentationElement; import org.opendcs.odcsapi.beans.ApiPresentationGroup; -import org.opendcs.odcsapi.dao.ApiPresentationDAO; +import org.opendcs.odcsapi.beans.ApiPresentationRef; 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 PresentationResources @@ -52,50 +59,150 @@ public class PresentationResources @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getPresentationRefs() throws DbException { - Logger.getLogger(ApiConstants.loggerName).fine("getPresentationRefs"); - try (DbInterface dbi = new DbInterface(); - ApiPresentationDAO dao = new ApiPresentationDAO(dbi)) + try { - return ApiHttpUtil.createResponse(dao.getPresentationRefs()); + PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + PresentationGroupList groupList = new PresentationGroupList(); + presGroupList.read(groupList); + return Response.status(HttpServletResponse.SC_OK).entity(map(groupList)).build(); + } + catch (SQLException | DatabaseException e) + { + throw new DbException("Unable to retrieve presentation groups", e); } } + static ArrayList map(PresentationGroupList groupList) + { + ArrayList ret = new ArrayList<>(); + for (PresentationGroup group : groupList.getVector()) + { + ApiPresentationRef presRef = new ApiPresentationRef(); + presRef.setGroupId(group.getId().getValue()); + presRef.setName(group.groupName); + presRef.setInheritsFrom(group.inheritsFrom); + presRef.setProduction(group.isProduction); + if (group.parent != null) + presRef.setInheritsFromId(group.parent.getId().getValue()); + presRef.setLastModified(group.lastModifyTime); + ret.add(presRef); + } + return ret; + } + @GET @Path("presentation") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_GUEST}) public Response getPresentation(@QueryParam("groupid") Long groupId) - throws WebAppException, DbException, SQLException + throws WebAppException, DbException { if (groupId == null) throw new WebAppException(ErrorCodes.MISSING_ID, "Missing required groupid parameter."); - Logger.getLogger(ApiConstants.loggerName).fine("getPresentation id=" + groupId); - try (DbInterface dbi = new DbInterface(); - ApiPresentationDAO dao = new ApiPresentationDAO(dbi)) + try + { + PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + PresentationGroup group = new PresentationGroup(); + group.setId(DbKey.createDbKey(groupId)); + presGroupList.readPresentationGroup(group, false); + return Response.status(HttpServletResponse.SC_OK).entity(map(group)).build(); + } + catch (DatabaseException e) { - return ApiHttpUtil.createResponse(dao.getPresentation(groupId)); + throw new DbException(String.format("Unable to retrieve presentation group with ID: %s", groupId), e); } } + static ApiPresentationGroup map(PresentationGroup group) + { + ApiPresentationGroup presGrp = new ApiPresentationGroup(); + presGrp.setLastModified(group.lastModifyTime); + presGrp.setName(group.groupName); + presGrp.setProduction(group.isProduction); + if (group.parent != null) + { + presGrp.setInheritsFrom(group.parent.groupName); + presGrp.setInheritsFromId(group.parent.getId().getValue()); + } + presGrp.setGroupId(group.getId().getValue()); + presGrp.setElements(map(group.dataPresentations)); + return presGrp; + } + + static ArrayList map(Vector dataPresentations) + { + ArrayList ret = new ArrayList<>(); + for(DataPresentation dp : dataPresentations) + { + ApiPresentationElement ape = new ApiPresentationElement(); + ape.setDataTypeCode(dp.getDataType().getCode()); + ape.setDataTypeStd(dp.getDataType().getStandard()); + ape.setFractionalDigits(dp.getMaxDecimals()); + ape.setMax(dp.getMaxValue()); + ape.setMin(dp.getMinValue()); + ape.setUnits(dp.getUnitsAbbr()); + ret.add(ape); + } + return ret; + } + @POST @Path("presentation") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) - public Response postPresentation(ApiPresentationGroup presGrp) throws WebAppException, DbException, SQLException + public Response postPresentation(ApiPresentationGroup presGrp) throws DbException, SQLException { - Logger.getLogger(ApiConstants.loggerName) - .fine("post presentation received presentation " + presGrp.getName() - + " with ID=" + presGrp.getGroupId()); + try + { + PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + presGroupList.write(map(presGrp)); + return Response.status(HttpServletResponse.SC_OK) + .entity("Successfully stored presentation group") + .build(); + } + catch (DatabaseException e) + { + throw new DbException("Unable to store presentation group", e); + } + } - try (DbInterface dbi = new DbInterface(); - ApiPresentationDAO dao = new ApiPresentationDAO(dbi)) + static PresentationGroup map(ApiPresentationGroup presGrp) throws DatabaseException + { + PresentationGroup group = new PresentationGroup(); + group.lastModifyTime = presGrp.getLastModified(); + group.groupName = presGrp.getName(); + group.setId(DbKey.createDbKey(presGrp.getGroupId())); + group.isProduction = presGrp.isProduction(); + group.inheritsFrom = presGrp.getInheritsFrom(); + PresentationGroup apiGroup = new PresentationGroup(); + apiGroup.groupName = presGrp.getInheritsFrom(); + if (presGrp.getInheritsFromId() != null) { - dao.writePresentation(presGrp); - return ApiHttpUtil.createResponse(presGrp); + apiGroup.setId(DbKey.createDbKey(presGrp.getInheritsFromId())); } + group.parent = apiGroup; + group.dataPresentations = map(presGrp.getElements()); + + return group; + } + + static Vector map(ArrayList elements) { + Vector ret = new Vector<>(); + + for (ApiPresentationElement ape : elements) + { + DataPresentation dataPres = new DataPresentation(); + dataPres.setUnitsAbbr(ape.getUnits()); + dataPres.setDataType(new DataType(ape.getDataTypeStd(), ape.getDataTypeCode())); + dataPres.setMaxDecimals(ape.getFractionalDigits()); + dataPres.setMinValue(ape.getMin()); + dataPres.setMaxValue(ape.getMax()); + ret.add(dataPres); + } + return ret; } @DELETE @@ -105,21 +212,26 @@ public Response postPresentation(ApiPresentationGroup presGrp) throws WebAppExce @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) public Response deletePresentation(@QueryParam("groupid") Long groupId) throws DbException, SQLException { - Logger.getLogger(ApiConstants.loggerName) - .fine("DELETE presentation received groupid=" + groupId); - - // Use username and password to attempt to connect to the database - try (DbInterface dbi = new DbInterface(); - ApiPresentationDAO dao = new ApiPresentationDAO(dbi)) + try + { + PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + PresentationGroup group = new PresentationGroup(); + group.setId(DbKey.createDbKey(groupId)); + + // TODO: Add support for this check +// String s = dao.routSpecsUsing(groupId); +// if (s != null) +// return ApiHttpUtil.createResponse("Cannot delete presentation group " + groupId +// + " because it is used by the following routing specs: " +// + s, ErrorCodes.NOT_ALLOWED); + presGroupList.delete(group); + return Response.status(HttpServletResponse.SC_OK) + .entity("Presentation Group with ID " + groupId + " deleted") + .build(); + } + catch (DatabaseException e) { - String s = dao.routSpecsUsing(groupId); - if (s != null) - return ApiHttpUtil.createResponse("Cannot delete presentation group " + groupId - + " because it is used by the following routing specs: " - + s, ErrorCodes.NOT_ALLOWED); - - dao.deletePresentation(groupId); - return ApiHttpUtil.createResponse("Presentation Group with ID " + groupId + " deleted"); + throw new DbException("Unable to delete presentation group", e); } } } diff --git a/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/PresentationResourcesTest.java b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/PresentationResourcesTest.java new file mode 100644 index 000000000..0ccc9b27b --- /dev/null +++ b/opendcs-rest-api/src/test/java/org/opendcs/odcsapi/res/PresentationResourcesTest.java @@ -0,0 +1,133 @@ +package org.opendcs.odcsapi.res; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Date; +import java.util.Vector; + +import decodes.db.DataPresentation; +import decodes.db.DataType; +import decodes.db.PresentationGroup; +import decodes.db.PresentationGroupList; +import decodes.sql.DbKey; +import org.junit.jupiter.api.Test; +import org.opendcs.odcsapi.beans.ApiPresentationElement; +import org.opendcs.odcsapi.beans.ApiPresentationGroup; +import org.opendcs.odcsapi.beans.ApiPresentationRef; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +final class PresentationResourcesTest +{ + @Test + void testPresentationGroupListMap() throws Exception + { + PresentationGroupList pgl = new PresentationGroupList(); + PresentationGroup pg = new PresentationGroup(); + pg.setId(DbKey.createDbKey(1234L)); + pg.inheritsFrom = "Parent"; + pg.groupName = "Test"; + pg.lastModifyTime = Date.from(Instant.parse("2021-07-01T00:00:00Z")); + pg.isProduction = true; + DataPresentation dataPres = new DataPresentation(); + dataPres.setDataType(new DataType("Test", "TST")); + dataPres.setId(DbKey.createDbKey(1234567L)); + dataPres.setMaxDecimals(2); + dataPres.setMaxValue(100.0); + dataPres.setMinValue(0.0); + dataPres.setUnitsAbbr("TST"); + pg.addDataPresentation(dataPres); + pgl.add(pg); + + ArrayList presentationRefs = PresentationResources.map(pgl); + assertNotNull(presentationRefs); + assertEquals(1, presentationRefs.size()); + ApiPresentationRef apiPresentationRef = presentationRefs.get(0); + assertEquals(pg.inheritsFrom, apiPresentationRef.getInheritsFrom()); + assertEquals(pg.groupName, apiPresentationRef.getName()); + assertEquals(pg.isProduction, apiPresentationRef.isProduction()); + assertEquals(pg.getId().getValue(), apiPresentationRef.getGroupId()); + assertEquals(pg.lastModifyTime, apiPresentationRef.getLastModified()); + } + + @Test + void testPresentationGroupMap() throws Exception + { + PresentationGroup pg = new PresentationGroup(); + pg.groupName = "Test"; + pg.inheritsFrom = "Parent"; + pg.isProduction = true; + PresentationGroup parentGroup = new PresentationGroup(); + parentGroup.groupName = "Parent"; + parentGroup.setId(DbKey.createDbKey(99895L)); + pg.parent = parentGroup; + pg.lastModifyTime = Date.from(Instant.parse("2021-07-01T00:00:00Z")); + DataPresentation dataPres = new DataPresentation(); + dataPres.setDataType(new DataType("Test", "TST")); + dataPres.setId(DbKey.createDbKey(1234567L)); + dataPres.setMaxDecimals(2); + dataPres.setMaxValue(100.0); + dataPres.setMinValue(0.0); + dataPres.setUnitsAbbr("TST"); + pg.addDataPresentation(dataPres); + + ApiPresentationGroup apiPresentationGroup = PresentationResources.map(pg); + assertNotNull(apiPresentationGroup); + assertEquals(pg.inheritsFrom, apiPresentationGroup.getInheritsFrom()); + assertEquals(pg.groupName, apiPresentationGroup.getName()); + assertEquals(pg.isProduction, apiPresentationGroup.isProduction()); + assertEquals(pg.getId().getValue(), apiPresentationGroup.getGroupId()); + assertEquals(pg.lastModifyTime, apiPresentationGroup.getLastModified()); + assertEquals(pg.getId().getValue(), apiPresentationGroup.getGroupId()); + } + + @Test + void testApiPresentationGroupMap() throws Exception + { + ApiPresentationGroup apiPresentationGroup = new ApiPresentationGroup(); + apiPresentationGroup.setGroupId(1234L); + apiPresentationGroup.setInheritsFrom("Parent"); + apiPresentationGroup.setName("Test"); + apiPresentationGroup.setProduction(true); + apiPresentationGroup.setLastModified(Date.from(Instant.parse("2021-07-01T00:00:00Z"))); + ArrayList elements = new ArrayList<>(); + ApiPresentationElement ape = new ApiPresentationElement(); + ape.setDataTypeCode("TST"); + ape.setMax(100.0); + ape.setMin(0.0); + ape.setUnits("TST"); + ape.setDataTypeStd("Test"); + ape.setFractionalDigits(2); + elements.add(ape); + apiPresentationGroup.setElements(elements); + + PresentationGroup pg = PresentationResources.map(apiPresentationGroup); + + assertNotNull(pg); + assertEquals(apiPresentationGroup.getInheritsFrom(), pg.inheritsFrom); + assertEquals(apiPresentationGroup.getName(), pg.groupName); + assertEquals(apiPresentationGroup.isProduction(), pg.isProduction); + assertEquals(apiPresentationGroup.getGroupId(), pg.getId().getValue()); + assertEquals(apiPresentationGroup.getLastModified(), pg.lastModifyTime); + assertMatch(apiPresentationGroup.getElements(), pg.dataPresentations); + } + + private void assertMatch(ArrayList elements, Vector dataPresentations) + { + assertEquals(elements.size(), dataPresentations.size()); + int index = 0; + for (DataPresentation presentation : dataPresentations) + { + ApiPresentationElement element = elements.get(index); + assertEquals(element.getDataTypeCode(), presentation.getDataType().getCode()); + assertEquals(element.getUnits(), presentation.getUnitsAbbr()); + assertEquals(element.getFractionalDigits(), presentation.getMaxDecimals()); + assertEquals(element.getMax(), presentation.getMaxValue()); + assertEquals(element.getMin(), presentation.getMinValue()); + index++; + } + } + + +} From a8d969a594734c89a7d65d1d9567d9a20c700cbc Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 10 Dec 2024 13:47:55 -0800 Subject: [PATCH 8/8] Updated PresentationResources to utilize Legacy DB DAI retrieval --- .../odcsapi/res/PresentationResources.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java index 202d73f84..1a62a5a2a 100644 --- a/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java +++ b/opendcs-rest-api/src/main/java/org/opendcs/odcsapi/res/PresentationResources.java @@ -15,7 +15,6 @@ package org.opendcs.odcsapi.res; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Vector; @@ -36,10 +35,10 @@ import decodes.db.DataPresentation; import decodes.db.DataType; import decodes.db.DatabaseException; +import decodes.db.DatabaseIO; import decodes.db.PresentationGroup; import decodes.db.PresentationGroupList; import decodes.sql.DbKey; -import decodes.sql.PresentationGroupListIO; import org.opendcs.odcsapi.beans.ApiPresentationElement; import org.opendcs.odcsapi.beans.ApiPresentationGroup; import org.opendcs.odcsapi.beans.ApiPresentationRef; @@ -49,7 +48,7 @@ import org.opendcs.odcsapi.sec.AuthorizationCheck; @Path("/") -public class PresentationResources +public class PresentationResources extends OpenDcsResource { @Context HttpHeaders httpHeaders; @@ -61,12 +60,12 @@ public Response getPresentationRefs() throws DbException { try { - PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + DatabaseIO dbio = getLegacyDatabase(); PresentationGroupList groupList = new PresentationGroupList(); - presGroupList.read(groupList); + dbio.readPresentationGroupList(groupList); return Response.status(HttpServletResponse.SC_OK).entity(map(groupList)).build(); } - catch (SQLException | DatabaseException e) + catch (DatabaseException e) { throw new DbException("Unable to retrieve presentation groups", e); } @@ -103,10 +102,10 @@ public Response getPresentation(@QueryParam("groupid") Long groupId) try { - PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + DatabaseIO dbio = getLegacyDatabase(); PresentationGroup group = new PresentationGroup(); group.setId(DbKey.createDbKey(groupId)); - presGroupList.readPresentationGroup(group, false); + dbio.readPresentationGroup(group); return Response.status(HttpServletResponse.SC_OK).entity(map(group)).build(); } catch (DatabaseException e) @@ -153,12 +152,12 @@ static ArrayList map(Vector dataPresen @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) - public Response postPresentation(ApiPresentationGroup presGrp) throws DbException, SQLException + public Response postPresentation(ApiPresentationGroup presGrp) throws DbException { try { - PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); - presGroupList.write(map(presGrp)); + DatabaseIO dbio = getLegacyDatabase(); + dbio.writePresentationGroup(map(presGrp)); return Response.status(HttpServletResponse.SC_OK) .entity("Successfully stored presentation group") .build(); @@ -210,11 +209,11 @@ static Vector map(ArrayList elements) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @RolesAllowed({AuthorizationCheck.ODCS_API_ADMIN, AuthorizationCheck.ODCS_API_USER}) - public Response deletePresentation(@QueryParam("groupid") Long groupId) throws DbException, SQLException + public Response deletePresentation(@QueryParam("groupid") Long groupId) throws DbException { try { - PresentationGroupListIO presGroupList = new PresentationGroupListIO(null); + DatabaseIO dbio = getLegacyDatabase(); PresentationGroup group = new PresentationGroup(); group.setId(DbKey.createDbKey(groupId)); @@ -224,7 +223,7 @@ public Response deletePresentation(@QueryParam("groupid") Long groupId) throws D // return ApiHttpUtil.createResponse("Cannot delete presentation group " + groupId // + " because it is used by the following routing specs: " // + s, ErrorCodes.NOT_ALLOWED); - presGroupList.delete(group); + dbio.deletePresentationGroup(group); return Response.status(HttpServletResponse.SC_OK) .entity("Presentation Group with ID " + groupId + " deleted") .build();