Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.HasScheme;
import dev.learning.xapi.model.validation.constraints.ValidLanguageMap;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -33,11 +34,13 @@ public class ActivityDefinition {
/**
* The human readable/visual name of the Activity.
*/
@ValidLanguageMap
private LanguageMap name;

/**
* A description of the Activity.
*/
@ValidLanguageMap
private LanguageMap description;

/**
Expand Down Expand Up @@ -92,7 +95,8 @@ public class ActivityDefinition {
*/
private Map<@HasScheme URI, Object> extensions;

// **Warning** do not add fields that are not required by the xAPI specification.
// **Warning** do not add fields that are not required by the xAPI
// specification.

/**
* Builder for ActivityDefinition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.ValidLanguageMap;
import jakarta.validation.constraints.NotNull;
import java.net.URI;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -41,11 +42,13 @@ public class Attachment {
* Display name of this Attachment.
*/
@NotNull
@ValidLanguageMap
private LanguageMap display;

/**
* A description of the Attachment.
*/
@ValidLanguageMap
private LanguageMap description;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.ValidLanguageMap;
import jakarta.validation.constraints.NotNull;
import java.util.Locale;
import lombok.Builder;
Expand Down Expand Up @@ -36,6 +37,7 @@ public class InteractionComponent {
/**
* A description of the interaction component.
*/
@ValidLanguageMap
private LanguageMap description;

// **Warning** do not add fields that are not required by the xAPI specification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public class Statement implements CoreStatement {
/**
* Agent or Group who is asserting this Statement is true.
*/
@Valid
@ValidActor
@ValidAuthority
private Actor authority;
Expand All @@ -113,6 +114,7 @@ public class Statement implements CoreStatement {
/**
* Headers for Attachments to the Statement.
*/
@Valid
@JsonFormat(without = {JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY})
private List<Attachment> attachments;

Expand Down Expand Up @@ -349,7 +351,7 @@ public Builder addAttachment(Attachment attachment) {
*/
public Builder addAttachment(Consumer<Attachment.Builder> attachment) {

final Attachment.Builder builder = Attachment.builder();
final var builder = Attachment.builder();

attachment.accept(builder);

Expand Down
2 changes: 2 additions & 0 deletions xapi-model/src/main/java/dev/learning/xapi/model/Verb.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import dev.learning.xapi.model.validation.constraints.HasScheme;
import dev.learning.xapi.model.validation.constraints.ValidLanguageMap;
import jakarta.validation.constraints.NotNull;
import java.net.URI;
import java.util.Locale;
Expand Down Expand Up @@ -351,6 +352,7 @@ public class Verb {
* impact on the meaning of the Statement, but serves to give a human-readable display of the
* meaning already determined by the chosen Verb.
*/
@ValidLanguageMap
private LanguageMap display;

// **Warning** do not add fields that are not required by the xAPI specification.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
*/

package dev.learning.xapi.model.validation.constraints;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* All of the keys in the annotated LanguageMap must have a ISO3 Language and Country.
*
* @author István Rátkai (Selindek)
*/
@Documented
@Constraint(validatedBy = {})
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface ValidLanguageMap {

/**
* Error Message.
*/
String message() default "all keys must have a ISO3 Language and Country";

/**
* Groups.
*/
Class<?>[] groups() default {};

/**
* Payload.
*/
Class<? extends Payload>[] payload() default {};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
*/

package dev.learning.xapi.model.validation.internal.validators;

import dev.learning.xapi.model.LanguageMap;
import dev.learning.xapi.model.validation.constraints.ValidLanguageMap;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Locale;
import java.util.MissingResourceException;

/**
* The Locale being validated must have a ISO3 Language and Country.
*
* @author István Rátkai (Selindek)
* @author Thomas Turrell-Croft
*/
public class LanguageMapValidator implements ConstraintValidator<ValidLanguageMap, LanguageMap> {

@Override
public boolean isValid(LanguageMap value, ConstraintValidatorContext context) {

if (value == null) {
return true;
}

return value.keySet().stream().allMatch(this::valid);

}

private boolean valid(Locale locale) {

try {
locale.getISO3Language();
locale.getISO3Country();

return true;
} catch (final MissingResourceException e1) {

// Handle locale instantiated with Locale#Locale(String)
final var blar = Locale.forLanguageTag(locale.toString());

try {
blar.getISO3Language();
blar.getISO3Country();

return true;
} catch (final MissingResourceException e2) {

return false;
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ dev.learning.xapi.model.validation.internal.validators.StatementRevisionValidato
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.LanguageMapValidator
dev.learning.xapi.model.validation.internal.validators.ScoreValidator
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2016-2023 Berry Cloud Ltd. All rights reserved.
*/

package dev.learning.xapi.model.validation.internal.validators;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import dev.learning.xapi.model.LanguageMap;
import java.util.Locale;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

/**
* ScaledScoreValidator Tests.
*
* @author István Rátkai (Selindek)
*/
@DisplayName("ScaledSoreValidator tests")
class LanguageMapValidatorTests {

private static final LanguageMapValidator validator = new LanguageMapValidator();

@Test
void whenValueIsNullThenResultIsTrue() {

// When Value Is Null
final var result = validator.isValid(null, null);

// Then Result Is True
assertTrue(result);
}

@Test
void whenCallingIsValidOnLanguageMapWithUKKeyThenResultIsTrue() {

final var languageMap = new LanguageMap();
languageMap.put(Locale.UK, "Hello World!");

// When Calling Is Valid On Language Map With UK Key
final var result = validator.isValid(languageMap, null);

// Then Result Is True
assertTrue(result);
}

@Test
void whenCallingIsValidOnLanguageMapWithENKeyThenResultIsTrue() {

final var languageMap = new LanguageMap();
languageMap.put(Locale.ENGLISH, "Hello World!");

// When Calling Is Valid On Language Map With EN Key
final var result = validator.isValid(languageMap, null);

// Then Result Is True
assertTrue(result);
}

@Test
void whenCallingIsValidOnLanguageMapWithENAndUKKeysThenResultIsTrue() {

final var languageMap = new LanguageMap();
languageMap.put(Locale.ENGLISH, "Hello World!");
languageMap.put(Locale.UK, "Hello World!");

// When Calling Is Valid On Language Map With EN And UK Keys
final var result = validator.isValid(languageMap, null);

// Then Result Is True
assertTrue(result);
}

@Test
void whenCallingIsValidOnLanguageMapWithENAndUnknownKeysThenResultIsFalse() {

final var languageMap = new LanguageMap();
languageMap.put(Locale.ENGLISH, "Hello World!");
languageMap.put(Locale.forLanguageTag("unknown"), "Hello World!");

// When Calling Is Valid On Language Map With EN And Unknown Keys
final var result = validator.isValid(languageMap, null);

// Then Result Is False
assertFalse(result);
}

@Test
void whenCallingIsValidOnLanguageMapWithChineseSimplifiedKeyUsingForLangugeTagThenResultIsTrue() {

final var languageMap = new LanguageMap();
languageMap.put(Locale.forLanguageTag("zh-CHS"), "Hello World!");

// When Calling Is Valid On Language Map With Chinese Simplified Key
final var result = validator.isValid(languageMap, null);

// Then Result Is True
assertTrue(result);
}

@ParameterizedTest
@ValueSource(strings = {"und", "zh-CHS", "zh-CN", "zh-Hans", "zh-Hant", "zh-HK"})
void whenCallingIsValidOnLanguageMapWithValidKeyThenResultIsTrue(String arg) {

final var languageMap = new LanguageMap();
languageMap.put(new Locale(arg), "Hello World!");

// When Calling Is Valid On Language Map With Valid Key
final var result = validator.isValid(languageMap, null);

// Then Result Is True
assertTrue(result);
}

@Test
void whenCallingIsValidOnLanguageMapWithUnknownKeyThenResultIsFalse() {

final var languageMap = new LanguageMap();
languageMap.put(new Locale("unknown"), "Hello World!");

// When Calling Is Valid On Language Map With Unknown Key
final var result = validator.isValid(languageMap, null);

// Then Result Is False
assertFalse(result);
}

}