diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/Location.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/Location.java index d73e76856..3450297bd 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/Location.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/Location.java @@ -18,7 +18,6 @@ import cwms.cda.formatters.json.JsonV2; import cwms.cda.formatters.xml.XMLv1; import cwms.cda.formatters.xml.XMLv2; - import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; @@ -251,7 +250,7 @@ public static class Builder { private Double latitude; private Double longitude; private String officeId; - private boolean active = true; + private Boolean active = true; private String publicName; private String longName; private String description; @@ -292,6 +291,12 @@ public Builder(@JsonProperty(value = "name") String name, @JsonProperty(value = buildPropertyFunctions(); } + public Builder(String office, String name) { + this.officeId = office; + this.name = name; + buildPropertyFunctions(); + } + public Builder(Location location) { this.name = location.getName(); this.latitude = location.getLatitude(); @@ -416,7 +421,7 @@ public Builder withLongName(String longName) { return this; } - public Builder withActive(boolean active) { + public Builder withActive(Boolean active) { this.active = active; return this; } diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/Project.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/Project.java new file mode 100644 index 000000000..87be4c425 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/Project.java @@ -0,0 +1,293 @@ +package cwms.cda.data.dto; + + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import cwms.cda.api.errors.FieldException; +import cwms.cda.formatters.Formats; +import cwms.cda.formatters.annotations.FormattableWith; +import cwms.cda.formatters.json.JsonV2; +import java.time.Instant; + +@JsonDeserialize(builder = Project.Builder.class) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) +@FormattableWith(contentType = Formats.JSON, formatter = JsonV2.class) +public class Project extends CwmsDTO { + + private final String name; + private final Double federalCost; + private final Double nonFederalCost; + private final Instant costYear; + private final String costUnit; + private final Double federalOAndMCost; + private final Double nonFederalOAndMCost; + private final String authorizingLaw; + private final String projectOwner; + private final String hydropowerDesc; + private final String sedimentationDesc; + private final String downstreamUrbanDesc; + private final String bankFullCapacityDesc; + private final Location pumpBackLocation; + private final Location nearGageLocation; + private final Instant yieldTimeFrameStart; + private final Instant yieldTimeFrameEnd; + private final String projectRemarks; + + + private Project(Project.Builder builder) { + super(builder.officeId); + this.name = builder.name; + this.federalCost = builder.federalCost; + this.nonFederalCost = builder.nonFederalCost; + this.costYear = builder.costYear; + this.costUnit = builder.costUnit; + this.federalOAndMCost = builder.federalOAndMCost; + this.nonFederalOAndMCost = builder.nonFederalOandMCost; + this.authorizingLaw = builder.authorizingLaw; + this.projectOwner = builder.projectOwner; + this.hydropowerDesc = builder.hydropowerDesc; + this.sedimentationDesc = builder.sedimentationDesc; + this.downstreamUrbanDesc = builder.downstreamUrbanDesc; + this.bankFullCapacityDesc = builder.bankFullCapacityDesc; + this.pumpBackLocation = builder.pumpBackLocation; + this.nearGageLocation = builder.nearGageLocation; + this.yieldTimeFrameStart = builder.yieldTimeFrameStart; + this.yieldTimeFrameEnd = builder.yieldTimeFrameEnd; + this.projectRemarks = builder.projectRemarks; + } + + @Override + public void validate() throws FieldException { + + } + + public String getAuthorizingLaw() { + return authorizingLaw; + } + + public String getBankFullCapacityDesc() { + return bankFullCapacityDesc; + } + + public String getDownstreamUrbanDesc() { + return downstreamUrbanDesc; + } + + public Double getFederalCost() { + return federalCost; + } + + public String getHydropowerDesc() { + return hydropowerDesc; + } + + public Location getNearGageLocation() { + return nearGageLocation; + } + + public Double getNonFederalCost() { + return nonFederalCost; + } + + public Double getFederalOAndMCost() { + return federalOAndMCost; + } + + public Double getNonFederalOAndMCost() { + return nonFederalOAndMCost; + } + + public Instant getCostYear() { + return costYear; + } + + public String getCostUnit() { + return costUnit; + } + + public String getName() { + return name; + } + + public String getProjectOwner() { + return projectOwner; + } + + public String getProjectRemarks() { + return projectRemarks; + } + + public Location getPumpBackLocation() { + return pumpBackLocation; + } + + public String getSedimentationDesc() { + return sedimentationDesc; + } + + public Instant getYieldTimeFrameEnd() { + return yieldTimeFrameEnd; + } + + public Instant getYieldTimeFrameStart() { + return yieldTimeFrameStart; + } + + @JsonPOJOBuilder + @JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class) + public static class Builder { + private String officeId; + private String name; + private Double federalCost; + private Double nonFederalCost; + private Instant costYear; + private String costUnit; + private Double federalOAndMCost; + private Double nonFederalOandMCost; + private String authorizingLaw; + private String projectOwner; + private String hydropowerDesc; + private String sedimentationDesc; + private String downstreamUrbanDesc; + private String bankFullCapacityDesc; + private Location pumpBackLocation; + private Location nearGageLocation; + private Instant yieldTimeFrameStart; + private Instant yieldTimeFrameEnd; + private String projectRemarks; + + + public Project build() { + return new Project(this); + } + + /** + * Copy the values from the given project into this builder. + * + * @param project the project to copy values from + * @return this builder + */ + public Builder from(Project project) { + return this.withOfficeId(project.getOfficeId()) + .withName(project.getName()) + .withFederalCost(project.getFederalCost()) + .withNonFederalCost(project.getNonFederalCost()) + .withCostYear(project.getCostYear()) + .withCostUnit(project.getCostUnit()) + .withFederalOAndMCost(project.getFederalOAndMCost()) + .withNonFederalOAndMCost(project.getNonFederalOAndMCost()) + .withAuthorizingLaw(project.getAuthorizingLaw()) + .withProjectOwner(project.getProjectOwner()) + .withHydropowerDesc(project.getHydropowerDesc()) + .withSedimentationDesc(project.getSedimentationDesc()) + .withDownstreamUrbanDesc(project.getDownstreamUrbanDesc()) + .withBankFullCapacityDesc(project.getBankFullCapacityDesc()) + .withPumpBackLocation(project.getPumpBackLocation()) + .withNearGageLocation(project.getNearGageLocation()) + .withYieldTimeFrameStart(project.getYieldTimeFrameStart()) + .withYieldTimeFrameEnd(project.getYieldTimeFrameEnd()) + .withProjectRemarks(project.getProjectRemarks()); + } + + public Builder withOfficeId(String officeId) { + this.officeId = officeId; + return this; + } + + public Builder withName(String projectId) { + this.name = projectId; + return this; + } + + public Builder withFederalCost(Double federalCost) { + this.federalCost = federalCost; + return this; + } + + public Builder withNonFederalCost(Double nonFederalCost) { + this.nonFederalCost = nonFederalCost; + return this; + } + + public Builder withCostYear(Instant costYear) { + this.costYear = costYear; + return this; + } + + public Builder withCostUnit(String costUnit) { + this.costUnit = costUnit; + return this; + } + + public Builder withFederalOAndMCost(Double federalOandMCost) { + this.federalOAndMCost = federalOandMCost; + return this; + } + + public Builder withNonFederalOAndMCost(Double nonFederalOandMCost) { + this.nonFederalOandMCost = nonFederalOandMCost; + return this; + } + + public Builder withAuthorizingLaw(String authorizingLaw) { + this.authorizingLaw = authorizingLaw; + return this; + } + + public Builder withProjectOwner(String projectOwner) { + this.projectOwner = projectOwner; + return this; + } + + public Builder withHydropowerDesc(String hydropowerDesc) { + this.hydropowerDesc = hydropowerDesc; + return this; + } + + public Builder withSedimentationDesc(String sedimentationDesc) { + this.sedimentationDesc = sedimentationDesc; + return this; + } + + public Builder withDownstreamUrbanDesc(String downstreamUrbanDesc) { + this.downstreamUrbanDesc = downstreamUrbanDesc; + return this; + } + + public Builder withBankFullCapacityDesc(String bankFullCapacityDesc) { + this.bankFullCapacityDesc = bankFullCapacityDesc; + return this; + } + + public Builder withPumpBackLocation(Location pbLoc) { + this.pumpBackLocation = pbLoc; + return this; + } + + public Builder withNearGageLocation(Location ngLoc) { + this.nearGageLocation = ngLoc; + return this; + } + + public Builder withYieldTimeFrameStart(Instant yieldTimeFrameStart) { + this.yieldTimeFrameStart = yieldTimeFrameStart; + return this; + } + + public Builder withYieldTimeFrameEnd(Instant yieldTimeFrameEnd) { + this.yieldTimeFrameEnd = yieldTimeFrameEnd; + return this; + } + + public Builder withProjectRemarks(String projectRemarks) { + this.projectRemarks = projectRemarks; + return this; + } + + } + +} diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dto/ProjectTest.java b/cwms-data-api/src/test/java/cwms/cda/data/dto/ProjectTest.java new file mode 100644 index 000000000..051d681cf --- /dev/null +++ b/cwms-data-api/src/test/java/cwms/cda/data/dto/ProjectTest.java @@ -0,0 +1,97 @@ +package cwms.cda.data.dto; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import cwms.cda.formatters.json.JsonV2; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +class ProjectTest { + + + @Test + void testProject() throws JsonProcessingException { + + Location pbLoc = new Location.Builder("SPK","Pumpback Location Id") + .withActive(null) + .build(); + Location ngLoc = new Location.Builder("SPK","Near Gage Location Id") + .withActive(null) + .build(); + + Project project = new Project.Builder() + .withOfficeId("SPK") + .withName("Project Id") + .withProjectOwner("Project Owner") + .withAuthorizingLaw("Authorizing Law") + .withFederalCost(100.0) + .withNonFederalCost(50.0) + .withFederalOAndMCost(10.0) + .withNonFederalOAndMCost(5.0) + .withCostYear(Instant.now()) + .withCostUnit("$") + .withYieldTimeFrameEnd(Instant.now()) + .withYieldTimeFrameStart(Instant.now()) + .withFederalOAndMCost(10.0) + .withNonFederalOAndMCost(5.0) + .withProjectRemarks("Remarks") + .withPumpBackLocation(pbLoc) + .withNearGageLocation(ngLoc) + .withBankFullCapacityDesc("Bank Full Capacity Description") + .withDownstreamUrbanDesc("Downstream Urban Description") + .withHydropowerDesc("Hydropower Description") + .withSedimentationDesc("Sedimentation Description") + .build(); + + ObjectMapper om = JsonV2.buildObjectMapper(); + ObjectWriter ow = om.writerWithDefaultPrettyPrinter(); + + String json = ow.writeValueAsString(project); + + assertNotNull(json); + } + + @Test + void testDeserialize() throws IOException { + InputStream stream = ProjectTest.class.getClassLoader().getResourceAsStream( + "cwms/cda/data/dto/project.json"); + assertNotNull(stream); + String input = IOUtils.toString(stream, StandardCharsets.UTF_8); + + ObjectMapper om = JsonV2.buildObjectMapper(); + Project project = om.readValue(input, Project.class); + + assertNotNull(project); + + assertEquals("SPK", project.getOfficeId()); + assertEquals("Project Id", project.getName()); + assertEquals("Project Owner", project.getProjectOwner()); + assertEquals("Authorizing Law", project.getAuthorizingLaw()); + assertEquals(100.0, project.getFederalCost()); + assertEquals(50.0, project.getNonFederalCost()); + assertEquals(10.0, project.getFederalOAndMCost()); + assertEquals(5.0, project.getNonFederalOAndMCost()); + assertEquals(1717199914902L, project.getCostYear().toEpochMilli()); + assertEquals("$", project.getCostUnit()); + assertEquals(1717199914902L, project.getYieldTimeFrameStart().toEpochMilli()); + assertEquals(1717199914902L, project.getYieldTimeFrameEnd().toEpochMilli()); + assertEquals("Remarks", project.getProjectRemarks()); + assertEquals("Pumpback Location Id", project.getPumpBackLocation().getName()); + assertEquals("SPK", project.getPumpBackLocation().getOfficeId()); + assertEquals("Near Gage Location Id", project.getNearGageLocation().getName()); + assertEquals("SPK", project.getNearGageLocation().getOfficeId()); + assertEquals("Bank Full Capacity Description", project.getBankFullCapacityDesc()); + assertEquals("Downstream Urban Description", project.getDownstreamUrbanDesc()); + assertEquals("Hydropower Description", project.getHydropowerDesc()); + assertEquals("Sedimentation Description", project.getSedimentationDesc()); + + } +} diff --git a/cwms-data-api/src/test/resources/cwms/cda/data/dto/project.json b/cwms-data-api/src/test/resources/cwms/cda/data/dto/project.json new file mode 100644 index 000000000..59670e1f0 --- /dev/null +++ b/cwms-data-api/src/test/resources/cwms/cda/data/dto/project.json @@ -0,0 +1,27 @@ +{ + "office-id": "SPK", + "name" : "Project Id", + "federal-cost" : 100.0, + "non-federal-cost" : 50.0, + "cost-year" : 1717199914902, + "cost-unit" : "$", + "federal-o-and-m-cost" : 10.0, + "non-federal-o-and-m-cost" : 5.0, + "authorizing-law" : "Authorizing Law", + "project-owner" : "Project Owner", + "hydropower-desc" : "Hydropower Description", + "sedimentation-desc" : "Sedimentation Description", + "downstream-urban-desc" : "Downstream Urban Description", + "bank-full-capacity-desc" : "Bank Full Capacity Description", + "pump-back-location" : { + "office-id" : "SPK", + "name" : "Pumpback Location Id" + }, + "near-gage-location" : { + "office-id" : "SPK", + "name" : "Near Gage Location Id" + }, + "yield-time-frame-start" : 1717199914902, + "yield-time-frame-end" : 1717199914902, + "project-remarks" : "Remarks" +} \ No newline at end of file