From 9acbac9f53cdf2efdf5ad516306da62804c8feb6 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Tue, 14 Mar 2023 15:22:50 +0000
Subject: [PATCH 01/34] Add validators
---
pom.xml | 4 +-
xapi-model/pom.xml | 8 ++--
.../java/dev/learning/xapi/model/Score.java | 17 -------
.../java/dev/learning/xapi/model/Verb.java | 2 +
.../validation/constraints/HasScheme.java | 45 +++++++++++++++++++
.../validators/HasSchemeValidatorForUri.java | 25 +++++++++++
6 files changed, 78 insertions(+), 23 deletions(-)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java
diff --git a/pom.xml b/pom.xml
index 8492f437..dcacde67 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,7 +79,7 @@
xapi-model
xapi-client
- samples
+ samples
@@ -266,7 +266,7 @@
dev.learning.xapi
xapi-client
1.0.9-SNAPSHOT
-
+
diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml
index 4c32faac..0960e432 100644
--- a/xapi-model/pom.xml
+++ b/xapi-model/pom.xml
@@ -10,10 +10,6 @@
xAPI Model
learning.dev xAPI Model
-
- org.springframework.boot
- spring-boot-starter-validation
-
com.fasterxml.jackson.core
jackson-databind
@@ -27,6 +23,10 @@
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
+
+ jakarta.validation
+ jakarta.validation-api
+
org.springframework.boot
spring-boot-starter-test
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Score.java b/xapi-model/src/main/java/dev/learning/xapi/model/Score.java
index 267677df..ad4f878b 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Score.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Score.java
@@ -8,7 +8,6 @@
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import lombok.Builder;
import lombok.Value;
-import org.springframework.util.Assert;
/**
* This class represents the xAPI Score object.
@@ -51,22 +50,6 @@ public class Score {
*/
public static class Builder {
- protected Float scaled;
-
- /**
- * Sets the scaled score.
- *
- * @param scaled The scaled score.
- *
- * @return This builder
- */
- public Builder scaled(Float scaled) {
- Assert.isTrue(scaled == null || (scaled >= -1.0 && scaled <= 1.0),
- "Scaled score vaule must be between -1.0 and 1.0");
- this.scaled = scaled;
- return this;
- }
-
// This static class extends the lombok builder.
}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Verb.java b/xapi-model/src/main/java/dev/learning/xapi/model/Verb.java
index 8cd20038..8adbeb31 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Verb.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Verb.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.HasScheme;
import jakarta.validation.constraints.NotNull;
import java.net.URI;
import java.util.Locale;
@@ -342,6 +343,7 @@ public class Verb {
* not the word.
*/
@NotNull
+ @HasScheme
private URI id;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java
new file mode 100644
index 00000000..89d0f189
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must have a scheme.
+ *
+ * @author Thomas Turrell-Croft
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+public @interface HasScheme {
+
+ /**
+ * Error Message.
+ */
+ String message() default "must have a scheme";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+ boolean schemaRequired() default false;
+
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java
new file mode 100644
index 00000000..1ca38811
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.validation.constraints.HasScheme;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import java.net.URI;
+
+public class HasSchemeValidatorForUri implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(URI value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ return value.getScheme() != null;
+
+ }
+
+}
From 698f050a96f309ddffeeb135db26405ca0e1f4e0 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Tue, 14 Mar 2023 17:30:42 +0000
Subject: [PATCH 02/34] tip
---
samples/xapi-server/pom.xml | 7 ++++++-
xapi-model/pom.xml | 2 +-
.../src/main/java/dev/learning/xapi/model/About.java | 3 ++-
.../dev/learning/xapi/model/ActivityDefinition.java | 3 ++-
.../src/main/java/dev/learning/xapi/model/Context.java | 3 ++-
.../src/main/java/dev/learning/xapi/model/Result.java | 3 ++-
.../main/java/dev/learning/xapi/model/Statement.java | 6 ++++++
.../xapi/model/validation/constraints/HasScheme.java | 10 ++++++----
.../internal/validators/HasSchemeValidatorForUri.java | 5 +++++
.../services/jakarta.validation.ConstraintValidator | 1 +
10 files changed, 33 insertions(+), 10 deletions(-)
create mode 100644 xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
diff --git a/samples/xapi-server/pom.xml b/samples/xapi-server/pom.xml
index e9002673..eca14f48 100644
--- a/samples/xapi-server/pom.xml
+++ b/samples/xapi-server/pom.xml
@@ -13,7 +13,12 @@
org.springframework.boot
spring-boot-starter-web
-
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
dev.learning.xapi
xapi-model
diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml
index 0960e432..ca190d1d 100644
--- a/xapi-model/pom.xml
+++ b/xapi-model/pom.xml
@@ -26,7 +26,7 @@
jakarta.validation
jakarta.validation-api
-
+
org.springframework.boot
spring-boot-starter-test
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/About.java b/xapi-model/src/main/java/dev/learning/xapi/model/About.java
index f73a02ab..2765b44a 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/About.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/About.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.HasScheme;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
@@ -29,7 +30,7 @@ public class About {
private List version;
- private LinkedHashMap extensions;
+ private LinkedHashMap<@HasScheme URI, Object> extensions;
// **Warning** do not add fields that are not required by the xAPI specification.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/ActivityDefinition.java b/xapi-model/src/main/java/dev/learning/xapi/model/ActivityDefinition.java
index ec9c9d49..a0f67459 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/ActivityDefinition.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/ActivityDefinition.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.HasScheme;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@@ -89,7 +90,7 @@ public class ActivityDefinition {
/**
* A map of other properties as needed.
*/
- private Map extensions;
+ private Map<@HasScheme URI, Object> extensions;
// **Warning** do not add fields that are not required by the xAPI specification.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
index eaf903e6..33e0bea0 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.HasScheme;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.LinkedHashMap;
@@ -76,7 +77,7 @@ public class Context {
/**
* A map of any other domain-specific context relevant to this Statement.
*/
- private LinkedHashMap extensions;
+ private LinkedHashMap<@HasScheme URI, Object> extensions;
// **Warning** do not add fields that are not required by the xAPI specification.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Result.java b/xapi-model/src/main/java/dev/learning/xapi/model/Result.java
index 0f9d5a89..aef4516b 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Result.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Result.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.HasScheme;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Pattern;
import java.net.URI;
@@ -58,7 +59,7 @@ public class Result {
message = "Must be a valid ISO 8601:2004 duration format.")
private String duration;
- private LinkedHashMap extensions;
+ private LinkedHashMap<@HasScheme URI, Object> extensions;
// **Warning** do not add fields that are not required by the xAPI specification.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index b989554a..0dd26cb1 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -8,6 +8,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import java.time.Instant;
@@ -46,28 +47,33 @@ public class Statement {
* Whom the Statement is about, as an Agent or Group Object.
*/
@NotNull
+ @Valid
private Actor actor;
/**
* Action taken by the Actor.
*/
@NotNull
+ @Valid
private Verb verb;
/**
* Activity, Agent, or another Statement that is the Object of the Statement.
*/
@NotNull
+ @Valid
private StatementObject object;
/**
* Result Object, further details representing a measured outcome.
*/
+ @Valid
private Result result;
/**
* Context that gives the Statement more meaning.
*/
+ @Valid
private Context context;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java
index 89d0f189..4f9a2733 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/HasScheme.java
@@ -4,9 +4,14 @@
package dev.learning.xapi.model.validation.constraints;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
@@ -20,7 +25,7 @@
*/
@Documented
@Constraint(validatedBy = {})
-@Target({METHOD, FIELD})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface HasScheme {
@@ -39,7 +44,4 @@
*/
Class extends Payload>[] payload() default {};
- boolean schemaRequired() default false;
-
-
}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java
index 1ca38811..9ead1319 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUri.java
@@ -9,6 +9,11 @@
import jakarta.validation.ConstraintValidatorContext;
import java.net.URI;
+/**
+ * The URI being validated must have a schema.
+ *
+ * @author Thomas Turrell-Croft
+ */
public class HasSchemeValidatorForUri implements ConstraintValidator {
@Override
diff --git a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
new file mode 100644
index 00000000..cdc68d5f
--- /dev/null
+++ b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
@@ -0,0 +1 @@
+ dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri
\ No newline at end of file
From be2d94960281a1334a1a1740ba0cad7239608f0d Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Tue, 14 Mar 2023 20:35:09 +0000
Subject: [PATCH 03/34] tip
---
.../learning/xapi/model/ActivityState.java | 2 +
.../java/dev/learning/xapi/model/Context.java | 2 +
.../dev/learning/xapi/model/Statement.java | 2 +
.../xapi/model/StatementReference.java | 2 +
.../model/validation/constraints/Variant.java | 53 +++++++++++++++++++
.../validators/VariantValidatorForUuid.java | 38 +++++++++++++
.../jakarta.validation.ConstraintValidator | 3 +-
7 files changed, 101 insertions(+), 1 deletion(-)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java b/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java
index 3a91c547..8d4ee606 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import java.util.UUID;
import lombok.Builder;
@@ -32,6 +33,7 @@ public class ActivityState {
@Valid
private Agent agent;
+ @Variant(2)
private UUID registration;
private ObjectNode state;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
index 33e0bea0..a64d7e85 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.HasScheme;
+import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.LinkedHashMap;
@@ -32,6 +33,7 @@ public class Context {
/**
* The registration that the Statement is associated with.
*/
+ @Variant(2)
private UUID registration;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index 0dd26cb1..775aa554 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -8,6 +8,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
@@ -41,6 +42,7 @@ public class Statement {
/**
* UUID assigned by LRS if not set by the Learning Record Provider.
*/
+ @Variant(2)
private UUID id;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/StatementReference.java b/xapi-model/src/main/java/dev/learning/xapi/model/StatementReference.java
index ebe4b071..2499e688 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/StatementReference.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/StatementReference.java
@@ -4,6 +4,7 @@
package dev.learning.xapi.model;
+import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.constraints.NotNull;
import java.util.UUID;
import lombok.Builder;
@@ -25,6 +26,7 @@ public class StatementReference implements StatementObject, SubStatementObject {
/**
* The UUID of a Statement.
*/
+ @Variant(2)
@NotNull
private UUID id;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
new file mode 100644
index 00000000..eba167f1
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must have a scheme.
+ *
+ * @author Thomas Turrell-Croft
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+public @interface Variant {
+
+ /**
+ * Error Message.
+ */
+ String message() default "variant must be {variant}";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+ /**
+ * The valid variant, defaults to 2.
+ */
+ int value() default 2;
+
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
new file mode 100644
index 00000000..71fa37b3
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.validation.constraints.Variant;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import java.util.UUID;
+
+/**
+ * The UUID being validated must have the specified variant.
+ *
+ * @author Thomas Turrell-Croft
+ */
+public class VariantValidatorForUuid implements ConstraintValidator {
+
+ private int variant;
+
+ @Override
+ public void initialize(Variant constraintAnnotation) {
+
+ variant = constraintAnnotation.value();
+ }
+
+ @Override
+ public boolean isValid(UUID value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ return value.variant() == variant;
+
+ }
+
+}
diff --git a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
index cdc68d5f..6f307c80 100644
--- a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
+++ b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
@@ -1 +1,2 @@
- dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri
\ No newline at end of file
+dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri
+dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid
\ No newline at end of file
From c4dd79c6f29821ea5b11fe9d44417054a3ce4f65 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Tue, 14 Mar 2023 22:30:54 +0000
Subject: [PATCH 04/34] tip
---
xapi-model/pom.xml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml
index ca190d1d..26cb0af9 100644
--- a/xapi-model/pom.xml
+++ b/xapi-model/pom.xml
@@ -32,6 +32,11 @@
spring-boot-starter-test
test
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ test
+
From 9a67a6efd656f660d75dbb0146bba6a8a29d6c37 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Wed, 15 Mar 2023 00:20:01 +0000
Subject: [PATCH 05/34] Apply suggestions from code review
---
xapi-model/src/main/java/dev/learning/xapi/model/About.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/About.java b/xapi-model/src/main/java/dev/learning/xapi/model/About.java
index 2765b44a..f73a02ab 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/About.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/About.java
@@ -6,7 +6,6 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
-import dev.learning.xapi.model.validation.constraints.HasScheme;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
@@ -30,7 +29,7 @@ public class About {
private List version;
- private LinkedHashMap<@HasScheme URI, Object> extensions;
+ private LinkedHashMap extensions;
// **Warning** do not add fields that are not required by the xAPI specification.
From fd10bdf207058872d9e01b76f467550e87b2709f Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Wed, 15 Mar 2023 10:13:03 +0000
Subject: [PATCH 06/34] tip
---
.../learning/xapi/model/validation/constraints/Variant.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
index eba167f1..a288cb9a 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
@@ -11,7 +11,6 @@
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
@@ -19,7 +18,7 @@
import java.lang.annotation.Target;
/**
- * The annotated element must have a scheme.
+ * The annotated UUID must have the specified variant.
*
* @author Thomas Turrell-Croft
*/
From 5cf185ed971f1478e3d9427ffabb2473ec1e631e Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Wed, 15 Mar 2023 15:23:32 +0000
Subject: [PATCH 07/34] tip
---
.../dev/learning/xapi/model/validation/constraints/Variant.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
index a288cb9a..1e561a23 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Variant.java
@@ -11,6 +11,7 @@
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
From 88ef3a2e152c10c1df818febfb244feb53bdf2ef Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Wed, 15 Mar 2023 16:17:45 +0000
Subject: [PATCH 08/34] tip
---
.../dev/learning/xapi/model/Statement.java | 2 +
.../dev/learning/xapi/model/SubStatement.java | 2 +
.../constraints/ValidStatement.java | 44 ++++++++
.../validators/ValidatorForStatement.java | 106 ++++++++++++++++++
.../validators/ValidatorForSubStatement.java | 59 ++++++++++
.../jakarta.validation.ConstraintValidator | 4 +-
.../learning/xapi/model/StatementTests.java | 1 +
7 files changed, 217 insertions(+), 1 deletion(-)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index 775aa554..651feb57 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -8,6 +8,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.ValidStatement;
import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
@@ -37,6 +38,7 @@
@JsonIgnoreProperties("inProgress")
@JsonInclude(Include.NON_EMPTY)
@EqualsAndHashCode(of = {"actor", "verb", "object", "result", "context"})
+@ValidStatement
public class Statement {
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index 176548f5..3229e8c4 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -4,6 +4,7 @@
package dev.learning.xapi.model;
+import dev.learning.xapi.model.validation.constraints.ValidStatement;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.time.Instant;
@@ -24,6 +25,7 @@
@Value
@Builder
@EqualsAndHashCode(exclude = {"timestamp", "attachments"})
+@ValidStatement
public class SubStatement implements StatementObject {
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java
new file mode 100644
index 00000000..8d3843eb
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must be a valid statement.
+ *
+ * @author Thomas Turrell-Croft
+ * @see Statement
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target(TYPE)
+@Retention(RUNTIME)
+public @interface ValidStatement {
+
+ /**
+ * Error Message.
+ */
+ String message() default "must be a valid statement";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
new file mode 100644
index 00000000..4ec25049
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016-2019 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.Activity;
+import dev.learning.xapi.model.Agent;
+import dev.learning.xapi.model.Context;
+import dev.learning.xapi.model.Group;
+import dev.learning.xapi.model.Statement;
+import dev.learning.xapi.model.StatementReference;
+import dev.learning.xapi.model.Verb;
+import dev.learning.xapi.model.validation.constraints.ValidStatement;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The Statement being validated must be valid.
+ */
+public class ValidatorForStatement implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(Statement value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ // Can not happen with annotation target set to type
+ return true;
+ }
+
+ // TODO consider adding conversion logic here
+
+ context.disableDefaultConstraintViolation();
+
+ return isVoidingVerbValid(value, context) && isValidRevision(value, context)
+ && isValidPlatform(value, context) && isValidAuthority(value, context);
+ }
+
+ private boolean isVoidingVerbValid(Statement value, ConstraintValidatorContext context) {
+
+ Verb verb = value.getVerb();
+
+ if (verb == null || !verb.isVoided()
+ || (verb.isVoided() && value.getObject() instanceof StatementReference)) {
+ return true;
+ }
+
+ context
+ .buildConstraintViolationWithTemplate(
+ "invalid voiding statement, object must be of type statement reference")
+ .addConstraintViolation();
+
+ return false;
+ }
+
+ private boolean isValidRevision(Statement value, ConstraintValidatorContext context) {
+
+ Context c = value.getContext();
+
+ if (c == null || c.getRevision() == null || value.getObject() instanceof Activity) {
+ return true;
+ }
+
+ context.buildConstraintViolationWithTemplate(
+ "invalid revision property, object must of type activity").addConstraintViolation();
+
+ return false;
+ }
+
+ private boolean isValidPlatform(Statement value, ConstraintValidatorContext context) {
+
+ Context c = value.getContext();
+
+ if (c == null || c.getPlatform() == null || value.getObject() instanceof Activity) {
+ return true;
+ }
+
+ context.buildConstraintViolationWithTemplate(
+ "invalid platform property, object must be of type activity").addConstraintViolation();
+
+ return false;
+ }
+
+ private boolean isValidAuthority(Statement value, ConstraintValidatorContext context) {
+
+ // can be null or Agent
+ if (value.getAuthority() == null || value.getAuthority() instanceof Agent) {
+ return true;
+ }
+
+ final var group = (Group) value.getAuthority();
+ // ... or must be an anonymous Group with exactly two members
+ if (group.getAccount() == null && group.getMbox() == null && group.getMboxSha1sum() == null
+ && group.getOpenid() == null && group.getMember() != null
+ && group.getMember().size() == 2) {
+ return true;
+
+ }
+
+ context.buildConstraintViolationWithTemplate("invalid authority property")
+ .addConstraintViolation();
+
+ return false;
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
new file mode 100644
index 00000000..92903357
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016-2019 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.Activity;
+import dev.learning.xapi.model.Context;
+import dev.learning.xapi.model.SubStatement;
+import dev.learning.xapi.model.validation.constraints.ValidStatement;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The SubStatement being validated must be valid.
+ */
+public class ValidatorForSubStatement implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(SubStatement value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ context.disableDefaultConstraintViolation();
+
+ return isValidRevision(value, context) && isValidPlatform(value, context);
+ }
+
+ private boolean isValidRevision(SubStatement value, ConstraintValidatorContext context) {
+
+ Context c = value.getContext();
+
+ if (c == null || c.getRevision() == null || value.getObject() instanceof Activity) {
+ return true;
+ }
+
+ context.buildConstraintViolationWithTemplate(
+ "invalid revision property, object must of type activity").addConstraintViolation();
+
+ return false;
+ }
+
+ private boolean isValidPlatform(SubStatement value, ConstraintValidatorContext context) {
+
+ Context c = value.getContext();
+
+ if (c == null || c.getPlatform() == null || value.getObject() instanceof Activity) {
+ return true;
+ }
+
+ context.buildConstraintViolationWithTemplate(
+ "invalid platform property, object must be of type activity").addConstraintViolation();
+
+ return false;
+ }
+
+}
diff --git a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
index 6f307c80..a095133a 100644
--- a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
+++ b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
@@ -1,2 +1,4 @@
dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri
-dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid
\ No newline at end of file
+dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid
+dev.learning.xapi.model.validation.internal.validators.ValidatorForSubStatement
+dev.learning.xapi.model.validation.internal.validators.ValidatorForStatement
\ No newline at end of file
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
index e3fe087b..0fc125f8 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
@@ -8,6 +8,7 @@
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.ConstraintViolation;
From c3f81d9cc1ac230bc210bed8992fce2b6b33b96d Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 00:31:49 +0000
Subject: [PATCH 09/34] tip
---
.../java/dev/learning/xapi/model/Group.java | 6 ++
.../dev/learning/xapi/model/Statement.java | 4 +-
.../dev/learning/xapi/model/SubStatement.java | 2 -
...alidStatement.java => ValidAuthority.java} | 17 ++--
.../validators/AuthorityValidator.java | 40 +++++++++
.../validators/ValidatorForStatement.java | 30 +------
.../validators/ValidatorForSubStatement.java | 4 +-
.../validators/AuthorityValidatorTests.java | 89 +++++++++++++++++++
.../HasSchemeValidatorForUriTests.java | 33 +++++++
9 files changed, 185 insertions(+), 40 deletions(-)
rename xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/{ValidStatement.java => ValidAuthority.java} (52%)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
index 15f61da9..ca384fb6 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
@@ -38,6 +38,12 @@ public class Group extends Actor {
// **Warning** do not add fields that are not required by the xAPI specification.
+ public boolean isAnonymous() {
+
+ return account == null && mbox == null && mboxSha1sum == null && openid == null
+ && member != null && !member.isEmpty();
+ }
+
/**
* Builder for Group.
*/
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index 651feb57..8a16c8c5 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -8,7 +8,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
-import dev.learning.xapi.model.validation.constraints.ValidStatement;
+import dev.learning.xapi.model.validation.constraints.ValidAuthority;
import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
@@ -38,7 +38,6 @@
@JsonIgnoreProperties("inProgress")
@JsonInclude(Include.NON_EMPTY)
@EqualsAndHashCode(of = {"actor", "verb", "object", "result", "context"})
-@ValidStatement
public class Statement {
/**
@@ -93,6 +92,7 @@ public class Statement {
/**
* Agent or Group who is asserting this Statement is true.
*/
+ @ValidAuthority
private Actor authority;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index 3229e8c4..176548f5 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -4,7 +4,6 @@
package dev.learning.xapi.model;
-import dev.learning.xapi.model.validation.constraints.ValidStatement;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.time.Instant;
@@ -25,7 +24,6 @@
@Value
@Builder
@EqualsAndHashCode(exclude = {"timestamp", "attachments"})
-@ValidStatement
public class SubStatement implements StatementObject {
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java
similarity index 52%
rename from xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java
rename to xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java
index 8d3843eb..ef54bf1c 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java
@@ -4,7 +4,12 @@
package dev.learning.xapi.model.validation.constraints;
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import jakarta.validation.Constraint;
@@ -14,22 +19,20 @@
import java.lang.annotation.Target;
/**
- * The annotated element must be a valid statement.
+ * The annotated element must have a scheme.
*
* @author Thomas Turrell-Croft
- * @see Statement
*/
@Documented
@Constraint(validatedBy = {})
-@Target(TYPE)
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
-public @interface ValidStatement {
+public @interface ValidAuthority {
/**
* Error Message.
*/
- String message() default "must be a valid statement";
+ String message() default "must be of type agent or a group with two agents";
/**
* Groups.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
new file mode 100644
index 00000000..5c2fb270
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.Actor;
+import dev.learning.xapi.model.Agent;
+import dev.learning.xapi.model.Group;
+import dev.learning.xapi.model.validation.constraints.ValidAuthority;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The Actor being validated must be null, an agent or an anonymous group with two agents.
+ *
+ * @author István Rátkai (Selindek)
+ * @author Thomas Turrell-Croft
+ */
+public class AuthorityValidator implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(Actor value, ConstraintValidatorContext context) {
+
+ // can be null or Agent
+ if (value == null || value instanceof Agent) {
+ return true;
+ }
+
+ final var group = (Group) value;
+ // ... or must be an anonymous Group with exactly two members
+ if (group.isAnonymous() && group.getMember().size() == 2) {
+ return true;
+ }
+
+ return false;
+
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
index 4ec25049..eff78359 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
@@ -5,20 +5,18 @@
package dev.learning.xapi.model.validation.internal.validators;
import dev.learning.xapi.model.Activity;
-import dev.learning.xapi.model.Agent;
import dev.learning.xapi.model.Context;
-import dev.learning.xapi.model.Group;
import dev.learning.xapi.model.Statement;
import dev.learning.xapi.model.StatementReference;
import dev.learning.xapi.model.Verb;
-import dev.learning.xapi.model.validation.constraints.ValidStatement;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
+import jakarta.validation.Valid;
/**
* The Statement being validated must be valid.
*/
-public class ValidatorForStatement implements ConstraintValidator {
+public class ValidatorForStatement implements ConstraintValidator {
@Override
public boolean isValid(Statement value, ConstraintValidatorContext context) {
@@ -33,7 +31,7 @@ public boolean isValid(Statement value, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
return isVoidingVerbValid(value, context) && isValidRevision(value, context)
- && isValidPlatform(value, context) && isValidAuthority(value, context);
+ && isValidPlatform(value, context);
}
private boolean isVoidingVerbValid(Statement value, ConstraintValidatorContext context) {
@@ -81,26 +79,4 @@ private boolean isValidPlatform(Statement value, ConstraintValidatorContext cont
return false;
}
- private boolean isValidAuthority(Statement value, ConstraintValidatorContext context) {
-
- // can be null or Agent
- if (value.getAuthority() == null || value.getAuthority() instanceof Agent) {
- return true;
- }
-
- final var group = (Group) value.getAuthority();
- // ... or must be an anonymous Group with exactly two members
- if (group.getAccount() == null && group.getMbox() == null && group.getMboxSha1sum() == null
- && group.getOpenid() == null && group.getMember() != null
- && group.getMember().size() == 2) {
- return true;
-
- }
-
- context.buildConstraintViolationWithTemplate("invalid authority property")
- .addConstraintViolation();
-
- return false;
- }
-
}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
index 92903357..3659eb12 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
@@ -7,14 +7,14 @@
import dev.learning.xapi.model.Activity;
import dev.learning.xapi.model.Context;
import dev.learning.xapi.model.SubStatement;
-import dev.learning.xapi.model.validation.constraints.ValidStatement;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
+import jakarta.validation.Valid;
/**
* The SubStatement being validated must be valid.
*/
-public class ValidatorForSubStatement implements ConstraintValidator {
+public class ValidatorForSubStatement implements ConstraintValidator {
@Override
public boolean isValid(SubStatement value, ConstraintValidatorContext context) {
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java
new file mode 100644
index 00000000..e3b54b38
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java
@@ -0,0 +1,89 @@
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+import dev.learning.xapi.model.Agent;
+import dev.learning.xapi.model.Group;
+import org.junit.jupiter.api.Test;
+
+class AuthorityValidatorTests {
+
+ private AuthorityValidator constraintValidator = new AuthorityValidator();
+
+ @Test
+ void whenCallingIsValidWithNullThenResultIsTrue() {
+
+ // When Calling Is Valid With Null
+ boolean result = constraintValidator.isValid(null, null);
+
+ // Then Result Is True
+ assertThat(result, is(true));
+ }
+
+ @Test
+ void whenCallingIsValidWithAgentThenResultIsTrue() {
+
+ Agent agent = Agent.builder().name("A N Other").mbox("mailto:another@example.com").build();
+
+ // When Calling Is Valid With Agent
+ boolean result = constraintValidator.isValid(agent, null);
+
+ // Then Result Is True
+ assertThat(result, is(true));
+ }
+
+ @Test
+ void whenCallingIsValidWithIdentifiedGroupThenResultIsFalse() {
+
+ Group group = Group.builder().name("A N Other").mbox("mailto:another@example.com").build();
+
+ // When Calling Is Valid With Identified Group
+ boolean result = constraintValidator.isValid(group, null);
+
+ // Then Result Is False
+ assertThat(result, is(false));
+ }
+
+ @Test
+ void whenCallingIsValidWithIdentifiedGroupWithMembersThenResultIsFalse() {
+
+ Group group = Group.builder().name("A N Other").mbox("mailto:another@example.com")
+ .addMember(m -> m.name("A N Other").mbox("mailto:another@example.com")).build();
+
+ // When Calling Is Valid With Identified Group
+ boolean result = constraintValidator.isValid(group, null);
+
+ // Then Result Is False
+ assertThat(result, is(false));
+ }
+
+ @Test
+ void whenCallingIsValidWithGroupWithOneMemberThenResultIsFalse() {
+
+ Group group = Group.builder()
+ .addMember(m -> m.name("A N Other").mbox("mailto:another@example.com")).build();
+
+ // When Calling Is Valid With Group With One Member
+ boolean result = constraintValidator.isValid(group, null);
+
+ // Then Result Is False
+ assertThat(result, is(false));
+ }
+
+ @Test
+ void whenCallingIsValidWithGroupWithTwoMembersThenResultIsTrue() {
+
+ Group group =
+ Group.builder().addMember(m -> m.name("A N Other").mbox("mailto:another@example.com"))
+ .addMember(m -> m.name("A N Other").mbox("mailto:another@example.com")).build();
+
+ // When Calling IsValid With Group With Two Members
+ boolean result = constraintValidator.isValid(group, null);
+
+ // Then Result Is True
+ assertThat(result, is(true));
+
+ }
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
new file mode 100644
index 00000000..880592d9
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
@@ -0,0 +1,33 @@
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+import java.net.URI;
+import org.junit.jupiter.api.Test;
+
+class HasSchemeValidatorForUriTests {
+
+ private HasSchemeValidatorForUri constraintValidator = new HasSchemeValidatorForUri();
+
+ @Test
+ void whenCallingIsValidWithURIWithoutSchemeThenResultIsFalse() {
+
+ // When Calling IsValid With URI Without Scheme
+ boolean valid = constraintValidator.isValid(URI.create("example.com"), null);
+
+ // Then Result Is False
+ assertThat(valid, is(false));
+ }
+
+ @Test
+ void whenCallingIsValidWithURIWithSchemeThenResultIsTrue() {
+
+ // When Calling IsValid With URI With Scheme
+ boolean result = constraintValidator.isValid(URI.create("https://example.com"), null);
+
+ // Then Result Is True
+ assertThat(result, is(true));
+ }
+
+}
From bfeb10cb1af2512144b1e815ba88e8ba292e152f Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 16:45:04 +0000
Subject: [PATCH 10/34] tip
---
.../java/dev/learning/xapi/model/Group.java | 2 +
.../dev/learning/xapi/model/GroupTests.java | 94 +++++++++++++++++++
.../validators/AuthorityValidatorTests.java | 4 +
.../HasSchemeValidatorForUriTests.java | 4 +
4 files changed, 104 insertions(+)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
index ca384fb6..671c6a38 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
@@ -5,6 +5,7 @@
package dev.learning.xapi.model;
import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.validation.Valid;
import java.util.ArrayList;
import java.util.List;
@@ -38,6 +39,7 @@ public class Group extends Actor {
// **Warning** do not add fields that are not required by the xAPI specification.
+ @JsonIgnore
public boolean isAnonymous() {
return account == null && mbox == null && mboxSha1sum == null && openid == null
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java
index f706aa70..2fa35142 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java
@@ -7,6 +7,9 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
@@ -106,4 +109,95 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
}
+ @Test
+ void givenGroupWithNameAndMembersWhenCallingIsAnonymousThenResultIsTrue() throws IOException {
+
+ // Given Group With Name And Members
+ final Group group = Group.builder()
+
+ .name("Example Group")
+
+ .addMember(a -> a.name("Member 1").mbox("mailto:member1@example.com"))
+
+ .addMember(a -> a.name("Member 2").openid(URI.create("https://example.com/openId")))
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is True
+ assertTrue(result);
+
+ }
+
+ @Test
+ void givenGroupWithMboxAndMembersWhenCallingIsAnonymousThenResultIsFalse() throws IOException {
+
+ // Given Group With MBox And Members
+ final Group group = Group.builder()
+
+ .mbox("mailto:another@example.com")
+
+ .addMember(a -> a.name("Member 1").mbox("mailto:member1@example.com"))
+
+ .addMember(a -> a.name("Member 2").openid(URI.create("https://example.com/openId")))
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is False
+ assertFalse(result);
+
+ }
+
+ @Test
+ void givenGroupWithMboxSha1sumAndMembersWhenCallingIsAnonymousThenResultIsFalse()
+ throws IOException {
+
+ // Given Group With MboxSha1sum And Members
+ final Group group = Group.builder()
+
+ .mboxSha1sum("mailto:another@example.com")
+
+ .addMember(a -> a.name("Member 1").mbox("mailto:member1@example.com"))
+
+ .addMember(a -> a.name("Member 2").openid(URI.create("https://example.com/openId")))
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is False
+ assertFalse(result);
+
+ }
+
+ @Test
+ void givenGroupWithAccountAndMembersWhenCallingIsAnonymousThenResultIsFalse() throws IOException {
+
+ // Given Group With Account And Members
+ final Group group = Group.builder()
+
+ .addMember(a -> a.name("Member 1").mbox("mailto:member1@example.com"))
+
+ .addMember(a -> a.name("Member 2").openid(URI.create("https://example.com/openId")))
+
+ .account(a -> a.name("name").homePage(URI.create("https://example.com")))
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is False
+ assertFalse(result);
+
+ }
+
+
+
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java
index e3b54b38..1bdfaff2 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidatorTests.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
package dev.learning.xapi.model.validation.internal.validators;
import static org.hamcrest.MatcherAssert.assertThat;
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
index 880592d9..d54336ab 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
@@ -1,3 +1,7 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
package dev.learning.xapi.model.validation.internal.validators;
import static org.hamcrest.MatcherAssert.assertThat;
From a36e55dcbb78a2dd4c98526a4729db6ab856e12a Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 16:53:53 +0000
Subject: [PATCH 11/34] tip
---
.../dev/learning/xapi/model/GroupTests.java | 66 +++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java
index 2fa35142..9ef55caa 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/GroupTests.java
@@ -15,6 +15,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.util.ArrayList;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.util.ResourceUtils;
@@ -131,6 +132,47 @@ void givenGroupWithNameAndMembersWhenCallingIsAnonymousThenResultIsTrue() throws
}
+ @Test
+ void givenGroupWithNameAndNoMembersWhenCallingIsAnonymousThenResultIsFalse() throws IOException {
+
+ // Given Group With Name And Empty Members
+ final Group group = Group.builder()
+
+ .name("Example Group")
+
+ .member(new ArrayList())
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is False
+ assertFalse(result);
+
+ }
+
+ @Test
+ void givenGroupWithNameAndNullMembersWhenCallingIsAnonymousThenResultIsFalse()
+ throws IOException {
+
+ // Given Group With Name And Null Members
+ final Group group = Group.builder()
+
+ .name("Example Group")
+
+ .member(null)
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is False
+ assertFalse(result);
+
+ }
+
@Test
void givenGroupWithMboxAndMembersWhenCallingIsAnonymousThenResultIsFalse() throws IOException {
@@ -176,6 +218,30 @@ void givenGroupWithMboxSha1sumAndMembersWhenCallingIsAnonymousThenResultIsFalse(
}
+ @Test
+ void givenGroupWithOpenIDAndMembersWhenCallingIsAnonymousThenResultIsFalse() throws IOException {
+
+ // Given Group With OpenID And Members
+ final Group group = Group.builder()
+
+ .openid(URI.create("https://example.com"))
+
+ .addMember(a -> a.name("Member 1").mbox("mailto:member1@example.com"))
+
+ .addMember(a -> a.name("Member 2").openid(URI.create("https://example.com/openId")))
+
+ .build();
+
+ // When Calling Is Anonymous
+ boolean result = group.isAnonymous();
+
+ // Then Result Is False
+ assertFalse(result);
+
+ }
+
+
+
@Test
void givenGroupWithAccountAndMembersWhenCallingIsAnonymousThenResultIsFalse() throws IOException {
From 5efc061ec6d39107ffa353ef98ebe0e5e3b885be Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 18:06:01 +0000
Subject: [PATCH 12/34] tip
---
xapi-model/src/main/java/dev/learning/xapi/model/Group.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
index 671c6a38..676ae0bb 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
@@ -39,6 +39,9 @@ public class Group extends Actor {
// **Warning** do not add fields that are not required by the xAPI specification.
+ /**
+ * Returns true if the group is anonymous.
+ */
@JsonIgnore
public boolean isAnonymous() {
From b888404041ce676f73b2553efa72c39c473d2706 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 18:10:07 +0000
Subject: [PATCH 13/34] tip fix
---
.../META-INF/services/jakarta.validation.ConstraintValidator | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
index a095133a..3b87ca48 100644
--- a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
+++ b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
@@ -1,4 +1,3 @@
+dev.learning.xapi.model.validation.internal.validators.AuthorityValidator
dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri
dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid
-dev.learning.xapi.model.validation.internal.validators.ValidatorForSubStatement
-dev.learning.xapi.model.validation.internal.validators.ValidatorForStatement
\ No newline at end of file
From 606c59a2df1c41eeaea15e132f2b344b2f323265 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 19:07:05 +0000
Subject: [PATCH 14/34] Update AuthorityValidator.java
---
.../validation/internal/validators/AuthorityValidator.java | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
index 5c2fb270..c732bdae 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
@@ -29,11 +29,7 @@ public boolean isValid(Actor value, ConstraintValidatorContext context) {
final var group = (Group) value;
// ... or must be an anonymous Group with exactly two members
- if (group.isAnonymous() && group.getMember().size() == 2) {
- return true;
- }
-
- return false;
+ return group.isAnonymous() && group.getMember().size() == 2);
}
From 271976da73de864f2a854a87ab6d79517849fd01 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 19:15:23 +0000
Subject: [PATCH 15/34] Update
xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
---
.../validation/internal/validators/AuthorityValidator.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
index c732bdae..b3804ecc 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/AuthorityValidator.java
@@ -29,7 +29,7 @@ public boolean isValid(Actor value, ConstraintValidatorContext context) {
final var group = (Group) value;
// ... or must be an anonymous Group with exactly two members
- return group.isAnonymous() && group.getMember().size() == 2);
+ return group.isAnonymous() && group.getMember().size() == 2;
}
From f16325f79dfc50bd664df0ab999c163c3377740b Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Thu, 16 Mar 2023 23:27:16 +0000
Subject: [PATCH 16/34] tip
---
.../validators/ValidatorForStatement.java | 82 -------------------
.../validators/ValidatorForSubStatement.java | 59 -------------
2 files changed, 141 deletions(-)
delete mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
delete mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
deleted file mode 100644
index eff78359..00000000
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2016-2019 Berry Cloud Ltd. All rights reserved.
- */
-
-package dev.learning.xapi.model.validation.internal.validators;
-
-import dev.learning.xapi.model.Activity;
-import dev.learning.xapi.model.Context;
-import dev.learning.xapi.model.Statement;
-import dev.learning.xapi.model.StatementReference;
-import dev.learning.xapi.model.Verb;
-import jakarta.validation.ConstraintValidator;
-import jakarta.validation.ConstraintValidatorContext;
-import jakarta.validation.Valid;
-
-/**
- * The Statement being validated must be valid.
- */
-public class ValidatorForStatement implements ConstraintValidator {
-
- @Override
- public boolean isValid(Statement value, ConstraintValidatorContext context) {
-
- if (value == null) {
- // Can not happen with annotation target set to type
- return true;
- }
-
- // TODO consider adding conversion logic here
-
- context.disableDefaultConstraintViolation();
-
- return isVoidingVerbValid(value, context) && isValidRevision(value, context)
- && isValidPlatform(value, context);
- }
-
- private boolean isVoidingVerbValid(Statement value, ConstraintValidatorContext context) {
-
- Verb verb = value.getVerb();
-
- if (verb == null || !verb.isVoided()
- || (verb.isVoided() && value.getObject() instanceof StatementReference)) {
- return true;
- }
-
- context
- .buildConstraintViolationWithTemplate(
- "invalid voiding statement, object must be of type statement reference")
- .addConstraintViolation();
-
- return false;
- }
-
- private boolean isValidRevision(Statement value, ConstraintValidatorContext context) {
-
- Context c = value.getContext();
-
- if (c == null || c.getRevision() == null || value.getObject() instanceof Activity) {
- return true;
- }
-
- context.buildConstraintViolationWithTemplate(
- "invalid revision property, object must of type activity").addConstraintViolation();
-
- return false;
- }
-
- private boolean isValidPlatform(Statement value, ConstraintValidatorContext context) {
-
- Context c = value.getContext();
-
- if (c == null || c.getPlatform() == null || value.getObject() instanceof Activity) {
- return true;
- }
-
- context.buildConstraintViolationWithTemplate(
- "invalid platform property, object must be of type activity").addConstraintViolation();
-
- return false;
- }
-
-}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
deleted file mode 100644
index 3659eb12..00000000
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016-2019 Berry Cloud Ltd. All rights reserved.
- */
-
-package dev.learning.xapi.model.validation.internal.validators;
-
-import dev.learning.xapi.model.Activity;
-import dev.learning.xapi.model.Context;
-import dev.learning.xapi.model.SubStatement;
-import jakarta.validation.ConstraintValidator;
-import jakarta.validation.ConstraintValidatorContext;
-import jakarta.validation.Valid;
-
-/**
- * The SubStatement being validated must be valid.
- */
-public class ValidatorForSubStatement implements ConstraintValidator {
-
- @Override
- public boolean isValid(SubStatement value, ConstraintValidatorContext context) {
-
- if (value == null) {
- return true;
- }
-
- context.disableDefaultConstraintViolation();
-
- return isValidRevision(value, context) && isValidPlatform(value, context);
- }
-
- private boolean isValidRevision(SubStatement value, ConstraintValidatorContext context) {
-
- Context c = value.getContext();
-
- if (c == null || c.getRevision() == null || value.getObject() instanceof Activity) {
- return true;
- }
-
- context.buildConstraintViolationWithTemplate(
- "invalid revision property, object must of type activity").addConstraintViolation();
-
- return false;
- }
-
- private boolean isValidPlatform(SubStatement value, ConstraintValidatorContext context) {
-
- Context c = value.getContext();
-
- if (c == null || c.getPlatform() == null || value.getObject() instanceof Activity) {
- return true;
- }
-
- context.buildConstraintViolationWithTemplate(
- "invalid platform property, object must be of type activity").addConstraintViolation();
-
- return false;
- }
-
-}
From 26c99c1d8c2f8e0814d5ed73e7b5bf63b3be8a0e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 10:20:18 +0000
Subject: [PATCH 17/34] Add Mbox, AllowedLocale and ScaledScore validators
(#86)
---
xapi-model/pom.xml | 5 +
.../dev/learning/xapi/model/Activity.java | 2 +
.../learning/xapi/model/ActivityState.java | 2 +
.../java/dev/learning/xapi/model/Actor.java | 2 +
.../dev/learning/xapi/model/AgentProfile.java | 2 +
.../dev/learning/xapi/model/Attachment.java | 4 +-
.../java/dev/learning/xapi/model/Context.java | 5 +
.../java/dev/learning/xapi/model/Group.java | 3 +-
.../java/dev/learning/xapi/model/Person.java | 3 +-
.../java/dev/learning/xapi/model/Score.java | 2 +
.../dev/learning/xapi/model/Statement.java | 4 +
.../dev/learning/xapi/model/SubStatement.java | 3 +
.../model/validation/constraints/Mbox.java | 47 ++++
.../constraints/NotUndetermined.java | 48 ++++
.../validation/constraints/ScaledScore.java | 47 ++++
.../constraints/ValidActivityDefinition.java | 49 ++++
.../validation/constraints/ValidActor.java | 49 ++++
.../ActivityDefinitionValidator.java | 36 +++
.../internal/validators/ActorValidator.java | 63 +++++
.../internal/validators/MboxValidator.java | 42 +++
.../validators/NotUndeterminedValidator.java | 30 +++
.../validators/ScaledScoreValidator.java | 29 +++
.../jakarta.validation.ConstraintValidator | 5 +
.../ActivityDefinitionValidatorTest.java | 122 +++++++++
.../validators/ActorValidatorTest.java | 246 ++++++++++++++++++
.../validators/MboxValidatorTest.java | 103 ++++++++
.../NotUndeterminedValidatorTest.java | 54 ++++
.../validators/ScaledScoreValidatorTest.java | 93 +++++++
28 files changed, 1096 insertions(+), 4 deletions(-)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Mbox.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/NotUndetermined.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ScaledScore.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActivityDefinition.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActor.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidator.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidator.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml
index 26cb0af9..3e032a76 100644
--- a/xapi-model/pom.xml
+++ b/xapi-model/pom.xml
@@ -37,6 +37,11 @@
spring-boot-starter-validation
test
+
+ org.hibernate.validator
+ hibernate-validator
+ provided
+
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Activity.java b/xapi-model/src/main/java/dev/learning/xapi/model/Activity.java
index 6e7ead1d..87e33e2c 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Activity.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Activity.java
@@ -4,6 +4,7 @@
package dev.learning.xapi.model;
+import dev.learning.xapi.model.validation.constraints.ValidActivityDefinition;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.net.URI;
@@ -38,6 +39,7 @@ public class Activity implements StatementObject, SubStatementObject {
* Metadata.
*/
@Valid
+ @ValidActivityDefinition
private ActivityDefinition definition;
// **Warning** do not add fields that are not required by the xAPI specification.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java b/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java
index 8d4ee606..a70c6269 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/ActivityState.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import java.util.UUID;
@@ -31,6 +32,7 @@ public class ActivityState {
private String stateId;
@Valid
+ @ValidActor
private Agent agent;
@Variant(2)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Actor.java b/xapi-model/src/main/java/dev/learning/xapi/model/Actor.java
index 9da1bedf..9a767aad 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Actor.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Actor.java
@@ -10,6 +10,7 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+import dev.learning.xapi.model.validation.constraints.Mbox;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.function.Consumer;
@@ -48,6 +49,7 @@ public abstract class Actor implements StatementObject, SubStatementObject {
/**
* An email address. The required format is "mailto:email address".
*/
+ @Mbox
String mbox;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/AgentProfile.java b/xapi-model/src/main/java/dev/learning/xapi/model/AgentProfile.java
index 46df4a3d..5b88f93f 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/AgentProfile.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/AgentProfile.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
import jakarta.validation.Valid;
import lombok.Builder;
import lombok.Value;
@@ -25,6 +26,7 @@
public class AgentProfile {
@Valid
+ @ValidActor
private Agent agent;
private String profileId;
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 d7191459..48dfb75b 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
@@ -86,7 +86,7 @@ public static class Builder {
*
* @return This builder
*
- * @see ActivityDefinition#description
+ * @see Attachment#description
*/
public Builder addDisplay(Locale key, String value) {
@@ -106,7 +106,7 @@ public Builder addDisplay(Locale key, String value) {
*
* @return This builder
*
- * @see ActivityDefinition#description
+ * @see Attachment#description
*/
public Builder addDescription(Locale key, String value) {
if (this.description == null) {
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
index a64d7e85..8b4fd44d 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
@@ -7,6 +7,8 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.HasScheme;
+import dev.learning.xapi.model.validation.constraints.NotUndetermined;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import java.net.URI;
@@ -41,12 +43,14 @@ public class Context {
* Instructor that the Statement relates to, if not included as the Actor of the Statement.
*/
@Valid
+ @ValidActor
private Actor instructor;
/**
* Team that this Statement relates to, if not included as the Actor of the Statement.
*/
@Valid
+ @ValidActor
private Group team;
/**
@@ -68,6 +72,7 @@ public class Context {
/**
* The language in which the experience being recorded in this Statement (mainly) occurred in.
*/
+ @NotUndetermined
private Locale language;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
index 676ae0bb..6b2e5715 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Group.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
import jakarta.validation.Valid;
import java.util.ArrayList;
import java.util.List;
@@ -35,7 +36,7 @@ public class Group extends Actor {
*/
@Valid
@JsonFormat(without = {JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY})
- private final List member;
+ private final List<@ValidActor Agent> member;
// **Warning** do not add fields that are not required by the xAPI specification.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Person.java b/xapi-model/src/main/java/dev/learning/xapi/model/Person.java
index 936e380c..68522a42 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Person.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Person.java
@@ -8,6 +8,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
+import dev.learning.xapi.model.validation.constraints.Mbox;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.ArrayList;
@@ -43,7 +44,7 @@ public class Person {
/**
* List of e-mail addresses.
*/
- private List mbox;
+ private List<@Mbox String> mbox;
/**
* List of the SHA1 hashes of mailto IRIs.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Score.java b/xapi-model/src/main/java/dev/learning/xapi/model/Score.java
index ad4f878b..1dafbff6 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Score.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Score.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.ScaledScore;
import lombok.Builder;
import lombok.Value;
@@ -25,6 +26,7 @@ public class Score {
/**
* The score related to the experience as modified by scaling and/or normalization.
*/
+ @ScaledScore
private Float scaled;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index 8a16c8c5..8608e348 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -8,6 +8,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
import dev.learning.xapi.model.validation.constraints.ValidAuthority;
import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
@@ -51,6 +52,7 @@ public class Statement {
*/
@NotNull
@Valid
+ @ValidActor
private Actor actor;
/**
@@ -65,6 +67,7 @@ public class Statement {
*/
@NotNull
@Valid
+ @ValidActor
private StatementObject object;
/**
@@ -92,6 +95,7 @@ public class Statement {
/**
* Agent or Group who is asserting this Statement is true.
*/
+ @ValidActor
@ValidAuthority
private Actor authority;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index 176548f5..f03b05cf 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -4,6 +4,7 @@
package dev.learning.xapi.model;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.time.Instant;
@@ -31,6 +32,7 @@ public class SubStatement implements StatementObject {
*/
@NotNull
@Valid
+ @ValidActor
private Actor actor;
/**
@@ -45,6 +47,7 @@ public class SubStatement implements StatementObject {
*/
@NotNull
@Valid
+ @ValidActor
private SubStatementObject object;
/**
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Mbox.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Mbox.java
new file mode 100644
index 00000000..11b16e6c
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Mbox.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must be a valid Mbox.
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+public @interface Mbox {
+
+ /**
+ * Error Message.
+ */
+ String message() default "must be a valid mbox";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/NotUndetermined.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/NotUndetermined.java
new file mode 100644
index 00000000..24ef0e0f
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/NotUndetermined.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+/**
+ * The annotated element must be a not undetermined {@link Locale}.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+public @interface NotUndetermined {
+
+ /**
+ * Error Message.
+ */
+ String message() default "undetermined (und) locale is not allowed";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ScaledScore.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ScaledScore.java
new file mode 100644
index 00000000..970c34dc
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ScaledScore.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must be a valid scaled score.
+ *
+ * @author István Rátkai (Selindek)
+ * @see xAPI Score details
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+public @interface ScaledScore {
+
+ /**
+ * Error Message.
+ */
+ String message() default "scaled score must be between -1 and 1";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActivityDefinition.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActivityDefinition.java
new file mode 100644
index 00000000..ba5c4046
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActivityDefinition.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016-2019 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must be a valid Activity Definition.
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ * @see Activity
+ * Definition
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+public @interface ValidActivityDefinition {
+
+ /**
+ * Error Message.
+ */
+ String message() default "must be a valid Activity Definition";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActor.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActor.java
new file mode 100644
index 00000000..d9c8c3c1
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016-2019 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import dev.learning.xapi.model.Actor;
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must be a valid {@link Actor}.
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ * @see Actor
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+@Retention(RUNTIME)
+public @interface ValidActor {
+
+ /**
+ * Error Message.
+ */
+ String message() default "actor must be valid";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java
new file mode 100644
index 00000000..5e4546b4
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.ActivityDefinition;
+import dev.learning.xapi.model.validation.constraints.ValidActivityDefinition;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The {@link ActivityDefinition} being validated must be valid.
+ *
+ * @author István Rátkai (Selindek)
+ * @see Activity
+ * Definition
+ */
+public class ActivityDefinitionValidator
+ implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(ActivityDefinition value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ return !(value.getInteractionType() == null
+ && (value.getCorrectResponsesPattern() != null || value.getChoices() != null
+ || value.getScale() != null || value.getSource() != null || value.getTarget() != null
+ || value.getSteps() != null));
+
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java
new file mode 100644
index 00000000..bc45b1ed
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.Actor;
+import dev.learning.xapi.model.Agent;
+import dev.learning.xapi.model.Group;
+import dev.learning.xapi.model.StatementObject;
+import dev.learning.xapi.model.validation.constraints.ValidActor;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The {@link StatementObject} being validated must be valid.
+ *
+ * @author István Rátkai (Selindek)
+ * @see Actor
+ */
+public class ActorValidator implements ConstraintValidator {
+
+ /**
+ * Checks if this {@link Actor} contains exactly one identifier.
+ *
+ * @return true if this object is valid.
+ */
+ @Override
+ public boolean isValid(StatementObject value, ConstraintValidatorContext context) {
+
+ if (value instanceof final Group group) {
+ return group.getAccount() == null && group.getMbox() == null && group.getMboxSha1sum() == null
+ && group.getOpenid() == null ? group.getMember() != null && !group.getMember().isEmpty()
+ : hasSingleIdentifier(group);
+ } else if (value instanceof final Agent agent) {
+ return hasSingleIdentifier(agent);
+ }
+
+ return true;
+
+ }
+
+ private boolean hasSingleIdentifier(Actor value) {
+
+ var n = 0;
+
+ if (value.getMbox() != null) {
+ n++;
+ }
+ if (value.getMboxSha1sum() != null) {
+ n++;
+ }
+ if (value.getOpenid() != null) {
+ n++;
+ }
+ if (value.getAccount() != null) {
+ n++;
+ }
+
+ return n == 1;
+ }
+
+}
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
new file mode 100644
index 00000000..157c6aea
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.validation.constraints.Mbox;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator;
+
+/**
+ * The String being validated must be a valid mbox.
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ * @see Mbox
+ */
+public class MboxValidator implements ConstraintValidator {
+
+ public static final String PREFIX = "mailto:";
+
+ EmailValidator emailValidator;
+
+ @Override
+ public void initialize(Mbox mbox) {
+
+ emailValidator = new EmailValidator();
+ }
+
+ @Override
+ public boolean isValid(String value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ return value.startsWith(PREFIX)
+ && emailValidator.isValid(value.substring(PREFIX.length()), context);
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidator.java
new file mode 100644
index 00000000..c3632f18
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.validation.constraints.NotUndetermined;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import java.util.Locale;
+
+/**
+ * The Locale being validated must be a non undetermined {@link Locale}.
+ *
+ * @author István Rátkai (Selindek)
+ */
+public class NotUndeterminedValidator implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(Locale value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ return !value.toLanguageTag().equalsIgnoreCase("und");
+
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidator.java
new file mode 100644
index 00000000..8ab73cf7
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.validation.constraints.ScaledScore;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The Float being validated must be a valid scaled score.
+ *
+ * @author István Rátkai (Selindek)
+ * @see xAPI Score details
+ */
+public class ScaledScoreValidator implements ConstraintValidator {
+
+ @Override
+ public boolean isValid(Float value, ConstraintValidatorContext context) {
+
+ if (value == null) {
+ return true;
+ }
+
+ return value >= -1F && value <= 1F;
+ }
+
+}
diff --git a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
index 3b87ca48..9e253511 100644
--- a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
+++ b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
@@ -1,3 +1,8 @@
dev.learning.xapi.model.validation.internal.validators.AuthorityValidator
dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri
dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid
+dev.learning.xapi.model.validation.internal.validators.NotUndeterminedValidator
+dev.learning.xapi.model.validation.internal.validators.MboxValidator
+dev.learning.xapi.model.validation.internal.validators.ScaledScoreValidator
+dev.learning.xapi.model.validation.internal.validators.ActivityDefinitionValidator
+dev.learning.xapi.model.validation.internal.validators.ActorValidator
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
new file mode 100644
index 00000000..4d5946e3
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import dev.learning.xapi.model.ActivityDefinition;
+import dev.learning.xapi.model.InteractionType;
+
+/**
+ * ActivityDefinitionValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("ActivityDefinitionValidator tests")
+public class ActivityDefinitionValidatorTest {
+
+ private static final ActivityDefinitionValidator validator = new ActivityDefinitionValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+
+ @Test
+ void whenValueHasInteractionTypeThenResultIsTrue() {
+
+ // When Value Has InteractionType
+ var value = ActivityDefinition.builder().interactionType(InteractionType.CHOICE).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNoInteractionTypeButHasCorrectResponsepatternThenResultIsFalse() {
+
+ // When Value Has No InteractionType But Has CorrectResponsePatters
+ var value = ActivityDefinition.builder().correctResponsesPattern(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasNoInteractionTypeButHasChoicesThenResultIsFalse() {
+
+ // When Value Has No InteractionType But Has Choices
+ var value = ActivityDefinition.builder().choices(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasNoInteractionTypeButHasScaleThenResultIsFalse() {
+
+ // When Value Has No InteractionType But Has Scale
+ var value = ActivityDefinition.builder().scale(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasNoInteractionTypeButHasSourceThenResultIsFalse() {
+
+ // When Value Has No InteractionType But Has Source
+ var value = ActivityDefinition.builder().source(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasNoInteractionTypeButHasTargetThenResultIsFalse() {
+
+ // When Value Has No InteractionType But Has Target
+ var value = ActivityDefinition.builder().target(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasNoInteractionTypeButHasStepsThenResultIsFalse() {
+
+ // When Value Has No InteractionType But Has Steps
+ var value = ActivityDefinition.builder().steps(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
new file mode 100644
index 00000000..5fdb29c5
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.net.URI;
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import dev.learning.xapi.model.Activity;
+import dev.learning.xapi.model.Agent;
+import dev.learning.xapi.model.Group;
+import dev.learning.xapi.model.StatementReference;
+import dev.learning.xapi.model.SubStatement;
+
+/**
+ * ActorValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("ActorValidator tests")
+public class ActorValidatorTest {
+
+ private static final ActorValidator validator = new ActorValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsActivityThenResultIsTrue() {
+
+ // When Value Is Activity
+ var value = Activity.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsSubStatementThenResultIsTrue() {
+
+ // When Value Is SubStatement
+ var value = SubStatement.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsStatementReferenceThenResultIsTrue() {
+
+ // When Value Is StatementReference
+ var value = StatementReference.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenAgentValueHasNoIdentifierThenResultIsFalse() {
+
+ // When Agent Value Has No Identifier
+ var value = Agent.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenAgentValueHasOnlyMboxThenResultIsTrue() {
+
+ // When Agent Value Has Only Mbox
+ var value = Agent.builder().mbox("mailto:fred@example.com").build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenAgentValueHasOnlyMboxSha1sumThenResultIsTrue() {
+
+ // When Agent Value Has Only MboxSha1sum
+ var value = Agent.builder().mboxSha1sum("121212121212121212121212").build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenAgentValueHasOnlyOpenIdThenResultIsTrue() {
+
+ // When Agent Value Has Only MboxSha1sum
+ var value = Agent.builder().openid(URI.create("http://example.com/openid/121212121212121212")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenAgentValueHasOnlyAccountThenResultIsTrue() {
+
+ // When Agent Value Has Only Account
+ var value = Agent.builder().account(a->a.homePage(URI.create("http://example.com")).name("fred")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenAgentValueHasMoreThanOneIdentifierThenResultIsFalse() {
+
+ // When Agent Value Has More Than One Identifier
+ var value = Agent.builder().mbox("mailto:fred@example.com").mboxSha1sum("121212121212121212121212").build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenGroupValueHasNoIdentifierThenResultIsFalse() {
+
+ // When Group Value Has No Identifier
+ var value = Group.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenGroupValueHasNoIdentifierAndEmptyMembersThenResultIsFalse() {
+
+ // When Group Value Has No Identifier And Empty Members
+ var value = Group.builder().member(new ArrayList<>()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenGroupValueHasNoIdentifierButHasMemberThenResultIsTrue() {
+
+ // When Group Value Has No Identifier But Has Member
+ var value = Group.builder().addMember(a->a.mbox("mailto:fred@example.com")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenGroupValueHasOnlyMboxThenResultIsTrue() {
+
+ // When Group Value Has Only Mbox
+ var value = Group.builder().mbox("mailto:fred@example.com").build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenGroupValueHasOnlyMboxSha1sumThenResultIsTrue() {
+
+ // When Group Value Has Only MboxSha1sum
+ var value = Group.builder().mboxSha1sum("121212121212121212121212").build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenGroupValueHasOnlyOpenIdThenResultIsTrue() {
+
+ // When Group Value Has Only MboxSha1sum
+ var value = Group.builder().openid(URI.create("http://example.com/openid/121212121212121212")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenGroupValueHasOnlyAccountThenResultIsTrue() {
+
+ // When Group Value Has Only Account
+ var value = Group.builder().account(a->a.homePage(URI.create("http://example.com")).name("fred")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenGroupValueHasMoreThanOneIdentifierThenResultIsFalse() {
+
+ // When Group Value Has More Than One Identifier
+ var value = Group.builder().mbox("mailto:fred@example.com").mboxSha1sum("121212121212121212121212").build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
new file mode 100644
index 00000000..7f76a14a
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import jakarta.validation.Payload;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.lang.annotation.Annotation;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import dev.learning.xapi.model.validation.constraints.Mbox;
+
+/**
+ * MboxValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("MboxValidator tests")
+public class MboxValidatorTest {
+
+ private static final MboxValidator validator = new MboxValidator();
+
+ @BeforeAll
+ static void init() {
+ validator.initialize(new Mbox() {
+
+ @Override
+ public Class extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public Class extends Payload>[] payload() {
+ return null;
+ }
+
+ @Override
+ public String message() {
+ return null;
+ }
+
+ @Override
+ public Class>[] groups() {
+ return null;
+ }
+ });
+ }
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsValidMboxThenResultIsTrue() {
+
+ // When Value Is Valid Mbox
+ var result = validator.isValid("mailto:fred@example.com", null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasInvalidPrefixThenResultIsFalse() {
+
+ // When Value Has Invalid Prefix
+ var result = validator.isValid("email:fred@example.com", null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasNoPrefixThenResultIsFalse() {
+
+ // When Value Has No Prefix
+ var result = validator.isValid("fred@example.com", null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasInvalidEmailThenResultIsFalse() {
+
+ // When Value Has Invalid Email
+ var result = validator.isValid("mailto:fred@example@com", null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
new file mode 100644
index 00000000..18a843c2
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Locale;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * NotUndeterminedValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("NotUndeterminedValidator tests")
+public class NotUndeterminedValidatorTest {
+
+ private static final NotUndeterminedValidator validator = new NotUndeterminedValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ //Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsUndeterminedLocaleThenResultIsFalse() throws NoSuchFieldException, SecurityException {
+
+ // When Value Is Undetermined Locale
+ var result = validator.isValid(Locale.forLanguageTag("und"), null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueIsNotUndeterminedLocaleThenResultIsTrue() throws NoSuchFieldException, SecurityException {
+
+ // When Value Is Not Undetermined Locale
+ var result = validator.isValid(Locale.forLanguageTag("en-US"), null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
new file mode 100644
index 00000000..de11ac9f
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * ScaledScoreValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("ScaledSoreValidator tests")
+public class ScaledScoreValidatorTest {
+
+ private static final ScaledScoreValidator validator = new ScaledScoreValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsValidScaledScoreThenResultIsTrue() {
+
+ // When Value Is Valid Score
+ var result = validator.isValid(0F, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsValidMinimumScoreThenResultIsTrue() {
+
+ // When Value Is Valid Minimum Score
+ var result = validator.isValid(-1F, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueIsValidMaximumScoreThenResultIsTrue() {
+
+ // When Value Is Valid Maximum Score
+ var result = validator.isValid(1F, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void WhenValueIsOverMaximumScoreThenResultIsFalse() {
+
+ // when Value Is Over Maximum Score
+ var result = validator.isValid(1.001F, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueIsBelowMinimumScoreThenResultIsFalse() {
+
+ // When Value Is Below Minimum Score
+ var result = validator.isValid(-1.001F, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueIsNanThenResultIsFalse() {
+
+ // When Value Is NaN
+ var result = validator.isValid(Float.NaN, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+}
From fa1acfe2b0290a72e145773f94b983489d0d29bd Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Fri, 17 Mar 2023 12:48:45 +0000
Subject: [PATCH 18/34] tip
---
.../VariantValidatorForUuidTest.java | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java
new file mode 100644
index 00000000..4a45b35f
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.UUID;
+import org.junit.jupiter.api.Test;
+
+class VariantValidatorForUuidTest {
+
+ private VariantValidatorForUuid constraintValidator = new VariantValidatorForUuid();
+
+ @Test
+ void whenIsValidIsCalledWithNullUUIDThenValidIsTrue() {
+
+ // When IsValid Is Called With Null UUID
+ boolean valid = constraintValidator.isValid(null, null);
+
+ // Then Valid Is True
+ assertTrue(valid);
+ }
+
+ @Test
+ void whenIsValidIsCalledWithVersion4Variant2UUIDThenValidIsTrue() {
+
+ // When IsValid Is Called With Version 4 Variant 2 UUID
+ boolean valid =
+ constraintValidator.isValid(UUID.fromString("3441c47b-c098-4245-b22e-db3d1242098f"), null);
+
+ // Then Valid Is True
+ assertTrue(valid);
+ }
+
+ @Test
+ void whenIsValidIsCalledWithVersion4VariantMicrosoftGUIDUUIDThenResultIsFalse() {
+
+ // When IsValid Is Called With Version 4 Variant Microsoft GUID UUID
+ boolean valid =
+ constraintValidator.isValid(UUID.fromString("4c30eeb1-15ac-4833-cb0d-88613ba65267"), null);
+
+ // Then Valid Is False
+ assertFalse(valid);
+ }
+
+
+ //
+}
From f1d329f2644e3e188ebc93e858b33194698d271a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 13:43:30 +0000
Subject: [PATCH 19/34] add more validators
ValidStatementVerb
ValidStatementPlatform
ValidStatementRevision
---
.../dev/learning/xapi/model/Statement.java | 10 +-
.../learning/xapi/model/StatementObject.java | 2 +-
.../dev/learning/xapi/model/SubStatement.java | 6 +-
.../xapi/model/ValidableStatement.java | 21 ++++
.../constraints/ValidStatementPlatform.java | 42 +++++++
.../constraints/ValidStatementRevision.java | 42 +++++++
.../constraints/ValidStatementVerb.java | 42 +++++++
.../StatementPlatformValidator.java | 34 ++++++
.../StatementRevisionValidator.java | 34 ++++++
.../validators/StatementVerbValidator.java | 35 ++++++
.../jakarta.validation.ConstraintValidator | 3 +
.../StatementPlatformValidatorTest.java | 105 +++++++++++++++++
.../StatementRevisionValidatorTest.java | 106 ++++++++++++++++++
.../StatementVerbValidatorTest.java | 105 +++++++++++++++++
14 files changed, 582 insertions(+), 5 deletions(-)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementPlatform.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementRevision.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementVerb.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index 8608e348..9b071c68 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -5,11 +5,13 @@
package dev.learning.xapi.model;
import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.ValidActor;
import dev.learning.xapi.model.validation.constraints.ValidAuthority;
+import dev.learning.xapi.model.validation.constraints.ValidStatementPlatform;
+import dev.learning.xapi.model.validation.constraints.ValidStatementRevision;
+import dev.learning.xapi.model.validation.constraints.ValidStatementVerb;
import dev.learning.xapi.model.validation.constraints.Variant;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
@@ -35,11 +37,13 @@
*/
@With
@Value
+@ValidStatementPlatform
+@ValidStatementRevision
+@ValidStatementVerb
@Builder(toBuilder = true)
-@JsonIgnoreProperties("inProgress")
@JsonInclude(Include.NON_EMPTY)
@EqualsAndHashCode(of = {"actor", "verb", "object", "result", "context"})
-public class Statement {
+public class Statement implements ValidableStatement {
/**
* UUID assigned by LRS if not set by the Learning Record Provider.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/StatementObject.java b/xapi-model/src/main/java/dev/learning/xapi/model/StatementObject.java
index ce38625a..f381c5ab 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/StatementObject.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/StatementObject.java
@@ -14,7 +14,7 @@
* This interface represents the xAPI statement object.
*
* @author Thomas Turrell-Croft
- *
+ *
* @see xAPI
* Object
*/
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index f03b05cf..a13ac425 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -5,6 +5,8 @@
package dev.learning.xapi.model;
import dev.learning.xapi.model.validation.constraints.ValidActor;
+import dev.learning.xapi.model.validation.constraints.ValidStatementPlatform;
+import dev.learning.xapi.model.validation.constraints.ValidStatementRevision;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.time.Instant;
@@ -24,8 +26,10 @@
*/
@Value
@Builder
+@ValidStatementPlatform
+@ValidStatementRevision
@EqualsAndHashCode(exclude = {"timestamp", "attachments"})
-public class SubStatement implements StatementObject {
+public class SubStatement implements StatementObject, ValidableStatement {
/**
* Whom the Statement is about, as an Agent or Group Object.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java
new file mode 100644
index 00000000..7aaeeb2d
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model;
+
+/**
+ * This is a helper interface for signing Statement-like objects which can be targets of
+ * class level Statement-validators.
+ *
+ * @author István Rátkai (Selindek)
+ */
+public interface ValidableStatement {
+
+ Verb getVerb();
+
+ Object getObject();
+
+ Context getContext();
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementPlatform.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementPlatform.java
new file mode 100644
index 00000000..edfae752
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementPlatform.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must have a valid platform.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({TYPE})
+@Retention(RUNTIME)
+public @interface ValidStatementPlatform {
+
+ /**
+ * Error Message.
+ */
+ String message() default "invalid Statement Platform (Object must be an Activity)";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementRevision.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementRevision.java
new file mode 100644
index 00000000..054aee45
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementRevision.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must have a valid revision.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({TYPE})
+@Retention(RUNTIME)
+public @interface ValidStatementRevision {
+
+ /**
+ * Error Message.
+ */
+ String message() default "invalid Statement Revision (Object must be an Activity)";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementVerb.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementVerb.java
new file mode 100644
index 00000000..b59e8d0a
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatementVerb.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.constraints;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The annotated element must have a valid verb.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@Documented
+@Constraint(validatedBy = {})
+@Target({TYPE})
+@Retention(RUNTIME)
+public @interface ValidStatementVerb {
+
+ /**
+ * Error Message.
+ */
+ String message() default "voiding statement must have a statement reference";
+
+ /**
+ * Groups.
+ */
+ Class>[] groups() default {};
+
+ /**
+ * Payload.
+ */
+ Class extends Payload>[] payload() default {};
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java
new file mode 100644
index 00000000..388c99cd
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.Activity;
+import dev.learning.xapi.model.ValidableStatement;
+import dev.learning.xapi.model.validation.constraints.ValidStatementPlatform;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The Statement being validated must have a valid platform.
+ *
+ * If context.platform present, then object must be an {@link Activity}.
+ *
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ * @see
+ * Statement Context Requirements
+ */
+public class StatementPlatformValidator implements
+ ConstraintValidator {
+
+ @Override
+ public boolean isValid(ValidableStatement value, ConstraintValidatorContext context) {
+
+ return value == null || value.getContext() == null || value.getContext().getPlatform() == null
+ || value.getObject() instanceof Activity;
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
new file mode 100644
index 00000000..417e39c6
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.Activity;
+import dev.learning.xapi.model.ValidableStatement;
+import dev.learning.xapi.model.validation.constraints.ValidStatementRevision;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The Statement being validated must have a valid revision.
+ *
+ * If context.revision present, then object must be an {@link Activity}.
+ *
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ * @see
+ * Statement Context Requirements
+ */
+public class StatementRevisionValidator implements
+ ConstraintValidator {
+
+ @Override
+ public boolean isValid(ValidableStatement value, ConstraintValidatorContext context) {
+
+ return value == null || value.getContext() == null || value.getContext().getRevision() == null
+ || value.getObject() instanceof Activity;
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
new file mode 100644
index 00000000..f755923b
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import dev.learning.xapi.model.StatementReference;
+import dev.learning.xapi.model.ValidableStatement;
+import dev.learning.xapi.model.validation.constraints.ValidStatementVerb;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * The Statement being validated must have a valid revision.
+ *
+ * if verb is 'voided' then object must be a {@link StatementReference}.
+ *
+ *
+ * @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
+ * @see
+ * Voiding Statement Requirements
+ */
+public class StatementVerbValidator implements
+ ConstraintValidator {
+
+ @Override
+ public boolean isValid(ValidableStatement value, ConstraintValidatorContext context) {
+
+ return value == null || value.getVerb() == null || !value.getVerb().isVoided()
+ || value.getObject() instanceof StatementReference;
+
+ }
+
+}
diff --git a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
index 9e253511..0f706f9a 100644
--- a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
+++ b/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator
@@ -6,3 +6,6 @@ dev.learning.xapi.model.validation.internal.validators.MboxValidator
dev.learning.xapi.model.validation.internal.validators.ScaledScoreValidator
dev.learning.xapi.model.validation.internal.validators.ActivityDefinitionValidator
dev.learning.xapi.model.validation.internal.validators.ActorValidator
+dev.learning.xapi.model.validation.internal.validators.StatementRevisionValidator
+dev.learning.xapi.model.validation.internal.validators.StatementPlatformValidator
+dev.learning.xapi.model.validation.internal.validators.StatementVerbValidator
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java
new file mode 100644
index 00000000..58992706
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import dev.learning.xapi.model.Context;
+import dev.learning.xapi.model.Statement;
+import java.net.URI;
+import java.util.UUID;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * StatementPlatformValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("StatementPlatformValidator tests")
+public class StatementPlatformValidatorTest {
+
+ private static final StatementPlatformValidator validator = new StatementPlatformValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNoContextThenResultIsTrue() {
+
+ // When Value has No Context
+ var value = Statement.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNoContextPlatformThenResultIsTrue() {
+
+ // When Value has No Context Platform
+ var value = Statement.builder().context(Context.builder().build()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasContextPlatformButNoObjectThenResultIsFalse() {
+
+ // When Value has Context Platform But No Object
+ var value = Statement.builder().context(c->c.platform("platform")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasContextPlatformAndInvalidObjectThenResultIsFalse() {
+
+ // When Value has Context Platform And Invalid Object
+ var value = Statement.builder().context(c->c.platform("platform"))
+
+ .statementReferenceObject(sr->sr.id(UUID.randomUUID()))
+
+ .build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasContextPlatformAndValidObjectThenResultIsTrue() {
+
+ // When Value has Context Platform And Valid Object
+ var value = Statement.builder().context(c->c.platform("platform"))
+
+ .activityObject(a->a.id(URI.create("http://example.com/activity")))
+
+ .build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java
new file mode 100644
index 00000000..24598e42
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import dev.learning.xapi.model.Context;
+import dev.learning.xapi.model.Statement;
+import java.net.URI;
+import java.util.UUID;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * StatementRevisionValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("StatementRevisionValidator tests")
+public class StatementRevisionValidatorTest {
+
+ private static final StatementRevisionValidator validator = new StatementRevisionValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNoContextThenResultIsTrue() {
+
+ // When Value has No Context
+ var value = Statement.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNoContextRevisionThenResultIsTrue() {
+
+ // When Value has No Context Revision
+ var value = Statement.builder().context(Context.builder().build()).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasContextRevisionButNoObjectThenResultIsFalse() {
+
+ // When Value has Context Revision But No Object
+ var value = Statement.builder().context(c->c.revision("revision")).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasContextRevisionAndInvalidObjectThenResultIsFalse() {
+
+ // When Value has Context Revision And Invalid Object
+ var value = Statement.builder().context(c->c.revision("revision"))
+
+ .statementReferenceObject(sr->sr.id(UUID.randomUUID()))
+
+ .build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasContextRevisionAndValidObjectThenResultIsTrue() {
+
+ // When Value has Context Revision And Valid Object
+ var value = Statement.builder().context(c->c.revision("revision"))
+
+ .activityObject(a->a.id(URI.create("http://example.com/activity")))
+
+ .build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java
new file mode 100644
index 00000000..3566a85a
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import dev.learning.xapi.model.Statement;
+import dev.learning.xapi.model.Verb;
+import java.net.URI;
+import java.util.UUID;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * StatementVerbValidator Tests.
+ *
+ * @author István Rátkai (Selindek)
+ */
+@DisplayName("StatementVerbValidator tests")
+public class StatementVerbValidatorTest {
+
+ private static final StatementVerbValidator validator = new StatementVerbValidator();
+
+ @Test
+ void whenValueIsNullThenResultIsTrue() {
+
+ // When Value Is Null
+ var result = validator.isValid(null, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNoVerbThenResultIsTrue() {
+
+ // When Value has No Verb
+ var value = Statement.builder().build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasNonVoidedVerbThenResultIsTrue() {
+
+ // When Value has Non-Voided Verb
+ var value = Statement.builder().verb(Verb.ANSWERED).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenValueHasVoidedVerbButNoObjectThenResultIsFalse() {
+
+ // When Value has Voided Verb But No Object
+ var value = Statement.builder().verb(Verb.VOIDED).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasVoidedVerbAndInvalidObjectThenResultIsFalse() {
+
+ // When Value has Voided Verb And Invalid Object
+ var value = Statement.builder().verb(Verb.VOIDED)
+
+ .activityObject(a->a.id(URI.create("http://example.com/activity")))
+
+ .build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is False
+ assertFalse(result);
+ }
+
+ @Test
+ void whenValueHasVoidedVerbAndValidObjectThenResultIsTrue() {
+
+ // When Value has Voided Verb And Valid Object
+ var value = Statement.builder().verb(Verb.VOIDED)
+
+ .statementReferenceObject(sr->sr.id(UUID.randomUUID()))
+
+ .build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+}
From d5fd8e1eab842f308bcb3cd26e75bd1de5a06af6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 13:47:02 +0000
Subject: [PATCH 20/34] pom
---
xapi-model/pom.xml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml
index 3e032a76..a124410d 100644
--- a/xapi-model/pom.xml
+++ b/xapi-model/pom.xml
@@ -27,6 +27,11 @@
jakarta.validation
jakarta.validation-api
+
+ org.hibernate.validator
+ hibernate-validator
+ provided
+
org.springframework.boot
spring-boot-starter-test
@@ -37,11 +42,6 @@
spring-boot-starter-validation
test
-
- org.hibernate.validator
- hibernate-validator
- provided
-
From 10656e097b8d6c9f3cd865d407c9d19c72466869 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 13:54:23 +0000
Subject: [PATCH 21/34] fsi
---
.../ActivityDefinitionValidatorTest.java | 2 +-
.../validators/ActorValidatorTest.java | 2 +-
.../validators/MboxValidatorTest.java | 35 ++++++-------------
.../NotUndeterminedValidatorTest.java | 2 +-
.../validators/ScaledScoreValidatorTest.java | 2 +-
.../StatementPlatformValidatorTest.java | 2 +-
.../StatementRevisionValidatorTest.java | 2 +-
.../StatementVerbValidatorTest.java | 2 +-
8 files changed, 17 insertions(+), 32 deletions(-)
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
index 4d5946e3..17c027c1 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
@@ -19,7 +19,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ActivityDefinitionValidator tests")
-public class ActivityDefinitionValidatorTest {
+class ActivityDefinitionValidatorTest {
private static final ActivityDefinitionValidator validator = new ActivityDefinitionValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
index 5fdb29c5..bf148164 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
@@ -25,7 +25,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ActorValidator tests")
-public class ActorValidatorTest {
+class ActorValidatorTest {
private static final ActorValidator validator = new ActorValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
index 7f76a14a..226096fc 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
@@ -12,6 +12,9 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
import dev.learning.xapi.model.validation.constraints.Mbox;
/**
@@ -20,7 +23,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("MboxValidator tests")
-public class MboxValidatorTest {
+class MboxValidatorTest {
private static final MboxValidator validator = new MboxValidator();
@@ -71,33 +74,15 @@ void whenValueIsValidMboxThenResultIsTrue() {
}
@Test
- void whenValueHasInvalidPrefixThenResultIsFalse() {
+ @ParameterizedTest
+ @ValueSource(strings = {"email:fred@example.com", "fred@example.com", "mailto:fred@example@com"})
+ void whenValueIsInvalidThenResultIsFalse(String value) {
- // When Value Has Invalid Prefix
- var result = validator.isValid("email:fred@example.com", null);
+ // When Value Is Invalid
+ var result = validator.isValid(value, null);
// Then Result Is False
assertFalse(result);
}
-
- @Test
- void whenValueHasNoPrefixThenResultIsFalse() {
-
- // When Value Has No Prefix
- var result = validator.isValid("fred@example.com", null);
-
- // Then Result Is False
- assertFalse(result);
- }
-
- @Test
- void whenValueHasInvalidEmailThenResultIsFalse() {
-
- // When Value Has Invalid Email
- var result = validator.isValid("mailto:fred@example@com", null);
-
- // Then Result Is False
- assertFalse(result);
- }
-
+
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
index 18a843c2..d8fec9a4 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
@@ -17,7 +17,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("NotUndeterminedValidator tests")
-public class NotUndeterminedValidatorTest {
+class NotUndeterminedValidatorTest {
private static final NotUndeterminedValidator validator = new NotUndeterminedValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
index de11ac9f..c1bc4c95 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
@@ -16,7 +16,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ScaledSoreValidator tests")
-public class ScaledScoreValidatorTest {
+class ScaledScoreValidatorTest {
private static final ScaledScoreValidator validator = new ScaledScoreValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java
index 58992706..54e66cbd 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidatorTest.java
@@ -20,7 +20,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("StatementPlatformValidator tests")
-public class StatementPlatformValidatorTest {
+class StatementPlatformValidatorTest {
private static final StatementPlatformValidator validator = new StatementPlatformValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java
index 24598e42..9db981d0 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidatorTest.java
@@ -21,7 +21,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("StatementRevisionValidator tests")
-public class StatementRevisionValidatorTest {
+class StatementRevisionValidatorTest {
private static final StatementRevisionValidator validator = new StatementRevisionValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java
index 3566a85a..55dc3436 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidatorTest.java
@@ -21,7 +21,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("StatementVerbValidator tests")
-public class StatementVerbValidatorTest {
+class StatementVerbValidatorTest {
private static final StatementVerbValidator validator = new StatementVerbValidator();
From 2971ad3d7cf271930dfa5ff7efec6f0410ebf3d3 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Fri, 17 Mar 2023 14:07:56 +0000
Subject: [PATCH 22/34] top
---
.../validators/VariantValidatorForUuid.java | 1 +
... => ActivityDefinitionValidatorTests.java} | 2 +-
...atorTest.java => ActorValidatorTests.java} | 2 +-
.../HasSchemeValidatorForUriTests.java | 2 +
...datorTest.java => MboxValidatorTests.java} | 2 +-
...ava => NotUndeterminedValidatorTests.java} | 2 +-
...st.java => ScaledScoreValidatorTests.java} | 2 +-
.../VariantValidatorForUuidTest.java | 51 -----------
.../VariantValidatorForUuidTests.java | 91 +++++++++++++++++++
9 files changed, 99 insertions(+), 56 deletions(-)
rename xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/{ActivityDefinitionValidatorTest.java => ActivityDefinitionValidatorTests.java} (98%)
rename xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/{ActorValidatorTest.java => ActorValidatorTests.java} (99%)
rename xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/{MboxValidatorTest.java => MboxValidatorTests.java} (98%)
rename xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/{NotUndeterminedValidatorTest.java => NotUndeterminedValidatorTests.java} (96%)
rename xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/{ScaledScoreValidatorTest.java => ScaledScoreValidatorTests.java} (98%)
delete mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java
create mode 100644 xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTests.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
index 71fa37b3..a300c911 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
@@ -31,6 +31,7 @@ public boolean isValid(UUID value, ConstraintValidatorContext context) {
return true;
}
+ System.out.println("value " + value.variant());
return value.variant() == variant;
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
similarity index 98%
rename from xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
rename to xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
index 4d5946e3..52e21723 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
@@ -19,7 +19,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ActivityDefinitionValidator tests")
-public class ActivityDefinitionValidatorTest {
+public class ActivityDefinitionValidatorTests {
private static final ActivityDefinitionValidator validator = new ActivityDefinitionValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java
similarity index 99%
rename from xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
rename to xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java
index 5fdb29c5..bb440507 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java
@@ -25,7 +25,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ActorValidator tests")
-public class ActorValidatorTest {
+public class ActorValidatorTests {
private static final ActorValidator validator = new ActorValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
index d54336ab..a41d1762 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/HasSchemeValidatorForUriTests.java
@@ -8,8 +8,10 @@
import static org.hamcrest.core.Is.is;
import java.net.URI;
+import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+@DisplayName("HasSchemeValidatorForUri tests")
class HasSchemeValidatorForUriTests {
private HasSchemeValidatorForUri constraintValidator = new HasSchemeValidatorForUri();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
similarity index 98%
rename from xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
rename to xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
index 7f76a14a..8305c7fd 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
@@ -20,7 +20,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("MboxValidator tests")
-public class MboxValidatorTest {
+public class MboxValidatorTests {
private static final MboxValidator validator = new MboxValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java
similarity index 96%
rename from xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
rename to xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java
index 18a843c2..6869003f 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java
@@ -17,7 +17,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("NotUndeterminedValidator tests")
-public class NotUndeterminedValidatorTest {
+public class NotUndeterminedValidatorTests {
private static final NotUndeterminedValidator validator = new NotUndeterminedValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java
similarity index 98%
rename from xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
rename to xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java
index de11ac9f..8516deed 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java
@@ -16,7 +16,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ScaledSoreValidator tests")
-public class ScaledScoreValidatorTest {
+public class ScaledScoreValidatorTests {
private static final ScaledScoreValidator validator = new ScaledScoreValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java
deleted file mode 100644
index 4a45b35f..00000000
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
- */
-
-package dev.learning.xapi.model.validation.internal.validators;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.UUID;
-import org.junit.jupiter.api.Test;
-
-class VariantValidatorForUuidTest {
-
- private VariantValidatorForUuid constraintValidator = new VariantValidatorForUuid();
-
- @Test
- void whenIsValidIsCalledWithNullUUIDThenValidIsTrue() {
-
- // When IsValid Is Called With Null UUID
- boolean valid = constraintValidator.isValid(null, null);
-
- // Then Valid Is True
- assertTrue(valid);
- }
-
- @Test
- void whenIsValidIsCalledWithVersion4Variant2UUIDThenValidIsTrue() {
-
- // When IsValid Is Called With Version 4 Variant 2 UUID
- boolean valid =
- constraintValidator.isValid(UUID.fromString("3441c47b-c098-4245-b22e-db3d1242098f"), null);
-
- // Then Valid Is True
- assertTrue(valid);
- }
-
- @Test
- void whenIsValidIsCalledWithVersion4VariantMicrosoftGUIDUUIDThenResultIsFalse() {
-
- // When IsValid Is Called With Version 4 Variant Microsoft GUID UUID
- boolean valid =
- constraintValidator.isValid(UUID.fromString("4c30eeb1-15ac-4833-cb0d-88613ba65267"), null);
-
- // Then Valid Is False
- assertFalse(valid);
- }
-
-
- //
-}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTests.java
new file mode 100644
index 00000000..27ad2b48
--- /dev/null
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuidTests.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.model.validation.internal.validators;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import dev.learning.xapi.model.validation.constraints.Variant;
+import java.util.UUID;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.commons.util.AnnotationUtils;
+
+/**
+ * VariantValidatorForUuid Tests.
+ *
+ * @author Thomas Turrell-Croft
+ */
+@DisplayName("VariantValidatorForUuidTest tests")
+class VariantValidatorForUuidTests {
+
+ private VariantValidatorForUuid constraintValidator = new VariantValidatorForUuid();
+
+ @Variant(2)
+ private UUID variant2;
+
+ @Variant(6)
+ private UUID variant6;
+
+ @Test
+ void whenIsValidIsCalledWithNullUUIDThenValidIsTrue() {
+
+ // When IsValid Is Called With Null UUID
+ boolean valid = constraintValidator.isValid(null, null);
+
+ // Then Valid Is True
+ assertTrue(valid);
+ }
+
+ @Test
+ void GivenValidatorIsInitializedWith2WhenIsValidIsCalledWithVersion4Variant2UUIDThenValidIsTrue()
+ throws Exception {
+
+ // Given Validator Is Initialized With 2
+ constraintValidator.initialize(AnnotationUtils
+ .findAnnotation(getClass().getDeclaredField("variant2"), Variant.class).get());
+
+ // When IsValid Is Called With Version 4 Variant 2 UUID
+ boolean valid =
+ constraintValidator.isValid(UUID.fromString("3441c47b-c098-4245-b22e-db3d1242098f"), null);
+
+ // Then Valid Is True
+ assertTrue(valid);
+ }
+
+ @Test
+ void GivenValidatorIsInitializedWith2whenIsValidIsCalledWithVersion4VariantMicrosoftGUIDUUIDThenResultIsFalse()
+ throws Exception {
+
+ // Given Validator Is Initialized With 2
+ constraintValidator.initialize(AnnotationUtils
+ .findAnnotation(getClass().getDeclaredField("variant2"), Variant.class).get());
+
+ // When IsValid Is Called With Version 4 Variant Microsoft GUID UUID
+ boolean valid =
+ constraintValidator.isValid(UUID.fromString("4c30eeb1-15ac-4833-cb0d-88613ba65267"), null);
+
+ // Then Valid Is False
+ assertFalse(valid);
+ }
+
+
+ @Test
+ void GivenValidatorIsInitializedWith6whenIsValidIsCalledWithVersion4VariantMicrosoftGUIDUUIDThenResultIsTrue()
+ throws Exception {
+
+ // Given Validator Is Initialized With 6
+ constraintValidator.initialize(AnnotationUtils
+ .findAnnotation(getClass().getDeclaredField("variant6"), Variant.class).get());
+
+ // When IsValid Is Called With Version 4 Variant Microsoft GUID UUID
+ boolean valid =
+ constraintValidator.isValid(UUID.fromString("4c30eeb1-15ac-4833-cb0d-88613ba65267"), null);
+
+ // Then Valid Is False
+ assertTrue(valid);
+ }
+
+}
From 42c444f4f2d282f969dcc4071b388c59b71244e7 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Fri, 17 Mar 2023 14:25:24 +0000
Subject: [PATCH 23/34] tip
---
.../validators/VariantValidatorForUuid.java | 1 -
.../validators/MboxValidatorTests.java | 38 +++++++++----------
2 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
index a300c911..71fa37b3 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/VariantValidatorForUuid.java
@@ -31,7 +31,6 @@ public boolean isValid(UUID value, ConstraintValidatorContext context) {
return true;
}
- System.out.println("value " + value.variant());
return value.variant() == variant;
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
index c7d0511b..9d99b62d 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
@@ -4,10 +4,11 @@
package dev.learning.xapi.model.validation.internal.validators;
-import jakarta.validation.Payload;
-
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import dev.learning.xapi.model.validation.constraints.Mbox;
+import jakarta.validation.Payload;
import java.lang.annotation.Annotation;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
@@ -15,8 +16,6 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
-import dev.learning.xapi.model.validation.constraints.Mbox;
-
/**
* MboxValidator Tests.
*
@@ -26,63 +25,62 @@
public class MboxValidatorTests {
private static final MboxValidator validator = new MboxValidator();
-
+
@BeforeAll
static void init() {
validator.initialize(new Mbox() {
-
+
@Override
public Class extends Annotation> annotationType() {
return null;
}
-
+
@Override
public Class extends Payload>[] payload() {
return null;
}
-
+
@Override
public String message() {
return null;
}
-
+
@Override
public Class>[] groups() {
return null;
}
});
}
-
+
@Test
void whenValueIsNullThenResultIsTrue() {
-
+
// When Value Is Null
var result = validator.isValid(null, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenValueIsValidMboxThenResultIsTrue() {
-
+
// When Value Is Valid Mbox
var result = validator.isValid("mailto:fred@example.com", null);
-
+
// Then Result Is True
assertTrue(result);
}
-
- @Test
+
@ParameterizedTest
@ValueSource(strings = {"email:fred@example.com", "fred@example.com", "mailto:fred@example@com"})
void whenValueIsInvalidThenResultIsFalse(String value) {
-
+
// When Value Is Invalid
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
}
From c1ae8a21874773dfd4fa38af07ba16d6568abb2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 15:11:59 +0000
Subject: [PATCH 24/34] fix test
---
.../model/validation/internal/validators/MboxValidatorTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
index 226096fc..4180c5bb 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTest.java
@@ -73,7 +73,6 @@ void whenValueIsValidMboxThenResultIsTrue() {
assertTrue(result);
}
- @Test
@ParameterizedTest
@ValueSource(strings = {"email:fred@example.com", "fred@example.com", "mailto:fred@example@com"})
void whenValueIsInvalidThenResultIsFalse(String value) {
From b3af84992401902b37cc80453bd4b1f33d0e3d4e Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Fri, 17 Mar 2023 15:53:07 +0000
Subject: [PATCH 25/34] tip
---
.../ActivityDefinitionValidatorTests.java | 62 +++----
.../validators/ActorValidatorTests.java | 152 +++++++++---------
.../validators/MboxValidatorTests.java | 2 +-
.../NotUndeterminedValidatorTests.java | 26 +--
.../validators/ScaledScoreValidatorTests.java | 32 ++--
5 files changed, 140 insertions(+), 134 deletions(-)
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
index 52e21723..0cd6484f 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
@@ -7,11 +7,11 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import dev.learning.xapi.model.ActivityDefinition;
+import dev.learning.xapi.model.InteractionType;
import java.util.ArrayList;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
-import dev.learning.xapi.model.ActivityDefinition;
-import dev.learning.xapi.model.InteractionType;
/**
* ActivityDefinitionValidator Tests.
@@ -19,101 +19,101 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ActivityDefinitionValidator tests")
-public class ActivityDefinitionValidatorTests {
+class ActivityDefinitionValidatorTests {
private static final ActivityDefinitionValidator validator = new ActivityDefinitionValidator();
-
+
@Test
void whenValueIsNullThenResultIsTrue() {
-
+
// When Value Is Null
var result = validator.isValid(null, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
-
+
+
@Test
void whenValueHasInteractionTypeThenResultIsTrue() {
-
+
// When Value Has InteractionType
var value = ActivityDefinition.builder().interactionType(InteractionType.CHOICE).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenValueHasNoInteractionTypeButHasCorrectResponsepatternThenResultIsFalse() {
-
+
// When Value Has No InteractionType But Has CorrectResponsePatters
var value = ActivityDefinition.builder().correctResponsesPattern(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
@Test
void whenValueHasNoInteractionTypeButHasChoicesThenResultIsFalse() {
-
+
// When Value Has No InteractionType But Has Choices
var value = ActivityDefinition.builder().choices(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
@Test
void whenValueHasNoInteractionTypeButHasScaleThenResultIsFalse() {
-
+
// When Value Has No InteractionType But Has Scale
var value = ActivityDefinition.builder().scale(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
@Test
void whenValueHasNoInteractionTypeButHasSourceThenResultIsFalse() {
-
+
// When Value Has No InteractionType But Has Source
var value = ActivityDefinition.builder().source(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
@Test
void whenValueHasNoInteractionTypeButHasTargetThenResultIsFalse() {
-
+
// When Value Has No InteractionType But Has Target
var value = ActivityDefinition.builder().target(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
@Test
void whenValueHasNoInteractionTypeButHasStepsThenResultIsFalse() {
-
+
// When Value Has No InteractionType But Has Steps
var value = ActivityDefinition.builder().steps(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java
index bb440507..74b65525 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActorValidatorTests.java
@@ -7,17 +7,15 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.net.URI;
-import java.util.ArrayList;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
import dev.learning.xapi.model.Activity;
import dev.learning.xapi.model.Agent;
import dev.learning.xapi.model.Group;
import dev.learning.xapi.model.StatementReference;
import dev.learning.xapi.model.SubStatement;
+import java.net.URI;
+import java.util.ArrayList;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
/**
* ActorValidator Tests.
@@ -25,220 +23,226 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ActorValidator tests")
-public class ActorValidatorTests {
+class ActorValidatorTests {
private static final ActorValidator validator = new ActorValidator();
-
+
@Test
void whenValueIsNullThenResultIsTrue() {
-
+
// When Value Is Null
var result = validator.isValid(null, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenValueIsActivityThenResultIsTrue() {
-
+
// When Value Is Activity
var value = Activity.builder().build();
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenValueIsSubStatementThenResultIsTrue() {
-
+
// When Value Is SubStatement
var value = SubStatement.builder().build();
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenValueIsStatementReferenceThenResultIsTrue() {
-
+
// When Value Is StatementReference
var value = StatementReference.builder().build();
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenAgentValueHasNoIdentifierThenResultIsFalse() {
-
+
// When Agent Value Has No Identifier
var value = Agent.builder().build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
@Test
void whenAgentValueHasOnlyMboxThenResultIsTrue() {
-
+
// When Agent Value Has Only Mbox
var value = Agent.builder().mbox("mailto:fred@example.com").build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenAgentValueHasOnlyMboxSha1sumThenResultIsTrue() {
-
+
// When Agent Value Has Only MboxSha1sum
var value = Agent.builder().mboxSha1sum("121212121212121212121212").build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenAgentValueHasOnlyOpenIdThenResultIsTrue() {
-
+
// When Agent Value Has Only MboxSha1sum
- var value = Agent.builder().openid(URI.create("http://example.com/openid/121212121212121212")).build();
-
+ var value =
+ Agent.builder().openid(URI.create("http://example.com/openid/121212121212121212")).build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenAgentValueHasOnlyAccountThenResultIsTrue() {
-
+
// When Agent Value Has Only Account
- var value = Agent.builder().account(a->a.homePage(URI.create("http://example.com")).name("fred")).build();
-
+ var value = Agent.builder()
+ .account(a -> a.homePage(URI.create("http://example.com")).name("fred")).build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenAgentValueHasMoreThanOneIdentifierThenResultIsFalse() {
-
+
// When Agent Value Has More Than One Identifier
- var value = Agent.builder().mbox("mailto:fred@example.com").mboxSha1sum("121212121212121212121212").build();
-
+ var value = Agent.builder().mbox("mailto:fred@example.com")
+ .mboxSha1sum("121212121212121212121212").build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
@Test
void whenGroupValueHasNoIdentifierThenResultIsFalse() {
-
+
// When Group Value Has No Identifier
var value = Group.builder().build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
@Test
void whenGroupValueHasNoIdentifierAndEmptyMembersThenResultIsFalse() {
-
+
// When Group Value Has No Identifier And Empty Members
var value = Group.builder().member(new ArrayList<>()).build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
@Test
void whenGroupValueHasNoIdentifierButHasMemberThenResultIsTrue() {
-
+
// When Group Value Has No Identifier But Has Member
- var value = Group.builder().addMember(a->a.mbox("mailto:fred@example.com")).build();
-
+ var value = Group.builder().addMember(a -> a.mbox("mailto:fred@example.com")).build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenGroupValueHasOnlyMboxThenResultIsTrue() {
-
+
// When Group Value Has Only Mbox
var value = Group.builder().mbox("mailto:fred@example.com").build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenGroupValueHasOnlyMboxSha1sumThenResultIsTrue() {
-
+
// When Group Value Has Only MboxSha1sum
var value = Group.builder().mboxSha1sum("121212121212121212121212").build();
-
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenGroupValueHasOnlyOpenIdThenResultIsTrue() {
-
+
// When Group Value Has Only MboxSha1sum
- var value = Group.builder().openid(URI.create("http://example.com/openid/121212121212121212")).build();
-
+ var value =
+ Group.builder().openid(URI.create("http://example.com/openid/121212121212121212")).build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenGroupValueHasOnlyAccountThenResultIsTrue() {
-
+
// When Group Value Has Only Account
- var value = Group.builder().account(a->a.homePage(URI.create("http://example.com")).name("fred")).build();
-
+ var value = Group.builder()
+ .account(a -> a.homePage(URI.create("http://example.com")).name("fred")).build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenGroupValueHasMoreThanOneIdentifierThenResultIsFalse() {
-
+
// When Group Value Has More Than One Identifier
- var value = Group.builder().mbox("mailto:fred@example.com").mboxSha1sum("121212121212121212121212").build();
-
+ var value = Group.builder().mbox("mailto:fred@example.com")
+ .mboxSha1sum("121212121212121212121212").build();
+
var result = validator.isValid(value, null);
-
+
// Then Result Is False
assertFalse(result);
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
index 9d99b62d..7bb7071a 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/MboxValidatorTests.java
@@ -22,7 +22,7 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("MboxValidator tests")
-public class MboxValidatorTests {
+class MboxValidatorTests {
private static final MboxValidator validator = new MboxValidator();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java
index 6869003f..862eb54f 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/NotUndeterminedValidatorTests.java
@@ -17,36 +17,38 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("NotUndeterminedValidator tests")
-public class NotUndeterminedValidatorTests {
+class NotUndeterminedValidatorTests {
private static final NotUndeterminedValidator validator = new NotUndeterminedValidator();
-
+
@Test
void whenValueIsNullThenResultIsTrue() {
-
+
// When Value Is Null
var result = validator.isValid(null, null);
-
- //Then Result Is True
+
+ // Then Result Is True
assertTrue(result);
}
@Test
- void whenValueIsUndeterminedLocaleThenResultIsFalse() throws NoSuchFieldException, SecurityException {
-
+ void whenValueIsUndeterminedLocaleThenResultIsFalse()
+ throws NoSuchFieldException, SecurityException {
+
// When Value Is Undetermined Locale
var result = validator.isValid(Locale.forLanguageTag("und"), null);
-
+
// Then Result Is False
assertFalse(result);
}
-
+
@Test
- void whenValueIsNotUndeterminedLocaleThenResultIsTrue() throws NoSuchFieldException, SecurityException {
-
+ void whenValueIsNotUndeterminedLocaleThenResultIsTrue()
+ throws NoSuchFieldException, SecurityException {
+
// When Value Is Not Undetermined Locale
var result = validator.isValid(Locale.forLanguageTag("en-US"), null);
-
+
// Then Result Is True
assertTrue(result);
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java
index 8516deed..44c1f6c5 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ScaledScoreValidatorTests.java
@@ -16,76 +16,76 @@
* @author István Rátkai (Selindek)
*/
@DisplayName("ScaledSoreValidator tests")
-public class ScaledScoreValidatorTests {
+class ScaledScoreValidatorTests {
private static final ScaledScoreValidator validator = new ScaledScoreValidator();
@Test
void whenValueIsNullThenResultIsTrue() {
-
+
// When Value Is Null
var result = validator.isValid(null, null);
-
+
// Then Result Is True
assertTrue(result);
}
-
+
@Test
void whenValueIsValidScaledScoreThenResultIsTrue() {
-
+
// When Value Is Valid Score
var result = validator.isValid(0F, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenValueIsValidMinimumScoreThenResultIsTrue() {
-
+
// When Value Is Valid Minimum Score
var result = validator.isValid(-1F, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void whenValueIsValidMaximumScoreThenResultIsTrue() {
-
+
// When Value Is Valid Maximum Score
var result = validator.isValid(1F, null);
-
+
// Then Result Is True
assertTrue(result);
}
@Test
void WhenValueIsOverMaximumScoreThenResultIsFalse() {
-
+
// when Value Is Over Maximum Score
var result = validator.isValid(1.001F, null);
-
+
// Then Result Is False
assertFalse(result);
}
@Test
void whenValueIsBelowMinimumScoreThenResultIsFalse() {
-
+
// When Value Is Below Minimum Score
var result = validator.isValid(-1.001F, null);
-
+
// Then Result Is False
assertFalse(result);
}
@Test
void whenValueIsNanThenResultIsFalse() {
-
+
// When Value Is NaN
var result = validator.isValid(Float.NaN, null);
-
+
// Then Result Is False
assertFalse(result);
}
From 98ab2fe128e39be018db848d23a92beff2ef3aa2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 16:06:12 +0000
Subject: [PATCH 26/34] add Locale Serializer/Deserializer
---
.../xapi/jackson/LocaleDeserializer.java | 79 +++++++++++++++++++
.../xapi/jackson/LocaleSerializer.java | 55 +++++++++++++
.../java/dev/learning/xapi/model/Context.java | 7 ++
.../dev/learning/xapi/model/LanguageMap.java | 8 ++
.../xapi/model/ActivityDefinitionTests.java | 40 +++++-----
.../learning/xapi/model/ActivityTests.java | 4 +-
.../dev/learning/xapi/model/ContextTests.java | 6 +-
.../xapi/model/InteractionComponentTests.java | 12 +--
.../learning/xapi/model/LanguageMapTests.java | 2 +-
.../learning/xapi/model/StatementTests.java | 6 +-
.../xapi/model/SubStatementTests.java | 10 +--
.../dev/learning/xapi/model/VerbTests.java | 14 ++--
.../src/test/resources/activity/activity.json | 4 +-
.../activity/activity_with_object_type.json | 4 +-
.../activity_definition.json | 14 ++--
.../activity_definition_without_type.json | 2 +-
.../resources/activity_definition/choice.json | 12 +--
.../activity_definition/true_false.json | 4 +-
.../src/test/resources/context/context.json | 2 +-
.../context_with_empty_registration.json | 2 +-
.../context/context_without_registration.json | 2 +-
.../interaction_component.json | 2 +-
.../test/resources/statement/statement.json | 6 +-
.../sub_statement/sub_statement.json | 8 +-
...ent_with_object_of_type_sub_statement.json | 2 +-
xapi-model/src/test/resources/verb/verb.json | 2 +-
26 files changed, 229 insertions(+), 80 deletions(-)
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
create mode 100644 xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
new file mode 100644
index 00000000..8136b638
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.jackson;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.KeyDeserializer;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+
+/**
+ * Specific Locale converter using {@link Locale#forLanguageTag(String)} instead of {@link Locale#Locale(String)}.
+ *
+ * @author István Rátkai (Selindek)
+ */
+public class LocaleDeserializer extends StdDeserializer {
+
+ private static final long serialVersionUID = 7182941951585541965L;
+
+ public LocaleDeserializer() {
+ super(String.class);
+ }
+
+ @Override
+ public Locale deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
+ if (jsonParser.getCurrentToken() != JsonToken.VALUE_STRING) {
+ throw deserializationContext.wrongTokenException(jsonParser, (JavaType) null, JsonToken.VALUE_STRING,
+ "Attempted to parse non-String value to Locale");
+ }
+
+ return validateLocale(jsonParser.getValueAsString(), deserializationContext);
+ }
+
+ static Locale validateLocale(String localeString, DeserializationContext deserializationContext)
+ throws JsonMappingException {
+
+ var locale = Locale.forLanguageTag(localeString);
+
+ try {
+ // test validity of language and country codes (throws exception)
+ locale.getISO3Language();
+ locale.getISO3Country();
+ } catch (final MissingResourceException e) {
+ locale = null;
+ }
+ // test the validity of the whole key
+ if (locale == null || !locale.toLanguageTag().equalsIgnoreCase(localeString)) {
+ throw deserializationContext.weirdStringException(localeString, Locale.class, "Invalid locale");
+ }
+ return locale;
+ }
+
+ /**
+ *
+ * Locale Key Deserializer.
+ *
+ * For deserializing Locale keys in {@link Map}s
+ *
+ * @author István Rátkai (Selindek)
+ */
+ public static class LocaleKeyDeserializer extends KeyDeserializer {
+
+ @Override
+ public Object deserializeKey(String key, DeserializationContext deserializationContext) throws IOException {
+
+ return validateLocale(key, deserializationContext);
+ }
+
+ }
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
new file mode 100644
index 00000000..db47198f
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
+ */
+
+package dev.learning.xapi.jackson;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Specific Locale serializer using {@link Locale#toLanguageTag()} instead of {@link Locale#toString()}.
+ *
+ * @author István Rátkai (Selindek)
+ */
+public class LocaleSerializer extends StdSerializer {
+
+ private static final long serialVersionUID = 7182941951585541965L;
+
+ public LocaleSerializer() {
+ super(Locale.class);
+ }
+
+ @Override
+ public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+ gen.writeString(value.toLanguageTag());
+ }
+
+ /**
+ *
+ * Locale Key Serializer.
+ *
+ * For serializing Locale keys in {@link Map}s
+ *
+ * @author István Rátkai (Selindek)
+ */
+ public static class LocaleKeySerializer extends StdSerializer {
+
+ private static final long serialVersionUID = 7182941951585541965L;
+
+ public LocaleKeySerializer() {
+ super(Locale.class);
+ }
+
+ @Override
+ public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+ gen.writeFieldName(value.toLanguageTag());
+ }
+
+ }
+
+}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
index 8b4fd44d..ccdf4b43 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
@@ -6,6 +6,11 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import dev.learning.xapi.jackson.LocaleDeserializer;
+import dev.learning.xapi.jackson.LocaleSerializer;
import dev.learning.xapi.model.validation.constraints.HasScheme;
import dev.learning.xapi.model.validation.constraints.NotUndetermined;
import dev.learning.xapi.model.validation.constraints.ValidActor;
@@ -73,6 +78,8 @@ public class Context {
* The language in which the experience being recorded in this Statement (mainly) occurred in.
*/
@NotUndetermined
+ @JsonSerialize(using = LocaleSerializer.class)
+ @JsonDeserialize(using = LocaleDeserializer.class)
private Locale language;
/**
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 9566f5ed..4b3e6e34 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
@@ -11,6 +11,12 @@
import java.util.Map;
import java.util.Optional;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import dev.learning.xapi.jackson.LocaleDeserializer;
+import dev.learning.xapi.jackson.LocaleSerializer;
+
/**
* A language map is a dictionary where the key is a RFC 5646 Language Tag, and the value is a
* string in the language specified in the tag.
@@ -20,6 +26,8 @@
* @see Language
* Maps
*/
+@JsonSerialize(keyUsing = LocaleSerializer.LocaleKeySerializer.class)
+@JsonDeserialize(keyUsing = LocaleDeserializer.LocaleKeyDeserializer.class)
public class LanguageMap extends LinkedHashMap {
private static final long serialVersionUID = 7375610804995032187L;
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java
index e8f848a1..c34d292a 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java
@@ -114,7 +114,7 @@ void whenDeserializingActivityDefinitionThenNameIsExpected() throws Exception {
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Name Is Expected
- assertThat(result.getName().get(Locale.ENGLISH),
+ assertThat(result.getName().get(Locale.US),
is("Does the xAPI include the concept of statements?"));
}
@@ -129,7 +129,7 @@ void whenDeserializingActivityDefinitionThenDescriptionIsExpected() throws Excep
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Description Is Expected
- assertThat(result.getDescription().get(Locale.ENGLISH), is("pong[.]1:[,]dg[.]:10[,]lunch[.]"));
+ assertThat(result.getDescription().get(Locale.US), is("pong[.]1:[,]dg[.]:10[,]lunch[.]"));
}
@@ -188,7 +188,7 @@ void whenDeserializingActivityDefinitionWithChoicesThenChoicesDescriptionIsExpec
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Choices Description Is Expected
- assertThat(result.getChoices().get(0).getDescription().get(Locale.ENGLISH),
+ assertThat(result.getChoices().get(0).getDescription().get(Locale.US),
is("Does the xAPI include the concept of statements?"));
}
@@ -218,7 +218,7 @@ void whenDeserializingActivityDefinitionWithScaledThenScaleDescriptionIsExpected
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Scale Description Is Expected
- assertThat(result.getScale().get(0).getDescription().get(Locale.ENGLISH),
+ assertThat(result.getScale().get(0).getDescription().get(Locale.US),
is("Does the xAPI include the concept of statements?"));
}
@@ -248,7 +248,7 @@ void whenDeserializingActivityDefinitionWithSourceThenSourceDescriptionIsExpecte
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Source Description Is Expected
- assertThat(result.getSource().get(0).getDescription().get(Locale.ENGLISH),
+ assertThat(result.getSource().get(0).getDescription().get(Locale.US),
is("Does the xAPI include the concept of statements?"));
}
@@ -278,7 +278,7 @@ void whenDeserializingActivityDefinitionWithTargetThenTargetDescriptionIsExpecte
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Target Description Is Expected
- assertThat(result.getTarget().get(0).getDescription().get(Locale.ENGLISH),
+ assertThat(result.getTarget().get(0).getDescription().get(Locale.US),
is("Does the xAPI include the concept of statements?"));
}
@@ -308,7 +308,7 @@ void whenDeserializingActivityDefinitionWithStepsThenStepsDescriptionIsExpected(
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Steps Description Is Expected
- assertThat(result.getSteps().get(0).getDescription().get(Locale.ENGLISH),
+ assertThat(result.getSteps().get(0).getDescription().get(Locale.US),
is("Does the xAPI include the concept of statements?"));
}
@@ -319,9 +319,9 @@ void whenSerializingActivityDefinitionOfInteractionTypeTrueFalseThenResultIsEqua
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.ENGLISH, "True false question")
+ .addName(Locale.US, "True false question")
- .addDescription(Locale.ENGLISH, "Does the xAPI include the concept of statements?")
+ .addDescription(Locale.US, "Does the xAPI include the concept of statements?")
.interactionType(InteractionType.TRUE_FALSE)
@@ -347,21 +347,21 @@ void whenSerializingActivityDefinitionOfInteractionTypeChoiceThenResultIsEqualTo
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.ENGLISH, "Choice")
+ .addName(Locale.US, "Choice")
- .addDescription(Locale.ENGLISH, "Which of these prototypes are available at the beta site?")
+ .addDescription(Locale.US, "Which of these prototypes are available at the beta site?")
.interactionType(InteractionType.CHOICE)
.correctResponsesPattern(Collections.singletonList("golf[,]tetris"))
- .addChoice(c -> c.id("golf").addDescription(Locale.ENGLISH, "Golf Example"))
+ .addChoice(c -> c.id("golf").addDescription(Locale.US, "Golf Example"))
- .addChoice(c -> c.id("facebook").addDescription(Locale.ENGLISH, "Facebook App"))
+ .addChoice(c -> c.id("facebook").addDescription(Locale.US, "Facebook App"))
- .addChoice(c -> c.id("tetris").addDescription(Locale.ENGLISH, "Tetris Example"))
+ .addChoice(c -> c.id("tetris").addDescription(Locale.US, "Tetris Example"))
- .addChoice(c -> c.id("scrabble").addDescription(Locale.ENGLISH, "Scrabble Example"))
+ .addChoice(c -> c.id("scrabble").addDescription(Locale.US, "Scrabble Example"))
.type(URI.create("http://adlnet.gov/expapi/activities/cmi.interaction"))
@@ -389,7 +389,7 @@ void whenCallingToStringThenResultIsExpected() throws Exception {
// Then Result Is Expected
assertThat(result, is(
- "ActivityDefinition(name={en=Does the xAPI include the concept of statements?}, description={en=pong[.]1:[,]dg[.]:10[,]lunch[.]}, type=http://adlnet.gov/expapi/activities/cmi.interaction, moreInfo=http://example.com/more, interactionType=TRUE_FALSE, correctResponsesPattern=[{case_matters=false}{lang=en}To store and provide access to learning experiences.], choices=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], scale=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], source=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], target=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], steps=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], extensions={http://url=www.example.com})"));
+ "ActivityDefinition(name={en_US=Does the xAPI include the concept of statements?}, description={en_US=pong[.]1:[,]dg[.]:10[,]lunch[.]}, type=http://adlnet.gov/expapi/activities/cmi.interaction, moreInfo=http://example.com/more, interactionType=TRUE_FALSE, correctResponsesPattern=[{case_matters=false}{lang=en}To store and provide access to learning experiences.], choices=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], scale=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], source=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], target=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], steps=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], extensions={http://url=www.example.com})"));
}
@Test
@@ -398,11 +398,11 @@ void whenBuildingActivityDefinitionWithTwoNameValuesThenNameLanguageMapHasTwoEnt
// When Building ActivityDefinition With Two Name Values
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.ENGLISH, "True false question")
+ .addName(Locale.US, "True false question")
.addName(Locale.GERMAN, "Richtig / Falsch-Frage")
- .addDescription(Locale.ENGLISH, "Does the xAPI include the concept of statements?")
+ .addDescription(Locale.US, "Does the xAPI include the concept of statements?")
.interactionType(InteractionType.TRUE_FALSE)
@@ -423,9 +423,9 @@ void whenBuildingActivityDefinitionWithTwoDescriptionValuesThenDescriptionLangua
// When Building ActivityDefinition With Two Description Values
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.ENGLISH, "True false question")
+ .addName(Locale.US, "True false question")
- .addDescription(Locale.ENGLISH, "Does the xAPI include the concept of statements?")
+ .addDescription(Locale.US, "Does the xAPI include the concept of statements?")
.addDescription(Locale.GERMAN, "Enthält die xAPI das Konzept von Anweisungen?")
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java
index f30d4f41..933dfb1e 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java
@@ -79,9 +79,9 @@ void whenSerializingActivityThenResultIsEqualToExpectedJson() throws IOException
.definition(d -> d
- .addName(Locale.ENGLISH, "simple statement")
+ .addName(Locale.US, "simple statement")
- .addDescription(Locale.ENGLISH,
+ .addDescription(Locale.US,
"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."))
.build();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java
index 1e834553..c6902fe2 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java
@@ -93,7 +93,7 @@ void whenDeserializingContextThenLanguageIsExpected() throws Exception {
final Context result = objectMapper.readValue(file, Context.class);
// Then Language Is Expected
- assertThat(result.getLanguage(), is(Locale.ENGLISH));
+ assertThat(result.getLanguage(), is(Locale.US));
}
@@ -230,7 +230,7 @@ void whenSerializingContextThenResultIsEqualToExpectedJson() throws IOException
.platform("platform")
- .language(Locale.ENGLISH)
+ .language(Locale.US)
.statementReference(s -> s.id(UUID.fromString("e9b6b9ed-ef48-4986-9b86-2ef697578bf7")))
@@ -268,7 +268,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
// Then Result Is Expected
assertThat(result, is(
- "Context(registration=1d527164-ed0d-4b1d-9f9b-39aab0e4a089, instructor=Agent(super=Actor(name=Andrew Downes, mbox=mailto:andrew@example.co.uk, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=https://example.com/activity/1, definition=null)], grouping=[Activity(id=https://example.com/activity/2, definition=null)], category=[Activity(id=https://example.com/activity/3, definition=null)], other=[Activity(id=https://example.com/activity/4, definition=null)]), revision=revision, platform=platform, language=en, statement=StatementReference(id=e9b6b9ed-ef48-4986-9b86-2ef697578bf7), extensions={http://url=www.example.com})"));
+ "Context(registration=1d527164-ed0d-4b1d-9f9b-39aab0e4a089, instructor=Agent(super=Actor(name=Andrew Downes, mbox=mailto:andrew@example.co.uk, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=https://example.com/activity/1, definition=null)], grouping=[Activity(id=https://example.com/activity/2, definition=null)], category=[Activity(id=https://example.com/activity/3, definition=null)], other=[Activity(id=https://example.com/activity/4, definition=null)]), revision=revision, platform=platform, language=en_US, statement=StatementReference(id=e9b6b9ed-ef48-4986-9b86-2ef697578bf7), extensions={http://url=www.example.com})"));
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java
index 05f986f0..6daa5363 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java
@@ -75,7 +75,7 @@ void whenDeserializingInteractionComponentThenDescriptionIsExpected() throws Exc
final InteractionComponent result = objectMapper.readValue(file, InteractionComponent.class);
// Then Description Is Expected
- assertThat(result.getDescription().get(Locale.ENGLISH), is("value"));
+ assertThat(result.getDescription().get(Locale.US), is("value"));
}
@@ -86,7 +86,7 @@ void whenSerializingInteractionComponentThenResultIsEqualToExpectedJson() throws
.id("1")
- .addDescription(Locale.ENGLISH, "value")
+ .addDescription(Locale.US, "value")
.build();
@@ -111,7 +111,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
final String result = interactionComponent.toString();
// Then Result Is Expected
- assertThat(result, is("InteractionComponent(id=1, description={en=value})"));
+ assertThat(result, is("InteractionComponent(id=1, description={en_US=value})"));
}
@@ -120,7 +120,7 @@ void whenBuildingInteractionComponentWithTwoDescriptionValuesThenDisplayLanguage
// When Building InteractionComponent With Two Description Values
final InteractionComponent interactionComponent = InteractionComponent.builder().id("1")
- .addDescription(Locale.ENGLISH, "value").addDescription(Locale.GERMAN, "Wert").build();
+ .addDescription(Locale.US, "value").addDescription(Locale.GERMAN, "Wert").build();
// Then Description Language Map Has Two Entries
assertThat(interactionComponent.getDescription(), aMapWithSize(2));
@@ -131,7 +131,7 @@ void whenBuildingInteractionComponentWithTwoDescriptionValuesThenDisplayLanguage
void whenValidatingInteractionComponentWithAllRequiredPropertiesThenConstraintViolationsSizeIsZero() {
final InteractionComponent interactionComponent =
- InteractionComponent.builder().id("1").addDescription(Locale.ENGLISH, "value").build();
+ InteractionComponent.builder().id("1").addDescription(Locale.US, "value").build();
// When Validating Interaction Component With All Required Properties
final Set> constraintViolations =
@@ -146,7 +146,7 @@ void whenValidatingInteractionComponentWithAllRequiredPropertiesThenConstraintVi
void whenValidatingInteractionComponentWithoutIdThenConstraintViolationsSizeIsOne() {
final InteractionComponent interactionComponent =
- InteractionComponent.builder().addDescription(Locale.ENGLISH, "value").build();
+ InteractionComponent.builder().addDescription(Locale.US, "value").build();
// When Validating Interaction Component Without Id
final Set> constraintViolations =
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java
index 2373e136..6cb22782 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java
@@ -68,7 +68,7 @@ void givenFrenchAndEnglishKeyWhenGettingUSValueThenValueIsEnglish() throws Excep
// Given French And English Key
languageMap.put(Locale.FRENCH, "Couleur");
- languageMap.put(Locale.ENGLISH, "Color");
+ languageMap.put(Locale.US, "Color");
// When Getting US Value
final String value = languageMap.get(LanguageRange.parse("en-US"));
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
index 0fc125f8..5ac03318 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
@@ -240,9 +240,9 @@ void whenSerializingStatementThenResultIsEqualToExpectedJson() throws IOExceptio
final Attachment attachment = Attachment.builder().usageType(URI.create("http://example.com"))
.fileUrl(URI.create("http://example.com"))
- .addDisplay(Locale.ENGLISH, "value")
+ .addDisplay(Locale.US, "value")
- .addDescription(Locale.ENGLISH, "value")
+ .addDescription(Locale.US, "value")
.length(123)
@@ -282,7 +282,7 @@ void whenSerializingStatementThenResultIsEqualToExpectedJson() throws IOExceptio
.platform("Example virtual meeting software")
- .language(Locale.ENGLISH)
+ .language(Locale.US)
.statementReference(s -> s.id(UUID.fromString("6690e6c9-3ef0-4ed3-8b37-7f3964730bee")))
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
index d9bdaf61..94c7b5bc 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
@@ -280,7 +280,7 @@ void whenSerializingSubStatementThenResultIsEqualToExpectedJson() throws IOExcep
.platform("platform")
- .language(Locale.forLanguageTag("en"))
+ .language(Locale.US)
.instructor(agent)
@@ -297,9 +297,9 @@ void whenSerializingSubStatementThenResultIsEqualToExpectedJson() throws IOExcep
final Attachment attachment = Attachment.builder().usageType(URI.create("http://example.com"))
.fileUrl(URI.create("http://example.com"))
- .addDisplay(Locale.ENGLISH, "value")
+ .addDisplay(Locale.US, "value")
- .addDescription(Locale.ENGLISH, "value")
+ .addDescription(Locale.US, "value")
.length(123)
@@ -315,7 +315,7 @@ void whenSerializingSubStatementThenResultIsEqualToExpectedJson() throws IOExcep
.actor(agent)
- .verb(v -> v.id(URI.create("http://example.com/confirmed")).addDisplay(Locale.ENGLISH,
+ .verb(v -> v.id(URI.create("http://example.com/confirmed")).addDisplay(Locale.US,
"confirmed"))
.object(statementRef)
@@ -351,7 +351,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
// Then Result Is Expected
assertThat(result, is(
- "SubStatement(actor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), verb=Verb(id=http://example.com/confirmed, display={en=confirmed}), object=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), result=Result(score=Score(scaled=1.0, raw=1.0, min=0.0, max=5.0), success=true, completion=true, response=test, duration=P1D, extensions=null), context=Context(registration=6d969975-8d7e-4506-ac19-877c57f2921a, instructor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], grouping=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], category=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], other=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)]), revision=revision, platform=platform, language=en, statement=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), extensions={http://url=www.example.com}), timestamp=2015-11-18T11:17:00Z, attachments=[Attachment(usageType=http://example.com, display={en=value}, description={en=value}, contentType=file, length=123, sha2=123, fileUrl=http://example.com)])"));
+ "SubStatement(actor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), verb=Verb(id=http://example.com/confirmed, display={en_US=confirmed}), object=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), result=Result(score=Score(scaled=1.0, raw=1.0, min=0.0, max=5.0), success=true, completion=true, response=test, duration=P1D, extensions=null), context=Context(registration=6d969975-8d7e-4506-ac19-877c57f2921a, instructor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], grouping=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], category=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], other=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)]), revision=revision, platform=platform, language=en_US, statement=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), extensions={http://url=www.example.com}), timestamp=2015-11-18T11:17:00Z, attachments=[Attachment(usageType=http://example.com, display={en_US=value}, description={en_US=value}, contentType=file, length=123, sha2=123, fileUrl=http://example.com)])"));
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java
index 6b660629..5017dcda 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java
@@ -78,7 +78,7 @@ void whenSerializingVerbThenResultIsEqualToExpectedJson() throws IOException {
.id(URI.create("http://adlnet.gov/expapi/verbs/answered"))
- .addDisplay(Locale.ENGLISH, "answered")
+ .addDisplay(Locale.US, "answered")
.build();
@@ -128,7 +128,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
// Then Result Is Expected
assertThat(result,
- is("Verb(id=http://adlnet.gov/expapi/verbs/answered, display={en=answered})"));
+ is("Verb(id=http://adlnet.gov/expapi/verbs/answered, display={en_US=answered})"));
}
@@ -187,7 +187,7 @@ void whenBuildingVerbWithTwoDisplayValuesThenDisplayLanguageMapHasTwoEntries() {
.id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.ENGLISH, "answered")
+ .addDisplay(Locale.US, "answered")
.addDisplay(Locale.GERMAN, "antwortete")
@@ -217,7 +217,7 @@ void givenVerbWithoutDisplayPropertyWhenTestingEqualityWithVerbWithDisplayProper
.id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.ENGLISH, "answered")
+ .addDisplay(Locale.US, "answered")
.build());
@@ -243,7 +243,7 @@ void givenVerbWithGermanDisplayPropertyWhenTestingEqualityWithVerbWithEnglishDis
.id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.ENGLISH, "answered")
+ .addDisplay(Locale.US, "answered")
.build());
@@ -318,7 +318,7 @@ void givenVerbDoesNotHaveIdVoidedWhenCallingIsVoidedThenResultIsFalse() {
void whenValidatingVerbWithAllRequiredPropertiesThenConstraintViolationsSizeIsZero() {
final Verb verb = Verb.builder().id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.ENGLISH, "answered").build();
+ .addDisplay(Locale.US, "answered").build();
// When Validating Interaction Component With All Required Properties
final Set> constraintViolations = validator.validate(verb);
@@ -331,7 +331,7 @@ void whenValidatingVerbWithAllRequiredPropertiesThenConstraintViolationsSizeIsZe
@Test
void whenValidatingVerbWithoutIdThenConstraintViolationsSizeIsOne() {
- final Verb verb = Verb.builder().addDisplay(Locale.ENGLISH, "answered").build();
+ final Verb verb = Verb.builder().addDisplay(Locale.US, "answered").build();
// When Validating Interaction Component Without Id
final Set> constraintViolations = validator.validate(verb);
diff --git a/xapi-model/src/test/resources/activity/activity.json b/xapi-model/src/test/resources/activity/activity.json
index b4627ef1..138307a8 100644
--- a/xapi-model/src/test/resources/activity/activity.json
+++ b/xapi-model/src/test/resources/activity/activity.json
@@ -2,10 +2,10 @@
"id":"http://example.com/xapi/activity/simplestatement",
"definition":{
"name":{
- "en":"simple statement"
+ "en-US":"simple statement"
},
"description":{
- "en":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
+ "en-US":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
}
}
}
\ No newline at end of file
diff --git a/xapi-model/src/test/resources/activity/activity_with_object_type.json b/xapi-model/src/test/resources/activity/activity_with_object_type.json
index adfae696..b9825af2 100644
--- a/xapi-model/src/test/resources/activity/activity_with_object_type.json
+++ b/xapi-model/src/test/resources/activity/activity_with_object_type.json
@@ -3,10 +3,10 @@
"id":"http://example.com/xapi/activity/simplestatement",
"definition":{
"name":{
- "en":"simple statement"
+ "en-US":"simple statement"
},
"description":{
- "en":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
+ "en-US":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
}
}
}
\ No newline at end of file
diff --git a/xapi-model/src/test/resources/activity_definition/activity_definition.json b/xapi-model/src/test/resources/activity_definition/activity_definition.json
index b6cad8f5..31a19763 100644
--- a/xapi-model/src/test/resources/activity_definition/activity_definition.json
+++ b/xapi-model/src/test/resources/activity_definition/activity_definition.json
@@ -6,40 +6,40 @@
"http://url" : "www.example.com"
},
"name" : {
- "en" : "Does the xAPI include the concept of statements?"
+ "en-US" : "Does the xAPI include the concept of statements?"
},
"description" : {
- "en" : "pong[.]1:[,]dg[.]:10[,]lunch[.]"
+ "en-US" : "pong[.]1:[,]dg[.]:10[,]lunch[.]"
},
"type" : "http://adlnet.gov/expapi/activities/cmi.interaction",
"choices" : [ {
"id" : "1",
"description" : {
- "en" : "Does the xAPI include the concept of statements?"
+ "en-US" : "Does the xAPI include the concept of statements?"
}
} ],
"scale" : [ {
"id" : "1",
"description" : {
- "en" : "Does the xAPI include the concept of statements?"
+ "en-US" : "Does the xAPI include the concept of statements?"
}
} ],
"source" : [ {
"id" : "1",
"description" : {
- "en" : "Does the xAPI include the concept of statements?"
+ "en-US" : "Does the xAPI include the concept of statements?"
}
} ],
"target" : [ {
"id" : "1",
"description" : {
- "en" : "Does the xAPI include the concept of statements?"
+ "en-US" : "Does the xAPI include the concept of statements?"
}
} ],
"steps" : [ {
"id" : "1",
"description" : {
- "en" : "Does the xAPI include the concept of statements?"
+ "en-US" : "Does the xAPI include the concept of statements?"
}
} ]
}
diff --git a/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json b/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json
index 505fb28e..90c3470c 100644
--- a/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json
+++ b/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json
@@ -1,6 +1,6 @@
{
"description": {
- "en": "Does the xAPI include the concept of statements?"
+ "en-US": "Does the xAPI include the concept of statements?"
},
"interactionType": "fill-in",
"correctResponsesPattern": [
diff --git a/xapi-model/src/test/resources/activity_definition/choice.json b/xapi-model/src/test/resources/activity_definition/choice.json
index 1d1bfbad..cf411f4a 100644
--- a/xapi-model/src/test/resources/activity_definition/choice.json
+++ b/xapi-model/src/test/resources/activity_definition/choice.json
@@ -1,9 +1,9 @@
{
"name": {
- "en": "Choice"
+ "en-US": "Choice"
},
"description": {
- "en": "Which of these prototypes are available at the beta site?"
+ "en-US": "Which of these prototypes are available at the beta site?"
},
"type": "http://adlnet.gov/expapi/activities/cmi.interaction",
"interactionType": "choice",
@@ -14,25 +14,25 @@
{
"id": "golf",
"description": {
- "en": "Golf Example"
+ "en-US": "Golf Example"
}
},
{
"id": "facebook",
"description": {
- "en": "Facebook App"
+ "en-US": "Facebook App"
}
},
{
"id": "tetris",
"description": {
- "en": "Tetris Example"
+ "en-US": "Tetris Example"
}
},
{
"id": "scrabble",
"description": {
- "en": "Scrabble Example"
+ "en-US": "Scrabble Example"
}
}
]
diff --git a/xapi-model/src/test/resources/activity_definition/true_false.json b/xapi-model/src/test/resources/activity_definition/true_false.json
index 6523da45..b1a64e3a 100644
--- a/xapi-model/src/test/resources/activity_definition/true_false.json
+++ b/xapi-model/src/test/resources/activity_definition/true_false.json
@@ -1,9 +1,9 @@
{
"name":{
- "en":"True false question"
+ "en-US":"True false question"
},
"description":{
- "en":"Does the xAPI include the concept of statements?"
+ "en-US":"Does the xAPI include the concept of statements?"
},
"type":"http://adlnet.gov/expapi/activities/cmi.interaction",
"interactionType":"true-false",
diff --git a/xapi-model/src/test/resources/context/context.json b/xapi-model/src/test/resources/context/context.json
index 06d476a4..bb044dca 100644
--- a/xapi-model/src/test/resources/context/context.json
+++ b/xapi-model/src/test/resources/context/context.json
@@ -2,7 +2,7 @@
"registration": "1d527164-ed0d-4b1d-9f9b-39aab0e4a089",
"revision": "revision",
"platform": "platform",
- "language": "en",
+ "language": "en-US",
"instructor": {
"objectType": "Agent",
"name": "Andrew Downes",
diff --git a/xapi-model/src/test/resources/context/context_with_empty_registration.json b/xapi-model/src/test/resources/context/context_with_empty_registration.json
index 990ffb74..59e0f7af 100644
--- a/xapi-model/src/test/resources/context/context_with_empty_registration.json
+++ b/xapi-model/src/test/resources/context/context_with_empty_registration.json
@@ -2,7 +2,7 @@
"registration": "",
"revision": "revision",
"platform": "platform",
- "language": "en",
+ "language": "en-US",
"instructor": {
"name": "Andrew Downes",
"mbox": "mailto:andrew@example.co.uk"
diff --git a/xapi-model/src/test/resources/context/context_without_registration.json b/xapi-model/src/test/resources/context/context_without_registration.json
index cd324ee9..50f37e08 100644
--- a/xapi-model/src/test/resources/context/context_without_registration.json
+++ b/xapi-model/src/test/resources/context/context_without_registration.json
@@ -1,7 +1,7 @@
{
"revision": "revision",
"platform": "platform",
- "language": "en",
+ "language": "en-US",
"instructor": {
"name": "Andrew Downes",
"mbox": "mailto:andrew@example.co.uk"
diff --git a/xapi-model/src/test/resources/interaction_component/interaction_component.json b/xapi-model/src/test/resources/interaction_component/interaction_component.json
index b01f6834..546d196b 100644
--- a/xapi-model/src/test/resources/interaction_component/interaction_component.json
+++ b/xapi-model/src/test/resources/interaction_component/interaction_component.json
@@ -1,6 +1,6 @@
{
"id": "1",
"description": {
- "en": "value"
+ "en-US": "value"
}
}
diff --git a/xapi-model/src/test/resources/statement/statement.json b/xapi-model/src/test/resources/statement/statement.json
index c0b6e5ee..0f1baf6f 100644
--- a/xapi-model/src/test/resources/statement/statement.json
+++ b/xapi-model/src/test/resources/statement/statement.json
@@ -32,7 +32,7 @@
"objectType": "Group"
},
"platform": "Example virtual meeting software",
- "language": "en",
+ "language": "en-US",
"statement": {
"objectType": "StatementRef",
"id": "6690e6c9-3ef0-4ed3-8b37-7f3964730bee"
@@ -69,10 +69,10 @@
{
"usageType": "http://example.com",
"display": {
- "en": "value"
+ "en-US": "value"
},
"description": {
- "en": "value"
+ "en-US": "value"
},
"contentType": "file",
"length": 123,
diff --git a/xapi-model/src/test/resources/sub_statement/sub_statement.json b/xapi-model/src/test/resources/sub_statement/sub_statement.json
index 58955494..a4db3e02 100644
--- a/xapi-model/src/test/resources/sub_statement/sub_statement.json
+++ b/xapi-model/src/test/resources/sub_statement/sub_statement.json
@@ -4,7 +4,7 @@
"verb" : {
"id" : "http://example.com/confirmed",
"display" : {
- "en" : "confirmed"
+ "en-US" : "confirmed"
}
},
"actor" : {
@@ -31,7 +31,7 @@
"registration" : "6d969975-8d7e-4506-ac19-877c57f2921a",
"revision" : "revision",
"platform" : "platform",
- "language" : "en",
+ "language" : "en-US",
"instructor" : {
"objectType" : "Agent",
"mbox" : "mailto:agent@example.com"
@@ -69,10 +69,10 @@
"attachments" : [ {
"usageType" : "http://example.com",
"display" : {
- "en" : "value"
+ "en-US" : "value"
},
"description" : {
- "en" : "value"
+ "en-US" : "value"
},
"contentType" : "file",
"length" : 123,
diff --git a/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json b/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json
index 4b6cd007..e5c65d94 100644
--- a/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json
+++ b/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json
@@ -19,7 +19,7 @@
"verb":{
"id":"http://example.com/confirmed",
"display":{
- "en":"confirmed"
+ "en-US":"confirmed"
}
},
"object":{
diff --git a/xapi-model/src/test/resources/verb/verb.json b/xapi-model/src/test/resources/verb/verb.json
index 78c1c7c7..5d9236b9 100644
--- a/xapi-model/src/test/resources/verb/verb.json
+++ b/xapi-model/src/test/resources/verb/verb.json
@@ -1,6 +1,6 @@
{
"id": "http://adlnet.gov/expapi/verbs/answered",
"display": {
- "en": "answered"
+ "en-US": "answered"
}
}
From 08070f03bc393de9767a324def52ba950b4442cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?=
Date: Fri, 17 Mar 2023 16:11:37 +0000
Subject: [PATCH 27/34] fcs
---
.../xapi/jackson/LocaleDeserializer.java | 19 +++++++++++--------
.../xapi/jackson/LocaleSerializer.java | 11 +++++++----
.../java/dev/learning/xapi/model/Context.java | 1 -
.../dev/learning/xapi/model/LanguageMap.java | 10 ++++------
4 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
index 8136b638..200286fb 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
@@ -11,14 +11,14 @@
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
/**
- * Specific Locale converter using {@link Locale#forLanguageTag(String)} instead of {@link Locale#Locale(String)}.
+ * Specific Locale converter using {@link Locale#forLanguageTag(String)} instead of
+ * {@link Locale#Locale(String)}.
*
* @author István Rátkai (Selindek)
*/
@@ -31,10 +31,11 @@ public LocaleDeserializer() {
}
@Override
- public Locale deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
+ public Locale deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
+ throws IOException {
if (jsonParser.getCurrentToken() != JsonToken.VALUE_STRING) {
- throw deserializationContext.wrongTokenException(jsonParser, (JavaType) null, JsonToken.VALUE_STRING,
- "Attempted to parse non-String value to Locale");
+ throw deserializationContext.wrongTokenException(jsonParser, (JavaType) null,
+ JsonToken.VALUE_STRING, "Attempted to parse non-String value to Locale");
}
return validateLocale(jsonParser.getValueAsString(), deserializationContext);
@@ -54,7 +55,8 @@ static Locale validateLocale(String localeString, DeserializationContext deseria
}
// test the validity of the whole key
if (locale == null || !locale.toLanguageTag().equalsIgnoreCase(localeString)) {
- throw deserializationContext.weirdStringException(localeString, Locale.class, "Invalid locale");
+ throw deserializationContext.weirdStringException(localeString, Locale.class,
+ "Invalid locale");
}
return locale;
}
@@ -64,13 +66,14 @@ static Locale validateLocale(String localeString, DeserializationContext deseria
* Locale Key Deserializer.
*
* For deserializing Locale keys in {@link Map}s
- *
+ *
* @author István Rátkai (Selindek)
*/
public static class LocaleKeyDeserializer extends KeyDeserializer {
@Override
- public Object deserializeKey(String key, DeserializationContext deserializationContext) throws IOException {
+ public Object deserializeKey(String key, DeserializationContext deserializationContext)
+ throws IOException {
return validateLocale(key, deserializationContext);
}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
index db47198f..02253f2e 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
@@ -12,8 +12,9 @@
import java.util.Map;
/**
- * Specific Locale serializer using {@link Locale#toLanguageTag()} instead of {@link Locale#toString()}.
- *
+ * Specific Locale serializer using {@link Locale#toLanguageTag()} instead of
+ * {@link Locale#toString()}.
+ *
* @author István Rátkai (Selindek)
*/
public class LocaleSerializer extends StdSerializer {
@@ -25,7 +26,8 @@ public LocaleSerializer() {
}
@Override
- public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+ public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider)
+ throws IOException {
gen.writeString(value.toLanguageTag());
}
@@ -46,7 +48,8 @@ public LocaleKeySerializer() {
}
@Override
- public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+ public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider)
+ throws IOException {
gen.writeFieldName(value.toLanguageTag());
}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
index ccdf4b43..eca82581 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
@@ -8,7 +8,6 @@
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-
import dev.learning.xapi.jackson.LocaleDeserializer;
import dev.learning.xapi.jackson.LocaleSerializer;
import dev.learning.xapi.model.validation.constraints.HasScheme;
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 4b3e6e34..5d18d88b 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
@@ -4,6 +4,10 @@
package dev.learning.xapi.model;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import dev.learning.xapi.jackson.LocaleDeserializer;
+import dev.learning.xapi.jackson.LocaleSerializer;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@@ -11,12 +15,6 @@
import java.util.Map;
import java.util.Optional;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-
-import dev.learning.xapi.jackson.LocaleDeserializer;
-import dev.learning.xapi.jackson.LocaleSerializer;
-
/**
* A language map is a dictionary where the key is a RFC 5646 Language Tag, and the value is a
* string in the language specified in the tag.
From 8d5a40488b83f16f4220b209a1a78c36a059d096 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Sat, 18 Mar 2023 07:00:46 +0000
Subject: [PATCH 28/34] Update xapi-model/pom.xml
---
xapi-model/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml
index a124410d..8b21d1f5 100644
--- a/xapi-model/pom.xml
+++ b/xapi-model/pom.xml
@@ -30,7 +30,7 @@
org.hibernate.validator
hibernate-validator
- provided
+ true
org.springframework.boot
From 80fbdad9b3e2cbe5bfe22a9156677a325a0712e0 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Sat, 18 Mar 2023 15:56:31 +0000
Subject: [PATCH 29/34] tip
---
.../{ValidableStatement.java => CoreStatement.java} | 10 ++++++----
.../main/java/dev/learning/xapi/model/Statement.java | 2 +-
.../java/dev/learning/xapi/model/SubStatement.java | 2 +-
.../validators/StatementPlatformValidator.java | 6 +++---
.../validators/StatementRevisionValidator.java | 6 +++---
.../internal/validators/StatementVerbValidator.java | 12 ++++++------
6 files changed, 20 insertions(+), 18 deletions(-)
rename xapi-model/src/main/java/dev/learning/xapi/model/{ValidableStatement.java => CoreStatement.java} (70%)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java
similarity index 70%
rename from xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java
rename to xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java
index 7aaeeb2d..ed7f1e9c 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/ValidableStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java
@@ -5,15 +5,17 @@
package dev.learning.xapi.model;
/**
- * This is a helper interface for signing Statement-like objects which can be targets of
- * class level Statement-validators.
+ * This is a helper interface for signing Statement-like objects which can be targets of class level
+ * Statement-validators.
*
* @author István Rátkai (Selindek)
*/
-public interface ValidableStatement {
+public interface CoreStatement {
+
+ Actor getActor();
Verb getVerb();
-
+
Object getObject();
Context getContext();
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
index 9b071c68..3f0b057e 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Statement.java
@@ -43,7 +43,7 @@
@Builder(toBuilder = true)
@JsonInclude(Include.NON_EMPTY)
@EqualsAndHashCode(of = {"actor", "verb", "object", "result", "context"})
-public class Statement implements ValidableStatement {
+public class Statement implements CoreStatement {
/**
* UUID assigned by LRS if not set by the Learning Record Provider.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index a13ac425..c9dbb53c 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -29,7 +29,7 @@
@ValidStatementPlatform
@ValidStatementRevision
@EqualsAndHashCode(exclude = {"timestamp", "attachments"})
-public class SubStatement implements StatementObject, ValidableStatement {
+public class SubStatement implements StatementObject, CoreStatement {
/**
* Whom the Statement is about, as an Agent or Group Object.
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java
index 388c99cd..ab3a0090 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementPlatformValidator.java
@@ -5,7 +5,7 @@
package dev.learning.xapi.model.validation.internal.validators;
import dev.learning.xapi.model.Activity;
-import dev.learning.xapi.model.ValidableStatement;
+import dev.learning.xapi.model.CoreStatement;
import dev.learning.xapi.model.validation.constraints.ValidStatementPlatform;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
@@ -22,10 +22,10 @@
* Statement Context Requirements
*/
public class StatementPlatformValidator implements
- ConstraintValidator {
+ ConstraintValidator {
@Override
- public boolean isValid(ValidableStatement value, ConstraintValidatorContext context) {
+ public boolean isValid(CoreStatement value, ConstraintValidatorContext context) {
return value == null || value.getContext() == null || value.getContext().getPlatform() == null
|| value.getObject() instanceof Activity;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
index 417e39c6..cbfc33d2 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
@@ -5,7 +5,7 @@
package dev.learning.xapi.model.validation.internal.validators;
import dev.learning.xapi.model.Activity;
-import dev.learning.xapi.model.ValidableStatement;
+import dev.learning.xapi.model.CoreStatement;
import dev.learning.xapi.model.validation.constraints.ValidStatementRevision;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
@@ -22,10 +22,10 @@
* Statement Context Requirements
*/
public class StatementRevisionValidator implements
- ConstraintValidator {
+ ConstraintValidator {
@Override
- public boolean isValid(ValidableStatement value, ConstraintValidatorContext context) {
+ public boolean isValid(CoreStatement value, ConstraintValidatorContext context) {
return value == null || value.getContext() == null || value.getContext().getRevision() == null
|| value.getObject() instanceof Activity;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
index f755923b..71334043 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
@@ -4,8 +4,8 @@
package dev.learning.xapi.model.validation.internal.validators;
+import dev.learning.xapi.model.CoreStatement;
import dev.learning.xapi.model.StatementReference;
-import dev.learning.xapi.model.ValidableStatement;
import dev.learning.xapi.model.validation.constraints.ValidStatementVerb;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
@@ -21,15 +21,15 @@
* @see
* Voiding Statement Requirements
*/
-public class StatementVerbValidator implements
- ConstraintValidator {
+public class StatementVerbValidator
+ implements ConstraintValidator {
@Override
- public boolean isValid(ValidableStatement value, ConstraintValidatorContext context) {
+ public boolean isValid(CoreStatement value, ConstraintValidatorContext context) {
- return value == null || value.getVerb() == null || !value.getVerb().isVoided()
+ return value == null || value.getVerb() == null || !value.getVerb().isVoided()
|| value.getObject() instanceof StatementReference;
-
+
}
}
From 751ffbf8269c2bc50c578116e6b73b6eba42c691 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Sat, 18 Mar 2023 17:19:44 +0000
Subject: [PATCH 30/34] tip
---
.../validation/internal/validators/ActorValidator.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java
index bc45b1ed..4c057a33 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java
@@ -18,7 +18,7 @@
* @author István Rátkai (Selindek)
* @see Actor
*/
-public class ActorValidator implements ConstraintValidator {
+public class ActorValidator implements ConstraintValidator {
/**
* Checks if this {@link Actor} contains exactly one identifier.
@@ -26,7 +26,7 @@ public class ActorValidator implements ConstraintValidator
Date: Sat, 18 Mar 2023 17:52:23 +0000
Subject: [PATCH 31/34] tip
---
.../dev/learning/xapi/model/SubStatement.java | 36 +++++++++++++++++++
.../learning/xapi/model/StatementTests.java | 34 ++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index c9dbb53c..faa911e7 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -86,6 +86,42 @@ public static class Builder {
// This static class extends the lombok builder.
+ /**
+ * Consumer Builder for agent.
+ *
+ * @param agent The Consumer Builder for agent
+ *
+ * @return This builder
+ *
+ * @see SubStatement#actor
+ */
+ public Builder actor(Consumer> agent) {
+
+ // TODO Handle a Group Builder
+
+ final Agent.Builder, ?> builder = Agent.builder();
+
+ agent.accept(builder);
+
+ return actor(builder.build());
+ }
+
+ /**
+ * Sets the agent.
+ *
+ * @param actor The actor of the Statement
+ *
+ * @return This builder
+ *
+ * @see SubStatement#actor
+ */
+ public Builder actor(Actor actor) {
+
+ this.actor = actor;
+
+ return this;
+ }
+
/**
* Consumer Builder for verb.
*
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
index 5ac03318..c2fdcb1c 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
@@ -449,5 +449,39 @@ void whenValidatingStatementWithoutAnActivityThenConstraintViolationsSizeIsOne()
}
+ @Test
+ void whenValidatingStatementWithSubStatementWithStatementRefrenceThenConstraintViolationsSizeIsZero() {
+
+ StatementReference statementRef = StatementReference.builder()
+ .id(UUID.fromString("9e13cefd-53d3-4eac-b5ed-2cf6693903bb")).build();
+
+ SubStatement subStatement = SubStatement.builder()
+
+ .actor(a -> a.name("A N Other").mbox("mailto:another@example.com"))
+
+ .verb(Verb.EXPERIENCED)
+
+ .object(statementRef)
+
+ .build();
+
+ final Statement statement = Statement.builder()
+
+ .actor(a -> a.name("A N Other").mbox("mailto:another@example.com"))
+
+ .verb(Verb.EXPERIENCED)
+
+ .object(subStatement)
+
+ .build();
+
+ // When Validating Statement With SubStatement With StatementRefrence
+ final Set> constraintViolations = validator.validate(statement);
+
+ // Then ConstraintViolations Size Is Zero
+ assertThat(constraintViolations, hasSize(0));
+
+ }
+
}
From 5c8832e0966bb5174a58c5e7b7b86d8c58a30d73 Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Sun, 19 Mar 2023 13:13:22 +0000
Subject: [PATCH 32/34] tip
---
.../learning/xapi/model/CoreStatement.java | 33 +++++++++++++++++--
.../dev/learning/xapi/model/SubStatement.java | 18 ++++++----
.../xapi/model/SubStatementTests.java | 1 +
3 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java
index ed7f1e9c..374d5b3f 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/CoreStatement.java
@@ -4,20 +4,49 @@
package dev.learning.xapi.model;
+import java.time.Instant;
+import java.util.List;
+
/**
- * This is a helper interface for signing Statement-like objects which can be targets of class level
- * Statement-validators.
+ * Contains the methods that are in common between Statement and SubStatement.
*
* @author István Rátkai (Selindek)
*/
public interface CoreStatement {
+ /**
+ * Whom the Statement is about, as an Agent or Group Object.
+ */
Actor getActor();
+ /**
+ * Action taken by the Actor.
+ */
Verb getVerb();
+ /**
+ * Activity, Agent, or another Statement that is the Object of the Statement.
+ */
Object getObject();
+ /**
+ * Result Object, further details representing a measured outcome.
+ */
+ Result getResult();
+
+ /**
+ * Context that gives the Statement more meaning.
+ */
Context getContext();
+ /**
+ * Timestamp of when the events described within this Statement occurred.
+ */
+ Instant getTimestamp();
+
+ /**
+ * Headers for Attachments to the Statement.
+ */
+ List getAttachments();
+
}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
index faa911e7..a7fdab11 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/SubStatement.java
@@ -32,7 +32,7 @@
public class SubStatement implements StatementObject, CoreStatement {
/**
- * Whom the Statement is about, as an Agent or Group Object.
+ * {@inheritDoc}
*/
@NotNull
@Valid
@@ -40,14 +40,18 @@ public class SubStatement implements StatementObject, CoreStatement {
private Actor actor;
/**
- * Action taken by the Actor.
+ * {@inheritDoc}
*/
@NotNull
@Valid
private Verb verb;
/**
- * Activity or Agent.
+ * {@inheritDoc}
+ *
+ *
+ * A SubStatement MUST NOT contain a SubStatement of its own, i.e., cannot be nested.
+ *
*/
@NotNull
@Valid
@@ -55,24 +59,24 @@ public class SubStatement implements StatementObject, CoreStatement {
private SubStatementObject object;
/**
- * Result Object, further details representing a measured outcome.
+ * {@inheritDoc}
*/
@Valid
private Result result;
/**
- * Context that gives the Statement more meaning.
+ * {@inheritDoc}
*/
@Valid
private Context context;
/**
- * Timestamp of when the events described within this Statement occurred.
+ * {@inheritDoc}
*/
private Instant timestamp;
/**
- * Headers for Attachments to the Statement.
+ * {@inheritDoc}
*/
@Valid
private List attachments;
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
index 94c7b5bc..da8eb198 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
@@ -8,6 +8,7 @@
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
From c7587fa694d43ead45964520a3bcf2a82ca862fc Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Sun, 19 Mar 2023 13:53:47 +0000
Subject: [PATCH 33/34] tip
---
.../xapi/jackson/LocaleDeserializer.java | 82 -------------------
.../xapi/jackson/LocaleSerializer.java | 58 -------------
.../java/dev/learning/xapi/model/Context.java | 6 --
.../dev/learning/xapi/model/LanguageMap.java | 6 --
.../xapi/model/ActivityDefinitionTests.java | 40 ++++-----
.../learning/xapi/model/ActivityTests.java | 4 +-
.../dev/learning/xapi/model/ContextTests.java | 6 +-
.../xapi/model/InteractionComponentTests.java | 12 +--
.../learning/xapi/model/LanguageMapTests.java | 2 +-
.../learning/xapi/model/StatementTests.java | 10 +--
.../xapi/model/SubStatementTests.java | 10 +--
.../dev/learning/xapi/model/VerbTests.java | 14 ++--
.../src/test/resources/activity/activity.json | 4 +-
.../activity/activity_with_object_type.json | 4 +-
.../activity_definition.json | 14 ++--
.../activity_definition_without_type.json | 2 +-
.../resources/activity_definition/choice.json | 12 +--
.../activity_definition/true_false.json | 4 +-
.../src/test/resources/context/context.json | 2 +-
.../context_with_empty_registration.json | 2 +-
.../context/context_without_registration.json | 2 +-
.../interaction_component.json | 2 +-
.../test/resources/statement/statement.json | 6 +-
.../sub_statement/sub_statement.json | 8 +-
...ent_with_object_of_type_sub_statement.json | 2 +-
xapi-model/src/test/resources/verb/verb.json | 2 +-
26 files changed, 82 insertions(+), 234 deletions(-)
delete mode 100644 xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
delete mode 100644 xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
diff --git a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
deleted file mode 100644
index 200286fb..00000000
--- a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleDeserializer.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
- */
-
-package dev.learning.xapi.jackson;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.KeyDeserializer;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Map;
-import java.util.MissingResourceException;
-
-/**
- * Specific Locale converter using {@link Locale#forLanguageTag(String)} instead of
- * {@link Locale#Locale(String)}.
- *
- * @author István Rátkai (Selindek)
- */
-public class LocaleDeserializer extends StdDeserializer {
-
- private static final long serialVersionUID = 7182941951585541965L;
-
- public LocaleDeserializer() {
- super(String.class);
- }
-
- @Override
- public Locale deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
- throws IOException {
- if (jsonParser.getCurrentToken() != JsonToken.VALUE_STRING) {
- throw deserializationContext.wrongTokenException(jsonParser, (JavaType) null,
- JsonToken.VALUE_STRING, "Attempted to parse non-String value to Locale");
- }
-
- return validateLocale(jsonParser.getValueAsString(), deserializationContext);
- }
-
- static Locale validateLocale(String localeString, DeserializationContext deserializationContext)
- throws JsonMappingException {
-
- var locale = Locale.forLanguageTag(localeString);
-
- try {
- // test validity of language and country codes (throws exception)
- locale.getISO3Language();
- locale.getISO3Country();
- } catch (final MissingResourceException e) {
- locale = null;
- }
- // test the validity of the whole key
- if (locale == null || !locale.toLanguageTag().equalsIgnoreCase(localeString)) {
- throw deserializationContext.weirdStringException(localeString, Locale.class,
- "Invalid locale");
- }
- return locale;
- }
-
- /**
- *
- * Locale Key Deserializer.
- *
- * For deserializing Locale keys in {@link Map}s
- *
- * @author István Rátkai (Selindek)
- */
- public static class LocaleKeyDeserializer extends KeyDeserializer {
-
- @Override
- public Object deserializeKey(String key, DeserializationContext deserializationContext)
- throws IOException {
-
- return validateLocale(key, deserializationContext);
- }
-
- }
-}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java b/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
deleted file mode 100644
index 02253f2e..00000000
--- a/xapi-model/src/main/java/dev/learning/xapi/jackson/LocaleSerializer.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
- */
-
-package dev.learning.xapi.jackson;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Specific Locale serializer using {@link Locale#toLanguageTag()} instead of
- * {@link Locale#toString()}.
- *
- * @author István Rátkai (Selindek)
- */
-public class LocaleSerializer extends StdSerializer {
-
- private static final long serialVersionUID = 7182941951585541965L;
-
- public LocaleSerializer() {
- super(Locale.class);
- }
-
- @Override
- public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider)
- throws IOException {
- gen.writeString(value.toLanguageTag());
- }
-
- /**
- *
- * Locale Key Serializer.
- *
- * For serializing Locale keys in {@link Map}s
- *
- * @author István Rátkai (Selindek)
- */
- public static class LocaleKeySerializer extends StdSerializer {
-
- private static final long serialVersionUID = 7182941951585541965L;
-
- public LocaleKeySerializer() {
- super(Locale.class);
- }
-
- @Override
- public void serialize(Locale value, JsonGenerator gen, SerializerProvider provider)
- throws IOException {
- gen.writeFieldName(value.toLanguageTag());
- }
-
- }
-
-}
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
index eca82581..8b4fd44d 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/Context.java
@@ -6,10 +6,6 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import dev.learning.xapi.jackson.LocaleDeserializer;
-import dev.learning.xapi.jackson.LocaleSerializer;
import dev.learning.xapi.model.validation.constraints.HasScheme;
import dev.learning.xapi.model.validation.constraints.NotUndetermined;
import dev.learning.xapi.model.validation.constraints.ValidActor;
@@ -77,8 +73,6 @@ public class Context {
* The language in which the experience being recorded in this Statement (mainly) occurred in.
*/
@NotUndetermined
- @JsonSerialize(using = LocaleSerializer.class)
- @JsonDeserialize(using = LocaleDeserializer.class)
private Locale language;
/**
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 5d18d88b..9566f5ed 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
@@ -4,10 +4,6 @@
package dev.learning.xapi.model;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import dev.learning.xapi.jackson.LocaleDeserializer;
-import dev.learning.xapi.jackson.LocaleSerializer;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@@ -24,8 +20,6 @@
* @see Language
* Maps
*/
-@JsonSerialize(keyUsing = LocaleSerializer.LocaleKeySerializer.class)
-@JsonDeserialize(keyUsing = LocaleDeserializer.LocaleKeyDeserializer.class)
public class LanguageMap extends LinkedHashMap {
private static final long serialVersionUID = 7375610804995032187L;
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java
index c34d292a..e8f848a1 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityDefinitionTests.java
@@ -114,7 +114,7 @@ void whenDeserializingActivityDefinitionThenNameIsExpected() throws Exception {
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Name Is Expected
- assertThat(result.getName().get(Locale.US),
+ assertThat(result.getName().get(Locale.ENGLISH),
is("Does the xAPI include the concept of statements?"));
}
@@ -129,7 +129,7 @@ void whenDeserializingActivityDefinitionThenDescriptionIsExpected() throws Excep
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Description Is Expected
- assertThat(result.getDescription().get(Locale.US), is("pong[.]1:[,]dg[.]:10[,]lunch[.]"));
+ assertThat(result.getDescription().get(Locale.ENGLISH), is("pong[.]1:[,]dg[.]:10[,]lunch[.]"));
}
@@ -188,7 +188,7 @@ void whenDeserializingActivityDefinitionWithChoicesThenChoicesDescriptionIsExpec
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Choices Description Is Expected
- assertThat(result.getChoices().get(0).getDescription().get(Locale.US),
+ assertThat(result.getChoices().get(0).getDescription().get(Locale.ENGLISH),
is("Does the xAPI include the concept of statements?"));
}
@@ -218,7 +218,7 @@ void whenDeserializingActivityDefinitionWithScaledThenScaleDescriptionIsExpected
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Scale Description Is Expected
- assertThat(result.getScale().get(0).getDescription().get(Locale.US),
+ assertThat(result.getScale().get(0).getDescription().get(Locale.ENGLISH),
is("Does the xAPI include the concept of statements?"));
}
@@ -248,7 +248,7 @@ void whenDeserializingActivityDefinitionWithSourceThenSourceDescriptionIsExpecte
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Source Description Is Expected
- assertThat(result.getSource().get(0).getDescription().get(Locale.US),
+ assertThat(result.getSource().get(0).getDescription().get(Locale.ENGLISH),
is("Does the xAPI include the concept of statements?"));
}
@@ -278,7 +278,7 @@ void whenDeserializingActivityDefinitionWithTargetThenTargetDescriptionIsExpecte
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Target Description Is Expected
- assertThat(result.getTarget().get(0).getDescription().get(Locale.US),
+ assertThat(result.getTarget().get(0).getDescription().get(Locale.ENGLISH),
is("Does the xAPI include the concept of statements?"));
}
@@ -308,7 +308,7 @@ void whenDeserializingActivityDefinitionWithStepsThenStepsDescriptionIsExpected(
final ActivityDefinition result = objectMapper.readValue(file, ActivityDefinition.class);
// Then Steps Description Is Expected
- assertThat(result.getSteps().get(0).getDescription().get(Locale.US),
+ assertThat(result.getSteps().get(0).getDescription().get(Locale.ENGLISH),
is("Does the xAPI include the concept of statements?"));
}
@@ -319,9 +319,9 @@ void whenSerializingActivityDefinitionOfInteractionTypeTrueFalseThenResultIsEqua
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.US, "True false question")
+ .addName(Locale.ENGLISH, "True false question")
- .addDescription(Locale.US, "Does the xAPI include the concept of statements?")
+ .addDescription(Locale.ENGLISH, "Does the xAPI include the concept of statements?")
.interactionType(InteractionType.TRUE_FALSE)
@@ -347,21 +347,21 @@ void whenSerializingActivityDefinitionOfInteractionTypeChoiceThenResultIsEqualTo
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.US, "Choice")
+ .addName(Locale.ENGLISH, "Choice")
- .addDescription(Locale.US, "Which of these prototypes are available at the beta site?")
+ .addDescription(Locale.ENGLISH, "Which of these prototypes are available at the beta site?")
.interactionType(InteractionType.CHOICE)
.correctResponsesPattern(Collections.singletonList("golf[,]tetris"))
- .addChoice(c -> c.id("golf").addDescription(Locale.US, "Golf Example"))
+ .addChoice(c -> c.id("golf").addDescription(Locale.ENGLISH, "Golf Example"))
- .addChoice(c -> c.id("facebook").addDescription(Locale.US, "Facebook App"))
+ .addChoice(c -> c.id("facebook").addDescription(Locale.ENGLISH, "Facebook App"))
- .addChoice(c -> c.id("tetris").addDescription(Locale.US, "Tetris Example"))
+ .addChoice(c -> c.id("tetris").addDescription(Locale.ENGLISH, "Tetris Example"))
- .addChoice(c -> c.id("scrabble").addDescription(Locale.US, "Scrabble Example"))
+ .addChoice(c -> c.id("scrabble").addDescription(Locale.ENGLISH, "Scrabble Example"))
.type(URI.create("http://adlnet.gov/expapi/activities/cmi.interaction"))
@@ -389,7 +389,7 @@ void whenCallingToStringThenResultIsExpected() throws Exception {
// Then Result Is Expected
assertThat(result, is(
- "ActivityDefinition(name={en_US=Does the xAPI include the concept of statements?}, description={en_US=pong[.]1:[,]dg[.]:10[,]lunch[.]}, type=http://adlnet.gov/expapi/activities/cmi.interaction, moreInfo=http://example.com/more, interactionType=TRUE_FALSE, correctResponsesPattern=[{case_matters=false}{lang=en}To store and provide access to learning experiences.], choices=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], scale=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], source=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], target=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], steps=[InteractionComponent(id=1, description={en_US=Does the xAPI include the concept of statements?})], extensions={http://url=www.example.com})"));
+ "ActivityDefinition(name={en=Does the xAPI include the concept of statements?}, description={en=pong[.]1:[,]dg[.]:10[,]lunch[.]}, type=http://adlnet.gov/expapi/activities/cmi.interaction, moreInfo=http://example.com/more, interactionType=TRUE_FALSE, correctResponsesPattern=[{case_matters=false}{lang=en}To store and provide access to learning experiences.], choices=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], scale=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], source=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], target=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], steps=[InteractionComponent(id=1, description={en=Does the xAPI include the concept of statements?})], extensions={http://url=www.example.com})"));
}
@Test
@@ -398,11 +398,11 @@ void whenBuildingActivityDefinitionWithTwoNameValuesThenNameLanguageMapHasTwoEnt
// When Building ActivityDefinition With Two Name Values
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.US, "True false question")
+ .addName(Locale.ENGLISH, "True false question")
.addName(Locale.GERMAN, "Richtig / Falsch-Frage")
- .addDescription(Locale.US, "Does the xAPI include the concept of statements?")
+ .addDescription(Locale.ENGLISH, "Does the xAPI include the concept of statements?")
.interactionType(InteractionType.TRUE_FALSE)
@@ -423,9 +423,9 @@ void whenBuildingActivityDefinitionWithTwoDescriptionValuesThenDescriptionLangua
// When Building ActivityDefinition With Two Description Values
final ActivityDefinition activityDefinition = ActivityDefinition.builder()
- .addName(Locale.US, "True false question")
+ .addName(Locale.ENGLISH, "True false question")
- .addDescription(Locale.US, "Does the xAPI include the concept of statements?")
+ .addDescription(Locale.ENGLISH, "Does the xAPI include the concept of statements?")
.addDescription(Locale.GERMAN, "Enthält die xAPI das Konzept von Anweisungen?")
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java
index 933dfb1e..f30d4f41 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/ActivityTests.java
@@ -79,9 +79,9 @@ void whenSerializingActivityThenResultIsEqualToExpectedJson() throws IOException
.definition(d -> d
- .addName(Locale.US, "simple statement")
+ .addName(Locale.ENGLISH, "simple statement")
- .addDescription(Locale.US,
+ .addDescription(Locale.ENGLISH,
"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."))
.build();
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java
index c6902fe2..1e834553 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/ContextTests.java
@@ -93,7 +93,7 @@ void whenDeserializingContextThenLanguageIsExpected() throws Exception {
final Context result = objectMapper.readValue(file, Context.class);
// Then Language Is Expected
- assertThat(result.getLanguage(), is(Locale.US));
+ assertThat(result.getLanguage(), is(Locale.ENGLISH));
}
@@ -230,7 +230,7 @@ void whenSerializingContextThenResultIsEqualToExpectedJson() throws IOException
.platform("platform")
- .language(Locale.US)
+ .language(Locale.ENGLISH)
.statementReference(s -> s.id(UUID.fromString("e9b6b9ed-ef48-4986-9b86-2ef697578bf7")))
@@ -268,7 +268,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
// Then Result Is Expected
assertThat(result, is(
- "Context(registration=1d527164-ed0d-4b1d-9f9b-39aab0e4a089, instructor=Agent(super=Actor(name=Andrew Downes, mbox=mailto:andrew@example.co.uk, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=https://example.com/activity/1, definition=null)], grouping=[Activity(id=https://example.com/activity/2, definition=null)], category=[Activity(id=https://example.com/activity/3, definition=null)], other=[Activity(id=https://example.com/activity/4, definition=null)]), revision=revision, platform=platform, language=en_US, statement=StatementReference(id=e9b6b9ed-ef48-4986-9b86-2ef697578bf7), extensions={http://url=www.example.com})"));
+ "Context(registration=1d527164-ed0d-4b1d-9f9b-39aab0e4a089, instructor=Agent(super=Actor(name=Andrew Downes, mbox=mailto:andrew@example.co.uk, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=https://example.com/activity/1, definition=null)], grouping=[Activity(id=https://example.com/activity/2, definition=null)], category=[Activity(id=https://example.com/activity/3, definition=null)], other=[Activity(id=https://example.com/activity/4, definition=null)]), revision=revision, platform=platform, language=en, statement=StatementReference(id=e9b6b9ed-ef48-4986-9b86-2ef697578bf7), extensions={http://url=www.example.com})"));
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java
index 6daa5363..05f986f0 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/InteractionComponentTests.java
@@ -75,7 +75,7 @@ void whenDeserializingInteractionComponentThenDescriptionIsExpected() throws Exc
final InteractionComponent result = objectMapper.readValue(file, InteractionComponent.class);
// Then Description Is Expected
- assertThat(result.getDescription().get(Locale.US), is("value"));
+ assertThat(result.getDescription().get(Locale.ENGLISH), is("value"));
}
@@ -86,7 +86,7 @@ void whenSerializingInteractionComponentThenResultIsEqualToExpectedJson() throws
.id("1")
- .addDescription(Locale.US, "value")
+ .addDescription(Locale.ENGLISH, "value")
.build();
@@ -111,7 +111,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
final String result = interactionComponent.toString();
// Then Result Is Expected
- assertThat(result, is("InteractionComponent(id=1, description={en_US=value})"));
+ assertThat(result, is("InteractionComponent(id=1, description={en=value})"));
}
@@ -120,7 +120,7 @@ void whenBuildingInteractionComponentWithTwoDescriptionValuesThenDisplayLanguage
// When Building InteractionComponent With Two Description Values
final InteractionComponent interactionComponent = InteractionComponent.builder().id("1")
- .addDescription(Locale.US, "value").addDescription(Locale.GERMAN, "Wert").build();
+ .addDescription(Locale.ENGLISH, "value").addDescription(Locale.GERMAN, "Wert").build();
// Then Description Language Map Has Two Entries
assertThat(interactionComponent.getDescription(), aMapWithSize(2));
@@ -131,7 +131,7 @@ void whenBuildingInteractionComponentWithTwoDescriptionValuesThenDisplayLanguage
void whenValidatingInteractionComponentWithAllRequiredPropertiesThenConstraintViolationsSizeIsZero() {
final InteractionComponent interactionComponent =
- InteractionComponent.builder().id("1").addDescription(Locale.US, "value").build();
+ InteractionComponent.builder().id("1").addDescription(Locale.ENGLISH, "value").build();
// When Validating Interaction Component With All Required Properties
final Set> constraintViolations =
@@ -146,7 +146,7 @@ void whenValidatingInteractionComponentWithAllRequiredPropertiesThenConstraintVi
void whenValidatingInteractionComponentWithoutIdThenConstraintViolationsSizeIsOne() {
final InteractionComponent interactionComponent =
- InteractionComponent.builder().addDescription(Locale.US, "value").build();
+ InteractionComponent.builder().addDescription(Locale.ENGLISH, "value").build();
// When Validating Interaction Component Without Id
final Set> constraintViolations =
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java
index 6cb22782..2373e136 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/LanguageMapTests.java
@@ -68,7 +68,7 @@ void givenFrenchAndEnglishKeyWhenGettingUSValueThenValueIsEnglish() throws Excep
// Given French And English Key
languageMap.put(Locale.FRENCH, "Couleur");
- languageMap.put(Locale.US, "Color");
+ languageMap.put(Locale.ENGLISH, "Color");
// When Getting US Value
final String value = languageMap.get(LanguageRange.parse("en-US"));
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
index c2fdcb1c..7a2c3a28 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/StatementTests.java
@@ -240,9 +240,9 @@ void whenSerializingStatementThenResultIsEqualToExpectedJson() throws IOExceptio
final Attachment attachment = Attachment.builder().usageType(URI.create("http://example.com"))
.fileUrl(URI.create("http://example.com"))
- .addDisplay(Locale.US, "value")
+ .addDisplay(Locale.ENGLISH, "value")
- .addDescription(Locale.US, "value")
+ .addDescription(Locale.ENGLISH, "value")
.length(123)
@@ -282,7 +282,7 @@ void whenSerializingStatementThenResultIsEqualToExpectedJson() throws IOExceptio
.platform("Example virtual meeting software")
- .language(Locale.US)
+ .language(Locale.ENGLISH)
.statementReference(s -> s.id(UUID.fromString("6690e6c9-3ef0-4ed3-8b37-7f3964730bee")))
@@ -450,7 +450,7 @@ void whenValidatingStatementWithoutAnActivityThenConstraintViolationsSizeIsOne()
}
@Test
- void whenValidatingStatementWithSubStatementWithStatementRefrenceThenConstraintViolationsSizeIsZero() {
+ void whenValidatingStatementWithSubStatementWithStatementReferenceThenConstraintViolationsSizeIsZero() {
StatementReference statementRef = StatementReference.builder()
.id(UUID.fromString("9e13cefd-53d3-4eac-b5ed-2cf6693903bb")).build();
@@ -475,7 +475,7 @@ void whenValidatingStatementWithSubStatementWithStatementRefrenceThenConstraintV
.build();
- // When Validating Statement With SubStatement With StatementRefrence
+ // When Validating Statement With SubStatement With StatementReference
final Set> constraintViolations = validator.validate(statement);
// Then ConstraintViolations Size Is Zero
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
index da8eb198..4d5e903c 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/SubStatementTests.java
@@ -281,7 +281,7 @@ void whenSerializingSubStatementThenResultIsEqualToExpectedJson() throws IOExcep
.platform("platform")
- .language(Locale.US)
+ .language(Locale.forLanguageTag("en"))
.instructor(agent)
@@ -298,9 +298,9 @@ void whenSerializingSubStatementThenResultIsEqualToExpectedJson() throws IOExcep
final Attachment attachment = Attachment.builder().usageType(URI.create("http://example.com"))
.fileUrl(URI.create("http://example.com"))
- .addDisplay(Locale.US, "value")
+ .addDisplay(Locale.ENGLISH, "value")
- .addDescription(Locale.US, "value")
+ .addDescription(Locale.ENGLISH, "value")
.length(123)
@@ -316,7 +316,7 @@ void whenSerializingSubStatementThenResultIsEqualToExpectedJson() throws IOExcep
.actor(agent)
- .verb(v -> v.id(URI.create("http://example.com/confirmed")).addDisplay(Locale.US,
+ .verb(v -> v.id(URI.create("http://example.com/confirmed")).addDisplay(Locale.ENGLISH,
"confirmed"))
.object(statementRef)
@@ -352,7 +352,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
// Then Result Is Expected
assertThat(result, is(
- "SubStatement(actor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), verb=Verb(id=http://example.com/confirmed, display={en_US=confirmed}), object=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), result=Result(score=Score(scaled=1.0, raw=1.0, min=0.0, max=5.0), success=true, completion=true, response=test, duration=P1D, extensions=null), context=Context(registration=6d969975-8d7e-4506-ac19-877c57f2921a, instructor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], grouping=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], category=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], other=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)]), revision=revision, platform=platform, language=en_US, statement=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), extensions={http://url=www.example.com}), timestamp=2015-11-18T11:17:00Z, attachments=[Attachment(usageType=http://example.com, display={en_US=value}, description={en_US=value}, contentType=file, length=123, sha2=123, fileUrl=http://example.com)])"));
+ "SubStatement(actor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), verb=Verb(id=http://example.com/confirmed, display={en=confirmed}), object=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), result=Result(score=Score(scaled=1.0, raw=1.0, min=0.0, max=5.0), success=true, completion=true, response=test, duration=P1D, extensions=null), context=Context(registration=6d969975-8d7e-4506-ac19-877c57f2921a, instructor=Agent(super=Actor(name=null, mbox=mailto:agent@example.com, mboxSha1sum=null, openid=null, account=null)), team=Group(super=Actor(name=Example Group, mbox=null, mboxSha1sum=null, openid=null, account=null), member=null), contextActivities=ContextActivities(parent=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], grouping=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], category=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)], other=[Activity(id=http://www.example.co.uk/exampleactivity, definition=null)]), revision=revision, platform=platform, language=en, statement=StatementReference(id=9e13cefd-53d3-4eac-b5ed-2cf6693903bb), extensions={http://url=www.example.com}), timestamp=2015-11-18T11:17:00Z, attachments=[Attachment(usageType=http://example.com, display={en=value}, description={en=value}, contentType=file, length=123, sha2=123, fileUrl=http://example.com)])"));
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java
index 5017dcda..6b660629 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/VerbTests.java
@@ -78,7 +78,7 @@ void whenSerializingVerbThenResultIsEqualToExpectedJson() throws IOException {
.id(URI.create("http://adlnet.gov/expapi/verbs/answered"))
- .addDisplay(Locale.US, "answered")
+ .addDisplay(Locale.ENGLISH, "answered")
.build();
@@ -128,7 +128,7 @@ void whenCallingToStringThenResultIsExpected() throws IOException {
// Then Result Is Expected
assertThat(result,
- is("Verb(id=http://adlnet.gov/expapi/verbs/answered, display={en_US=answered})"));
+ is("Verb(id=http://adlnet.gov/expapi/verbs/answered, display={en=answered})"));
}
@@ -187,7 +187,7 @@ void whenBuildingVerbWithTwoDisplayValuesThenDisplayLanguageMapHasTwoEntries() {
.id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.US, "answered")
+ .addDisplay(Locale.ENGLISH, "answered")
.addDisplay(Locale.GERMAN, "antwortete")
@@ -217,7 +217,7 @@ void givenVerbWithoutDisplayPropertyWhenTestingEqualityWithVerbWithDisplayProper
.id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.US, "answered")
+ .addDisplay(Locale.ENGLISH, "answered")
.build());
@@ -243,7 +243,7 @@ void givenVerbWithGermanDisplayPropertyWhenTestingEqualityWithVerbWithEnglishDis
.id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.US, "answered")
+ .addDisplay(Locale.ENGLISH, "answered")
.build());
@@ -318,7 +318,7 @@ void givenVerbDoesNotHaveIdVoidedWhenCallingIsVoidedThenResultIsFalse() {
void whenValidatingVerbWithAllRequiredPropertiesThenConstraintViolationsSizeIsZero() {
final Verb verb = Verb.builder().id("http://adlnet.gov/expapi/verbs/answered")
- .addDisplay(Locale.US, "answered").build();
+ .addDisplay(Locale.ENGLISH, "answered").build();
// When Validating Interaction Component With All Required Properties
final Set> constraintViolations = validator.validate(verb);
@@ -331,7 +331,7 @@ void whenValidatingVerbWithAllRequiredPropertiesThenConstraintViolationsSizeIsZe
@Test
void whenValidatingVerbWithoutIdThenConstraintViolationsSizeIsOne() {
- final Verb verb = Verb.builder().addDisplay(Locale.US, "answered").build();
+ final Verb verb = Verb.builder().addDisplay(Locale.ENGLISH, "answered").build();
// When Validating Interaction Component Without Id
final Set> constraintViolations = validator.validate(verb);
diff --git a/xapi-model/src/test/resources/activity/activity.json b/xapi-model/src/test/resources/activity/activity.json
index 138307a8..b4627ef1 100644
--- a/xapi-model/src/test/resources/activity/activity.json
+++ b/xapi-model/src/test/resources/activity/activity.json
@@ -2,10 +2,10 @@
"id":"http://example.com/xapi/activity/simplestatement",
"definition":{
"name":{
- "en-US":"simple statement"
+ "en":"simple statement"
},
"description":{
- "en-US":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
+ "en":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
}
}
}
\ No newline at end of file
diff --git a/xapi-model/src/test/resources/activity/activity_with_object_type.json b/xapi-model/src/test/resources/activity/activity_with_object_type.json
index b9825af2..adfae696 100644
--- a/xapi-model/src/test/resources/activity/activity_with_object_type.json
+++ b/xapi-model/src/test/resources/activity/activity_with_object_type.json
@@ -3,10 +3,10 @@
"id":"http://example.com/xapi/activity/simplestatement",
"definition":{
"name":{
- "en-US":"simple statement"
+ "en":"simple statement"
},
"description":{
- "en-US":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
+ "en":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object."
}
}
}
\ No newline at end of file
diff --git a/xapi-model/src/test/resources/activity_definition/activity_definition.json b/xapi-model/src/test/resources/activity_definition/activity_definition.json
index 31a19763..b6cad8f5 100644
--- a/xapi-model/src/test/resources/activity_definition/activity_definition.json
+++ b/xapi-model/src/test/resources/activity_definition/activity_definition.json
@@ -6,40 +6,40 @@
"http://url" : "www.example.com"
},
"name" : {
- "en-US" : "Does the xAPI include the concept of statements?"
+ "en" : "Does the xAPI include the concept of statements?"
},
"description" : {
- "en-US" : "pong[.]1:[,]dg[.]:10[,]lunch[.]"
+ "en" : "pong[.]1:[,]dg[.]:10[,]lunch[.]"
},
"type" : "http://adlnet.gov/expapi/activities/cmi.interaction",
"choices" : [ {
"id" : "1",
"description" : {
- "en-US" : "Does the xAPI include the concept of statements?"
+ "en" : "Does the xAPI include the concept of statements?"
}
} ],
"scale" : [ {
"id" : "1",
"description" : {
- "en-US" : "Does the xAPI include the concept of statements?"
+ "en" : "Does the xAPI include the concept of statements?"
}
} ],
"source" : [ {
"id" : "1",
"description" : {
- "en-US" : "Does the xAPI include the concept of statements?"
+ "en" : "Does the xAPI include the concept of statements?"
}
} ],
"target" : [ {
"id" : "1",
"description" : {
- "en-US" : "Does the xAPI include the concept of statements?"
+ "en" : "Does the xAPI include the concept of statements?"
}
} ],
"steps" : [ {
"id" : "1",
"description" : {
- "en-US" : "Does the xAPI include the concept of statements?"
+ "en" : "Does the xAPI include the concept of statements?"
}
} ]
}
diff --git a/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json b/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json
index 90c3470c..505fb28e 100644
--- a/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json
+++ b/xapi-model/src/test/resources/activity_definition/activity_definition_without_type.json
@@ -1,6 +1,6 @@
{
"description": {
- "en-US": "Does the xAPI include the concept of statements?"
+ "en": "Does the xAPI include the concept of statements?"
},
"interactionType": "fill-in",
"correctResponsesPattern": [
diff --git a/xapi-model/src/test/resources/activity_definition/choice.json b/xapi-model/src/test/resources/activity_definition/choice.json
index cf411f4a..1d1bfbad 100644
--- a/xapi-model/src/test/resources/activity_definition/choice.json
+++ b/xapi-model/src/test/resources/activity_definition/choice.json
@@ -1,9 +1,9 @@
{
"name": {
- "en-US": "Choice"
+ "en": "Choice"
},
"description": {
- "en-US": "Which of these prototypes are available at the beta site?"
+ "en": "Which of these prototypes are available at the beta site?"
},
"type": "http://adlnet.gov/expapi/activities/cmi.interaction",
"interactionType": "choice",
@@ -14,25 +14,25 @@
{
"id": "golf",
"description": {
- "en-US": "Golf Example"
+ "en": "Golf Example"
}
},
{
"id": "facebook",
"description": {
- "en-US": "Facebook App"
+ "en": "Facebook App"
}
},
{
"id": "tetris",
"description": {
- "en-US": "Tetris Example"
+ "en": "Tetris Example"
}
},
{
"id": "scrabble",
"description": {
- "en-US": "Scrabble Example"
+ "en": "Scrabble Example"
}
}
]
diff --git a/xapi-model/src/test/resources/activity_definition/true_false.json b/xapi-model/src/test/resources/activity_definition/true_false.json
index b1a64e3a..6523da45 100644
--- a/xapi-model/src/test/resources/activity_definition/true_false.json
+++ b/xapi-model/src/test/resources/activity_definition/true_false.json
@@ -1,9 +1,9 @@
{
"name":{
- "en-US":"True false question"
+ "en":"True false question"
},
"description":{
- "en-US":"Does the xAPI include the concept of statements?"
+ "en":"Does the xAPI include the concept of statements?"
},
"type":"http://adlnet.gov/expapi/activities/cmi.interaction",
"interactionType":"true-false",
diff --git a/xapi-model/src/test/resources/context/context.json b/xapi-model/src/test/resources/context/context.json
index bb044dca..06d476a4 100644
--- a/xapi-model/src/test/resources/context/context.json
+++ b/xapi-model/src/test/resources/context/context.json
@@ -2,7 +2,7 @@
"registration": "1d527164-ed0d-4b1d-9f9b-39aab0e4a089",
"revision": "revision",
"platform": "platform",
- "language": "en-US",
+ "language": "en",
"instructor": {
"objectType": "Agent",
"name": "Andrew Downes",
diff --git a/xapi-model/src/test/resources/context/context_with_empty_registration.json b/xapi-model/src/test/resources/context/context_with_empty_registration.json
index 59e0f7af..990ffb74 100644
--- a/xapi-model/src/test/resources/context/context_with_empty_registration.json
+++ b/xapi-model/src/test/resources/context/context_with_empty_registration.json
@@ -2,7 +2,7 @@
"registration": "",
"revision": "revision",
"platform": "platform",
- "language": "en-US",
+ "language": "en",
"instructor": {
"name": "Andrew Downes",
"mbox": "mailto:andrew@example.co.uk"
diff --git a/xapi-model/src/test/resources/context/context_without_registration.json b/xapi-model/src/test/resources/context/context_without_registration.json
index 50f37e08..cd324ee9 100644
--- a/xapi-model/src/test/resources/context/context_without_registration.json
+++ b/xapi-model/src/test/resources/context/context_without_registration.json
@@ -1,7 +1,7 @@
{
"revision": "revision",
"platform": "platform",
- "language": "en-US",
+ "language": "en",
"instructor": {
"name": "Andrew Downes",
"mbox": "mailto:andrew@example.co.uk"
diff --git a/xapi-model/src/test/resources/interaction_component/interaction_component.json b/xapi-model/src/test/resources/interaction_component/interaction_component.json
index 546d196b..b01f6834 100644
--- a/xapi-model/src/test/resources/interaction_component/interaction_component.json
+++ b/xapi-model/src/test/resources/interaction_component/interaction_component.json
@@ -1,6 +1,6 @@
{
"id": "1",
"description": {
- "en-US": "value"
+ "en": "value"
}
}
diff --git a/xapi-model/src/test/resources/statement/statement.json b/xapi-model/src/test/resources/statement/statement.json
index 0f1baf6f..c0b6e5ee 100644
--- a/xapi-model/src/test/resources/statement/statement.json
+++ b/xapi-model/src/test/resources/statement/statement.json
@@ -32,7 +32,7 @@
"objectType": "Group"
},
"platform": "Example virtual meeting software",
- "language": "en-US",
+ "language": "en",
"statement": {
"objectType": "StatementRef",
"id": "6690e6c9-3ef0-4ed3-8b37-7f3964730bee"
@@ -69,10 +69,10 @@
{
"usageType": "http://example.com",
"display": {
- "en-US": "value"
+ "en": "value"
},
"description": {
- "en-US": "value"
+ "en": "value"
},
"contentType": "file",
"length": 123,
diff --git a/xapi-model/src/test/resources/sub_statement/sub_statement.json b/xapi-model/src/test/resources/sub_statement/sub_statement.json
index a4db3e02..58955494 100644
--- a/xapi-model/src/test/resources/sub_statement/sub_statement.json
+++ b/xapi-model/src/test/resources/sub_statement/sub_statement.json
@@ -4,7 +4,7 @@
"verb" : {
"id" : "http://example.com/confirmed",
"display" : {
- "en-US" : "confirmed"
+ "en" : "confirmed"
}
},
"actor" : {
@@ -31,7 +31,7 @@
"registration" : "6d969975-8d7e-4506-ac19-877c57f2921a",
"revision" : "revision",
"platform" : "platform",
- "language" : "en-US",
+ "language" : "en",
"instructor" : {
"objectType" : "Agent",
"mbox" : "mailto:agent@example.com"
@@ -69,10 +69,10 @@
"attachments" : [ {
"usageType" : "http://example.com",
"display" : {
- "en-US" : "value"
+ "en" : "value"
},
"description" : {
- "en-US" : "value"
+ "en" : "value"
},
"contentType" : "file",
"length" : 123,
diff --git a/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json b/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json
index e5c65d94..4b6cd007 100644
--- a/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json
+++ b/xapi-model/src/test/resources/sub_statement/sub_statement_with_object_of_type_sub_statement.json
@@ -19,7 +19,7 @@
"verb":{
"id":"http://example.com/confirmed",
"display":{
- "en-US":"confirmed"
+ "en":"confirmed"
}
},
"object":{
diff --git a/xapi-model/src/test/resources/verb/verb.json b/xapi-model/src/test/resources/verb/verb.json
index 5d9236b9..78c1c7c7 100644
--- a/xapi-model/src/test/resources/verb/verb.json
+++ b/xapi-model/src/test/resources/verb/verb.json
@@ -1,6 +1,6 @@
{
"id": "http://adlnet.gov/expapi/verbs/answered",
"display": {
- "en-US": "answered"
+ "en": "answered"
}
}
From 52097e6035473a3b2ba6995541b86930c6e54fca Mon Sep 17 00:00:00 2001
From: Thomas Turrell-Croft
Date: Sun, 19 Mar 2023 14:46:24 +0000
Subject: [PATCH 34/34] tip
---
.../ActivityDefinitionValidator.java | 12 +-
.../ActivityDefinitionValidatorTests.java | 123 +++++++++++++++---
2 files changed, 113 insertions(+), 22 deletions(-)
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java
index 5e4546b4..8da803d9 100644
--- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidator.java
@@ -13,10 +13,11 @@
* The {@link ActivityDefinition} being validated must be valid.
*
* @author István Rátkai (Selindek)
- * @see Activity
+ * @see Activity
* Definition
*/
-public class ActivityDefinitionValidator
+public class ActivityDefinitionValidator
implements ConstraintValidator {
@Override
@@ -26,10 +27,9 @@ public boolean isValid(ActivityDefinition value, ConstraintValidatorContext cont
return true;
}
- return !(value.getInteractionType() == null
- && (value.getCorrectResponsesPattern() != null || value.getChoices() != null
- || value.getScale() != null || value.getSource() != null || value.getTarget() != null
- || value.getSteps() != null));
+ return !(value.getInteractionType() == null && (value.getCorrectResponsesPattern() != null
+ || value.getChoices() != null || value.getScale() != null || value.getSource() != null
+ || value.getTarget() != null || value.getSteps() != null));
}
diff --git a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
index 0cd6484f..15ca16c2 100644
--- a/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
+++ b/xapi-model/src/test/java/dev/learning/xapi/model/validation/internal/validators/ActivityDefinitionValidatorTests.java
@@ -24,22 +24,33 @@ class ActivityDefinitionValidatorTests {
private static final ActivityDefinitionValidator validator = new ActivityDefinitionValidator();
@Test
- void whenValueIsNullThenResultIsTrue() {
+ void whenIsValidIsCalledWithNullActivityDefinitionThenResultIsTrue() {
- // When Value Is Null
+ // When IsValid Is Called With Null Activity Definition
var result = validator.isValid(null, null);
// Then Result Is True
assertTrue(result);
}
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThenResultIsTrue() {
+
+ var value = ActivityDefinition.builder().build();
+
+ // When IsValid Is Called With Activity Definition
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
@Test
- void whenValueHasInteractionTypeThenResultIsTrue() {
+ void whenIsValidIsCalledWithActivityDefinitionThatHasInteractionTypeThenResultIsTrue() {
- // When Value Has InteractionType
var value = ActivityDefinition.builder().interactionType(InteractionType.CHOICE).build();
+ // When IsValid Is Called With Activity Definition That Has Interaction Type
var result = validator.isValid(value, null);
// Then Result Is True
@@ -47,11 +58,11 @@ void whenValueHasInteractionTypeThenResultIsTrue() {
}
@Test
- void whenValueHasNoInteractionTypeButHasCorrectResponsepatternThenResultIsFalse() {
+ void whenIsValidIsCalledWithActivityDefinitionThatHasCorrectResponsesPatternThenResultIsFalse() {
- // When Value Has No InteractionType But Has CorrectResponsePatters
var value = ActivityDefinition.builder().correctResponsesPattern(new ArrayList<>()).build();
+ // When IsValid Is Called With Activity Definition That Has Correct Responses Pattern
var result = validator.isValid(value, null);
// Then Result Is False
@@ -59,11 +70,25 @@ void whenValueHasNoInteractionTypeButHasCorrectResponsepatternThenResultIsFalse(
}
@Test
- void whenValueHasNoInteractionTypeButHasChoicesThenResultIsFalse() {
+ void whenIsValidIsCalledWithActivityDefinitionThatHasCorrectResponsesPatternAndInteractionTypeThenResultIsTrue() {
+
+ var value = ActivityDefinition.builder().correctResponsesPattern(new ArrayList<>())
+ .interactionType(InteractionType.CHOICE).build();
+
+ // When IsValid Is Called With Activity Definition That Has Correct Responses Pattern And
+ // InteractionType
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThatHasChoicesThenResultIsFalse() {
- // When Value Has No InteractionType But Has Choices
var value = ActivityDefinition.builder().choices(new ArrayList<>()).build();
+ // When IsValid Is Called With Activity Definition That Has Choices
var result = validator.isValid(value, null);
// Then Result Is False
@@ -71,11 +96,24 @@ void whenValueHasNoInteractionTypeButHasChoicesThenResultIsFalse() {
}
@Test
- void whenValueHasNoInteractionTypeButHasScaleThenResultIsFalse() {
+ void whenIsValidIsCalledWithActivityDefinitionThatHasChoicesAndInteractionTypeThenResultIsTrue() {
+
+ var value = ActivityDefinition.builder().choices(new ArrayList<>())
+ .interactionType(InteractionType.CHOICE).build();
+
+ // When IsValid Is Called With Activity Definition That Has Choices And InteractionType
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThatHasScaleThenResultIsFalse() {
- // When Value Has No InteractionType But Has Scale
var value = ActivityDefinition.builder().scale(new ArrayList<>()).build();
+ // When IsValid Is Called With Activity Definition That Has Scale
var result = validator.isValid(value, null);
// Then Result Is False
@@ -83,11 +121,24 @@ void whenValueHasNoInteractionTypeButHasScaleThenResultIsFalse() {
}
@Test
- void whenValueHasNoInteractionTypeButHasSourceThenResultIsFalse() {
+ void whenIsValidIsCalledWithActivityDefinitionThatHasScaleAndInteractionTypeThenResultIsTrue() {
+
+ var value = ActivityDefinition.builder().scale(new ArrayList<>())
+ .interactionType(InteractionType.LIKERT).build();
+
+ // When IsValid Is Called With Activity Definition That Has Scale And InteractionType
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThatHasSourceThenResultIsFalse() {
- // When Value Has No InteractionType But Has Source
var value = ActivityDefinition.builder().source(new ArrayList<>()).build();
+ // When IsValid Is Called With Activity Definition That Has Source
var result = validator.isValid(value, null);
// Then Result Is False
@@ -95,9 +146,22 @@ void whenValueHasNoInteractionTypeButHasSourceThenResultIsFalse() {
}
@Test
- void whenValueHasNoInteractionTypeButHasTargetThenResultIsFalse() {
+ void whenIsValidIsCalledWithActivityDefinitionAndInteractionTypeThatHasSourceThenResultIsTrue() {
+
+ var value = ActivityDefinition.builder().source(new ArrayList<>())
+ .interactionType(InteractionType.MATCHING).build();
+
+ // When IsValid Is Called With Activity Definition That Has Source And InteractionType
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThatHasTargetThenResultIsFalse() {
- // When Value Has No InteractionType But Has Target
+ // When IsValid Is Called With Activity Definition That Has Target
var value = ActivityDefinition.builder().target(new ArrayList<>()).build();
var result = validator.isValid(value, null);
@@ -107,16 +171,43 @@ void whenValueHasNoInteractionTypeButHasTargetThenResultIsFalse() {
}
@Test
- void whenValueHasNoInteractionTypeButHasStepsThenResultIsFalse() {
+ void whenIsValidIsCalledWithActivityDefinitionThatHasTargetAndInteractionTypeThenResultIsTrue() {
+
+ // When IsValid Is Called With Activity Definition That Has Target And InteractionType
+ var value = ActivityDefinition.builder().target(new ArrayList<>())
+ .interactionType(InteractionType.MATCHING).build();
+
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
+
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThatHasStepsThenResultIsFalse() {
- // When Value Has No InteractionType But Has Steps
var value = ActivityDefinition.builder().steps(new ArrayList<>()).build();
+ // When IsValid Is Called With Activity Definition That Has Steps
var result = validator.isValid(value, null);
// Then Result Is False
assertFalse(result);
}
+ @Test
+ void whenIsValidIsCalledWithActivityDefinitionThatHasStepsAndInteractionTypeThenResultIsTrue() {
+
+ var value = ActivityDefinition.builder().steps(new ArrayList<>())
+ .interactionType(InteractionType.PERFORMANCE).build();
+
+ // When IsValid Is Called With Activity Definition That Has Steps And InteractionType
+ var result = validator.isValid(value, null);
+
+ // Then Result Is True
+ assertTrue(result);
+ }
+
}