Skip to content

Add support for virtual location levels #1086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from

Conversation

zack-rma
Copy link
Collaborator

@zack-rma zack-rma commented Apr 28, 2025

Fixes #469

Adds support for virtual location levels to the levels endpoint. Integration testing included.

@MikeNeilson
Copy link
Contributor

@zack-rma merge develop in for the nicer test report.

@zack-rma zack-rma force-pushed the feature/virtual_loc_levels branch from c4b372b to 09fb5be Compare April 30, 2025 20:34
@zack-rma zack-rma marked this pull request as ready for review May 1, 2025 15:43
Copy link
Contributor

@MikeNeilson MikeNeilson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks reasonable. Only issue is with the level of duplication within the test code.

assertThat(response.path("constituents[1].name"), equalTo(existingSpec));
assertThat(response.path("constituents[1].type"), equalTo("RATING"));

CwmsDataApiSetupCallback.getDatabaseLink().connection(c -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These won't get called on failure which can hinder repeatability of tests.

If the location is registered with create location the cascade delete should take care of the ratings so these shouldn't be required.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed ratings cleanup methods

String specXml = RatingSpecXmlFactory.toXml(specContainer, "", 0, true);
String setXml = RatingContainerXmlFactory.toXml(container, "", 0, true, false);

CwmsDataApiSetupCallback.getDatabaseLink().connection(c -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This large block is repeated in a near identical way. Some sort of helper function (similar to createLocation) should be created.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added helper methods to reduce code duplication

@zack-rma zack-rma requested a review from MikeNeilson May 1, 2025 22:02
MikeNeilson
MikeNeilson previously approved these changes May 2, 2025
@@ -808,4 +1266,63 @@ enum GetAllTestNewAliases
_expectedContentType = expectedContentType;
}
}

private String createRatingSpec(String locationName) throws Exception
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preferably these would've gone in the DataApiTest class, but this at least makes it easier for the next person to yank up and make more generic.

@zack-rma zack-rma requested a review from adamkorynta May 6, 2025 22:48
@adamkorynta adamkorynta linked an issue May 7, 2025 that may be closed by this pull request
Copy link
Collaborator Author

@zack-rma zack-rma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some issues resolved, more fixes to come

@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class)
@FormattableWith(contentType = Formats.XMLV2, formatter = XMLv2.class, aliases = {Formats.XML})
@JsonIgnoreProperties(ignoreUnknown = true)
public class LocationLevel extends CwmsDTO
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamkorynta considering this new class hierarchy can we ever meaningfully have a plain "LocationLevel"? if not seems like this should be marked abstract.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made abstract

@@ -15,7 +42,8 @@

@JsonRootName("location-levels")
@FormattableWith(contentType = Formats.JSONV2, formatter = JsonV2.class, aliases = {Formats.DEFAULT, Formats.JSON})
public class LocationLevels extends CwmsDTOPaginated {
public class LocationLevels extends CwmsDTOPaginated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do keep the curly on the same line in this project.

}
} catch (NullPointerException e) {
//gets thrown if required field is null
throw new IllegalArgumentException(e.getMessage());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should include the exception so that the stacktrace can hit the log and people can trace issues, should they happen.

also what is throwing null that we can't check for directly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated throw to include the exception.

Looking into the NPE catch now.


ContentType contentType = Formats.parseHeader(Formats.JSONV2, LocationLevel.class);
String jsonStr = Formats.format(contentType, level);

// If JSONv2 isn't setup correctly it will serialize the level like:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even though these comments are duplicate, they should be retained, and probably even added to the one above.

anyone of these tests should be reasonable in isolation so it is reasonable to see duplication we would otherwise avoid in normal code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments to other similar methods.

Copy link
Contributor

@MikeNeilson MikeNeilson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nitpicks, and an change to the builder pattern.

int newPageSize = pageSize - builderMap.size();
int newOffset = offset - builderMap.size(); // TODO: check if this is correct, this may cause issues with paging
int virtualPageSize = pageSize - builderMap.size();
int virtualOffset = offset - builderMap.size(); // TODO: check if this is correct, this may cause issues with paging
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this todo seems fairly important.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated query to combine tables for consistent paging results. In order to get the VirtualLocationLevel constituents list a subquery would be needed, along with some more logic that is currently in a PL/SQL method for a single retrieval. Retrieving a single VirtualLocationLevel would include the constituent data, currently.

@@ -574,49 +569,44 @@ private VirtualLocationLevel buildVirtualLocationLevel(LOCATION_LEVEL_T level, S

private ConstantLocationLevel buildConstantLocationLevel(LOCATION_LEVEL_T level, String officeId, String units,
String locationLevelName, ZonedDateTime realEffectiveDate, Double constantValue) {
return new ConstantLocationLevel.Builder(locationLevelName, realEffectiveDate)
return ((ConstantLocationLevel.Builder) new ConstantLocationLevel.Builder(locationLevelName, realEffectiveDate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast seems odd.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unnecessary casts.

} else {
throw new RequiredFieldException("Either interval-minutes or interval-months must be set, but not both");
}
validator.mutuallyExclusive("Only one of the following can be defined at once for a seasonal location level: "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this duplicates the login of the above if/else if/else section.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed duplicate logic above

@@ -155,10 +155,10 @@ void test_retrieve_effective_date() throws Exception {
String levelId = "level_with_effect.Flow.Ave.1Day.Regulating";
ZonedDateTime time = ZonedDateTime.of(2023, 6, 1, 0, 0, 0, 0, ZoneId.of("America/Los_Angeles"));
CwmsDataApiSetupCallback.getDatabaseLink().connection(c -> {
LocationLevel level = new ConstantLocationLevel.Builder(levelId, time)
LocationLevel level = ((ConstantLocationLevel.Builder) new ConstantLocationLevel.Builder(levelId, time)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, the amount of casting you're doing really shouldn't be required.

Was it the compiler or the IDE complaining about this? Because somehow this behaves right for the things we do in testcontainers-cwms.. I'll go back and look at the root location level builder.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unnecessary casts

@zack-rma
Copy link
Collaborator Author

@MikeNeilson It seems this PR and #1109 are failing from the StreamDAOTestIT failing in the same way. It seems to be inconsistent, as it hasn't been failing on all PRs...

MikeNeilson
MikeNeilson previously approved these changes May 27, 2025
Copy link
Contributor

@MikeNeilson MikeNeilson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concerns have been address.

}
}

public static <T extends LocationLevel> T castLocationLevel(LocationLevel level, ZonedDateTime unmarshalledDateTime) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not doing what you think it is doing...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed method and refactored logic

attributeUnitsId = null;
}

if (existingLevel instanceof VirtualLocationLevel) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the common builder attributes should get extracted

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted common builder attributes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for virtual location levels
3 participants