From f23baf8128a6859d78c96e807ff2b614ee725374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Wed, 16 Apr 2025 10:36:28 +0200 Subject: [PATCH 01/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index f6df815c..12f1cd69 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -71,20 +71,19 @@ public static boolean isValidUid(String code) { /** * Generates a pseudo random string with alphanumeric characters. * - * @param codeSize the number of characters in the code. + * @param length the number of characters in the code. * @return the code. */ - public static String generateCode(int codeSize) { - ThreadLocalRandom r = ThreadLocalRandom.current(); + public static String generateCode(int length) { + ThreadLocalRandom rand = ThreadLocalRandom.current(); - char[] randomChars = new char[codeSize]; + char[] randomChars = new char[length]; - // First char should be a letter + // First char must be a letter + randomChars[0] = ALPHABET.charAt(rand.nextInt(ALPHABET.length())); - randomChars[0] = ALPHABET.charAt(r.nextInt(ALPHABET.length())); - - for (int i = 1; i < codeSize; ++i) { - randomChars[i] = ALLOWED_CHARS.charAt(r.nextInt(CHAR_LENGTH)); + for (int i = 1; i < length; ++i) { + randomChars[i] = ALLOWED_CHARS.charAt(rand.nextInt(CHAR_LENGTH)); } return new String(randomChars); From 24bc834deb1f2fe1793c50c222767143f17edfed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Wed, 16 Apr 2025 10:43:19 +0200 Subject: [PATCH 02/14] fix: Update code --- .../java/org/hisp/dhis/util/UidUtils.java | 74 ++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index 12f1cd69..66b6557e 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -27,6 +27,10 @@ */ package org.hisp.dhis.util; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; import lombok.AccessLevel; @@ -44,7 +48,7 @@ public class UidUtils { private static final Pattern UID_PATTERN = Pattern.compile("^[a-zA-Z]{1}[a-zA-Z0-9]{10}$"); /** - * Generates a UID according to the following rules. + * Generates a DHIS2 UID according to the following rules. * * * - * @return a UID string. + * @return a DHIS2 UID string. */ public static String generateUid() { return generateCode(UID_LENGTH); @@ -88,4 +92,70 @@ public static String generateCode(int length) { return new String(randomChars); } + + /** + * Generates a DHIS2 UID from an input string. The algorithm is deterministic and minimizes risk + * of collisions. + * + * @param input the input string. + * @return a DHIS2 UID. Returns null if the input is invalid. Returns an empty string if the input + * string is empty. + */ + public static String generateDHIS2UID(String input) { + if (input == null) { + return null; + } + if (input.isEmpty()) { + return ""; + } + + if (input.length() < 20 || input.length() > 40) { + throw new IllegalArgumentException("Input string must be between 20 and 40 characters long."); + } + + try { + // Hash input string using SHA-256 + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + + // Convert hash to a BigInteger. + BigInteger bigInteger = new BigInteger(1, hashBytes); + + // Convert BigInteger to Base62 + String base62 = fromBigInteger(bigInteger, ALPHABET, UID_LENGTH); + + // Ensure the UID starts with a letter + if (Character.isDigit(base62.charAt(0))) { + // If first character is a digit, shift Base62 string by one character + // Move first char to the end and append 'A' + base62 = base62.substring(1) + ALPHABET.charAt(0); + } + return base62; + + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException("SHA-256 algorithm not found", ex); + } + } + + /** + * Converts a BigInteger to a Base62 string of a specified length. + * + * @param value the BigInteger to convert. + * @param alphabet the Base62 alphabet. + * @param length the desired length of the Base62 string. + * @return a Base62 string of the specified length. + */ + private static String fromBigInteger(BigInteger value, String alphabet, int length) { + StringBuilder sb = new StringBuilder(); + BigInteger base = BigInteger.valueOf(alphabet.length()); + + for (int i = 0; i < length; i++) { + BigInteger[] qr = value.divideAndRemainder(base); + value = qr[0]; + BigInteger remainder = qr[1]; + sb.insert(0, alphabet.charAt(remainder.intValue())); + } + + return sb.toString(); + } } From 4f474b0fe6b2800c04a7e50471ceed1c29d97d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 10:57:04 +0200 Subject: [PATCH 03/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index e1639b4a..c2245522 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -119,7 +119,7 @@ public static String generateDHIS2UID(String input) { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8)); - // Convert hash to a BigInteger. + // Convert hash to a BigInteger BigInteger bigInteger = new BigInteger(1, hashBytes); // Convert BigInteger to Base62 From 1718a8ccf3408f0cac5d2ea2c68595de1af32578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 10:57:56 +0200 Subject: [PATCH 04/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 5 ++--- 1 file changed, 2 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 c2245522..a2bcc275 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -99,8 +99,7 @@ public static String generateCode(int length) { * of collisions. * * @param input the input string. - * @return a DHIS2 UID. Returns null if the input is invalid. Returns an empty string if the input - * string is empty. + * @return a DHIS2 UID. Returns null if the input is invalid, empty string if input is empty. */ public static String generateDHIS2UID(String input) { if (input == null) { @@ -111,7 +110,7 @@ public static String generateDHIS2UID(String input) { } if (input.length() < 20 || input.length() > 40) { - throw new IllegalArgumentException("Input string must be between 20 and 40 characters long."); + throw new IllegalArgumentException("Input string must be between 20 and 40 characters long"); } try { From a45125fd36801ca09b62cd67017adba77470645a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 10:58:24 +0200 Subject: [PATCH 05/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index a2bcc275..87af7212 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -35,6 +35,7 @@ import java.util.regex.Pattern; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; /** Utilities for UID. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -106,7 +107,7 @@ public static String generateDHIS2UID(String input) { return null; } if (input.isEmpty()) { - return ""; + return StringUtils.EMPTY; } if (input.length() < 20 || input.length() > 40) { From 49b6f70610ad92ef1e977d4d129e033993394788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 11:30:22 +0200 Subject: [PATCH 06/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index 87af7212..3324a64b 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -110,8 +110,8 @@ public static String generateDHIS2UID(String input) { return StringUtils.EMPTY; } - if (input.length() < 20 || input.length() > 40) { - throw new IllegalArgumentException("Input string must be between 20 and 40 characters long"); + if (input.length() < 3 || input.length() > 1024) { + throw new IllegalArgumentException("Input string must be between 3 and 1024 characters long"); } try { From 9e9e1dd499f74e52372d24bd079dd27d6e55a0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 11:35:53 +0200 Subject: [PATCH 07/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 6 +++--- src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index 3324a64b..5c4c7924 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -33,11 +33,11 @@ import java.security.NoSuchAlgorithmException; import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; -/** Utilities for UID. */ +/** Utilities for DHIS2 UID generation. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class UidUtils { private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -102,7 +102,7 @@ public static String generateCode(int length) { * @param input the input string. * @return a DHIS2 UID. Returns null if the input is invalid, empty string if input is empty. */ - public static String generateDHIS2UID(String input) { + public static String toUid(String input) { if (input == null) { return null; } diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 392214c9..7546699b 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -31,7 +31,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; - import org.hisp.dhis.support.TestTags; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -56,4 +55,9 @@ void testUidIsValid() { assertFalse(UidUtils.isValidUid("QX4LpiTZmUHg")); assertFalse(UidUtils.isValidUid("1T1hdS_WjfD")); } + + @Test + void testToUid() { + UidUtils.toUid(""); + } } From 67d6a7c4deba10a6a88f420acec60c105c9c1758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:20:01 +0200 Subject: [PATCH 08/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 6 +++--- .../java/org/hisp/dhis/util/UidUtilsTest.java | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index 5c4c7924..ddd4fc35 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -33,9 +33,9 @@ import java.security.NoSuchAlgorithmException; import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; -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) @@ -127,8 +127,8 @@ public static String toUid(String input) { // Ensure the UID starts with a letter if (Character.isDigit(base62.charAt(0))) { - // If first character is a digit, shift Base62 string by one character - // Move first char to the end and append 'A' + // If first character is a digit, shift Base62 string by one character by moving first char + // to the end and append 'A' base62 = base62.substring(1) + ALPHABET.charAt(0); } return base62; diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 7546699b..181698a1 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; + import org.hisp.dhis.support.TestTags; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -58,6 +59,21 @@ void testUidIsValid() { @Test void testToUid() { - UidUtils.toUid(""); + assertToUid("PpZ!m3thN#sm8QVcOdwTcil4"); + assertToUid("5$tiq7K9zMmUX$9VFXaQLFK6d&ShHQUw"); + assertToUid("9ceyjK4b^Xoc0&lKCn0Bqz5xAsYz&$heWypB"); + assertToUid("B5*GfX&Yklr!OHIK1KdaGeXGUt97U4hTAE*bA**ce7@#oO2lB^0Rs9E#G8sJe"); + assertToUid("!OGvawSH8fKIUtIpVl$9^TfMV%V08vHm%uDeT1hnh6d22q7OQSjS7csF05bFRATeUIN&8wX2"); + assertToUid("yjZ2ec#*s9RMpmt^svZN8LyBJUOt&mY8&7nHZ3u%13^ObekBDA!a8ov&enxPE$EuE$GPh1xiy6parm"); + } + + /** + * Asserts that the method generates a valid UID based on the given identifier. + * + * @param uid + */ + private void assertToUid(String id) { + String msg = String.format("UID not valid: '%s'", id); + assertTrue(UidUtils.isValidUid(UidUtils.toUid(id)), msg); } } From fa1252de1d6649a4b4f4bc308e5fbb31882bb3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:44:42 +0200 Subject: [PATCH 09/14] fix: Update code --- .../java/org/hisp/dhis/util/UidUtils.java | 8 +++---- .../java/org/hisp/dhis/util/UidUtilsTest.java | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index ddd4fc35..a09109f9 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -97,20 +97,20 @@ public static String generateCode(int length) { /** * Generates a DHIS2 UID from an input string. The algorithm is deterministic and minimizes risk - * of collisions. + * of collisions. The input must be between 2 and 1024 characters long. * * @param input the input string. - * @return a DHIS2 UID. Returns null if the input is invalid, empty string if input is empty. + * @return a DHIS2 UID. Returns null if the input is invalid, empty string if input is blank. */ public static String toUid(String input) { if (input == null) { return null; } - if (input.isEmpty()) { + if (input.isBlank()) { return StringUtils.EMPTY; } - if (input.length() < 3 || input.length() > 1024) { + if (input.length() < 2 || input.length() > 1024) { throw new IllegalArgumentException("Input string must be between 3 and 1024 characters long"); } diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 181698a1..02b59f73 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -30,8 +30,10 @@ 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 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; import org.junit.jupiter.api.Test; @@ -67,6 +69,26 @@ void testToUid() { assertToUid("yjZ2ec#*s9RMpmt^svZN8LyBJUOt&mY8&7nHZ3u%13^ObekBDA!a8ov&enxPE$EuE$GPh1xiy6parm"); } + @Test + void testToUidNullAndBlank() { + assertNull(UidUtils.toUid(null)); + assertEquals("", UidUtils.toUid(" ")); + assertEquals("", UidUtils.toUid("")); + } + + @Test + void testToDeterminisism() { + String input = UidUtils.toUid("fDv!oHopG7F8asPsvAU8c3MK8$#H7iwW"); + String output = "WpFckPBZBnO"; + + IntStream.of(10) + .forEach( + i -> { + String msg = String.format("Index: %d, input: '%s', output: '%s'", i, input, output); + assertEquals(output, UidUtils.toUid(input), msg); + }); + } + /** * Asserts that the method generates a valid UID based on the given identifier. * From 92c40e02168a342e0683e7105d0e83eea8d47043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:46:12 +0200 Subject: [PATCH 10/14] fix: Update code --- src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index 02b59f73..b6e335de 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -94,8 +94,9 @@ void testToDeterminisism() { * * @param uid */ - private void assertToUid(String id) { - String msg = String.format("UID not valid: '%s'", id); - assertTrue(UidUtils.isValidUid(UidUtils.toUid(id)), msg); + private void assertToUid(String input) { + String output = UidUtils.toUid(input); + String msg = String.format("Output: '%s' not valid for input: '%s'", output, input); + assertTrue(UidUtils.isValidUid(output), msg); } } From c990bea9fafcc83ef8bfc2941f8b19f893cc70af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:47:09 +0200 Subject: [PATCH 11/14] fix: Update code --- src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index b6e335de..e8463733 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -81,7 +81,7 @@ void testToDeterminisism() { String input = UidUtils.toUid("fDv!oHopG7F8asPsvAU8c3MK8$#H7iwW"); String output = "WpFckPBZBnO"; - IntStream.of(10) + IntStream.range(0, 10) .forEach( i -> { String msg = String.format("Index: %d, input: '%s', output: '%s'", i, input, output); From a57c3a95be769e1999a569f7124a754dd63044b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:48:27 +0200 Subject: [PATCH 12/14] fix: Update code --- src/test/java/org/hisp/dhis/util/UidUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java index e8463733..5f249fa3 100644 --- a/src/test/java/org/hisp/dhis/util/UidUtilsTest.java +++ b/src/test/java/org/hisp/dhis/util/UidUtilsTest.java @@ -77,7 +77,7 @@ void testToUidNullAndBlank() { } @Test - void testToDeterminisism() { + void testToUidDeterminisism() { String input = UidUtils.toUid("fDv!oHopG7F8asPsvAU8c3MK8$#H7iwW"); String output = "WpFckPBZBnO"; From 37e3f8942c1c5e8c9b71fbb271471153e08154ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:51:50 +0200 Subject: [PATCH 13/14] fix: Update code --- src/main/java/org/hisp/dhis/util/UidUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/hisp/dhis/util/UidUtils.java b/src/main/java/org/hisp/dhis/util/UidUtils.java index a09109f9..f907663a 100644 --- a/src/main/java/org/hisp/dhis/util/UidUtils.java +++ b/src/main/java/org/hisp/dhis/util/UidUtils.java @@ -134,7 +134,7 @@ public static String toUid(String input) { return base62; } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException("SHA-256 algorithm not found", ex); + throw new IllegalArgumentException("SHA-256 algorithm not found", ex); } } From 02787b476ef96e6502f2b4e908abcf6afbaa6076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Helge=20=C3=98verland?= Date: Fri, 2 May 2025 12:53:36 +0200 Subject: [PATCH 14/14] fix: Update code --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f8f60b21..e9710bee 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.hisp dhis2-java-client - 2.1.8 + 2.1.9-SNAPSHOT jar DHIS 2 API client for Java