From c05b02b30567fadfc39183012d500f1b99cc42a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Wed, 19 Apr 2023 12:41:37 +0100 Subject: [PATCH 01/12] add customizable validators --- .../src/main/resources/application.properties | 28 +++++++++--- .../xapi/XapiModelAutoConfiguration.java | 44 +++++++++---------- ...ot.autoconfigure.AutoConfiguration.imports | 1 + xapi-model/pom.xml | 5 +++ .../validation/constraints/HasScheme.java | 4 +- .../model/validation/constraints/Mbox.java | 3 +- .../constraints/NotUndetermined.java | 3 +- .../validation/constraints/ScaledScore.java | 3 +- .../validation/constraints/Statements.java | 4 +- .../validation/constraints/VaildScore.java | 4 +- .../constraints/ValidActivityDefinition.java | 3 +- .../validation/constraints/ValidActor.java | 3 +- .../constraints/ValidAuthority.java | 4 +- .../constraints/ValidStatementPlatform.java | 3 +- .../constraints/ValidStatementRevision.java | 3 +- .../constraints/ValidStatementVerb.java | 3 +- .../model/validation/constraints/Variant.java | 4 +- .../ActivityDefinitionValidator.java | 6 ++- .../internal/validators/ActorValidator.java | 8 ++++ .../validators/AuthorityValidator.java | 6 ++- .../validators/HasSchemeValidatorForUri.java | 6 ++- .../internal/validators/MboxValidator.java | 7 ++- .../validators/NotUndeterminedValidator.java | 6 ++- .../validators/ScaledScoreValidator.java | 6 ++- .../internal/validators/ScoreValidator.java | 6 ++- .../StatementPlatformValidator.java | 8 +++- .../StatementRevisionValidator.java | 8 +++- .../validators/StatementVerbValidator.java | 10 +++-- .../validators/StatementsValidator.java | 6 ++- .../validators/VariantValidatorForUuid.java | 6 ++- .../jakarta.validation.ConstraintValidator | 13 ------ .../src/main/resources/application.properties | 0 32 files changed, 152 insertions(+), 72 deletions(-) delete mode 100644 xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator delete mode 100644 xapi-model/src/main/resources/application.properties diff --git a/samples/xapi-server/src/main/resources/application.properties b/samples/xapi-server/src/main/resources/application.properties index 3c1776c4..b7435a3b 100644 --- a/samples/xapi-server/src/main/resources/application.properties +++ b/samples/xapi-server/src/main/resources/application.properties @@ -5,12 +5,26 @@ # with a wider range of xAPI activity providers. However, doing this is in violation of the xAPI # specification. -xApi.model.strictProperties = true -xApi.model.strictJson = true +xApi.model.validateProperties = true +xApi.model.validateJson = true -xApi.model.strictLocale = true -xApi.model.strictTimestamp = true -xApi.model.strictNullValues = true -xApi.model.strictLiterals = true +xApi.model.validateLocale = true +xApi.model.validateTimestamp = true +xApi.model.validateNullValues = true +xApi.model.validateLiterals = true -xApi.model.strictObjectType = true \ No newline at end of file +xApi.model.validateObjectType = true + +xApi.model.validateActivityDefinition = false +xApi.model.validateActor = false +xApi.model.validateAuthority = false +xApi.model.validateUriScheme = false +xApi.model.validateMbox = false +xApi.model.validateLocaleNotUndetermined = false +xApi.model.validateScaledScore = false +xApi.model.validateScore = false +xApi.model.validateStatementPlatform = false +xApi.model.validateStatementRevision = false +xApi.model.validateStatementListIds = false +xApi.model.validateStatementVerb = false +xApi.model.validateUuidVariant = false diff --git a/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java index 62194162..19e42c63 100644 --- a/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java +++ b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java @@ -25,7 +25,7 @@ * @author István Rátkai (Selindek) */ @Configuration -@AutoConfigureBefore(value = JacksonProperties.class) +@AutoConfigureBefore(JacksonProperties.class) public class XapiModelAutoConfiguration { /** @@ -39,84 +39,84 @@ public Jackson2ObjectMapperBuilderCustomizer singleValueArrayCustomizer() { } /** - * StrictObjectTypeCustomizer. + * ValidateObjectTypeCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictObjectType", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateObjectType", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictObjectTypeCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validateObjectTypeCustomizer() { return builder -> builder.postConfigurer(objectMapper -> objectMapper.registerModule(new XapiStrictObjectTypeModule()) ); } /** - * StrictLocaleCustomizer. + * ValidateLocaleCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictLocale", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateLocale", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictLocaleCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validateLocaleCustomizer() { return builder -> builder.postConfigurer(objectMapper -> objectMapper.registerModule(new XapiStrictLocaleModule()) ); } /** - * StrictTimestampCustomizer. + * ValidateTimestampCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictTimestamp", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateTimestamp", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictTimestampCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validateTimestampCustomizer() { return builder -> builder.postConfigurer(objectMapper -> objectMapper.registerModule(new XapiStrictTimestampModule()) ); } /** - * StrictNullValuesCustomizer. + * ValidateNullValuesCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictNullValues", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateNullValues", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictNullValuesCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validateNullValuesCustomizer() { return builder -> builder.postConfigurer(objectMapper -> objectMapper.registerModule(new XapiStrictNullValuesModule()) ); } /** - * SstrictPropertiesCustomizer. + * ValidatePropertiesCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictProperties", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateProperties", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictPropertiesCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validatePropertiesCustomizer() { return builder -> builder.postConfigurer(objectMapper -> objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true) ); } /** - * StrictJsonCustomizer. + * ValidateJsonCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictJson", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateJson", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictJsonCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validateJsonCustomizer() { return builder -> builder.postConfigurer(objectMapper -> objectMapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true) ); } /** - * StrictLiteralsCustomizer. + * ValidateLiteralsCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.strictLiterals", havingValue = "true", + @ConditionalOnProperty(name = "xApi.model.validateLiterals", havingValue = "true", matchIfMissing = true) - public Jackson2ObjectMapperBuilderCustomizer strictLiteralsCustomizer() { + public Jackson2ObjectMapperBuilderCustomizer validateLiteralsCustomizer() { return builder -> builder.postConfigurer(objectMapper -> { objectMapper.coercionConfigFor(LogicalType.Boolean) diff --git a/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 5c3edec2..413c3395 100644 --- a/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ dev.learning.xapi.XapiModelAutoConfiguration +dev.learning.xapi.model.validation.internal.validators.MboxValidator diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml index 4653ee4b..35860839 100644 --- a/xapi-model/pom.xml +++ b/xapi-model/pom.xml @@ -46,6 +46,11 @@ hibernate-validator true + + org.springframework + spring-beans + true + org.springframework.boot spring-boot-starter-test 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 4f9a2733..6ef315a8 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 @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -22,9 +23,10 @@ * The annotated element must have a scheme. * * @author Thomas Turrell-Croft + * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {HasSchemeValidatorForUri.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface HasScheme { 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 11b16e6c..c598f22e 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 @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.MboxValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -25,7 +26,7 @@ * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {MboxValidator.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface Mbox { 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 24ef0e0f..54386307 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 @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.NotUndeterminedValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -25,7 +26,7 @@ * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {NotUndeterminedValidator.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface NotUndetermined { 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 79a501a9..00c88a3c 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 @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.ScaledScoreValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -27,7 +28,7 @@ * details */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {ScaledScoreValidator.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface ScaledScore { diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Statements.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Statements.java index d7adf9c4..6967005a 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Statements.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/Statements.java @@ -8,6 +8,7 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; +import dev.learning.xapi.model.validation.internal.validators.StatementsValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Retention; @@ -18,8 +19,9 @@ * The annotated Statement list must be valid. * * @author Thomas Turrell-Croft + * @author István Rátkai (Selindek) */ -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {StatementsValidator.class}) @Target({METHOD, FIELD, PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface Statements { diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/VaildScore.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/VaildScore.java index 8c2f4a30..4340d388 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/VaildScore.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/VaildScore.java @@ -8,6 +8,7 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.ScoreValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -18,11 +19,12 @@ * The annotated element must be a valid score. * * @author Thomas Turrell-Croft + * @author István Rátkai (Selindek) * * @see Score */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {ScoreValidator.class}) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface VaildScore { 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 5bc4b795..9f89823a 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 @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.ActivityDefinitionValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -29,7 +30,7 @@ * Definition */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {ActivityDefinitionValidator.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface ValidActivityDefinition { 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 dfa4d336..a9074bd9 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 @@ -13,6 +13,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import dev.learning.xapi.model.Actor; +import dev.learning.xapi.model.validation.internal.validators.ActorValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -28,7 +29,7 @@ * @see Actor */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {ActorValidator.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface ValidActor { diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java index ef54bf1c..119fd24b 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/constraints/ValidAuthority.java @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.AuthorityValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -22,9 +23,10 @@ * The annotated element must have a scheme. * * @author Thomas Turrell-Croft + * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {AuthorityValidator.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface ValidAuthority { 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 index edfae752..c3d832e6 100644 --- 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 @@ -7,6 +7,7 @@ import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.StatementPlatformValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -19,7 +20,7 @@ * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {StatementPlatformValidator.class}) @Target({TYPE}) @Retention(RUNTIME) public @interface ValidStatementPlatform { 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 index 054aee45..5782966d 100644 --- 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 @@ -7,6 +7,7 @@ import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.StatementRevisionValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -19,7 +20,7 @@ * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {StatementRevisionValidator.class}) @Target({TYPE}) @Retention(RUNTIME) public @interface ValidStatementRevision { 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 index b59e8d0a..ac518a9a 100644 --- 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 @@ -7,6 +7,7 @@ import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.StatementVerbValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -19,7 +20,7 @@ * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {StatementVerbValidator.class}) @Target({TYPE}) @Retention(RUNTIME) public @interface ValidStatementVerb { 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 1e561a23..fab4b35d 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 @@ -12,6 +12,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.Documented; @@ -22,9 +23,10 @@ * The annotated UUID must have the specified variant. * * @author Thomas Turrell-Croft + * @author István Rátkai (Selindek) */ @Documented -@Constraint(validatedBy = {}) +@Constraint(validatedBy = {VariantValidatorForUuid.class}) @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface Variant { 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 c4d2b73c..082187a9 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 @@ -8,6 +8,7 @@ import dev.learning.xapi.model.validation.constraints.ValidActivityDefinition; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The {@link ActivityDefinition} being validated must be valid. @@ -21,10 +22,13 @@ public class ActivityDefinitionValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateActivityDefinition:true}}") + private boolean disabled; + @Override public boolean isValid(ActivityDefinition value, ConstraintValidatorContext context) { - if (value == null) { + if (disabled || value == null) { return true; } 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 79e084d0..3965ecf6 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 @@ -11,6 +11,7 @@ import dev.learning.xapi.model.validation.constraints.ValidActor; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The {@link StatementObject} being validated must be valid. @@ -21,6 +22,9 @@ */ public class ActorValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateActor:true}}") + private boolean disabled; + /** * Checks if this {@link Actor} contains exactly one identifier. * @@ -29,6 +33,10 @@ public class ActorValidator implements ConstraintValidator { @Override public boolean isValid(Object value, ConstraintValidatorContext context) { + if (disabled) { + 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() 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 b3804ecc..001efdef 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 @@ -10,6 +10,7 @@ import dev.learning.xapi.model.validation.constraints.ValidAuthority; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The Actor being validated must be null, an agent or an anonymous group with two agents. @@ -19,11 +20,14 @@ */ public class AuthorityValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateAuthority:true}}") + private boolean disabled; + @Override public boolean isValid(Actor value, ConstraintValidatorContext context) { // can be null or Agent - if (value == null || value instanceof Agent) { + if (disabled || value == null || value instanceof Agent) { return true; } 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 9ead1319..fca612d6 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 @@ -8,6 +8,7 @@ import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import java.net.URI; +import org.springframework.beans.factory.annotation.Value; /** * The URI being validated must have a schema. @@ -16,10 +17,13 @@ */ public class HasSchemeValidatorForUri implements ConstraintValidator { + @Value("#{!${xApi.model.validateUriScheme:true}}") + private boolean disabled; + @Override public boolean isValid(URI value, ConstraintValidatorContext context) { - if (value == null) { + if (disabled || value == null) { return true; } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java index 9c2a498d..75d20ec9 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java @@ -8,6 +8,7 @@ import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator; +import org.springframework.beans.factory.annotation.Value; /** * The String being validated must be a valid mbox. @@ -21,6 +22,9 @@ public class MboxValidator implements ConstraintValidator { public static final String PREFIX = "mailto:"; + @Value("#{!${xApi.model.validateMbox:true}}") + private boolean disabled; + EmailValidator emailValidator; @Override @@ -31,8 +35,7 @@ public void initialize(Mbox mbox) { @Override public boolean isValid(String value, ConstraintValidatorContext context) { - - if (value == null) { + if (disabled || value == null) { return true; } 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 index 76749b61..aeecc850 100644 --- 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 @@ -8,6 +8,7 @@ import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.Locale; +import org.springframework.beans.factory.annotation.Value; /** * The Locale being validated must be a non undetermined {@link Locale}. @@ -16,10 +17,13 @@ */ public class NotUndeterminedValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateLocaleNotUndetermined:true}}") + private boolean disabled; + @Override public boolean isValid(Locale value, ConstraintValidatorContext context) { - if (value == null) { + if (disabled || value == null) { return true; } 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 index 69886742..56bbf02e 100644 --- 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 @@ -7,6 +7,7 @@ import dev.learning.xapi.model.validation.constraints.ScaledScore; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The Float being validated must be a valid scaled score. @@ -18,10 +19,13 @@ */ public class ScaledScoreValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateScaledScore:true}}") + private boolean disabled; + @Override public boolean isValid(Float value, ConstraintValidatorContext context) { - if (value == null) { + if (disabled || value == null) { return true; } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java index 746d6915..7083988c 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java @@ -8,6 +8,7 @@ import dev.learning.xapi.model.validation.constraints.VaildScore; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The raw score must be greater or equal to min and less or equal to max. @@ -16,10 +17,13 @@ */ public class ScoreValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateScore:true}}") + private boolean disabled; + @Override public boolean isValid(Score value, ConstraintValidatorContext context) { - if (value == null) { + if (disabled || value == null) { return true; } 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 09195dfe..88fd2ba3 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 @@ -9,6 +9,7 @@ import dev.learning.xapi.model.validation.constraints.ValidStatementPlatform; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The Statement being validated must have a valid platform. @@ -25,11 +26,14 @@ public class StatementPlatformValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateStatementPlatform:true}}") + private boolean disabled; + @Override public boolean isValid(CoreStatement value, ConstraintValidatorContext context) { - return value == null || value.getContext() == null || value.getContext().getPlatform() == null - || value.getObject() instanceof Activity; + return disabled || 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 916e543d..5543fc20 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 @@ -9,6 +9,7 @@ import dev.learning.xapi.model.validation.constraints.ValidStatementRevision; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** * The Statement being validated must have a valid revision. @@ -25,11 +26,14 @@ public class StatementRevisionValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateStatementRevision:true}}") + private boolean disabled; + @Override public boolean isValid(CoreStatement value, ConstraintValidatorContext context) { - return value == null || value.getContext() == null || value.getContext().getRevision() == null - || value.getObject() instanceof Activity; + return disabled || 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 737e9039..2c9cdad4 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 @@ -9,11 +9,12 @@ import dev.learning.xapi.model.validation.constraints.ValidStatementVerb; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; +import org.springframework.beans.factory.annotation.Value; /** - * The Statement being validated must have a valid revision. + * The Statement being validated must have a valid verb. *

- * if verb is 'voided' then object must be a {@link StatementReference}. + * If the verb is 'voided' then the object must be a {@link StatementReference}. *

* * @author Thomas Turrell-Croft @@ -25,10 +26,13 @@ public class StatementVerbValidator implements ConstraintValidator { + @Value("#{!${xApi.model.validateStatementVerb:true}}") + private boolean disabled; + @Override public boolean isValid(CoreStatement value, ConstraintValidatorContext context) { - return value == null || value.getVerb() == null || !value.getVerb().isVoided() + return disabled || value == null || value.getVerb() == null || !value.getVerb().isVoided() || value.getObject() instanceof StatementReference; } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java index e1a2b054..b39f5580 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Set; import java.util.UUID; +import org.springframework.beans.factory.annotation.Value; /** * Validates a list of statements. @@ -20,13 +21,16 @@ */ public class StatementsValidator implements ConstraintValidator> { + @Value("#{!${xApi.model.validateStatementListIds:true}}") + private boolean disabled; + /** * {@inheritDoc} */ @Override public boolean isValid(List values, ConstraintValidatorContext context) { - if (values == null) { + if (disabled || values == null) { return true; } 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..970987f5 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 @@ -8,6 +8,7 @@ import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.UUID; +import org.springframework.beans.factory.annotation.Value; /** * The UUID being validated must have the specified variant. @@ -16,6 +17,9 @@ */ public class VariantValidatorForUuid implements ConstraintValidator { + @Value("#{!${xApi.model.validateUuidVariant:true}}") + private boolean disabled; + private int variant; @Override @@ -27,7 +31,7 @@ public void initialize(Variant constraintAnnotation) { @Override public boolean isValid(UUID value, ConstraintValidatorContext context) { - if (value == null) { + if (disabled || value == null) { return true; } 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 deleted file mode 100644 index fd019e08..00000000 --- a/xapi-model/src/main/resources/META-INF/services/jakarta.validation.ConstraintValidator +++ /dev/null @@ -1,13 +0,0 @@ -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 -dev.learning.xapi.model.validation.internal.validators.StatementRevisionValidator -dev.learning.xapi.model.validation.internal.validators.StatementPlatformValidator -dev.learning.xapi.model.validation.internal.validators.StatementVerbValidator -dev.learning.xapi.model.validation.internal.validators.StatementsValidator -dev.learning.xapi.model.validation.internal.validators.ScoreValidator diff --git a/xapi-model/src/main/resources/application.properties b/xapi-model/src/main/resources/application.properties deleted file mode 100644 index e69de29b..00000000 From 4e896de79366f2b3c7ad3a592322e7a7ac03c662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Wed, 19 Apr 2023 13:00:40 +0100 Subject: [PATCH 02/12] fix properties --- .../src/main/resources/application.properties | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/xapi-server/src/main/resources/application.properties b/samples/xapi-server/src/main/resources/application.properties index b7435a3b..d7a0b4bf 100644 --- a/samples/xapi-server/src/main/resources/application.properties +++ b/samples/xapi-server/src/main/resources/application.properties @@ -15,16 +15,16 @@ xApi.model.validateLiterals = true xApi.model.validateObjectType = true -xApi.model.validateActivityDefinition = false -xApi.model.validateActor = false -xApi.model.validateAuthority = false -xApi.model.validateUriScheme = false -xApi.model.validateMbox = false -xApi.model.validateLocaleNotUndetermined = false -xApi.model.validateScaledScore = false -xApi.model.validateScore = false -xApi.model.validateStatementPlatform = false -xApi.model.validateStatementRevision = false -xApi.model.validateStatementListIds = false -xApi.model.validateStatementVerb = false -xApi.model.validateUuidVariant = false +xApi.model.validateActivityDefinition = true +xApi.model.validateActor = true +xApi.model.validateAuthority = true +xApi.model.validateUriScheme = true +xApi.model.validateMbox = true +xApi.model.validateLocaleNotUndetermined = true +xApi.model.validateScaledScore = true +xApi.model.validateScore = true +xApi.model.validateStatementPlatform = true +xApi.model.validateStatementRevision = true +xApi.model.validateStatementListIds = true +xApi.model.validateStatementVerb = true +xApi.model.validateUuidVariant = true From c74ce6e1ce1acf5fa6a20523dd59756ab708d70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Wed, 19 Apr 2023 14:21:24 +0100 Subject: [PATCH 03/12] fixup --- ....springframework.boot.autoconfigure.AutoConfiguration.imports | 1 - 1 file changed, 1 deletion(-) diff --git a/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 413c3395..5c3edec2 100644 --- a/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/xapi-model-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1 @@ dev.learning.xapi.XapiModelAutoConfiguration -dev.learning.xapi.model.validation.internal.validators.MboxValidator From 76f8becde5e3c28527cd74e8a6eacf4d9b1d7885 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Wed, 19 Apr 2023 15:15:51 +0100 Subject: [PATCH 04/12] start adding readme documentation for properties --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 1c5e2e73..990adc29 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,14 @@ client.deleteState(r -> r.activityId("https://example.com/activity/1") .block(); ``` +## xAPI Model Spring Boot Autoconfigure + +The xAPI Model Spring Boot AutoConfigure uses picks up the following properties: + +| Property | Description | +| ----------------------------- | ------------------------------------------------------------------ | +| xapi.xxx | | + ### Samples The samples folder in this repository contains [sample applications](samples) that use the xAPI client. From b9478f317274fbdb1c379cd5df4f708125319ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Thu, 20 Apr 2023 12:15:19 +0100 Subject: [PATCH 05/12] remove Spring references from model --- README.md | 35 ++- .../src/main/resources/application.properties | 40 +-- xapi-model-spring-boot-autoconfigure/pom.xml | 4 + .../xapi/XapiModelAutoConfiguration.java | 237 +++++++++++++++++- xapi-model/pom.xml | 5 - .../disableable/DisableableValidator.java | 55 ++++ .../disableable/ValidatorDisabler.java | 20 ++ .../ActivityDefinitionValidator.java | 12 +- .../internal/validators/ActorValidator.java | 14 +- .../validators/AuthorityValidator.java | 12 +- .../validators/HasSchemeValidatorForUri.java | 12 +- .../internal/validators/MboxValidator.java | 12 +- .../validators/NotUndeterminedValidator.java | 12 +- .../validators/ScaledScoreValidator.java | 12 +- .../internal/validators/ScoreValidator.java | 12 +- .../StatementPlatformValidator.java | 14 +- .../StatementRevisionValidator.java | 14 +- .../validators/StatementVerbValidator.java | 12 +- .../validators/StatementsValidator.java | 12 +- .../validators/VariantValidatorForUuid.java | 13 +- 20 files changed, 414 insertions(+), 145 deletions(-) create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java create mode 100644 xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/ValidatorDisabler.java diff --git a/README.md b/README.md index 990adc29..c008cb12 100644 --- a/README.md +++ b/README.md @@ -256,11 +256,38 @@ client.deleteState(r -> r.activityId("https://example.com/activity/1") ## xAPI Model Spring Boot Autoconfigure -The xAPI Model Spring Boot AutoConfigure uses picks up the following properties: +The xAPI specification has extremely strict rules for API requests/responses formatting. +The xAPI Model has inbuilt validation for all of these rules. -| Property | Description | -| ----------------------------- | ------------------------------------------------------------------ | -| xapi.xxx | | +But if you plan to use the xAPI Model on a server side, you should keep in mind that some activity providers do not fully conform to these rules. + +In some cases it may be desirable to turn off some or all of the rules in order to be compatible with a wider range of xAPI activity providers. However, doing this is in violation of the xAPI specification. + +The xAPI Model Spring Boot Autoconfigure package provides an easy way to turn on/off these validation rules one by one. + +If you use Spring boor framework, simply add the following dependency into your pom.xml... + +``` + + dev.learning.xapi + xapi-model-spring-boot-autoconfigure + ... + +``` + +... and you can customize the rules using the following properties: + + +| Property | Description | +| ----------------------------------------- | ------------------------------------------------------------------ | +| xapi.model.validateProperties | Fail on unknown properties | + +| xapi.model.validateLocaleNotUndetermined | Fail on undetermined Locale objects | + +*todo: add other properties* + + +The default value is **TRUE** for all of the above properties. ### Samples diff --git a/samples/xapi-server/src/main/resources/application.properties b/samples/xapi-server/src/main/resources/application.properties index d7a0b4bf..31a5d713 100644 --- a/samples/xapi-server/src/main/resources/application.properties +++ b/samples/xapi-server/src/main/resources/application.properties @@ -5,26 +5,26 @@ # with a wider range of xAPI activity providers. However, doing this is in violation of the xAPI # specification. -xApi.model.validateProperties = true -xApi.model.validateJson = true +xapi.model.validateProperties = true +xapi.model.validateJson = true -xApi.model.validateLocale = true -xApi.model.validateTimestamp = true -xApi.model.validateNullValues = true -xApi.model.validateLiterals = true +xapi.model.validateLocale = true +xapi.model.validateTimestamp = true +xapi.model.validateNullValues = true +xapi.model.validateLiterals = true -xApi.model.validateObjectType = true +xapi.model.validateObjectType = true -xApi.model.validateActivityDefinition = true -xApi.model.validateActor = true -xApi.model.validateAuthority = true -xApi.model.validateUriScheme = true -xApi.model.validateMbox = true -xApi.model.validateLocaleNotUndetermined = true -xApi.model.validateScaledScore = true -xApi.model.validateScore = true -xApi.model.validateStatementPlatform = true -xApi.model.validateStatementRevision = true -xApi.model.validateStatementListIds = true -xApi.model.validateStatementVerb = true -xApi.model.validateUuidVariant = true +xapi.model.validateActivityDefinition = true +xapi.model.validateActor = true +xapi.model.validateAuthority = true +xapi.model.validateUriScheme = true +xapi.model.validateMbox = true +xapi.model.validateLocaleNotUndetermined = true +xapi.model.validateScaledScore = true +xapi.model.validateScore = true +xapi.model.validateStatementPlatform = true +xapi.model.validateStatementRevision = true +xapi.model.validateStatementListIds = true +xapi.model.validateStatementVerb = true +xapi.model.validateUuidVariant = true diff --git a/xapi-model-spring-boot-autoconfigure/pom.xml b/xapi-model-spring-boot-autoconfigure/pom.xml index 17acb448..a41cbefb 100644 --- a/xapi-model-spring-boot-autoconfigure/pom.xml +++ b/xapi-model-spring-boot-autoconfigure/pom.xml @@ -19,6 +19,10 @@ org.springframework.boot spring-boot-autoconfigure
+ + org.springframework.boot + spring-boot-starter-validation + dev.learning.xapi xapi-model diff --git a/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java index 19e42c63..14bf256b 100644 --- a/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java +++ b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java @@ -12,6 +12,21 @@ import dev.learning.xapi.jackson.XapiStrictNullValuesModule; import dev.learning.xapi.jackson.XapiStrictObjectTypeModule; import dev.learning.xapi.jackson.XapiStrictTimestampModule; +import dev.learning.xapi.model.validation.disableable.ValidatorDisabler; +import dev.learning.xapi.model.validation.internal.validators.ActivityDefinitionValidator; +import dev.learning.xapi.model.validation.internal.validators.ActorValidator; +import dev.learning.xapi.model.validation.internal.validators.AuthorityValidator; +import dev.learning.xapi.model.validation.internal.validators.HasSchemeValidatorForUri; +import dev.learning.xapi.model.validation.internal.validators.MboxValidator; +import dev.learning.xapi.model.validation.internal.validators.NotUndeterminedValidator; +import dev.learning.xapi.model.validation.internal.validators.ScaledScoreValidator; +import dev.learning.xapi.model.validation.internal.validators.ScoreValidator; +import dev.learning.xapi.model.validation.internal.validators.StatementPlatformValidator; +import dev.learning.xapi.model.validation.internal.validators.StatementRevisionValidator; +import dev.learning.xapi.model.validation.internal.validators.StatementVerbValidator; +import dev.learning.xapi.model.validation.internal.validators.StatementsValidator; +import dev.learning.xapi.model.validation.internal.validators.VariantValidatorForUuid; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; @@ -42,7 +57,7 @@ public Jackson2ObjectMapperBuilderCustomizer singleValueArrayCustomizer() { * ValidateObjectTypeCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateObjectType", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateObjectType", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validateObjectTypeCustomizer() { return builder -> builder.postConfigurer(objectMapper -> @@ -54,7 +69,7 @@ public Jackson2ObjectMapperBuilderCustomizer validateObjectTypeCustomizer() { * ValidateLocaleCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateLocale", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateLocale", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validateLocaleCustomizer() { return builder -> builder.postConfigurer(objectMapper -> @@ -66,7 +81,7 @@ public Jackson2ObjectMapperBuilderCustomizer validateLocaleCustomizer() { * ValidateTimestampCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateTimestamp", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateTimestamp", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validateTimestampCustomizer() { return builder -> builder.postConfigurer(objectMapper -> @@ -78,7 +93,7 @@ public Jackson2ObjectMapperBuilderCustomizer validateTimestampCustomizer() { * ValidateNullValuesCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateNullValues", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateNullValues", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validateNullValuesCustomizer() { return builder -> builder.postConfigurer(objectMapper -> @@ -90,7 +105,7 @@ public Jackson2ObjectMapperBuilderCustomizer validateNullValuesCustomizer() { * ValidatePropertiesCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateProperties", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateProperties", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validatePropertiesCustomizer() { return builder -> builder.postConfigurer(objectMapper -> @@ -102,7 +117,7 @@ public Jackson2ObjectMapperBuilderCustomizer validatePropertiesCustomizer() { * ValidateJsonCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateJson", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateJson", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validateJsonCustomizer() { return builder -> builder.postConfigurer(objectMapper -> @@ -114,7 +129,7 @@ public Jackson2ObjectMapperBuilderCustomizer validateJsonCustomizer() { * ValidateLiteralsCustomizer. */ @Bean - @ConditionalOnProperty(name = "xApi.model.validateLiterals", havingValue = "true", + @ConditionalOnProperty(name = "xapi.model.validateLiterals", havingValue = "true", matchIfMissing = true) public Jackson2ObjectMapperBuilderCustomizer validateLiteralsCustomizer() { return builder -> builder.postConfigurer(objectMapper -> { @@ -138,4 +153,212 @@ public Jackson2ObjectMapperBuilderCustomizer validateLiteralsCustomizer() { }); } + + /** + * ValidateActivityDefinitionPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateActivityDefinition", havingValue = "false") + public BeanPostProcessor validateActivityDefinitionPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof ActivityDefinitionValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateActorPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateActor", havingValue = "false") + public BeanPostProcessor validateActorPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof ActorValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateAuthorityPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateAuthority", havingValue = "false") + public BeanPostProcessor validateAuthorityPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof AuthorityValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateUriSchemePostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateUriScheme", havingValue = "false") + public BeanPostProcessor validateUriSchemePostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof HasSchemeValidatorForUri validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateMboxPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateMbox", havingValue = "false") + public BeanPostProcessor validateMboxPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof MboxValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateLocaleNotUndeterminedPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateLocaleNotUndetermined", havingValue = "false") + public BeanPostProcessor validateLocaleNotUndeterminedPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof NotUndeterminedValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateScaledScorePostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateScaledScore", havingValue = "false") + public BeanPostProcessor validateScaledScorePostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof ScaledScoreValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateScorePostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateScore", havingValue = "false") + public BeanPostProcessor validateScorePostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof ScoreValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateStatementPlatformPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateStatementPlatform", havingValue = "false") + public BeanPostProcessor validateStatementPlatformPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof StatementPlatformValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateStatementRevisionPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateStatementRevision", havingValue = "false") + public BeanPostProcessor validateStatementRevisionPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof StatementRevisionValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateStatementListIdsPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateStatementListIds", havingValue = "false") + public BeanPostProcessor validateStatementListIdsPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof StatementsValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateStatementVerbPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateStatementVerb", havingValue = "false") + public BeanPostProcessor validateStatementVerbPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof StatementVerbValidator validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } + + /** + * ValidateUuidVariantPostProcessor. + */ + @Bean + @ConditionalOnProperty(name = "xapi.model.validateUuidVariant", havingValue = "false") + public BeanPostProcessor validateUuidVariantPostProcessor() { + return new BeanPostProcessor() { + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof VariantValidatorForUuid validator) { + validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); + } + return bean; + } + }; + } } diff --git a/xapi-model/pom.xml b/xapi-model/pom.xml index 35860839..4653ee4b 100644 --- a/xapi-model/pom.xml +++ b/xapi-model/pom.xml @@ -46,11 +46,6 @@ hibernate-validator true - - org.springframework - spring-beans - true - org.springframework.boot spring-boot-starter-test diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java new file mode 100644 index 00000000..371f20ae --- /dev/null +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved. + */ + +package dev.learning.xapi.model.validation.disableable; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import java.lang.annotation.Annotation; +import lombok.Setter; + +/** + *

+ * Abstract superclass for disableable validators. + *

+ * Validators extending this class are enabled by default. + * {@link ValidatorDisabler#DEFAULT_DISABLER} can be used for completely disable a validator, or a + * custom {@link ValidatorDisabler} bean can be injected for enabling/disabling a validator based on + * a custom logic. + * + * @author István Rátkai (Selindek) + */ +public abstract class DisableableValidator + implements ConstraintValidator { + + @Setter + private ValidatorDisabler disabler = ValidatorDisabler.DEFAULT_ENABLER; + + @Override + public boolean isValid(T value, ConstraintValidatorContext context) { + return isDisabled() || isValidIfEnabled(value, context); + } + + /** + *

+ * Convenient method for completely removing the disabled/enabled logic from subclasses. + *

+ * By adding the validator logic into this method a subclass can contain only the actual validator + * logic. But if some more complex validation logic is needed (eg. some partial validation is + * needed even if the validator is disabled), then the {@link #isDisabled()} method can be used + * directly from the {@link ConstraintValidator#isValid(Object, ConstraintValidatorContext)} + * method. + */ + public boolean isValidIfEnabled(T value, ConstraintValidatorContext context) { + return true; + } + + /** + * Whether this validator is disabled. + */ + public boolean isDisabled() { + return disabler.isDisabled(this); + } + +} diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/ValidatorDisabler.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/ValidatorDisabler.java new file mode 100644 index 00000000..344a28e6 --- /dev/null +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/ValidatorDisabler.java @@ -0,0 +1,20 @@ +/* + * Copyright 2016-2023 Berry Cloud Ltd. All rights reserved. + */ + +package dev.learning.xapi.model.validation.disableable; + +/** + * Callback interface for disabling/enabling a {@link DisableableValidator}. + * + * @author István Rátkai (Selindek) + */ +@FunctionalInterface +public interface ValidatorDisabler { + + public static final ValidatorDisabler DEFAULT_DISABLER = v -> true; + public static final ValidatorDisabler DEFAULT_ENABLER = v -> false; + + public boolean isDisabled(DisableableValidator validator); + +} 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 082187a9..6f2a0050 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 @@ -6,9 +6,8 @@ import dev.learning.xapi.model.ActivityDefinition; import dev.learning.xapi.model.validation.constraints.ValidActivityDefinition; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The {@link ActivityDefinition} being validated must be valid. @@ -20,15 +19,12 @@ * Definition
*/ public class ActivityDefinitionValidator - implements ConstraintValidator { - - @Value("#{!${xApi.model.validateActivityDefinition:true}}") - private boolean disabled; + extends DisableableValidator { @Override - public boolean isValid(ActivityDefinition value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(ActivityDefinition value, ConstraintValidatorContext context) { - if (disabled || value == null) { + if (value == null) { return true; } 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 3965ecf6..53c9fcae 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 @@ -9,9 +9,8 @@ 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 dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The {@link StatementObject} being validated must be valid. @@ -20,10 +19,7 @@ * * @see Actor */ -public class ActorValidator implements ConstraintValidator { - - @Value("#{!${xApi.model.validateActor:true}}") - private boolean disabled; +public class ActorValidator extends DisableableValidator { /** * Checks if this {@link Actor} contains exactly one identifier. @@ -31,11 +27,7 @@ public class ActorValidator implements ConstraintValidator { * @return true if this object is valid. */ @Override - public boolean isValid(Object value, ConstraintValidatorContext context) { - - if (disabled) { - return true; - } + public boolean isValidIfEnabled(Object value, ConstraintValidatorContext context) { if (value instanceof final Group group) { return group.getAccount() == null && group.getMbox() == null && group.getMboxSha1sum() == null 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 001efdef..362233ff 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 @@ -8,9 +8,8 @@ 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 dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The Actor being validated must be null, an agent or an anonymous group with two agents. @@ -18,16 +17,13 @@ * @author István Rátkai (Selindek) * @author Thomas Turrell-Croft */ -public class AuthorityValidator implements ConstraintValidator { - - @Value("#{!${xApi.model.validateAuthority:true}}") - private boolean disabled; +public class AuthorityValidator extends DisableableValidator { @Override - public boolean isValid(Actor value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(Actor value, ConstraintValidatorContext context) { // can be null or Agent - if (disabled || value == null || value instanceof Agent) { + if (value == null || value instanceof Agent) { return true; } 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 fca612d6..48a1170d 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 @@ -5,25 +5,21 @@ package dev.learning.xapi.model.validation.internal.validators; import dev.learning.xapi.model.validation.constraints.HasScheme; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; import java.net.URI; -import org.springframework.beans.factory.annotation.Value; /** * The URI being validated must have a schema. * * @author Thomas Turrell-Croft */ -public class HasSchemeValidatorForUri implements ConstraintValidator { - - @Value("#{!${xApi.model.validateUriScheme:true}}") - private boolean disabled; +public class HasSchemeValidatorForUri extends DisableableValidator { @Override - public boolean isValid(URI value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(URI value, ConstraintValidatorContext context) { - if (disabled || value == null) { + if (value == null) { return true; } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java index 75d20ec9..fd5da13c 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java @@ -5,10 +5,9 @@ package dev.learning.xapi.model.validation.internal.validators; import dev.learning.xapi.model.validation.constraints.Mbox; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; import org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator; -import org.springframework.beans.factory.annotation.Value; /** * The String being validated must be a valid mbox. @@ -18,13 +17,10 @@ * * @see Mbox */ -public class MboxValidator implements ConstraintValidator { +public class MboxValidator extends DisableableValidator { public static final String PREFIX = "mailto:"; - @Value("#{!${xApi.model.validateMbox:true}}") - private boolean disabled; - EmailValidator emailValidator; @Override @@ -34,8 +30,8 @@ public void initialize(Mbox mbox) { } @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - if (disabled || value == null) { + public boolean isValidIfEnabled(String value, ConstraintValidatorContext context) { + if (value == null) { return true; } 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 index aeecc850..6bf82017 100644 --- 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 @@ -5,25 +5,21 @@ package dev.learning.xapi.model.validation.internal.validators; import dev.learning.xapi.model.validation.constraints.NotUndetermined; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.Locale; -import org.springframework.beans.factory.annotation.Value; /** * The Locale being validated must be a non undetermined {@link Locale}. * * @author István Rátkai (Selindek) */ -public class NotUndeterminedValidator implements ConstraintValidator { - - @Value("#{!${xApi.model.validateLocaleNotUndetermined:true}}") - private boolean disabled; +public class NotUndeterminedValidator extends DisableableValidator { @Override - public boolean isValid(Locale value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(Locale value, ConstraintValidatorContext context) { - if (disabled || value == null) { + if (value == null) { return true; } 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 index 56bbf02e..95b19347 100644 --- 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 @@ -5,9 +5,8 @@ package dev.learning.xapi.model.validation.internal.validators; import dev.learning.xapi.model.validation.constraints.ScaledScore; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The Float being validated must be a valid scaled score. @@ -17,15 +16,12 @@ * @see xAPI Score * details */ -public class ScaledScoreValidator implements ConstraintValidator { - - @Value("#{!${xApi.model.validateScaledScore:true}}") - private boolean disabled; +public class ScaledScoreValidator extends DisableableValidator { @Override - public boolean isValid(Float value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(Float value, ConstraintValidatorContext context) { - if (disabled || value == null) { + if (value == null) { return true; } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java index 7083988c..a1da16a9 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/ScoreValidator.java @@ -6,24 +6,20 @@ import dev.learning.xapi.model.Score; import dev.learning.xapi.model.validation.constraints.VaildScore; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The raw score must be greater or equal to min and less or equal to max. * * @author István Rátkai (Selindek) */ -public class ScoreValidator implements ConstraintValidator { - - @Value("#{!${xApi.model.validateScore:true}}") - private boolean disabled; +public class ScoreValidator extends DisableableValidator { @Override - public boolean isValid(Score value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(Score value, ConstraintValidatorContext context) { - if (disabled || value == null) { + if (value == null) { return true; } 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 88fd2ba3..8e9df58e 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 @@ -7,9 +7,8 @@ import dev.learning.xapi.model.Activity; import dev.learning.xapi.model.CoreStatement; import dev.learning.xapi.model.validation.constraints.ValidStatementPlatform; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The Statement being validated must have a valid platform. @@ -24,16 +23,13 @@ * Statement Context Requirements */ public class StatementPlatformValidator - implements ConstraintValidator { - - @Value("#{!${xApi.model.validateStatementPlatform:true}}") - private boolean disabled; + extends DisableableValidator { @Override - public boolean isValid(CoreStatement value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(CoreStatement value, ConstraintValidatorContext context) { - return disabled || value == null || value.getContext() == null - || value.getContext().getPlatform() == null || value.getObject() instanceof Activity; + 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 5543fc20..b0bf6328 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 @@ -7,9 +7,8 @@ import dev.learning.xapi.model.Activity; import dev.learning.xapi.model.CoreStatement; import dev.learning.xapi.model.validation.constraints.ValidStatementRevision; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The Statement being validated must have a valid revision. @@ -24,16 +23,13 @@ * Statement Context Requirements */ public class StatementRevisionValidator - implements ConstraintValidator { - - @Value("#{!${xApi.model.validateStatementRevision:true}}") - private boolean disabled; + extends DisableableValidator { @Override - public boolean isValid(CoreStatement value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(CoreStatement value, ConstraintValidatorContext context) { - return disabled || value == null || value.getContext() == null - || value.getContext().getRevision() == null || value.getObject() instanceof Activity; + 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 2c9cdad4..30fba1c1 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 @@ -7,9 +7,8 @@ import dev.learning.xapi.model.CoreStatement; import dev.learning.xapi.model.StatementReference; import dev.learning.xapi.model.validation.constraints.ValidStatementVerb; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Value; /** * The Statement being validated must have a valid verb. @@ -24,15 +23,12 @@ * Voiding Statement Requirements */ public class StatementVerbValidator - implements ConstraintValidator { - - @Value("#{!${xApi.model.validateStatementVerb:true}}") - private boolean disabled; + extends DisableableValidator { @Override - public boolean isValid(CoreStatement value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(CoreStatement value, ConstraintValidatorContext context) { - return disabled || value == null || value.getVerb() == null || !value.getVerb().isVoided() + return value == null || value.getVerb() == null || !value.getVerb().isVoided() || value.getObject() instanceof StatementReference; } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java index b39f5580..d3abdc7b 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementsValidator.java @@ -6,31 +6,27 @@ import dev.learning.xapi.model.Statement; import dev.learning.xapi.model.validation.constraints.Statements; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; -import org.springframework.beans.factory.annotation.Value; /** * Validates a list of statements. * * @author Thomas Turrell-Croft */ -public class StatementsValidator implements ConstraintValidator> { - - @Value("#{!${xApi.model.validateStatementListIds:true}}") - private boolean disabled; +public class StatementsValidator extends DisableableValidator> { /** * {@inheritDoc} */ @Override - public boolean isValid(List values, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(List values, ConstraintValidatorContext context) { - if (disabled || values == null) { + if (values == null) { return true; } 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 970987f5..259e869f 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 @@ -5,20 +5,17 @@ package dev.learning.xapi.model.validation.internal.validators; import dev.learning.xapi.model.validation.constraints.Variant; -import jakarta.validation.ConstraintValidator; +import dev.learning.xapi.model.validation.disableable.DisableableValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.UUID; -import org.springframework.beans.factory.annotation.Value; /** * The UUID being validated must have the specified variant. * * @author Thomas Turrell-Croft + * @author István Rátkai (Selindek) */ -public class VariantValidatorForUuid implements ConstraintValidator { - - @Value("#{!${xApi.model.validateUuidVariant:true}}") - private boolean disabled; +public class VariantValidatorForUuid extends DisableableValidator { private int variant; @@ -29,9 +26,9 @@ public void initialize(Variant constraintAnnotation) { } @Override - public boolean isValid(UUID value, ConstraintValidatorContext context) { + public boolean isValidIfEnabled(UUID value, ConstraintValidatorContext context) { - if (disabled || value == null) { + if (value == null) { return true; } From 344eb0d6d3577a670a47a9555a8f82e33135106c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Thu, 20 Apr 2023 12:33:23 +0100 Subject: [PATCH 06/12] fsi --- .../xapi/XapiModelAutoConfiguration.java | 13 +++++++++++++ .../disableable/DisableableValidator.java | 18 +++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java index 14bf256b..5b2fd924 100644 --- a/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java +++ b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java @@ -161,6 +161,7 @@ public Jackson2ObjectMapperBuilderCustomizer validateLiteralsCustomizer() { @ConditionalOnProperty(name = "xapi.model.validateActivityDefinition", havingValue = "false") public BeanPostProcessor validateActivityDefinitionPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ActivityDefinitionValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -177,6 +178,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateActor", havingValue = "false") public BeanPostProcessor validateActorPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ActorValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -193,6 +195,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateAuthority", havingValue = "false") public BeanPostProcessor validateAuthorityPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof AuthorityValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -209,6 +212,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateUriScheme", havingValue = "false") public BeanPostProcessor validateUriSchemePostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof HasSchemeValidatorForUri validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -225,6 +229,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateMbox", havingValue = "false") public BeanPostProcessor validateMboxPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof MboxValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -241,6 +246,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateLocaleNotUndetermined", havingValue = "false") public BeanPostProcessor validateLocaleNotUndeterminedPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof NotUndeterminedValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -257,6 +263,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateScaledScore", havingValue = "false") public BeanPostProcessor validateScaledScorePostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ScaledScoreValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -273,6 +280,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateScore", havingValue = "false") public BeanPostProcessor validateScorePostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ScoreValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -289,6 +297,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateStatementPlatform", havingValue = "false") public BeanPostProcessor validateStatementPlatformPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof StatementPlatformValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -305,6 +314,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateStatementRevision", havingValue = "false") public BeanPostProcessor validateStatementRevisionPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof StatementRevisionValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -321,6 +331,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateStatementListIds", havingValue = "false") public BeanPostProcessor validateStatementListIdsPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof StatementsValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -337,6 +348,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateStatementVerb", havingValue = "false") public BeanPostProcessor validateStatementVerbPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof StatementVerbValidator validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); @@ -353,6 +365,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { @ConditionalOnProperty(name = "xapi.model.validateUuidVariant", havingValue = "false") public BeanPostProcessor validateUuidVariantPostProcessor() { return new BeanPostProcessor() { + @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof VariantValidatorForUuid validator) { validator.setDisabler(ValidatorDisabler.DEFAULT_DISABLER); diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java index 371f20ae..3a1bbe42 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java @@ -33,15 +33,19 @@ public boolean isValid(T value, ConstraintValidatorContext context) { /** *

- * Convenient method for completely removing the disabled/enabled logic from subclasses. + * Convenient method for implementing the validation logic independently from the disabled/enabled + * logic. *

- * By adding the validator logic into this method a subclass can contain only the actual validator - * logic. But if some more complex validation logic is needed (eg. some partial validation is - * needed even if the validator is disabled), then the {@link #isDisabled()} method can be used - * directly from the {@link ConstraintValidator#isValid(Object, ConstraintValidatorContext)} - * method. + * If some more complex validation logic is needed (eg. some partial validation is needed even if + * the validator is disabled), then the {@link #isDisabled()} method can be used directly from the + * {@link ConstraintValidator#isValid(Object, ConstraintValidatorContext)} method. + * + * @param value object to validate + * @param context context in which the constraint is evaluated + * + * @return {@code false} if {@code value} does not pass the constraint */ - public boolean isValidIfEnabled(T value, ConstraintValidatorContext context) { + protected boolean isValidIfEnabled(T value, ConstraintValidatorContext context) { return true; } From ccc2b4f2f8f5d007709ac211eedcaddde8c62228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Thu, 20 Apr 2023 13:02:45 +0100 Subject: [PATCH 07/12] add auto-configuration property descriptions to README.md --- README.md | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c008cb12..c3aae712 100644 --- a/README.md +++ b/README.md @@ -275,16 +275,31 @@ If you use Spring boor framework, simply add the following dependency into your
``` -... and you can customize the rules using the following properties: +... and you can customize the validation rules using the following properties: -| Property | Description | -| ----------------------------------------- | ------------------------------------------------------------------ | -| xapi.model.validateProperties | Fail on unknown properties | - -| xapi.model.validateLocaleNotUndetermined | Fail on undetermined Locale objects | - -*todo: add other properties* +| Property | Description | +| ----------------------------------------- | -------------------------------------------------------------------------- | +| xapi.model.validateJson | Fail on trailing JSON tokens | +| xapi.model.validateProperties | Fail on unknown JSON properties | +| xapi.model.validateNullValues | Fail on null JSON properties | +| xapi.model.validateLiterals | Fail on number and boolean JSON properties defined as string | +| xapi.model.validateObjectType | Fail on invalid JSON objectType property | +| xapi.model.validateLocale | Fail on invalid Locale strings | +| xapi.model.validateTimestamp | Fail on negative zero timezone offsets | +| xapi.model.validateActivityDefinition | Fail on invalid xAPI ActivityDefinition (missing properties) | +| xapi.model.validateActor | Fail on invalid xAPI Actor (missing or multiple identifiers) | +| xapi.model.validateAuthority | Fail on invalid xAPI Authority object | +| xapi.model.validateUriScheme | Fail on invalid xAPI URI property (missing scheme) | +| xapi.model.validateMbox | Fail on invalid xAPI mbox property (missing 'mailto:' prefix) | +| xapi.model.validateLocaleNotUndetermined | Fail on invalid xAPI locale property (locale is undetermined) | +| xapi.model.validateScaledScore | Fail on invalid xAPI scaledScore property (out of -1 - 1 range) | +| xapi.model.validateScore | Fail on invalid xAPI Score (raw score is out of min/max range) | +| xapi.model.validateStatementPlatform | Fail on invalid xAPI context.platform (if present object must be Activity) | +| xapi.model.validateStatementRevision | Fail on invalid xAPI context.revision (if present object must be Activity) | +| xapi.model.validateStatementListIds | Fail on invalid xAPI statement List (conflicting statement ids) | +| xapi.model.validateStatementVerb | Fail on invalid xAPI voided statement (object must be StatemnetReference) | +| xapi.model.validateUuidVariant | Fail on invalid xAPI UUID property (must be UUID variant 4) | The default value is **TRUE** for all of the above properties. From 06d5fbdb0e3c959eddd1e71857307d7f122eea8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Thu, 20 Apr 2023 14:15:43 +0100 Subject: [PATCH 08/12] fixup readme --- README.md | 6 +++--- xapi-model-spring-boot-autoconfigure/pom.xml | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c3aae712..f9676f66 100644 --- a/README.md +++ b/README.md @@ -265,7 +265,7 @@ In some cases it may be desirable to turn off some or all of the rules in order The xAPI Model Spring Boot Autoconfigure package provides an easy way to turn on/off these validation rules one by one. -If you use Spring boor framework, simply add the following dependency into your pom.xml... +If you use Spring Boot framework, simply add the following dependency into your pom.xml... ``` @@ -275,7 +275,7 @@ If you use Spring boor framework, simply add the following dependency into your ``` -... and you can customize the validation rules using the following properties: +... and you can customize the validation rules using the following boolean properties: | Property | Description | @@ -291,7 +291,7 @@ If you use Spring boor framework, simply add the following dependency into your | xapi.model.validateActor | Fail on invalid xAPI Actor (missing or multiple identifiers) | | xapi.model.validateAuthority | Fail on invalid xAPI Authority object | | xapi.model.validateUriScheme | Fail on invalid xAPI URI property (missing scheme) | -| xapi.model.validateMbox | Fail on invalid xAPI mbox property (missing 'mailto:' prefix) | +| xapi.model.validateMbox | Fail on invalid xAPI mbox property (invalid email or missing prefix) | | xapi.model.validateLocaleNotUndetermined | Fail on invalid xAPI locale property (locale is undetermined) | | xapi.model.validateScaledScore | Fail on invalid xAPI scaledScore property (out of -1 - 1 range) | | xapi.model.validateScore | Fail on invalid xAPI Score (raw score is out of min/max range) | diff --git a/xapi-model-spring-boot-autoconfigure/pom.xml b/xapi-model-spring-boot-autoconfigure/pom.xml index a41cbefb..17acb448 100644 --- a/xapi-model-spring-boot-autoconfigure/pom.xml +++ b/xapi-model-spring-boot-autoconfigure/pom.xml @@ -19,10 +19,6 @@ org.springframework.boot spring-boot-autoconfigure - - org.springframework.boot - spring-boot-starter-validation - dev.learning.xapi xapi-model From 59bdce503677981c912e25b0f6bae623031a5855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20R=C3=A1tkai?= Date: Thu, 20 Apr 2023 15:08:16 +0100 Subject: [PATCH 09/12] add version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9676f66..df84c3b3 100644 --- a/README.md +++ b/README.md @@ -271,7 +271,7 @@ If you use Spring Boot framework, simply add the following dependency into your dev.learning.xapi xapi-model-spring-boot-autoconfigure - ... + 1.1.5 ``` From 5b9c09b23f9f080ed750870611fdcbeef7648217 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 21 Apr 2023 13:00:55 +0100 Subject: [PATCH 10/12] tidy readme --- README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index df84c3b3..5156c0f1 100644 --- a/README.md +++ b/README.md @@ -254,18 +254,60 @@ client.deleteState(r -> r.activityId("https://example.com/activity/1") .block(); ``` -## xAPI Model Spring Boot Autoconfigure -The xAPI specification has extremely strict rules for API requests/responses formatting. -The xAPI Model has inbuilt validation for all of these rules. -But if you plan to use the xAPI Model on a server side, you should keep in mind that some activity providers do not fully conform to these rules. -In some cases it may be desirable to turn off some or all of the rules in order to be compatible with a wider range of xAPI activity providers. However, doing this is in violation of the xAPI specification. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Samples + +The samples folder in this repository contains [sample applications](samples) that use the xAPI client. + +## xAPI Model Spring Boot Autoconfigure + +The xAPI specification has strict rules for API requests/responses formatting. The xAPI Model has inbuilt validation for all of these rules. However, if you plan to use the xAPI Model, you should keep in mind that some activity providers do not fully conform to these rules. + +In some cases it may be desirable to turn off some or all of the rules in order to be compatible with a wider range of xAPI activity providers. However, it should be noted that doing this is in violation of the xAPI specification. The xAPI Model Spring Boot Autoconfigure package provides an easy way to turn on/off these validation rules one by one. -If you use Spring Boot framework, simply add the following dependency into your pom.xml... +### Getting started + +To use the xAPI Model Spring Boot Autoconfigure include the appropriate XML in the `dependencies` section of your `pom.xml`, as shown in the following example: ``` @@ -275,8 +317,9 @@ If you use Spring Boot framework, simply add the following dependency into your ``` -... and you can customize the validation rules using the following boolean properties: - +### Configuration + +The xAPI Model Spring Boot Autoconfigure has a Spring AutoConfiguration bean which picks up the following properties: | Property | Description | | ----------------------------------------- | -------------------------------------------------------------------------- | @@ -304,9 +347,6 @@ If you use Spring Boot framework, simply add the following dependency into your The default value is **TRUE** for all of the above properties. -### Samples - -The samples folder in this repository contains [sample applications](samples) that use the xAPI client. ## xAPI Java Model From 024f381016b55a286d99f69326b2c113458b9c21 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Fri, 21 Apr 2023 13:03:19 +0100 Subject: [PATCH 11/12] fix up --- README.md | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/README.md b/README.md index 5156c0f1..50ec6541 100644 --- a/README.md +++ b/README.md @@ -254,45 +254,6 @@ client.deleteState(r -> r.activityId("https://example.com/activity/1") .block(); ``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Samples The samples folder in this repository contains [sample applications](samples) that use the xAPI client. From c9454364b2178d4ff6dbc935e1e42f1f222f5f56 Mon Sep 17 00:00:00 2001 From: Thomas Turrell-Croft Date: Mon, 24 Apr 2023 15:11:52 +0100 Subject: [PATCH 12/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 03fa7d85..c55dfc32 100644 --- a/README.md +++ b/README.md @@ -292,7 +292,7 @@ The xAPI specification has strict rules for API requests/responses formatting. T In some cases it may be desirable to turn off some or all of the rules in order to be compatible with a wider range of xAPI activity providers. However, it should be noted that doing this is in violation of the xAPI specification. -The xAPI Model Spring Boot Autoconfigure package provides an easy way to turn on/off these validation rules one by one. +The xAPI Model Spring Boot Autoconfigure package provides an easy way to turn on/off these validation rules. ### Getting started