From e5d13410832c7f2bafd66355e6e30b586c1791b3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 22:46:04 +0000 Subject: [PATCH 1/4] Initial plan From dc02da49467335b1028d7389c01ed8305cc9c3d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 22:50:19 +0000 Subject: [PATCH 2/4] Fix Java version incompatibility (25 -> 17) Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cf2ade43..55d401ff 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ learning.dev xAPI Build https://github.com/BerryCloud/xapi-java - 25 + 17 0.8.14 3.5.0 10.6.0 From ceed9ea23862c1708a93869fa47c2269f1e1f174 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 22:54:32 +0000 Subject: [PATCH 3/4] Optimize performance: cache Locale objects, EmailValidator, and improve hex conversion Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com> --- .../xapi/client/StatementHttpMessageWriter.java | 11 ++++++++--- .../java/dev/learning/xapi/model/Attachment.java | 9 ++++----- .../java/dev/learning/xapi/model/LanguageMap.java | 15 ++++++++++----- .../internal/validators/MboxValidator.java | 10 ++++++---- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java b/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java index 2969fe99..71fc305e 100644 --- a/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java +++ b/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java @@ -188,10 +188,15 @@ private List getParts(Object object) { */ private Stream getRealAttachments(Statement statement) { + Stream stream; + // handle the rare scenario when a sub-statement has an attachment - var stream = statement.getObject() instanceof final SubStatement substatement - && substatement.getAttachments() != null ? substatement.getAttachments().stream() - : Stream.empty(); + if (statement.getObject() instanceof final SubStatement substatement + && substatement.getAttachments() != null) { + stream = substatement.getAttachments().stream(); + } else { + stream = Stream.empty(); + } if (statement.getAttachments() != null) { stream = Stream.concat(stream, statement.getAttachments().stream()); diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java b/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java index dcca1fdf..0a831db3 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java @@ -210,11 +210,10 @@ private static String sha256Hex(byte[] data) { final var hash = digest.digest(data); final var hexString = new StringBuilder(2 * hash.length); for (final byte element : hash) { - final var hex = Integer.toHexString(0xff & element); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); + // Use bitwise operations to avoid string allocation per byte + final int value = 0xff & element; + hexString.append(Character.forDigit(value >>> 4, 16)); + hexString.append(Character.forDigit(value & 0x0f, 16)); } return hexString.toString(); } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java b/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java index 5db5af6f..b94824a7 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java @@ -26,6 +26,11 @@ public class LanguageMap extends LinkedHashMap { private static final long serialVersionUID = 7375610804995032187L; + /** + * Cached undefined locale instance to avoid repeated object creation. + */ + private static final Locale UNDEFINED_LOCALE = new Locale("und"); + /** * Constructs an empty LanguageMap. */ @@ -49,7 +54,7 @@ public LanguageMap(Map languageMap) { * @param value to be added with the undefined locale as a key */ public void put(String value) { - this.put(new Locale("und"), value); + this.put(UNDEFINED_LOCALE, value); } /** @@ -83,15 +88,15 @@ public String get(List languageRanges) { } // Otherwise return UND - final var und = get(new Locale("und")); + final var und = get(UNDEFINED_LOCALE); if (und != null) { return und; } // Otherwise return first - final var first = keySet().stream().findFirst(); - if (first.isPresent()) { - return get(first.get()); + final var iterator = keySet().iterator(); + if (iterator.hasNext()) { + return get(iterator.next()); } // Map must be empty diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java index 907866d4..bb246a33 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java @@ -21,12 +21,14 @@ public class MboxValidator extends DisableableValidator { public static final String PREFIX = "mailto:"; - EmailValidator emailValidator; + /** + * Cached email validator instance to avoid repeated object creation. + */ + private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator(); @Override public void initialize(Mbox mbox) { - - emailValidator = new EmailValidator(); + // No initialization needed - using static validator } @Override @@ -36,7 +38,7 @@ public boolean isValidIfEnabled(String value, ConstraintValidatorContext context } return value.startsWith(PREFIX) - && emailValidator.isValid(value.substring(PREFIX.length()), context); + && EMAIL_VALIDATOR.isValid(value.substring(PREFIX.length()), context); } } From d3dfa9409a396cd74e81a23d0679986a0202a7f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 00:51:45 +0000 Subject: [PATCH 4/4] Revert Java version change as requested (back to 25) Co-authored-by: thomasturrell <1552612+thomasturrell@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 55d401ff..cf2ade43 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ learning.dev xAPI Build https://github.com/BerryCloud/xapi-java - 17 + 25 0.8.14 3.5.0 10.6.0