Skip to content

[JXT-3] Validation #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e6d18dc
Add jakarta.validation-api dependency
kelvinqian00 Dec 3, 2024
8680376
Add validation implementation dep
kelvinqian00 Dec 3, 2024
cc0de68
Remove warnings in model package
kelvinqian00 Dec 4, 2024
4b2ba11
Remove warning in test case
kelvinqian00 Dec 4, 2024
847d1b9
Remove remaining warnings from xapi model
kelvinqian00 Dec 4, 2024
fa031cd
Add validation that Agents only have 1 IFI
kelvinqian00 Dec 5, 2024
1e1553c
Add validation for anonymous vs identified groups
kelvinqian00 Dec 5, 2024
dd6b673
Add NotNull constraints to Account
kelvinqian00 Dec 5, 2024
1798221
Add tests and TODOs for actor fields
kelvinqian00 Dec 5, 2024
6314acd
Don't forget imports in Agent and Group classes
kelvinqian00 Dec 5, 2024
8191807
Add Verb validation
kelvinqian00 Dec 5, 2024
f8e7427
Add Activity + ActivityDefinition validation
kelvinqian00 Dec 6, 2024
2bc3d50
Add Result and Score
kelvinqian00 Dec 6, 2024
7e54c63
Add InteractionComponent
kelvinqian00 Dec 6, 2024
94725e4
Add Attachment constraints
kelvinqian00 Dec 6, 2024
1007b07
Add StatementRef constraints
kelvinqian00 Dec 6, 2024
72445b6
Implement constraints for Statements (incl Authority checks)
kelvinqian00 Dec 6, 2024
9074e73
Add StatementResult
kelvinqian00 Dec 6, 2024
91d5ccd
Add ValidationUtils class with custom asserts
kelvinqian00 Dec 9, 2024
131c380
Add isEmpty function to validate that JSON objects are not empty
kelvinqian00 Dec 9, 2024
90704aa
Make statement's own isValidSubStmt method
kelvinqian00 Dec 10, 2024
46b9f84
Apply JsonIgnore annotation to prevent Jackson for serializing extra …
kelvinqian00 Dec 10, 2024
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
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@
<artifactId>json-path</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-jsr</artifactId>
<version>3.0.1</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
40 changes: 39 additions & 1 deletion src/main/java/com/yetanalytics/xapi/model/AbstractActor.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.yetanalytics.xapi.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.yetanalytics.xapi.model.deserializers.AbstractActorDeserializer;

import jakarta.validation.Valid;

/**
* Abstract Class for serialization and deserialization of xAPI Actors
*/
Expand All @@ -11,12 +14,18 @@ public abstract class AbstractActor extends AbstractObject {

private String name;

//IFI
// IFIs

// TODO: Validate mbox is a valid mailto IRI
private String mbox;
// TODO: Validate mbox_sha1sum is a valid hash string
private String mbox_sha1sum;
// TODO: Validate openid is a valid IRI
private String openid;
@Valid
private Account account;

// Getters and Setters
public String getName() {
return name;
}
Expand Down Expand Up @@ -51,4 +60,33 @@ public Account getAccount() {
public void setAccount(Account account) {
this.account = account;
}

// Validation
protected int countIFIs() {
int notNullCount = 0;
if (mbox != null) {
++notNullCount;
}
if (mbox_sha1sum != null) {
++notNullCount;
}
if (openid != null) {
++notNullCount;
}
if (account != null) {
++notNullCount;
}
return notNullCount;
}

public abstract boolean isValidAuthority();

@Override
@JsonIgnore
public boolean isEmpty() {
return (
mbox == null && mbox_sha1sum == null &&
openid == null && account == null
);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.yetanalytics.xapi.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.yetanalytics.xapi.model.deserializers.AbstractObjectDeserializer;

/**
* Abstract Class for serialization and deserialization of xAPI Objects
*/
@JsonDeserialize(using = AbstractObjectDeserializer.class)
public class AbstractObject {
public abstract class AbstractObject implements JSONObject {

private ObjectType objectType;

Expand All @@ -18,4 +19,7 @@ public void setObjectType(ObjectType objectType) {
this.objectType = objectType;
}

@Override
@JsonIgnore
public abstract boolean isEmpty();
}
16 changes: 14 additions & 2 deletions src/main/java/com/yetanalytics/xapi/model/Account.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.yetanalytics.xapi.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

import jakarta.validation.constraints.AssertFalse;
import jakarta.validation.constraints.NotNull;

/**
* Class representation of the Account Component of the
* <a href="https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#2424-account-object">9274.1.1 xAPI Specification</a>.
*/
@JsonInclude(Include.NON_NULL)
public class Account {
public class Account implements JSONObject {

@NotNull
private String homePage;

@NotNull
private String name;

public String getHomePage() {
Expand All @@ -27,4 +32,11 @@ public String getName() {
public void setName(String name) {
this.name = name;
}

@Override
@JsonIgnore
@AssertFalse
public boolean isEmpty() {
return homePage == null && name == null;
}
}
16 changes: 15 additions & 1 deletion src/main/java/com/yetanalytics/xapi/model/Activity.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.yetanalytics.xapi.model;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import jakarta.validation.Valid;
import jakarta.validation.constraints.AssertFalse;
import jakarta.validation.constraints.NotNull;

/**
* Class representation of the Activity Object Type of the
Expand All @@ -11,8 +16,10 @@
@JsonInclude(Include.NON_NULL)
@JsonDeserialize
public class Activity extends AbstractObject {
@NotNull
private String id;

@Valid
private ActivityDefinition definition;

public String getId() {
Expand All @@ -28,4 +35,11 @@ public ActivityDefinition getDefinition() {
public void setDefinition(ActivityDefinition definition) {
this.definition = definition;
}

@Override
@JsonIgnore
@AssertFalse
public boolean isEmpty() {
return id == null && definition == null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

import jakarta.validation.constraints.AssertFalse;
import jakarta.validation.constraints.AssertTrue;

/**
* Class representation of the Activity Definition Component of the
* <a href="https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#activity-definition">9274.1.1 xAPI Specification</a>.
*/
@JsonInclude(Include.NON_NULL)
public class ActivityDefinition {
public class ActivityDefinition implements JSONObject {

private LangMap name;
private LangMap description;
Expand Down Expand Up @@ -101,4 +105,95 @@ public List<InteractionComponent> getSteps() {
public void setSteps(List<InteractionComponent> steps) {
this.steps = steps;
}

// Validation

private boolean isChoices() {
return (
// choices is allowed
scale == null &&
source == null &&
target == null &&
steps == null
);
}

private boolean isScale() {
return (
// scale is allowed
choices == null &&
source == null &&
target == null &&
steps == null
);
}

private boolean isSourceTarget() {
return (
// source and target are allowed
choices == null &&
scale == null &&
steps == null
);
}

private boolean isSteps() {
return (
// steps is allowed
choices == null &&
scale == null &&
source == null &&
target == null
);
}

private boolean isNoInteractionComponents() {
return (
choices == null &&
scale == null &&
source == null &&
target == null &&
steps == null
);
}

private boolean isNoInteraction() {
return (
isNoInteractionComponents() &&
correctResponsesPattern == null
);
}

@Override
@JsonIgnore
@AssertFalse
public boolean isEmpty() {
return (
name == null && description == null &&
type == null && moreInfo == null && extensions == null &&
interactionType == null && isNoInteraction()
);
}

@JsonIgnore
@AssertTrue
public boolean isValidInteractionActivity() {
if (interactionType == null) {
return isNoInteraction();
}
switch (interactionType) {
case CHOICE:
return isChoices();
case SEQUENCING:
return isChoices();
case LIKERT:
return isScale();
case MATCHING:
return isSourceTarget();
case PERFORMANCE:
return isSteps();
default:
return isNoInteractionComponents();
}
}
}
30 changes: 29 additions & 1 deletion src/main/java/com/yetanalytics/xapi/model/Agent.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.yetanalytics.xapi.model;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import jakarta.validation.constraints.AssertFalse;
import jakarta.validation.constraints.AssertTrue;

/**
* A concrete class representation of the Agent Component of the
Expand All @@ -13,4 +17,28 @@
@JsonDeserialize
public class Agent extends AbstractActor {

// Validation

@Override
@JsonIgnore
@AssertFalse
public boolean isEmpty() {
return super.isEmpty();
}

/**
* Assertion that the Agent has only 1 Inverse Functional Identifier (IFI).
* @return true if the Agent has exactly 1 IFI, false otherwise
*/
@JsonIgnore
@AssertTrue
public boolean isIdentifiedAgent() {
return countIFIs() == 1;
}

@Override
@JsonIgnore
public boolean isValidAuthority() {
return true;
}
}
28 changes: 26 additions & 2 deletions src/main/java/com/yetanalytics/xapi/model/Attachment.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
package com.yetanalytics.xapi.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

import jakarta.validation.constraints.AssertFalse;
import jakarta.validation.constraints.NotNull;

/**
* Class representation of the Attachment Component of the
* <a href="https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#2411-attachments">9274.1.1 xAPI Specification</a>.
*/
@JsonInclude(Include.NON_NULL)
public class Attachment {
public class Attachment implements JSONObject {

@NotNull
private String usageType;
@NotNull
private LangMap display;
private LangMap description;
@NotNull
private String contentType;
@NotNull
private Integer length;
@NotNull
private String sha2;
private String fileUrl;

Expand Down Expand Up @@ -61,5 +70,20 @@ public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}


// Validation

@Override
@JsonIgnore
@AssertFalse
public boolean isEmpty() {
return (
usageType == null &&
display == null &&
description == null &&
contentType == null &&
length == null &&
sha2 == null &&
fileUrl == null
);
}
}
Loading
Loading