diff --git a/README.md b/README.md
index fff6be40..c55dfc32 100644
--- a/README.md
+++ b/README.md
@@ -286,6 +286,57 @@ client.deleteState(r -> r.activityId("https://example.com/activity/1")
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.
+
+### 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:
+
+```
+
+ dev.learning.xapi
+ xapi-model-spring-boot-autoconfigure
+ 1.1.5
+
+```
+
+### Configuration
+
+The xAPI Model Spring Boot Autoconfigure has a Spring AutoConfiguration bean which picks up the following 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 (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) |
+| 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.
+
+
## xAPI Java Model
The xAPI model can be used by clients that send xAPI data or by servers that receive xAPI data.
diff --git a/samples/xapi-server/src/main/resources/application.properties b/samples/xapi-server/src/main/resources/application.properties
index 3c1776c4..31a5d713 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 = 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/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java b/xapi-model-spring-boot-autoconfigure/src/main/java/dev/learning/xapi/XapiModelAutoConfiguration.java
index 62194162..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
@@ -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;
@@ -25,7 +40,7 @@
* @author István Rátkai (Selindek)
*/
@Configuration
-@AutoConfigureBefore(value = JacksonProperties.class)
+@AutoConfigureBefore(JacksonProperties.class)
public class XapiModelAutoConfiguration {
/**
@@ -39,84 +54,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)
@@ -138,4 +153,225 @@ public Jackson2ObjectMapperBuilderCustomizer strictLiteralsCustomizer() {
});
}
+
+ /**
+ * ValidateActivityDefinitionPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateActorPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateAuthorityPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateUriSchemePostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateMboxPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateLocaleNotUndeterminedPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateScaledScorePostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateScorePostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateStatementPlatformPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateStatementRevisionPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateStatementListIdsPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateStatementVerbPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
+
+ /**
+ * ValidateUuidVariantPostProcessor.
+ */
+ @Bean
+ @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);
+ }
+ return bean;
+ }
+ };
+ }
}
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/disableable/DisableableValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java
new file mode 100644
index 00000000..3a1bbe42
--- /dev/null
+++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/disableable/DisableableValidator.java
@@ -0,0 +1,59 @@
+/*
+ * 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 implementing the validation logic independently from the disabled/enabled
+ * logic.
+ *
+ * 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
+ */
+ protected 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 c4d2b73c..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,7 +6,7 @@
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;
/**
@@ -19,10 +19,10 @@
* Definition
*/
public class ActivityDefinitionValidator
- implements ConstraintValidator {
+ extends DisableableValidator {
@Override
- public boolean isValid(ActivityDefinition value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(ActivityDefinition value, ConstraintValidatorContext context) {
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 79e084d0..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,7 +9,7 @@
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;
/**
@@ -19,7 +19,7 @@
*
* @see Actor
*/
-public class ActorValidator implements ConstraintValidator {
+public class ActorValidator extends DisableableValidator {
/**
* Checks if this {@link Actor} contains exactly one identifier.
@@ -27,7 +27,7 @@ public class ActorValidator implements ConstraintValidator {
* @return true if this object is valid.
*/
@Override
- public boolean isValid(Object value, ConstraintValidatorContext context) {
+ 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 b3804ecc..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,7 +8,7 @@
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;
/**
@@ -17,10 +17,10 @@
* @author István Rátkai (Selindek)
* @author Thomas Turrell-Croft
*/
-public class AuthorityValidator implements ConstraintValidator {
+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 (value == null || value instanceof Agent) {
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..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,7 +5,7 @@
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;
@@ -14,10 +14,10 @@
*
* @author Thomas Turrell-Croft
*/
-public class HasSchemeValidatorForUri implements ConstraintValidator {
+public class HasSchemeValidatorForUri extends DisableableValidator {
@Override
- public boolean isValid(URI value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(URI value, ConstraintValidatorContext context) {
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 9c2a498d..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,7 +5,7 @@
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;
@@ -17,7 +17,7 @@
*
* @see Mbox
*/
-public class MboxValidator implements ConstraintValidator {
+public class MboxValidator extends DisableableValidator {
public static final String PREFIX = "mailto:";
@@ -30,8 +30,7 @@ public void initialize(Mbox mbox) {
}
@Override
- public boolean isValid(String value, ConstraintValidatorContext context) {
-
+ 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 76749b61..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,7 +5,7 @@
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;
@@ -14,10 +14,10 @@
*
* @author István Rátkai (Selindek)
*/
-public class NotUndeterminedValidator implements ConstraintValidator {
+public class NotUndeterminedValidator extends DisableableValidator {
@Override
- public boolean isValid(Locale value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(Locale value, ConstraintValidatorContext context) {
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 69886742..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,7 +5,7 @@
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;
/**
@@ -16,10 +16,10 @@
* @see xAPI Score
* details
*/
-public class ScaledScoreValidator implements ConstraintValidator {
+public class ScaledScoreValidator extends DisableableValidator {
@Override
- public boolean isValid(Float value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(Float value, ConstraintValidatorContext context) {
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 746d6915..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,7 +6,7 @@
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;
/**
@@ -14,10 +14,10 @@
*
* @author István Rátkai (Selindek)
*/
-public class ScoreValidator implements ConstraintValidator {
+public class ScoreValidator extends DisableableValidator {
@Override
- public boolean isValid(Score value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(Score value, ConstraintValidatorContext context) {
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 09195dfe..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,7 +7,7 @@
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;
/**
@@ -23,10 +23,10 @@
* Statement Context Requirements
*/
public class StatementPlatformValidator
- implements ConstraintValidator {
+ extends DisableableValidator {
@Override
- public boolean isValid(CoreStatement value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(CoreStatement value, ConstraintValidatorContext context) {
return value == null || value.getContext() == null || value.getContext().getPlatform() == null
|| value.getObject() instanceof Activity;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementRevisionValidator.java
index 916e543d..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,7 +7,7 @@
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;
/**
@@ -23,10 +23,10 @@
* Statement Context Requirements
*/
public class StatementRevisionValidator
- implements ConstraintValidator {
+ extends DisableableValidator {
@Override
- public boolean isValid(CoreStatement value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(CoreStatement value, ConstraintValidatorContext context) {
return value == null || value.getContext() == null || value.getContext().getRevision() == null
|| value.getObject() instanceof Activity;
diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/StatementVerbValidator.java
index 737e9039..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,13 +7,13 @@
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;
/**
- * 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
@@ -23,10 +23,10 @@
* Voiding Statement Requirements
*/
public class StatementVerbValidator
- implements ConstraintValidator {
+ extends DisableableValidator {
@Override
- public boolean isValid(CoreStatement value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(CoreStatement value, ConstraintValidatorContext context) {
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 e1a2b054..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,7 +6,7 @@
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;
@@ -18,13 +18,13 @@
*
* @author Thomas Turrell-Croft
*/
-public class StatementsValidator implements ConstraintValidator> {
+public class StatementsValidator extends DisableableValidator> {
/**
* {@inheritDoc}
*/
@Override
- public boolean isValid(List values, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(List values, ConstraintValidatorContext context) {
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 71fa37b3..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,7 +5,7 @@
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;
@@ -13,8 +13,9 @@
* The UUID being validated must have the specified variant.
*
* @author Thomas Turrell-Croft
+ * @author István Rátkai (Selindek)
*/
-public class VariantValidatorForUuid implements ConstraintValidator {
+public class VariantValidatorForUuid extends DisableableValidator {
private int variant;
@@ -25,7 +26,7 @@ public void initialize(Variant constraintAnnotation) {
}
@Override
- public boolean isValid(UUID value, ConstraintValidatorContext context) {
+ public boolean isValidIfEnabled(UUID value, ConstraintValidatorContext context) {
if (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