From f5d7531d996e6522fb4c73ad2561d22bb22f6f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Wed, 15 Mar 2023 17:08:55 +0000 Subject: [PATCH 01/11] add validators Mbox AllowedLocale ScaledScore ActivityDefinitionValidator ActorValidator --- 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 | 8 +- .../dev/learning/xapi/model/SubStatement.java | 5 + .../model/validation/constraints/Mbox.java | 47 ++++ .../constraints/NotUndetermined.java | 48 ++++ .../validation/constraints/ScaledScore.java | 47 ++++ .../constraints/ValidActivityDefinition.java | 49 ++++ .../validation/constraints/ValidActor.java | 49 ++++ .../constraints/ValidStatement.java | 44 ++++ .../ActivityDefinitionValidator.java | 36 +++ .../internal/validators/ActorValidator.java | 67 +++++ .../internal/validators/MboxValidator.java | 42 +++ .../validators/NotUndeterminedValidator.java | 30 +++ .../validators/ScaledScoreValidator.java | 29 +++ .../validators/ValidatorForStatement.java | 106 ++++++++ .../validators/ValidatorForSubStatement.java | 59 +++++ .../jakarta.validation.ConstraintValidator | 7 + .../ActivityDefinitionValidatorTest.java | 122 +++++++++ .../validators/ActorValidatorTest.java | 246 ++++++++++++++++++ .../validators/MboxValidatorTest.java | 103 ++++++++ .../NotUndeterminedValidatorTest.java | 54 ++++ .../validators/ScaledScoreValidatorTest.java | 93 +++++++ 31 files changed, 1315 insertions(+), 6 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/constraints/ValidStatement.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/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 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..b76cbdc9 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,8 @@ 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.ValidAuthority; +import dev.learning.xapi.model.validation.constraints.ValidActor; +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; @@ -38,6 +39,7 @@ @JsonIgnoreProperties("inProgress") @JsonInclude(Include.NON_EMPTY) @EqualsAndHashCode(of = {"actor", "verb", "object", "result", "context"}) +@ValidStatement public class Statement { /** @@ -51,6 +53,7 @@ public class Statement { */ @NotNull @Valid + @ValidActor private Actor actor; /** @@ -65,6 +68,7 @@ public class Statement { */ @NotNull @Valid + @ValidActor private StatementObject object; /** @@ -92,7 +96,7 @@ public class Statement { /** * Agent or Group who is asserting this Statement is true. */ - @ValidAuthority + @ValidActor 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..28a81897 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,8 @@ package dev.learning.xapi.model; +import dev.learning.xapi.model.validation.constraints.ValidActor; +import dev.learning.xapi.model.validation.constraints.ValidStatement; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import java.time.Instant; @@ -24,6 +26,7 @@ @Value @Builder @EqualsAndHashCode(exclude = {"timestamp", "attachments"}) +@ValidStatement public class SubStatement implements StatementObject { /** @@ -31,6 +34,7 @@ public class SubStatement implements StatementObject { */ @NotNull @Valid + @ValidActor private Actor actor; /** @@ -45,6 +49,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..b55c5b52 --- /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[] 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..7132b363 --- /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 "Locale is not allowed"; + + /** + * Groups. + */ + Class[] groups() default {}; + + /** + * Payload. + */ + Class[] 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..aabe8dbe --- /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[] 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..8370b72e --- /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[] 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..55b196a4 --- /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 contain exactly one identifier"; + + /** + * Groups. + */ + Class[] groups() default {}; + + /** + * Payload. + */ + Class[] payload() default {}; +} 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[] 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..6bf074df --- /dev/null +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ActorValidator.java @@ -0,0 +1,67 @@ +/* + * 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 == null) { + return true; + } + + 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/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 3b87ca48..57164749 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,10 @@ 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 +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 annotationType() { + return null; + } + + @Override + public Class[] 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 f2acbfb0c988309659a389d9f5f4f1670d1eab6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Fri, 17 Mar 2023 09:04:40 +0000 Subject: [PATCH 02/11] fix messed up merge --- xapi-model/src/main/java/dev/learning/xapi/model/Statement.java | 2 ++ 1 file changed, 2 insertions(+) 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 b76cbdc9..8f6b2ce9 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 @@ -9,6 +9,7 @@ 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.ValidStatement; import dev.learning.xapi.model.validation.constraints.Variant; import jakarta.validation.Valid; @@ -97,6 +98,7 @@ public class Statement { * Agent or Group who is asserting this Statement is true. */ @ValidActor + @ValidAuthority private Actor authority; /** From 3600d05b0f661dbe2cb1da64c1885b06031298b5 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 09:54:35 +0000 Subject: [PATCH 03/11] Apply suggestions from code review --- xapi-model/src/main/java/dev/learning/xapi/model/Statement.java | 1 - 1 file changed, 1 deletion(-) 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 8f6b2ce9..22bd0744 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 @@ -10,7 +10,6 @@ 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.ValidStatement; import dev.learning.xapi.model.validation.constraints.Variant; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; From 2dd89ebdbe09f8f649eb16cfdefbb68298be5f63 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 09:56:09 +0000 Subject: [PATCH 04/11] Update xapi-model/src/main/java/dev/learning/xapi/model/Statement.java --- xapi-model/src/main/java/dev/learning/xapi/model/Statement.java | 1 - 1 file changed, 1 deletion(-) 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 22bd0744..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 @@ -39,7 +39,6 @@ @JsonIgnoreProperties("inProgress") @JsonInclude(Include.NON_EMPTY) @EqualsAndHashCode(of = {"actor", "verb", "object", "result", "context"}) -@ValidStatement public class Statement { /** From 734477142a32996bca888cc15668a38cb475ac6b Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 10:02:13 +0000 Subject: [PATCH 05/11] Apply suggestions from code review --- .../src/main/java/dev/learning/xapi/model/SubStatement.java | 2 -- .../dev/learning/xapi/model/validation/constraints/Mbox.java | 2 +- .../xapi/model/validation/constraints/NotUndetermined.java | 2 +- .../learning/xapi/model/validation/constraints/ScaledScore.java | 2 +- .../model/validation/constraints/ValidActivityDefinition.java | 2 +- .../learning/xapi/model/validation/constraints/ValidActor.java | 2 +- 6 files changed, 5 insertions(+), 7 deletions(-) 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 28a81897..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 @@ -5,7 +5,6 @@ package dev.learning.xapi.model; import dev.learning.xapi.model.validation.constraints.ValidActor; -import dev.learning.xapi.model.validation.constraints.ValidStatement; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import java.time.Instant; @@ -26,7 +25,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/Mbox.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Mbox.java index b55c5b52..11b16e6c 100644 --- 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 @@ -33,7 +33,7 @@ /** * Error Message. */ - String message() default "Must be a valid mbox"; + String message() default "must be a valid mbox"; /** * Groups. 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 index 7132b363..24ef0e0f 100644 --- 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 @@ -33,7 +33,7 @@ /** * Error Message. */ - String message() default "Locale is not allowed"; + String message() default "undetermined (und) locale is not allowed"; /** * Groups. 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 index aabe8dbe..970c34dc 100644 --- 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 @@ -33,7 +33,7 @@ /** * Error Message. */ - String message() default "Scaled score must be between -1 and 1"; + String message() default "scaled score must be between -1 and 1"; /** * Groups. 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 index 8370b72e..ba5c4046 100644 --- 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 @@ -35,7 +35,7 @@ /** * Error Message. */ - String message() default "Must be a valid Activity Definition"; + String message() default "must be a valid Activity Definition"; /** * Groups. 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 index 55b196a4..1288545c 100644 --- 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 @@ -35,7 +35,7 @@ /** * Error Message. */ - String message() default "Actor must contain exactly one identifier"; + String message() default "actor must contain exactly one identifier"; /** * Groups. From d11bf0a24243fe1575cd01621ec1990992c1cf62 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 10:02:26 +0000 Subject: [PATCH 06/11] Delete ValidStatement.java --- .../constraints/ValidStatement.java | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java 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 deleted file mode 100644 index 8d3843eb..00000000 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidStatement.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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[] payload() default {}; - -} From 6f571d5dc1da488406a6d80ecb4dab77bac1c134 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 10:08:52 +0000 Subject: [PATCH 07/11] Update ActorValidator.java --- .../model/validation/internal/validators/ActorValidator.java | 4 ---- 1 file changed, 4 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 6bf074df..bc45b1ed 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 @@ -28,10 +28,6 @@ public class ActorValidator implements ConstraintValidator Date: Fri, 17 Mar 2023 10:14:21 +0000 Subject: [PATCH 08/11] Delete ValidatorForStatement.java --- .../validators/ValidatorForStatement.java | 106 ------------------ 1 file changed, 106 deletions(-) delete mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.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 4ec25049..00000000 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForStatement.java +++ /dev/null @@ -1,106 +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.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; - } - -} From 7c31889a19cba2561bafcee1accf250bbba4c14d Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 10:16:51 +0000 Subject: [PATCH 09/11] Delete ValidatorForSubStatement.java --- .../validators/ValidatorForSubStatement.java | 59 ------------------- 1 file changed, 59 deletions(-) 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/ValidatorForSubStatement.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ValidatorForSubStatement.java deleted file mode 100644 index 92903357..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 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; - } - -} From 2bbae457e15509379719520d265ceb606bdb5db5 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 10:18:19 +0000 Subject: [PATCH 10/11] Update jakarta.validation.ConstraintValidator --- .../META-INF/services/jakarta.validation.ConstraintValidator | 2 -- 1 file changed, 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 57164749..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,8 +1,6 @@ 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 dev.learning.xapi.model.validation.internal.validators.NotUndeterminedValidator dev.learning.xapi.model.validation.internal.validators.MboxValidator dev.learning.xapi.model.validation.internal.validators.ScaledScoreValidator From 61772cfbfaa6ae3f12ab294b3ceca6ff9edb0174 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 17 Mar 2023 10:19:13 +0000 Subject: [PATCH 11/11] Update xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidActor.java --- .../learning/xapi/model/validation/constraints/ValidActor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 1288545c..d9c8c3c1 100644 --- 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 @@ -35,7 +35,7 @@ /** * Error Message. */ - String message() default "actor must contain exactly one identifier"; + String message() default "actor must be valid"; /** * Groups.