From 677a60e1d92e53af6b56683bbbb390af14c7185a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 1 May 2025 22:30:03 +0200 Subject: [PATCH 01/17] fix: Update code --- pom.xml | 6 ++++ src/main/java/org/hisp/dhis/BaseDhis2.java | 23 ++++++++++--- .../dhis/query/analytics/AnalyticsQuery.java | 26 +++++++++++++++ .../dhis/{Dhis2Test.java => QueryTest.java} | 33 ++++++++++++------- 4 files changed, 73 insertions(+), 15 deletions(-) rename src/test/java/org/hisp/dhis/{Dhis2Test.java => QueryTest.java} (89%) diff --git a/pom.xml b/pom.xml index 2f3e9a2b..e92f8ecc 100644 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,7 @@ 3.5.2 2.18.0 3.17.0 + 4.5.0 2.44.3 @@ -89,6 +90,11 @@ commons-lang3 ${commons-lang3.version} + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + org.slf4j slf4j-api diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 061ac3d8..2e5235e6 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -114,6 +114,8 @@ public class BaseDhis2 { protected static final String NAME_FIELDS = String.format("%s,shortName,description", ID_FIELDS); + private static final String SEP_DIM = ";"; + /** Option set fields. */ protected static final String OPTION_SET_FIELDS = String.format("%s,valueType,version", ID_FIELDS); @@ -170,7 +172,9 @@ public class BaseDhis2 { /** Indicator fields. */ protected static final String INDICATOR_FIELDS = String.format( - "%1$s,annualized,numerator,numeratorDescription,denominator,denominatorDescription,url,indicatorType[%2$s]", + """ + %1$s,annualized,numerator,numeratorDescription,\ + denominator,denominatorDescription,url,indicatorType[%2$s]""", NAME_FIELDS, INDICATOR_TYPE_FIELDS); /** Indicator group set fields. */ @@ -234,7 +238,9 @@ public class BaseDhis2 { /** Me / current user fields. */ protected static final String ME_FIELDS = String.format( - "%1$s,username,surname,firstName,email,settings,programs,dataSets,authorities,organisationUnits[%2$s]", + """ + %1$s,username,surname,firstName,email,settings,programs,\ + dataSets,authorities,organisationUnits[%2$s]""", ID_FIELDS, ORG_UNIT_FIELDS); /** Log level system property. */ @@ -259,8 +265,8 @@ public class BaseDhis2 { protected static final String VALIDATION_RULE_FIELDS = String.format( """ - %1$s,dimensionItem,instruction,importance,periodType,displayDescription,displayInstruction,displayName,\ - leftSide[%2$s],operator,rightSide[%2$s],skipFormValidation,legendSets""", + %1$s,dimensionItem,instruction,importance,periodType,displayDescription,displayInstruction,\ + displayName,leftSide[%2$s],operator,rightSide[%2$s],skipFormValidation,legendSets""", NAME_FIELDS, VALIDATION_SIDE_FIELDS); protected static final String DATA_SET_VALIDATION_FIELDS = @@ -439,6 +445,7 @@ protected URI getAnalyticsQuery(URIBuilder uriBuilder, AnalyticsQuery query) { addParameter(uriBuilder, "skipData", query.getSkipData()); addParameter(uriBuilder, "skipRounding", query.getSkipRounding()); addParameter(uriBuilder, "ignoreLimit", query.getIgnoreLimit()); + addParameter(uriBuilder, "tableLayout", query.getTableLayout()); addParameter(uriBuilder, "showHierarchy", query.getShowHierarchy()); addParameter(uriBuilder, "includeNumDen", query.getIncludeNumDen()); addParameter(uriBuilder, "includeMetadataDetails", query.getIncludeMetadataDetails()); @@ -447,6 +454,14 @@ protected URI getAnalyticsQuery(URIBuilder uriBuilder, AnalyticsQuery query) { addParameter(uriBuilder, "outputDataElementIdScheme", query.getOutputDataElementIdScheme()); addParameter(uriBuilder, "inputIdScheme", query.getInputIdScheme()); + if (query.hasColumns()) { + addParameter(uriBuilder, "columns", String.join(SEP_DIM, query.getColumns())); + } + + if (query.hasRows()) { + addParameter(uriBuilder, "rows", String.join(SEP_DIM, query.getRows())); + } + return HttpUtils.build(uriBuilder); } diff --git a/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java b/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java index 9e7faa54..50e2bc6e 100644 --- a/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java +++ b/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java @@ -27,6 +27,8 @@ */ package org.hisp.dhis.query.analytics; +import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; + import java.util.ArrayList; import java.util.List; import lombok.Getter; @@ -58,6 +60,8 @@ public class AnalyticsQuery { private Boolean ignoreLimit; + private Boolean tableLayout; + private Boolean showHierarchy; private Boolean includeNumDen; @@ -72,6 +76,10 @@ public class AnalyticsQuery { private IdScheme inputIdScheme; + private List columns = new ArrayList<>(); + + private List rows = new ArrayList<>(); + private AnalyticsQuery() {} /** @@ -186,4 +194,22 @@ public AnalyticsQuery addPeriodFilter(List items) { public AnalyticsQuery addOrgUnitFilter(List items) { return addFilter(new Dimension(Dimension.DIMENSION_OU, items)); } + + /** + * Indicates whether any columns exist. + * + * @return true if any columns exist. + */ + public boolean hasColumns() { + return isNotEmpty(columns); + } + + /** + * Indicates whether any rows exist. + * + * @return true if any rows exist. + */ + public boolean hasRows() { + return isNotEmpty(rows); + } } diff --git a/src/test/java/org/hisp/dhis/Dhis2Test.java b/src/test/java/org/hisp/dhis/QueryTest.java similarity index 89% rename from src/test/java/org/hisp/dhis/Dhis2Test.java rename to src/test/java/org/hisp/dhis/QueryTest.java index 53b7c007..cbec3eb2 100644 --- a/src/test/java/org/hisp/dhis/Dhis2Test.java +++ b/src/test/java/org/hisp/dhis/QueryTest.java @@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.net.URI; +import java.util.List; import org.apache.hc.core5.net.URIBuilder; import org.hisp.dhis.model.AggregationType; import org.hisp.dhis.model.IdScheme; @@ -47,7 +48,7 @@ import org.junit.jupiter.api.Test; @Tag(TestTags.UNIT) -class Dhis2Test { +class QueryTest { @Test void testGetDhis2() { Dhis2Config config = getDhis2Config(); @@ -127,8 +128,10 @@ void testGetObjectQueryC() { URI uri = dhis2.getObjectQuery(uriBuilder, query); String expected = - "https://dhis2.org/api/dataSets?" - + "filter=name%3Alike%3AANC&page=1&pageSize=50&order=id%3Aasc"; + """ + https://dhis2.org/api/dataSets?\ + filter=name%3Alike%3AANC\ + &page=1&pageSize=50&order=id%3Aasc"""; assertEquals(expected, uri.toString()); } @@ -151,8 +154,10 @@ void testGetDataValueSetImportQuery() { URI uri = dhis2.getDataValueSetImportQuery(uriBuilder, options); String expected = - "https://dhis2.org/api/dataValueSets?" - + "async=true&dataElementIdScheme=code&dryRun=true&preheatCache=true&skipAudit=true"; + """ + https://dhis2.org/api/dataValueSets?\ + async=true&dataElementIdScheme=code&\ + dryRun=true&preheatCache=true&skipAudit=true"""; assertEquals(expected, uri.toString()); } @@ -170,7 +175,8 @@ void testGetAnalyticsQuery() { .setAggregationType(AggregationType.AVERAGE) .setIgnoreLimit(true) .setInputIdScheme(IdScheme.CODE) - .setOutputIdScheme(IdScheme.UID); + .setOutputIdScheme(IdScheme.UID) + .setColumns(List.of("dx", "pe")); URI uri = dhis2.getAnalyticsQuery(uriBuilder, query); @@ -180,7 +186,8 @@ void testGetAnalyticsQuery() { aggregationType=AVERAGE\ &ignoreLimit=true\ &outputIdScheme=uid\ - &inputIdScheme=code"""; + &inputIdScheme=code\ + &columns=dx%3Bpe"""; assertEquals(expected, uri.toString()); } @@ -204,8 +211,10 @@ void testGetEventsQuery() { URI uri = dhis2.getEventsQuery(uriBuilder, query); String expected = - "https://dhis2.org/api/tracker/events?" - + "program=hJhgt5cDs7j&programStatus=ACTIVE&followUp=true&idScheme=code"; + """ + https://dhis2.org/api/tracker/events?\ + program=hJhgt5cDs7j&programStatus=ACTIVE\ + &followUp=true&idScheme=code"""; assertEquals(expected, uri.toString()); } @@ -226,8 +235,10 @@ void testGetDataValueSetQuery() { .setChildren(true); String expected = - "https://dhis2.org/api/dataValueSets.json?" - + "dataElement=N9vniUuCcqY&orgUnit=ImspTQPwCqd&period=202211&children=true"; + """ + https://dhis2.org/api/dataValueSets.json?\ + dataElement=N9vniUuCcqY&orgUnit=ImspTQPwCqd\ + &period=202211&children=true"""; URI uri = dhis2.getDataValueSetQuery(uriBuilder, query); From 59bd52c05d5093efb17c309dd477a4f43ef374d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 13:00:14 +0200 Subject: [PATCH 02/17] fix: Update code --- src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 5f249fa3..995226fe 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -32,7 +32,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; - import java.util.stream.IntStream; import org.hisp.dhis.support.TestTags; import org.junit.jupiter.api.Tag; @@ -92,7 +91,7 @@ void testToUidDeterminisism() { /** * Asserts that the method generates a valid UID based on the given identifier. * - * @param uid + * @param input the input string. */ private void assertToUid(String input) { String output = UidUtils.toUid(input); From ca8d9923ef36be4818ba71fe3f01343a26d16396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 13:02:02 +0200 Subject: [PATCH 03/17] fix: Update code --- .../java/org/hisp/dhis/query/analytics/AnalyticsQuery.java | 6 +++++- src/main/java/org/hisp/dhis/query/analytics/Dimension.java | 5 +++++ .../CompleteDataSetRegistrationQuery.java | 1 + src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java b/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java index 50e2bc6e..f7865e2b 100644 --- a/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java +++ b/src/main/java/org/hisp/dhis/query/analytics/AnalyticsQuery.java @@ -37,7 +37,11 @@ import org.hisp.dhis.model.AggregationType; import org.hisp.dhis.model.IdScheme; -/** Analytics data query. */ +/** + * Analytics data query. + * + * @author Lars Helge Overland + */ @Getter @Setter @Accessors(chain = true) diff --git a/src/main/java/org/hisp/dhis/query/analytics/Dimension.java b/src/main/java/org/hisp/dhis/query/analytics/Dimension.java index 050df566..14d33a7a 100644 --- a/src/main/java/org/hisp/dhis/query/analytics/Dimension.java +++ b/src/main/java/org/hisp/dhis/query/analytics/Dimension.java @@ -33,6 +33,11 @@ import lombok.Setter; import org.apache.commons.lang3.StringUtils; +/** + * Analytics dimension. + * + * @author Lars Helge Overland + */ @Getter @Setter @RequiredArgsConstructor diff --git a/src/main/java/org/hisp/dhis/query/completedatasetregistration/CompleteDataSetRegistrationQuery.java b/src/main/java/org/hisp/dhis/query/completedatasetregistration/CompleteDataSetRegistrationQuery.java index 3d3832e8..6edb4e0a 100644 --- a/src/main/java/org/hisp/dhis/query/completedatasetregistration/CompleteDataSetRegistrationQuery.java +++ b/src/main/java/org/hisp/dhis/query/completedatasetregistration/CompleteDataSetRegistrationQuery.java @@ -35,6 +35,7 @@ import lombok.experimental.Accessors; import org.hisp.dhis.model.IdScheme; +/** Complete data set registration. */ @Getter @Setter @Accessors(chain = true) diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 995226fe..668f7d6c 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -32,6 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.stream.IntStream; import org.hisp.dhis.support.TestTags; import org.junit.jupiter.api.Tag; From aba06afcf1419f1f10d219baa1148181afd99ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 16:00:07 +0200 Subject: [PATCH 04/17] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 16 +++++++++++++++- .../java/org/hisp/dhis/util/UidUtilsTest.java | 8 ++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index f907663a..2e275c36 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -31,11 +31,13 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; +import java.util.stream.IntStream; +import org.apache.commons.lang3.StringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; /** Utilities for DHIS2 UID generation. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -63,6 +65,18 @@ public class UidUtils { public static String generateUid() { return generateCode(UID_LENGTH); } + + /** + * Generates the given number of DHIS2 UIDs. + * + * @param n the number of UIDs to generate. + * @return a list of DHIS2 UID strings. + */ + public static List generateUids(int n) { + return IntStream.range(0, n) + .mapToObj(i -> generateUid()) + .toList(); + } /** * Tests whether the given code is a valid UID. diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 668f7d6c..59f98979 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -32,7 +32,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; - import java.util.stream.IntStream; import org.hisp.dhis.support.TestTags; import org.junit.jupiter.api.Tag; @@ -41,12 +40,17 @@ @Tag(TestTags.UNIT) class UidUtilsTest { @Test - void testGetUid() { + void testGenerateUid() { String uid = UidUtils.generateUid(); assertNotNull(uid); assertEquals(11, uid.length()); } + + @Test + void testGenerateUids() { + assertEquals(3, UidUtils.generateUids(3).size()); + } @Test void testUidIsValid() { From e8f2a5526e4fddf4c455f54c318cdda29cb7f28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 16:09:14 +0200 Subject: [PATCH 05/17] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 10 ++++------ src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index 2e275c36..48d26f84 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -35,9 +35,9 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; import java.util.stream.IntStream; -import org.apache.commons.lang3.StringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; /** Utilities for DHIS2 UID generation. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -65,17 +65,15 @@ public class UidUtils { public static String generateUid() { return generateCode(UID_LENGTH); } - + /** * Generates the given number of DHIS2 UIDs. - * + * * @param n the number of UIDs to generate. * @return a list of DHIS2 UID strings. */ public static List generateUids(int n) { - return IntStream.range(0, n) - .mapToObj(i -> generateUid()) - .toList(); + return IntStream.range(0, n).mapToObj(i -> generateUid()).toList(); } /** diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 59f98979..be311d03 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -32,6 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.stream.IntStream; import org.hisp.dhis.support.TestTags; import org.junit.jupiter.api.Tag; @@ -46,7 +47,7 @@ void testGenerateUid() { assertNotNull(uid); assertEquals(11, uid.length()); } - + @Test void testGenerateUids() { assertEquals(3, UidUtils.generateUids(3).size()); From e8d343c187352cc90731274a3a608e3bedeee073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 18:28:57 +0200 Subject: [PATCH 06/17] fix: Update code --- src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java b/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java index 3c946cd6..be742a75 100644 --- a/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java @@ -28,13 +28,12 @@ package org.hisp.dhis.util; import static org.junit.jupiter.api.Assertions.assertEquals; - import java.util.List; import org.junit.jupiter.api.Test; public class ConfigUtilsTest { @Test - void testGetAsListA() { + void testGetAsList() { List expected = List.of("http://localhost", "http://localhost:3000", "https://localhost:3000"); From b821b1caa38a9faa7b58755cba1205e2045038e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:12:05 +0200 Subject: [PATCH 07/17] fix: Update code --- src/main/java/org/hisp/dhis/BaseDhis2.java | 9 ++-- .../java/org/hisp/dhis/model/Program.java | 34 ++++++++----- .../org/hisp/dhis/model/ProgramStage.java | 7 +-- .../hisp/dhis/model/ProgramStageSection.java | 25 ++++++++++ .../java/org/hisp/dhis/ProgramApiTest.java | 50 +++++++++++++++++-- .../org/hisp/dhis/util/ConfigUtilsTest.java | 1 + 6 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/hisp/dhis/model/ProgramStageSection.java diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 2e5235e6..11acb5f8 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -33,8 +33,6 @@ import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED; import static org.hisp.dhis.util.CollectionUtils.asList; import static org.hisp.dhis.util.HttpUtils.getUriAsString; - -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -47,7 +45,6 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.hc.client5.http.HttpResponseException; @@ -100,6 +97,8 @@ import org.hisp.dhis.response.objects.ObjectsResponse; import org.hisp.dhis.util.HttpUtils; import org.hisp.dhis.util.JacksonUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; /** * @author Lars Helge Overland @@ -224,7 +223,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..375d0c2b 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(); } /** @@ -134,7 +133,7 @@ public List getDataElements() { return programStages.stream() .flatMap(ps -> ps.getDataElements().stream()) .distinct() - .collect(Collectors.toUnmodifiableList()); + .toList(); } /** @@ -147,7 +146,7 @@ public List getAnalyticsDataElements() { return programStages.stream() .flatMap(ps -> ps.getAnalyticsDataElements().stream()) .distinct() - .collect(Collectors.toUnmodifiableList()); + .toList(); } /** @@ -162,7 +161,18 @@ 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}. + */ + 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..0d874578 100644 --- a/src/main/java/org/hisp/dhis/model/ProgramStage.java +++ b/src/main/java/org/hisp/dhis/model/ProgramStage.java @@ -28,12 +28,11 @@ package org.hisp.dhis.model; import static org.apache.commons.lang3.BooleanUtils.isFalse; - -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 com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -43,6 +42,8 @@ @NoArgsConstructor 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; 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..eaa973b3 --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java @@ -0,0 +1,25 @@ +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 description; + + @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..7c40bcec 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -32,12 +32,13 @@ import static org.hisp.dhis.support.Assertions.assertSize; import static org.junit.jupiter.api.Assertions.assertEquals; 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 +54,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 +131,49 @@ 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()); + + 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 be742a75..01da7ed0 100644 --- a/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/ConfigUtilsTest.java @@ -28,6 +28,7 @@ package org.hisp.dhis.util; import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.List; import org.junit.jupiter.api.Test; From 4b0b9ef9fa6a7f4a23f5bef2e3a09cea6a7ab46c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:33:28 +0200 Subject: [PATCH 08/17] fix: Update code --- src/main/java/org/hisp/dhis/BaseDhis2.java | 5 ++-- .../java/org/hisp/dhis/model/Program.java | 14 ++++----- .../org/hisp/dhis/model/ProgramStage.java | 7 +++-- .../hisp/dhis/model/ProgramStageSection.java | 29 +++++++++++++++++-- .../java/org/hisp/dhis/ProgramApiTest.java | 23 ++++++++------- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 11acb5f8..6c3640df 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -33,6 +33,8 @@ import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED; import static org.hisp.dhis.util.CollectionUtils.asList; import static org.hisp.dhis.util.HttpUtils.getUriAsString; + +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -45,6 +47,7 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.hc.client5.http.HttpResponseException; @@ -97,8 +100,6 @@ import org.hisp.dhis.response.objects.ObjectsResponse; import org.hisp.dhis.util.HttpUtils; import org.hisp.dhis.util.JacksonUtils; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; /** * @author Lars Helge Overland diff --git a/src/main/java/org/hisp/dhis/model/Program.java b/src/main/java/org/hisp/dhis/model/Program.java index 375d0c2b..541c2efd 100644 --- a/src/main/java/org/hisp/dhis/model/Program.java +++ b/src/main/java/org/hisp/dhis/model/Program.java @@ -130,10 +130,7 @@ public List getNonConfidentialTrackedEntityAttributes() */ @JsonIgnore public List getDataElements() { - return programStages.stream() - .flatMap(ps -> ps.getDataElements().stream()) - .distinct() - .toList(); + return programStages.stream().flatMap(ps -> ps.getDataElements().stream()).distinct().toList(); } /** @@ -163,16 +160,15 @@ public List getAnalyticsDataElementsWithLegendSet() { .distinct() .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(); + 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 0d874578..67713121 100644 --- a/src/main/java/org/hisp/dhis/model/ProgramStage.java +++ b/src/main/java/org/hisp/dhis/model/ProgramStage.java @@ -28,11 +28,12 @@ package org.hisp.dhis.model; import static org.apache.commons.lang3.BooleanUtils.isFalse; + +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 com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -42,7 +43,7 @@ @NoArgsConstructor public class ProgramStage extends NameableObject { @JsonProperty private List programStageDataElements = new ArrayList<>(); - + @JsonProperty private List programStageSections = new ArrayList<>(); public ProgramStage(String id, String name) { diff --git a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java index eaa973b3..99882ef0 100644 --- a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java +++ b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java @@ -1,3 +1,30 @@ +/* + * 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; @@ -11,8 +38,6 @@ @Setter @NoArgsConstructor public class ProgramStageSection extends NameableObject { - @JsonProperty private String description; - @JsonProperty private String formName; @JsonProperty private Integer sortOrder; diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index 7c40bcec..ae127f75 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -31,6 +31,7 @@ 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; @@ -140,17 +141,19 @@ void testGetProgramInpatientCase() { assertNotNull(pr); assertEquals("eBAyeGv0exc", pr.getId()); assertNotBlank(pr.getName()); - assertNotBlank(pr.getShortName()); + 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()); @@ -158,22 +161,22 @@ void testGetProgramInpatientCase() { 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); From 08691eebb3f5f7a23566fb631545cba04bad61e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:37:59 +0200 Subject: [PATCH 09/17] fix: Update code --- src/main/java/org/hisp/dhis/model/Program.java | 11 ++++++----- .../java/org/hisp/dhis/model/ProgramStageSection.java | 2 +- src/test/java/org/hisp/dhis/ProgramApiTest.java | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/hisp/dhis/model/Program.java b/src/main/java/org/hisp/dhis/model/Program.java index 541c2efd..14b939c2 100644 --- a/src/main/java/org/hisp/dhis/model/Program.java +++ b/src/main/java/org/hisp/dhis/model/Program.java @@ -28,18 +28,19 @@ 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 diff --git a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java index 99882ef0..aaa49d8c 100644 --- a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java +++ b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java @@ -27,9 +27,9 @@ */ package org.hisp.dhis.model; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index ae127f75..5816f974 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -33,6 +33,7 @@ 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; From 6dbf15db8a2e4a2e4d3c4419bdcbc35eb904b928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:39:24 +0200 Subject: [PATCH 10/17] fix: Update code --- src/main/java/org/hisp/dhis/Dhis2AsyncRequest.java | 5 +++-- src/main/java/org/hisp/dhis/model/Program.java | 11 ++++++----- .../java/org/hisp/dhis/model/ProgramStageSection.java | 2 +- src/main/java/org/hisp/dhis/response/Response.java | 2 +- src/test/java/org/hisp/dhis/ProgramApiTest.java | 1 + 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/hisp/dhis/Dhis2AsyncRequest.java b/src/main/java/org/hisp/dhis/Dhis2AsyncRequest.java index 529b2315..d0628a68 100644 --- a/src/main/java/org/hisp/dhis/Dhis2AsyncRequest.java +++ b/src/main/java/org/hisp/dhis/Dhis2AsyncRequest.java @@ -115,12 +115,13 @@ public T postEvent(HttpPost request, Class klass return getJobSummary(klass, message, jobInfo); } - private T getJobSummary(Class klass, JobInfoResponse message, JobInfo jobInfo) { + private T getJobSummary( + Class klass, JobInfoResponse message, JobInfo jobInfo) { log.info( "Push response: '{}', '{}', job: '{}'", message.getHttpStatus(), message.getMessage(), - jobInfo); + jobInfo); JobNotification notification = waitForCompletion(jobInfo); diff --git a/src/main/java/org/hisp/dhis/model/Program.java b/src/main/java/org/hisp/dhis/model/Program.java index 541c2efd..14b939c2 100644 --- a/src/main/java/org/hisp/dhis/model/Program.java +++ b/src/main/java/org/hisp/dhis/model/Program.java @@ -28,18 +28,19 @@ 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 diff --git a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java index 99882ef0..aaa49d8c 100644 --- a/src/main/java/org/hisp/dhis/model/ProgramStageSection.java +++ b/src/main/java/org/hisp/dhis/model/ProgramStageSection.java @@ -27,9 +27,9 @@ */ package org.hisp.dhis.model; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; diff --git a/src/main/java/org/hisp/dhis/response/Response.java b/src/main/java/org/hisp/dhis/response/Response.java index c2052df3..061d29dc 100644 --- a/src/main/java/org/hisp/dhis/response/Response.java +++ b/src/main/java/org/hisp/dhis/response/Response.java @@ -68,7 +68,7 @@ public Response(Status status, Integer httpStatusCode, String message, String er } public HttpStatus getHttpStatus() { - if (httpStatusCode != null){ + if (httpStatusCode != null) { return HttpStatus.valueOf(httpStatusCode); } diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index ae127f75..5816f974 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -33,6 +33,7 @@ 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; From 8929d422b40494d29f616ef01062c3baaa9bb5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:41:36 +0200 Subject: [PATCH 11/17] fix: Update code --- src/test/java/org/hisp/dhis/ProgramApiTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index 5816f974..38a91139 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -33,7 +33,6 @@ 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; @@ -145,7 +144,7 @@ void testGetProgramInpatientCase() { assertNotBlank(pr.getShortName()); assertNotNull(pr.getProgramStages()); assertNotNull(pr.getProgramStageSections()); - assertFalse(pr.getProgramStageSections().isEmpty()); + assertFalse (pr.getProgramStageSections().isEmpty()); ProgramStage ps = pr.getProgramStages().get(0); From c6f6d64e4cb517a87d18c067f6730c98dd955540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:41:42 +0200 Subject: [PATCH 12/17] fix: Update code --- src/test/java/org/hisp/dhis/ProgramApiTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index 38a91139..5816f974 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -33,6 +33,7 @@ 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; @@ -144,7 +145,7 @@ void testGetProgramInpatientCase() { assertNotBlank(pr.getShortName()); assertNotNull(pr.getProgramStages()); assertNotNull(pr.getProgramStageSections()); - assertFalse (pr.getProgramStageSections().isEmpty()); + assertFalse(pr.getProgramStageSections().isEmpty()); ProgramStage ps = pr.getProgramStages().get(0); From c57efdd92d7da048412dee052c430af6af1af455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 15:49:26 +0200 Subject: [PATCH 13/17] fix: Update code --- src/main/java/org/hisp/dhis/model/Dhis2Objects.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/hisp/dhis/model/Dhis2Objects.java b/src/main/java/org/hisp/dhis/model/Dhis2Objects.java index 6dff170c..fad3beaf 100644 --- a/src/main/java/org/hisp/dhis/model/Dhis2Objects.java +++ b/src/main/java/org/hisp/dhis/model/Dhis2Objects.java @@ -87,6 +87,10 @@ public class Dhis2Objects { @JsonProperty private List programs = new ArrayList<>(); + @JsonProperty private List programStages = new ArrayList<>(); + + @JsonProperty private List programStageSections = new ArrayList<>(); + @JsonProperty private List programIndicators = new ArrayList<>(); @JsonProperty private List trackedEntityTypes = new ArrayList<>(); From 885b43c7c18a045c46dabea4662e69c79604b982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 18:57:36 +0200 Subject: [PATCH 14/17] fix: Update code --- src/main/java/org/hisp/dhis/model/Me.java | 1 + .../java/org/hisp/dhis/model/user/User.java | 65 +++++++++++++++++++ .../dhis/model/{ => user}/UserSettings.java | 2 +- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/hisp/dhis/model/user/User.java rename src/main/java/org/hisp/dhis/model/{ => user}/UserSettings.java (98%) diff --git a/src/main/java/org/hisp/dhis/model/Me.java b/src/main/java/org/hisp/dhis/model/Me.java index cce61aea..47ebcc53 100644 --- a/src/main/java/org/hisp/dhis/model/Me.java +++ b/src/main/java/org/hisp/dhis/model/Me.java @@ -33,6 +33,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hisp.dhis.model.user.UserSettings; @Getter @Setter diff --git a/src/main/java/org/hisp/dhis/model/user/User.java b/src/main/java/org/hisp/dhis/model/user/User.java new file mode 100644 index 00000000..dc030861 --- /dev/null +++ b/src/main/java/org/hisp/dhis/model/user/User.java @@ -0,0 +1,65 @@ +/* + * 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.user; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hisp.dhis.model.IdentifiableObject; +import org.hisp.dhis.model.OrgUnit; + +@Getter +@Setter +@NoArgsConstructor +public class User extends IdentifiableObject { + @JsonProperty private String username; + + @JsonProperty private String firstName; + + @JsonProperty private String surname; + + @JsonProperty private String email; + + @JsonProperty private String phoneNumber; + + @JsonProperty private Boolean externalAuth; + + @JsonProperty private Date lastLogin; + + @JsonProperty private Boolean disabled; + + @JsonProperty private List organisationUnits = new ArrayList<>(); + + @JsonProperty private List dataViewOrganisationUnits = new ArrayList<>(); + + @JsonProperty private List teiSearchOrganisationUnits = new ArrayList<>(); +} diff --git a/src/main/java/org/hisp/dhis/model/UserSettings.java b/src/main/java/org/hisp/dhis/model/user/UserSettings.java similarity index 98% rename from src/main/java/org/hisp/dhis/model/UserSettings.java rename to src/main/java/org/hisp/dhis/model/user/UserSettings.java index b1b60b81..e0673982 100644 --- a/src/main/java/org/hisp/dhis/model/UserSettings.java +++ b/src/main/java/org/hisp/dhis/model/user/UserSettings.java @@ -25,7 +25,7 @@ * (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; +package org.hisp.dhis.model.user; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; From fa21b7e4f8d470997ca915ec00abd263e574c37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 20:31:15 +0200 Subject: [PATCH 15/17] fix: Update code --- src/main/java/org/hisp/dhis/BaseDhis2.java | 15 ++++- src/main/java/org/hisp/dhis/Dhis2.java | 41 +++++++++++- .../org/hisp/dhis/model/Dhis2Objects.java | 51 ++++++++------- .../CompleteDataSetRegistrationApiTest.java | 2 - .../java/org/hisp/dhis/ProgramApiTest.java | 3 +- src/test/java/org/hisp/dhis/UserApiTest.java | 63 +++++++++++++++++++ 6 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 src/test/java/org/hisp/dhis/UserApiTest.java diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 6c3640df..2d64a9e8 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -33,8 +33,6 @@ import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED; import static org.hisp.dhis.util.CollectionUtils.asList; import static org.hisp.dhis.util.HttpUtils.getUriAsString; - -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -47,7 +45,6 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.hc.client5.http.HttpResponseException; @@ -100,6 +97,8 @@ import org.hisp.dhis.response.objects.ObjectsResponse; import org.hisp.dhis.util.HttpUtils; import org.hisp.dhis.util.JacksonUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; /** * @author Lars Helge Overland @@ -244,6 +243,16 @@ public class BaseDhis2 { %1$s,username,surname,firstName,email,settings,programs,\ dataSets,authorities,organisationUnits[%2$s]""", ID_FIELDS, ORG_UNIT_FIELDS); + + /** + * User fields. + */ + protected static final String USER_FIELDS = + String.format( + """ + %1$s,username,firstName,surname,email,phoneNumber,externalAuth,lastLogin,\ + organisationUnits[%2$s],dataViewOrganisationUnits[%2$s],teiSearchOrganisationUnits[%2$s]""", + ID_FIELDS, NAME_FIELDS); /** Log level system property. */ private static final String LOG_LEVEL_SYSTEM_PROPERTY = "log.level.dhis2"; diff --git a/src/main/java/org/hisp/dhis/Dhis2.java b/src/main/java/org/hisp/dhis/Dhis2.java index f13836b2..cb619a9d 100644 --- a/src/main/java/org/hisp/dhis/Dhis2.java +++ b/src/main/java/org/hisp/dhis/Dhis2.java @@ -29,7 +29,6 @@ import static org.hisp.dhis.util.CollectionUtils.asList; import static org.hisp.dhis.util.CollectionUtils.list; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -98,6 +97,7 @@ import org.hisp.dhis.model.event.Events; import org.hisp.dhis.model.event.EventsResult; import org.hisp.dhis.model.trackedentity.TrackedEntityType; +import org.hisp.dhis.model.user.User; import org.hisp.dhis.model.validation.Period; import org.hisp.dhis.model.validation.Validation; import org.hisp.dhis.model.validation.ValidationRule; @@ -2157,6 +2157,45 @@ public List getDashboards(Query query) { .getDashboards(); } + // ------------------------------------------------------------------------- + // User + // ------------------------------------------------------------------------- + + /** + * Retrieves a {@link User}. + * + * @param id the object identifier. + * @return the {@link User}. + * @throws Dhis2ClientException if the object does not exist. + */ + public User getUser(String id) { + return getObject( + config + .getResolvedUriBuilder() + .appendPath("users") + .appendPath(id) + .addParameter(FIELDS_PARAM, USER_FIELDS), + Query.instance(), + User.class); + } + + /** + * Retrieves a list of {@link User}. + * + * @param query the {@link Query}. + * @return list of {@link User}. + */ + public List getUsers(Query query) { + return getObject( + config + .getResolvedUriBuilder() + .appendPath("users") + .addParameter(FIELDS_PARAM, USER_FIELDS), + query, + Dhis2Objects.class) + .getUsers(); + } + // ------------------------------------------------------------------------- // Dimension // ------------------------------------------------------------------------- diff --git a/src/main/java/org/hisp/dhis/model/Dhis2Objects.java b/src/main/java/org/hisp/dhis/model/Dhis2Objects.java index fad3beaf..171a7ae3 100644 --- a/src/main/java/org/hisp/dhis/model/Dhis2Objects.java +++ b/src/main/java/org/hisp/dhis/model/Dhis2Objects.java @@ -27,29 +27,49 @@ */ package org.hisp.dhis.model; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.experimental.Accessors; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistration; import org.hisp.dhis.model.dashboard.Dashboard; import org.hisp.dhis.model.trackedentity.TrackedEntityType; +import org.hisp.dhis.model.user.User; import org.hisp.dhis.model.validation.ValidationRule; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; @Getter @Setter @Accessors(chain = true) @NoArgsConstructor public class Dhis2Objects { + @JsonProperty private List analyticsTableHooks = new ArrayList<>(); + + @JsonProperty private List categoryOptions = new ArrayList<>(); + + @JsonProperty private List categories = new ArrayList<>(); + + @JsonProperty private List categoryCombos = new ArrayList<>(); + + @JsonProperty private List categoryOptionCombos = new ArrayList<>(); + + @JsonProperty private List categoryOptionGroups = new ArrayList<>(); + + @JsonProperty private List categoryOptionGroupSets = new ArrayList<>(); + + @JsonProperty + private List completeDataSetRegistrations = new ArrayList<>(); + @JsonProperty private List dashboards = new ArrayList<>(); @JsonProperty private List dataElements = new ArrayList<>(); @JsonProperty private List dataElementGroups = new ArrayList<>(); + @JsonProperty private List dimensions = new ArrayList<>(); + @JsonProperty private List organisationUnits = new ArrayList<>(); @JsonProperty private List organisationUnitGroups = new ArrayList<>(); @@ -58,21 +78,10 @@ public class Dhis2Objects { @JsonProperty private List organisationUnitLevels = new ArrayList<>(); - @JsonProperty private List categoryOptions = new ArrayList<>(); - - @JsonProperty private List categories = new ArrayList<>(); - - @JsonProperty private List categoryCombos = new ArrayList<>(); - - @JsonProperty private List categoryOptionCombos = new ArrayList<>(); - @JsonProperty private List dataElementGroupSets = new ArrayList<>(); @JsonProperty private List dataSets = new ArrayList<>(); - @JsonProperty - private List completeDataSetRegistrations = new ArrayList<>(); - @JsonProperty private List maps = new ArrayList(); @JsonProperty private List indicatorTypes = new ArrayList<>(); @@ -95,16 +104,10 @@ public class Dhis2Objects { @JsonProperty private List trackedEntityTypes = new ArrayList<>(); - @JsonProperty private List categoryOptionGroups = new ArrayList<>(); - - @JsonProperty private List categoryOptionGroupSets = new ArrayList<>(); - - @JsonProperty private List analyticsTableHooks = new ArrayList<>(); - - @JsonProperty private List dimensions = new ArrayList<>(); - @JsonProperty private List periodTypes = new ArrayList<>(); + @JsonProperty private List users = new ArrayList<>(); + @JsonProperty private List visualizations = new ArrayList<>(); @JsonProperty private List validationRules = new ArrayList<>(); diff --git a/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java b/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java index 92398409..9ab00fec 100644 --- a/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java +++ b/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java @@ -32,7 +32,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; - import java.util.List; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistration; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistrationImportOptions; @@ -47,7 +46,6 @@ @Tag(TestTags.INTEGRATION) class CompleteDataSetRegistrationApiTest { - @Test void testGetCompleteDataSetRegistrationsWithStartEndDates() { CompleteDataSetRegistrationQuery query = diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index 5816f974..2cba9082 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -33,7 +33,6 @@ 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; @@ -54,7 +53,7 @@ import org.junit.jupiter.api.Test; @Tag(TestTags.INTEGRATION) -public class ProgramApiTest { +class ProgramApiTest { @Test void testGetProgramChildProgram() { Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); diff --git a/src/test/java/org/hisp/dhis/UserApiTest.java b/src/test/java/org/hisp/dhis/UserApiTest.java new file mode 100644 index 00000000..09a99c7f --- /dev/null +++ b/src/test/java/org/hisp/dhis/UserApiTest.java @@ -0,0 +1,63 @@ +package org.hisp.dhis; + +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.OrgUnit; +import org.hisp.dhis.model.user.User; +import org.hisp.dhis.query.Filter; +import org.hisp.dhis.query.Query; +import org.hisp.dhis.support.TestTags; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag(TestTags.INTEGRATION) +class UserApiTest { + @Test + void testGetUser() { + Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); + + User user = dhis2.getUser("xE7jOejl9FI"); + + assertNotNull(user); + assertEquals("xE7jOejl9FI", user.getId()); + assertEquals("John Traore", user.getName()); + assertEquals("admin", user.getUsername()); + assertEquals("John", user.getFirstName()); + assertEquals("Traore", user.getSurname()); + assertEquals("dummy@dhis2.org", user.getEmail()); + assertFalse(user.getOrganisationUnits().isEmpty()); + + OrgUnit orgUnit = user.getOrganisationUnits().get(0); + + assertNotNull(orgUnit); + assertNotNull(orgUnit.getId()); + assertNotNull(orgUnit.getName()); + } + + @Test + void testGetUserByUsername() { + Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); + + List users = dhis2.getUsers(Query.instance().addFilter(Filter.eq("username", "admin"))); + + assertNotNull(users); + assertEquals(1, users.size()); + + User user = users.get(0); + + assertNotNull(user); + assertEquals("xE7jOejl9FI", user.getId()); + } + + @Test + void testGetUsers() { + Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); + + List users = dhis2.getUsers(Query.instance()); + + assertNotNull(users); + assertFalse(users.isEmpty()); + } +} From 1870f9425eb0c071a70f86a308474fa763c3b9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 20:31:22 +0200 Subject: [PATCH 16/17] fix: Update code --- src/main/java/org/hisp/dhis/BaseDhis2.java | 13 +++-- src/main/java/org/hisp/dhis/Dhis2.java | 3 +- .../org/hisp/dhis/model/Dhis2Objects.java | 12 ++--- .../CompleteDataSetRegistrationApiTest.java | 1 + .../java/org/hisp/dhis/ProgramApiTest.java | 1 + src/test/java/org/hisp/dhis/UserApiTest.java | 50 +++++++++++++++---- 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 2d64a9e8..f60fe46a 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -33,6 +33,8 @@ import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED; import static org.hisp.dhis.util.CollectionUtils.asList; import static org.hisp.dhis.util.HttpUtils.getUriAsString; + +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -45,6 +47,7 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.hc.client5.http.HttpResponseException; @@ -97,8 +100,6 @@ import org.hisp.dhis.response.objects.ObjectsResponse; import org.hisp.dhis.util.HttpUtils; import org.hisp.dhis.util.JacksonUtils; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; /** * @author Lars Helge Overland @@ -243,11 +244,9 @@ public class BaseDhis2 { %1$s,username,surname,firstName,email,settings,programs,\ dataSets,authorities,organisationUnits[%2$s]""", ID_FIELDS, ORG_UNIT_FIELDS); - - /** - * User fields. - */ - protected static final String USER_FIELDS = + + /** User fields. */ + protected static final String USER_FIELDS = String.format( """ %1$s,username,firstName,surname,email,phoneNumber,externalAuth,lastLogin,\ diff --git a/src/main/java/org/hisp/dhis/Dhis2.java b/src/main/java/org/hisp/dhis/Dhis2.java index cb619a9d..8dcdaeb7 100644 --- a/src/main/java/org/hisp/dhis/Dhis2.java +++ b/src/main/java/org/hisp/dhis/Dhis2.java @@ -29,6 +29,7 @@ import static org.hisp.dhis.util.CollectionUtils.asList; import static org.hisp.dhis.util.CollectionUtils.list; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -2195,7 +2196,7 @@ public List getUsers(Query query) { Dhis2Objects.class) .getUsers(); } - + // ------------------------------------------------------------------------- // Dimension // ------------------------------------------------------------------------- diff --git a/src/main/java/org/hisp/dhis/model/Dhis2Objects.java b/src/main/java/org/hisp/dhis/model/Dhis2Objects.java index 171a7ae3..8ac09fc9 100644 --- a/src/main/java/org/hisp/dhis/model/Dhis2Objects.java +++ b/src/main/java/org/hisp/dhis/model/Dhis2Objects.java @@ -27,18 +27,18 @@ */ package org.hisp.dhis.model; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistration; import org.hisp.dhis.model.dashboard.Dashboard; import org.hisp.dhis.model.trackedentity.TrackedEntityType; import org.hisp.dhis.model.user.User; import org.hisp.dhis.model.validation.ValidationRule; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.experimental.Accessors; @Getter @Setter @@ -107,7 +107,7 @@ public class Dhis2Objects { @JsonProperty private List periodTypes = new ArrayList<>(); @JsonProperty private List users = new ArrayList<>(); - + @JsonProperty private List visualizations = new ArrayList<>(); @JsonProperty private List validationRules = new ArrayList<>(); diff --git a/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java b/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java index 9ab00fec..b609aa35 100644 --- a/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java +++ b/src/test/java/org/hisp/dhis/CompleteDataSetRegistrationApiTest.java @@ -32,6 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; + import java.util.List; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistration; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistrationImportOptions; diff --git a/src/test/java/org/hisp/dhis/ProgramApiTest.java b/src/test/java/org/hisp/dhis/ProgramApiTest.java index 2cba9082..469e836d 100644 --- a/src/test/java/org/hisp/dhis/ProgramApiTest.java +++ b/src/test/java/org/hisp/dhis/ProgramApiTest.java @@ -33,6 +33,7 @@ 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; diff --git a/src/test/java/org/hisp/dhis/UserApiTest.java b/src/test/java/org/hisp/dhis/UserApiTest.java index 09a99c7f..237cb678 100644 --- a/src/test/java/org/hisp/dhis/UserApiTest.java +++ b/src/test/java/org/hisp/dhis/UserApiTest.java @@ -1,8 +1,36 @@ +/* + * 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; 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.OrgUnit; import org.hisp.dhis.model.user.User; @@ -17,9 +45,9 @@ class UserApiTest { @Test void testGetUser() { Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); - + User user = dhis2.getUser("xE7jOejl9FI"); - + assertNotNull(user); assertEquals("xE7jOejl9FI", user.getId()); assertEquals("John Traore", user.getName()); @@ -28,9 +56,9 @@ void testGetUser() { assertEquals("Traore", user.getSurname()); assertEquals("dummy@dhis2.org", user.getEmail()); assertFalse(user.getOrganisationUnits().isEmpty()); - + OrgUnit orgUnit = user.getOrganisationUnits().get(0); - + assertNotNull(orgUnit); assertNotNull(orgUnit.getId()); assertNotNull(orgUnit.getName()); @@ -39,24 +67,24 @@ void testGetUser() { @Test void testGetUserByUsername() { Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); - + List users = dhis2.getUsers(Query.instance().addFilter(Filter.eq("username", "admin"))); - + assertNotNull(users); assertEquals(1, users.size()); - + User user = users.get(0); assertNotNull(user); - assertEquals("xE7jOejl9FI", user.getId()); + assertEquals("xE7jOejl9FI", user.getId()); } - + @Test void testGetUsers() { Dhis2 dhis2 = new Dhis2(TestFixture.DEFAULT_CONFIG); - + List users = dhis2.getUsers(Query.instance()); - + assertNotNull(users); assertFalse(users.isEmpty()); } From c46e95444dc17f743a13f0cfe6ef76d32e551467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Thu, 8 May 2025 20:35:20 +0200 Subject: [PATCH 17/17] fix: Update code --- README.md | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e02cd8e0..3c8b6a3a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# DHIS 2 Java Client +# DHIS2 Java Client -DHIS 2 API client for Java. The client allows you to create, update and retrieve information from DHIS 2. The client is compatible with Java 17 and later JDK versions. +DHIS2 API client for Java. The client allows you to create, update and retrieve information from DHIS2. The client is compatible with Java 17 and later JDK versions. ## Getting started @@ -22,7 +22,7 @@ This section describes configuration and authentication of the client. #### Basic authentication -A minimal configuration of `dhis2-java-client` where the configuration parameters refer to the base URL, username and password for the DHIS 2 instance to connect to can be specified like this. The default authentication mechanism is *Basic authentication*. Note that you should *not* include the `api` part nor a trailing `/` in the base URL: +A minimal configuration of `dhis2-java-client` where the configuration parameters refer to the base URL, username and password for the DHIS2 instance to connect to can be specified like this. The default authentication mechanism is *Basic authentication*. Note that you should *not* include the `api` part nor a trailing `/` in the base URL: ```java Dhis2Config config = new Dhis2Config( @@ -32,7 +32,7 @@ Dhis2Config config = new Dhis2Config( Dhis2 dhis2 = new Dhis2(config); ``` -Alternatively, to use Basic authentication you can specify the username and password of the DHIS 2 account together with the base URL of the DHIS 2 instance: +Alternatively, to use Basic authentication you can specify the username and password of the DHIS2 account together with the base URL of the DHIS2 instance: ```java Dhis2 dhis2 = Dhis2.withBasicAuth( @@ -40,7 +40,7 @@ Dhis2 dhis2 = Dhis2.withBasicAuth( "admin", "district"); ``` -You can use the username and password of a regular DHIS 2 user account. +You can use the username and password of a regular DHIS2 user account. ### Personal access token authentication @@ -64,7 +64,7 @@ Dhis2 dhis2 = Dhis2.withCookieAuth( "5EC557E60D7E5CE8D78EEC1389592D3E"); ``` -The name of the session cookie used by the DHIS 2 API is `JSESSIONID`. The value can typically be retrieved from the `Cookie` HTTP request header sent with DHIS 2 API requests. +The name of the session cookie used by the DHIS2 API is `JSESSIONID`. The value can typically be retrieved from the `Cookie` HTTP request header sent with DHIS2 API requests. ### Get current user @@ -87,7 +87,7 @@ List authorities = dhis2.getUserAuthorization(); ## Metadata -This section explains operations for DHIS 2 metadata objects. +This section explains operations for DHIS2 metadata objects. ### Query objects @@ -195,9 +195,28 @@ boolean success = response.getHttpStatus().is2xxSuccessful(); String message = response.getMessage(); ``` +## Users + +This section explains operations for DHIS2 users. + +### Get user + +To get a user by ID. + +```java +User user = dhis2.getUser("xE7jOejl9FI"); +``` + +To get a user by username. + +```java +List users = dhis2.getUsers(Query.instance() + .addFilter(Filter.eq("username", "admin"))); +``` + ## System settings -This section explains operations for DHIS 2 system settings. +This section explains operations for DHIS2 system settings. ### Get system settings @@ -209,7 +228,7 @@ SystemSettings settings = dhis2.getSystemSettings(); ## Events -This section explains operations for DHIS 2 events. +This section explains operations for DHIS2 events. ### Save events @@ -255,7 +274,7 @@ EventResponse response = dhis2.removeEvent(event); ## Data values -This section explains operations for DHIS 2 data values. +This section explains operations for DHIS2 data values. ### Save data value set @@ -459,7 +478,7 @@ List notifications = dhis2 ## Development -This section covers development of the DHIS 2 Java client. +This section covers development of the DHIS2 Java client. Package: