Skip to content
Merged
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
22 changes: 22 additions & 0 deletions samples/get-agents/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.learning.xapi.samples</groupId>
<artifactId>xapi-samples-build</artifactId>
<version>1.0.6-SNAPSHOT</version>
</parent>
<artifactId>get-agents</artifactId>
<name>Get xAPI Agents Sample</name>
<description>Get xAPI Agents</description>
<dependencies>
<dependency>
<groupId>dev.learning.xapi</groupId>
<artifactId>xapi-client</artifactId>
</dependency>
<dependency>
<groupId>dev.learning.xapi.samples</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package dev.learning.xapi.samples.getagents;

import dev.learning.xapi.client.XapiClient;
import dev.learning.xapi.model.Person;
import dev.learning.xapi.model.Verb;
import java.util.Locale;
import java.util.UUID;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClient;

/**
* Sample using xAPI client to get agents.
*
* @author Thomas Turrell-Croft
*/
@SpringBootApplication
public class GetAgentsApplication implements CommandLineRunner {

private final XapiClient client;

/**
* Constructor for application. In this sample the WebClient.Builder instance is injected by the
* Spring Framework.
*/
public GetAgentsApplication(WebClient.Builder webClientBuilder) {

webClientBuilder
// Change for the URL of your LRS
.baseUrl("https://example.com/xapi/")
// Set the Authorization value
.defaultHeader("Authorization", "")

.build();


client = new XapiClient(webClientBuilder);
}

public static void main(String[] args) {
SpringApplication.run(GetAgentsApplication.class, args).close();
}

@Override
public void run(String... args) throws Exception {

// Post statement for later retrieval of activity
postStatement();

// Get Activity
ResponseEntity<Person> response =
client.getAgents(r -> r.agent(a -> a.name("A N Other").mbox("mailto:another@example.com")))
.block();

// Print the returned activity to the console
System.out.println(response.getBody());
}

private UUID postStatement() {

// Post a statement
ResponseEntity<
UUID> response =
client
.postStatement(r -> r.statement(
s -> s.actor(a -> a.name("A N Other").mbox("mailto:another@example.com"))

.verb(Verb.ATTEMPTED)

.activityObject(o -> o.id("https://example.com/activity/simplestatement")
.definition(d -> d.addName(Locale.ENGLISH, "Simple Statement")))))
.block();

return response.getBody();
}

}
7 changes: 4 additions & 3 deletions samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
<name>xAPI Samples Build</name>
<description>learning.dev xAPI Samples Build</description>
<properties>
<!-- Samples may violate sonar rules -->
<!-- Samples may violate sonar rules -->
<sonar.skip>true</sonar.skip>
</properties>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
Expand All @@ -34,10 +34,11 @@
<modules>
<module>core</module>
<module>delete-agent-profile</module>
<module>delete-state</module>
<module>delete-state</module>
<module>get-activity</module>
<module>get-agent-profile</module>
<module>get-agent-profiles</module>
<module>get-agents</module>
<module>get-state</module>
<module>get-statement</module>
<module>get-statements</module>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package dev.learning.xapi.client;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.learning.xapi.model.Agent;
import java.util.Map;
import java.util.function.Consumer;
import lombok.Builder;
import lombok.NonNull;
import org.springframework.http.HttpMethod;
import org.springframework.web.util.UriBuilder;

/**
* Return a special, Person Object for a specified Agent. The Person Object is very similar to an
* Agent Object, but instead of each attribute having a single value, each attribute has an array
* value, and it is legal to include multiple identifying properties.
*
* @see <a href=
* "https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Communication.md#24-agents-resourcehttps://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Communication.md#24-agents-resource">Agents
* Resource</a>
*
* @author Thomas Turrell-Croft
*/
@Builder
public class GetAgentsRequest implements Request {

private static final ObjectMapper objectMapper = new ObjectMapper();

/**
* The Agent representation to use in fetching expanded Agent information.
*/
@NonNull
private Agent agent;

@Override
public UriBuilder url(UriBuilder uriBuilder, Map<String, Object> queryParams) {

queryParams.put("agent", agentToJsonString());

return uriBuilder.path("/agents").queryParam("agent", "{agent}");
}

@Override
public HttpMethod getMethod() {
return HttpMethod.GET;
}

/**
* Builder for GetAgentsRequest.
*/
public static class Builder {

/**
* Consumer Builder for agent.
*
* @param agent The Consumer Builder for agent.
*
* @return This builder
*
* @see GetAgentsRequest#agent
*/
public Builder agent(Consumer<Agent.Builder<?, ?>> agent) {

final Agent.Builder<?, ?> builder = Agent.builder();

agent.accept(builder);

return agent(builder.build());

}

/**
* Sets the agent.
*
* @param agent The Agent of the GetAgentsRequest.
*
* @return This builder
*
* @see GetAgentsRequest#agent
*/
public Builder agent(Agent agent) {

this.agent = agent;

return this;

}

}


private String agentToJsonString() {

try {
return objectMapper.writeValueAsString(agent);
} catch (JsonProcessingException e) {
// Should not happen
return null;
}

}

}
45 changes: 45 additions & 0 deletions xapi-client/src/main/java/dev/learning/xapi/client/XapiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package dev.learning.xapi.client;

import dev.learning.xapi.model.Activity;
import dev.learning.xapi.model.Person;
import dev.learning.xapi.model.Statement;
import dev.learning.xapi.model.StatementResult;
import java.util.HashMap;
Expand Down Expand Up @@ -944,4 +945,48 @@ public Mono<ResponseEntity<Activity>> getActivity(Consumer<GetActivityRequest.Bu

}

/**
* Return a special, Person Object for a specified Agent. The Person Object is very similar to an
* Agent Object, but instead of each attribute having a single value, each attribute has an array
* value, and it is legal to include multiple identifying properties.
*
* @param request The parameters of the get agents request
*
* @return the ResponseEntity
*/
public Mono<ResponseEntity<Person>> getAgents(GetAgentsRequest request) {

Map<String, Object> queryParams = new HashMap<>();

return this.webClient

.method(request.getMethod())

.uri(u -> request.url(u, queryParams).build(queryParams))

.retrieve()

.toEntity(Person.class);

}

/**
* Return a special, Person Object for a specified Agent. The Person Object is very similar to an
* Agent Object, but instead of each attribute having a single value, each attribute has an array
* value, and it is legal to include multiple identifying properties.
*
* @param request The Consumer Builder for the get agents request
*
* @return the ResponseEntity
*/
public Mono<ResponseEntity<Person>> getAgents(Consumer<GetAgentsRequest.Builder> request) {

final GetAgentsRequest.Builder builder = GetAgentsRequest.builder();

request.accept(builder);

return getAgents(builder.build());

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import dev.learning.xapi.model.Activity;
import dev.learning.xapi.model.Person;
import dev.learning.xapi.model.Statement;
import dev.learning.xapi.model.StatementFormat;
import dev.learning.xapi.model.Verb;
Expand Down Expand Up @@ -1475,7 +1476,7 @@ void whenPuttingASingleAgentProfileWithoutContentTypeThenBodyIsExpected()

.profileId("person")

.profile(new Person("A N", "Other")))
.profile(new SamplePerson("A N", "Other")))

.block();

Expand Down Expand Up @@ -1593,7 +1594,7 @@ void whenPostingASingleAgentProfileWithoutContentTypeThenBodyIsExpected()

.profileId("person")

.profile(new Person("A N", "Other")))
.profile(new SamplePerson("A N", "Other")))

.block();

Expand Down Expand Up @@ -1668,7 +1669,7 @@ void whenGettingProfilesWithSinceParameterThenPathIsExpected() throws Interrupte
"/agents/profile?agent=%7B%22name%22%3A%22A%20N%20Other%22%2C%22mbox%22%3A%22mailto%3Aanother%40example.com%22%7D&since=2016-01-01T00%3A00%3A00Z"));
}

// Get Statement
// Get Activity

@Test
void whenGettingActivityThenMethodIsGet() throws InterruptedException {
Expand Down Expand Up @@ -1723,13 +1724,63 @@ void whenGettingActivityThenBodyIsInstanceOfActivity() throws InterruptedExcepti



// Get Agents

@Test
void whenGettingAgentsThenMethodIsGet() throws InterruptedException {

mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK"));

// When Getting Agents
client.getAgents(r -> r.agent(a -> a.mbox("mailto:another@example.com"))).block();

RecordedRequest recordedRequest = mockWebServer.takeRequest();

// Then Method Is Get
assertThat(recordedRequest.getMethod(), is("GET"));
}

@Test
void whenGettingAgentsThenPathIsExpected() throws InterruptedException {

mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK"));

// When Getting Agents
client.getAgents(r -> r.agent(a -> a.mbox("mailto:another@example.com"))).block();

RecordedRequest recordedRequest = mockWebServer.takeRequest();

// Then Path Is Expected
assertThat(recordedRequest.getPath(),
is("/agents?agent=%7B%22mbox%22%3A%22mailto%3Aanother%40example.com%22%7D"));
}

@Test
void whenGettingAgentsThenBodyIsInstanceOfPerson() throws InterruptedException {

mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK")

.setBody(
"{\"name\":[\"A N Other\"],\"mbox\":[\"mailto:another@example.com\"],\"objectType\":\"Person\"}")
.addHeader("Content-Type", "application/json; charset=utf-8"));

// When Getting Agents
var response =
client.getAgents(r -> r.agent(a -> a.mbox("mailto:another@example.com"))).block();

// Then Body Is Instance Of Activity
assertThat(response.getBody(), instanceOf(Person.class));
}



@Getter
private static class Person {
private static class SamplePerson {

private String firstName;
private String lastName;

public Person(String firstName, String lastName) {
public SamplePerson(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
Expand Down