From 0c43892018fdbd116f9a5335628d247d35c9510d Mon Sep 17 00:00:00 2001 From: Maikel Arabori <51713408+maikelarabori@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:04:50 +0100 Subject: [PATCH] feat: Add defaults to optionSetItem [DHIS2-18643] (#19536) * feat: Add defaults to optionSetItem [DHIS2-18643] * test: For absent aggregation [DHIS2-18643] --- .../hisp/dhis/common/DataDimensionItem.java | 35 ++++-- .../org/hisp/dhis/common/OptionSetItem.java | 14 +++ .../VisualizationControllerTest.java | 100 ++++++++++++++++++ 3 files changed, 142 insertions(+), 7 deletions(-) diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DataDimensionItem.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DataDimensionItem.java index 87a1317a19f..e0d189e0ad5 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DataDimensionItem.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DataDimensionItem.java @@ -27,6 +27,8 @@ */ package org.hisp.dhis.common; +import static org.hisp.dhis.analytics.Aggregation.AGGREGATED; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -40,6 +42,7 @@ import java.util.stream.Collectors; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import org.hisp.dhis.analytics.Aggregation; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementOperand; import org.hisp.dhis.expressiondimensionitem.ExpressionDimensionItem; @@ -113,16 +116,31 @@ public class DataDimensionItem { @AllArgsConstructor public static class Attributes implements Serializable { /** The option item for this dimension item. * */ - private OptionSetItem optionItem; + private OptionSetItem optionSetItem; @JsonProperty @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) public OptionSetItem getOptionSetItem() { - return optionItem; + return optionSetItem; + } + + /** + * This method ensure that existing persisted items will return default values, case the current + * {@link OptionSetItem} is null or does not have an {@link Aggregation} defined. + * + * @return the correct version of an {@link OptionSetItem}. + */ + public OptionSetItem getOptionSetItemOrDefault() { + if (optionSetItem != null) { + return new OptionSetItem( + optionSetItem.getOptions(), optionSetItem.getAggregationOrDefault()); + } + + return new OptionSetItem(Set.of(), AGGREGATED); } - public void setOptionSetItem(OptionSetItem optionItem) { - this.optionItem = optionItem; + public void setOptionSetItem(OptionSetItem optionSetItem) { + this.optionSetItem = optionSetItem; } } @@ -232,14 +250,17 @@ public DimensionalItemObject getDimensionalItemObject() { } /** - * Simply loads the internal attributes into the given item object. + * Simply loads the internal attributes into the given item object. Some objects, when null, will + * be loaded with their respective defaults. * * @param itemObject the {@link BaseDimensionalItemObject}. */ private void loadAttributes(BaseDimensionalItemObject itemObject) { - if (attributes != null) { - itemObject.setOptionSetItem(attributes.getOptionSetItem()); + if (attributes == null) { + attributes = new Attributes(); } + + itemObject.setOptionSetItem(attributes.getOptionSetItemOrDefault()); } @JsonProperty diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/OptionSetItem.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/OptionSetItem.java index 2a15915de4c..166085a45c8 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/OptionSetItem.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/OptionSetItem.java @@ -27,6 +27,7 @@ */ package org.hisp.dhis.common; +import static org.hisp.dhis.analytics.Aggregation.AGGREGATED; import static org.hisp.dhis.common.DxfNamespaces.DXF_2_0; import com.fasterxml.jackson.annotation.JsonProperty; @@ -71,4 +72,17 @@ public Aggregation getAggregation() { public void setAggregation(Aggregation aggregation) { this.aggregation = aggregation; } + + /** + * Returns the current {@link Aggregation} or default. + * + * @return the respective {@link Aggregation} object. + */ + public Aggregation getAggregationOrDefault() { + if (aggregation == null) { + return AGGREGATED; + } + + return aggregation; + } } diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/VisualizationControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/VisualizationControllerTest.java index 0c17eeb5c6f..5a4e7c5c2fa 100644 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/VisualizationControllerTest.java +++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/VisualizationControllerTest.java @@ -436,4 +436,104 @@ void testPostOptionSetItemInDataElement() { assertEquals( "[\"BFhv3jQZ8Cw\"]", itemsNode.get("optionSetItem").get("options").value().toString()); } + + @Test + void testPostWithoutOptionSetItemAndLoadDefaults() { + // Given + DataElement dataElement = createDataElement('A'); + manager.save(dataElement); + + String dataElementUid = dataElement.getUid(); + String jsonBody = + """ +{ + "type": "PIE", + "columns": [ + { + "dimension": "dx", + "items": [ + { + "id": "${dataElement}", + "name": "Data Element - OptionSet", + "dimensionItemType": "DATA_ELEMENT" + } + ] + } + ], + "name": "OptionSetItem - Test" +} +""" + .replace("${dataElement}", dataElementUid); + + // When + String uid = assertStatus(CREATED, POST("/visualizations/", jsonBody)); + + // Then + String getParams = "?fields=columns[:all,items[:all,optionSetItem[options,aggregation]]"; + JsonObject response = GET("/visualizations/" + uid + getParams).content(); + + JsonNode columnNode = response.get("columns").node().element(0); + JsonNode itemsNode = columnNode.get("items").elementOrNull(0); + + assertEquals("DATA_X", columnNode.get("dimensionType").value()); + assertTrue((boolean) columnNode.get("dataDimension").value()); + assertEquals("DATA_ELEMENT", itemsNode.get("dimensionItemType").value()); + assertEquals("SUM", itemsNode.get("aggregationType").value()); + assertEquals(dataElementUid, itemsNode.get("dimensionItem").value()); + assertEquals("AGGREGATED", itemsNode.get("optionSetItem").get("aggregation").value()); + assertEquals("[]", itemsNode.get("optionSetItem").get("options").value().toString()); + } + + @Test + void testPostOptionSetItemWithNoAggregation() { + // Given + DataElement dataElement = createDataElement('A'); + manager.save(dataElement); + + String dataElementUid = dataElement.getUid(); + String jsonBody = + """ +{ + "type": "PIE", + "columns": [ + { + "dimension": "dx", + "items": [ + { + "id": "${dataElement}", + "name": "Data Element - OptionSet", + "dimensionItemType": "DATA_ELEMENT", + "optionSetItem": { + "options": [ + "BFhv3jQZ8Cw" + ] + } + } + ] + } + ], + "name": "OptionSetItem - Test" +} +""" + .replace("${dataElement}", dataElementUid); + + // When + String uid = assertStatus(CREATED, POST("/visualizations/", jsonBody)); + + // Then + String getParams = "?fields=columns[:all,items[:all,optionSetItem[options,aggregation]]"; + JsonObject response = GET("/visualizations/" + uid + getParams).content(); + + JsonNode columnNode = response.get("columns").node().element(0); + JsonNode itemsNode = columnNode.get("items").elementOrNull(0); + + assertEquals("DATA_X", columnNode.get("dimensionType").value()); + assertTrue((boolean) columnNode.get("dataDimension").value()); + assertEquals("DATA_ELEMENT", itemsNode.get("dimensionItemType").value()); + assertEquals("SUM", itemsNode.get("aggregationType").value()); + assertEquals(dataElementUid, itemsNode.get("dimensionItem").value()); + assertEquals("AGGREGATED", itemsNode.get("optionSetItem").get("aggregation").value()); + assertEquals( + "[\"BFhv3jQZ8Cw\"]", itemsNode.get("optionSetItem").get("options").value().toString()); + } }