diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 2e5235e6..6c3640df 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -224,7 +224,9 @@ public class BaseDhis2 { String.format( """ %1$s,programType,trackedEntityType[%2$s],categoryCombo[%1$s,categories[%3$s]],\ - programStages[%1$s,programStageDataElements[%4$s]],\ + programStages[%1$s,\ + programStageDataElements[%4$s],\ + programStageSections[%1$s,formName,sortOrder,programStage[%1$s],dataElements[%1$s],programIndicators[%1$s]]],\ programTrackedEntityAttributes[id,code,name,trackedEntityAttribute[%5$s]]""", NAME_FIELDS, TRACKED_ENTITY_TYPE_FIELDS, diff --git a/src/main/java/org/hisp/dhis/model/Program.java b/src/main/java/org/hisp/dhis/model/Program.java index 99508fad..541c2efd 100644 --- a/src/main/java/org/hisp/dhis/model/Program.java +++ b/src/main/java/org/hisp/dhis/model/Program.java @@ -28,19 +28,18 @@ package org.hisp.dhis.model; import static org.hisp.dhis.util.CollectionUtils.notEmpty; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; import org.hisp.dhis.model.trackedentity.ProgramTrackedEntityAttribute; import org.hisp.dhis.model.trackedentity.TrackedEntityAttribute; import org.hisp.dhis.model.trackedentity.TrackedEntityType; import org.hisp.dhis.model.trackedentity.TrackedEntityTypeAttribute; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @Getter @Setter @@ -79,7 +78,7 @@ public List getTrackedEntityTypeAttributes() { return trackedEntityType.getTrackedEntityTypeAttributes().stream() .map(TrackedEntityTypeAttribute::getTrackedEntityAttribute) - .collect(Collectors.toUnmodifiableList()); + .toList(); } /** @@ -108,7 +107,7 @@ public List getNonConfidentialTrackedEntityTypeAttribute public List getTrackedEntityAttributes() { return programTrackedEntityAttributes.stream() .map(ProgramTrackedEntityAttribute::getTrackedEntityAttribute) - .collect(Collectors.toUnmodifiableList()); + .toList(); } /** @@ -121,7 +120,7 @@ public List getNonConfidentialTrackedEntityAttributes() return programTrackedEntityAttributes.stream() .map(ProgramTrackedEntityAttribute::getTrackedEntityAttribute) .filter(tea -> !tea.isConfidentialNullSafe()) - .collect(Collectors.toUnmodifiableList()); + .toList(); } /** @@ -131,10 +130,7 @@ public List getNonConfidentialTrackedEntityAttributes() */ @JsonIgnore public List getDataElements() { - return programStages.stream() - .flatMap(ps -> ps.getDataElements().stream()) - .distinct() - .collect(Collectors.toUnmodifiableList()); + return programStages.stream().flatMap(ps -> ps.getDataElements().stream()).distinct().toList(); } /** @@ -147,7 +143,7 @@ public List getAnalyticsDataElements() { return programStages.stream() .flatMap(ps -> ps.getAnalyticsDataElements().stream()) .distinct() - .collect(Collectors.toUnmodifiableList()); + .toList(); } /** @@ -162,7 +158,17 @@ public List getAnalyticsDataElementsWithLegendSet() { .flatMap(ps -> ps.getAnalyticsDataElements().stream()) .filter(de -> notEmpty(de.getLegendSets()) && de.getValueType().isNumeric()) .distinct() - .collect(Collectors.toUnmodifiableList()); + .toList(); + } + + /** + * Returns program stage sections which are part of the stages of this program. + * + * @return an immutable set of {@link ProgramStageSection}. + */ + @JsonIgnore + public List getProgramStageSections() { + return programStages.stream().flatMap(ps -> ps.getProgramStageSections().stream()).toList(); } /** diff --git a/src/main/java/org/hisp/dhis/model/ProgramStage.java b/src/main/java/org/hisp/dhis/model/ProgramStage.java index a25a3005..67713121 100644 --- a/src/main/java/org/hisp/dhis/model/ProgramStage.java +++ b/src/main/java/org/hisp/dhis/model/ProgramStage.java @@ -44,6 +44,8 @@ public class ProgramStage extends NameableObject { @JsonProperty private List programStageDataElements = new ArrayList<>(); + @JsonProperty private List programStageSections = new ArrayList<>(); + public ProgramStage(String id, String name) { this.id = id; this.name = name; diff --git a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java new file mode 100644 index 00000000..99882ef0 --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.model; + +import java.util.ArrayList; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class ProgramStageSection extends NameableObject { + @JsonProperty private String formName; + + @JsonProperty private Integer sortOrder; + + @JsonProperty private ProgramStage programStage; + + @JsonProperty private List dataElements = new ArrayList<>(); + + @JsonProperty private List programIndicators = new ArrayList<>(); +} diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index feb546e6..ae127f75 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -31,13 +31,15 @@ import static org.hisp.dhis.support.Assertions.assertNotEmpty; import static org.hisp.dhis.support.Assertions.assertSize; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; - import java.util.List; import org.hisp.dhis.model.DataElement; import org.hisp.dhis.model.Program; +import org.hisp.dhis.model.ProgramIndicator; import org.hisp.dhis.model.ProgramStage; import org.hisp.dhis.model.ProgramStageDataElement; +import org.hisp.dhis.model.ProgramStageSection; import org.hisp.dhis.model.ProgramType; import org.hisp.dhis.model.trackedentity.ProgramTrackedEntityAttribute; import org.hisp.dhis.model.trackedentity.TrackedEntityAttribute; @@ -53,15 +55,15 @@ @Tag(TestTags.INTEGRATION) public class ProgramApiTest { @Test - void testGetProgram() { + void testGetProgramChildProgram() { Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); Program pr = dhis2.getProgram("IpHINAT79UW"); assertNotNull(pr); assertEquals("IpHINAT79UW", pr.getId()); - assertNotBlank(pr.getShortName()); assertNotBlank(pr.getName()); + assertNotBlank(pr.getShortName()); assertNotNull(pr.getCreated()); assertNotNull(pr.getLastUpdated()); assertEquals(ProgramType.WITH_REGISTRATION, pr.getProgramType()); @@ -130,6 +132,51 @@ void testGetProgram() { assertNotEmpty(pr.getAnalyticsDataElements()); } + @Test + void testGetProgramInpatientCase() { + Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); + + Program pr = dhis2.getProgram("eBAyeGv0exc"); + + assertNotNull(pr); + assertEquals("eBAyeGv0exc", pr.getId()); + assertNotBlank(pr.getName()); + assertNotBlank(pr.getShortName()); + assertNotNull(pr.getProgramStages()); + assertNotNull(pr.getProgramStageSections()); + assertFalse(pr.getProgramStageSections().isEmpty()); + + ProgramStage ps = pr.getProgramStages().get(0); + + assertNotNull(ps); + assertEquals("Zj7UnCAulEk", ps.getId()); + assertNotNull(ps.getProgramStageSections()); + + ProgramStageSection pss = ps.getProgramStageSections().get(0); + + assertNotNull(pss); + assertEquals("d7ZILSbPgYh", pss.getId()); + assertNotBlank(pss.getName()); + assertNotBlank(pss.getDescription()); + assertNotNull(pss.getSortOrder()); + assertNotNull(pss.getDataElements()); + assertNotNull(pss.getProgramIndicators()); + + DataElement de = pss.getDataElements().get(0); + + assertNotNull(de); + assertEquals("oZg33kd9taw", de.getId()); + assertNotBlank(de.getName()); + assertNotBlank(de.getShortName()); + + ProgramIndicator pi = pss.getProgramIndicators().get(0); + + assertNotNull(pi); + assertEquals("x7PaHGvgWY2", pi.getId()); + assertNotBlank(pi.getName()); + assertNotBlank(pi.getShortName()); + } + @Test void testGetPrograms() { Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); diff --git a/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java b/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java index 3c946cd6..01da7ed0 100644 --- a/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java @@ -34,7 +34,7 @@ public class ConfigUtilsTest { @Test - void testGetAsListA() { + void testGetAsList() { List expected = List.of("http://localhost", "http://localhost:3000", "https://localhost:3000");