diff --git a/src/main/java/com/rusticisoftware/tincan/Activity.java b/src/main/java/com/rusticisoftware/tincan/Activity.java index 8598ba0..5adde65 100644 --- a/src/main/java/com/rusticisoftware/tincan/Activity.java +++ b/src/main/java/com/rusticisoftware/tincan/Activity.java @@ -15,6 +15,7 @@ */ package com.rusticisoftware.tincan; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -26,6 +27,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.rusticisoftware.tincan.json.JSONBase; import com.rusticisoftware.tincan.json.Mapper; +import com.rusticisoftware.tincan.json.StringOfJSON; /** * Activity model class @@ -67,6 +69,10 @@ public Activity(String id, String name, String description) throws URISyntaxExce this.setDefinition(new ActivityDefinition(name, description)); } + public Activity(StringOfJSON jsonStr) throws URISyntaxException, IOException { + this(jsonStr.toJSONNode()); + } + @Override public ObjectNode toJSONNode(TCAPIVersion version) { ObjectNode node = Mapper.getInstance().createObjectNode(); diff --git a/src/main/java/com/rusticisoftware/tincan/LRS.java b/src/main/java/com/rusticisoftware/tincan/LRS.java index 5f0bf57..ef4e148 100644 --- a/src/main/java/com/rusticisoftware/tincan/LRS.java +++ b/src/main/java/com/rusticisoftware/tincan/LRS.java @@ -41,12 +41,14 @@ public interface LRS { LRSResponse deleteState(StateDocument state); LRSResponse clearState(Activity activity, Agent agent, UUID registration); + ActivityLRSResponse retrieveActivity(Activity activity); ProfileKeysLRSResponse retrieveActivityProfileIds(Activity activity); ActivityProfileLRSResponse retrieveActivityProfile(String id, Activity activity); LRSResponse saveActivityProfile(ActivityProfileDocument profile); LRSResponse updateActivityProfile(ActivityProfileDocument profile); LRSResponse deleteActivityProfile(ActivityProfileDocument profile); + PersonLRSResponse retrievePerson(Agent agent); ProfileKeysLRSResponse retrieveAgentProfileIds(Agent agent); AgentProfileLRSResponse retrieveAgentProfile(String id, Agent agent); LRSResponse saveAgentProfile(AgentProfileDocument profile); diff --git a/src/main/java/com/rusticisoftware/tincan/LanguageMap.java b/src/main/java/com/rusticisoftware/tincan/LanguageMap.java index b52660e..ec2c6a7 100644 --- a/src/main/java/com/rusticisoftware/tincan/LanguageMap.java +++ b/src/main/java/com/rusticisoftware/tincan/LanguageMap.java @@ -22,6 +22,8 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.List; +import java.util.ArrayList; import com.rusticisoftware.tincan.json.JSONBase; import com.rusticisoftware.tincan.json.Mapper; @@ -39,6 +41,7 @@ private class LanguageMapIterator implements Iterator> public LanguageMapIterator() { iterator = _map.entrySet().iterator(); } + @Override public boolean hasNext() { return iterator.hasNext(); @@ -52,7 +55,8 @@ public Entry next() { @Override public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException( - "LanguageMap iterator does not implement the remove method"); + "LanguageMap iterator does not implement the remove method" + ); } } public LanguageMap(JsonNode jsonNode) { @@ -79,7 +83,7 @@ public ObjectNode toJSONNode(TCAPIVersion version) { public String put(String key, String val) { return this._map.put(key, val); } - + public String put(Map.Entry entry) { return this.put(entry.getKey(), entry.getValue()); } @@ -109,6 +113,14 @@ public Map.Entry findFirstValue(String value) { return retVal; } + public void populateWithAvailableLanguages(List list) { + Iterator> it = this.iterator(); + while (it.hasNext()) { + Map.Entry n = it.next(); + list.add(n.getKey()); + } + } + @Override public Iterator> iterator() { return new LanguageMapIterator(); diff --git a/src/main/java/com/rusticisoftware/tincan/Person.java b/src/main/java/com/rusticisoftware/tincan/Person.java new file mode 100644 index 0000000..ccf8e08 --- /dev/null +++ b/src/main/java/com/rusticisoftware/tincan/Person.java @@ -0,0 +1,153 @@ +/* + Copyright 2015 Rustici Software + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.rusticisoftware.tincan; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.rusticisoftware.tincan.json.JSONBase; +import com.rusticisoftware.tincan.json.Mapper; +import com.rusticisoftware.tincan.json.StringOfJSON; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Person Model class + */ +@Data +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +public class Person extends JSONBase { + protected final String objectType = "Person"; + private List name; + private List mbox; + private List mbox_sha1sum; + private List openid; + private List account; + + public Person(StringOfJSON jsonStr) throws IOException { + this(jsonStr.toJSONNode()); + } + + public Person(JsonNode jsonNode) { + this(); + + JsonNode nameNode = jsonNode.path("name"); + if (! nameNode.isMissingNode()) { + this.name = new ArrayList(); + + for (JsonNode element : nameNode) { + this.name.add(element.textValue()); + } + } + + JsonNode mboxNode = jsonNode.path("mbox"); + if (! mboxNode.isMissingNode()) { + this.mbox = new ArrayList(); + + for (JsonNode element : mboxNode) { + this.mbox.add(element.textValue()); + } + } + + JsonNode mbox_sha1sumNode = jsonNode.path("mbox_sha1sum"); + if (! mbox_sha1sumNode.isMissingNode()) { + this.mbox_sha1sum = new ArrayList(); + + for (JsonNode element : mbox_sha1sumNode) { + this.mbox_sha1sum.add(element.textValue()); + } + } + + JsonNode openidNode = jsonNode.path("openid"); + if (! openidNode.isMissingNode()) { + this.openid = new ArrayList(); + + for (JsonNode element : openidNode) { + this.openid.add(element.textValue()); + } + } + + JsonNode accountNode = jsonNode.path("account"); + if (! accountNode.isMissingNode()) { + this.account = new ArrayList(); + + for (JsonNode element : accountNode) { + this.account.add(new AgentAccount(element)); + } + } + } + + @Override + public ObjectNode toJSONNode(TCAPIVersion version) { + ObjectMapper mapper = Mapper.getInstance(); + ObjectNode node = mapper.createObjectNode(); + node.put("objectType", this.getObjectType()); + + if (this.name != null && this.name.size() > 0) { + ArrayNode name = mapper.createArrayNode(); + node.put("name", name); + + for (String element : this.getName()) { + name.add(element); + } + } + + if (this.mbox != null && this.mbox.size() > 0) { + ArrayNode mbox = mapper.createArrayNode(); + node.put("mbox", mbox); + + for (String element : this.getMbox()) { + mbox.add(element); + } + } + + if (this.mbox_sha1sum != null && this.mbox_sha1sum.size() > 0) { + ArrayNode mbox_sha1sum = mapper.createArrayNode(); + node.put("mbox_sha1sum", mbox_sha1sum); + + for (String element : this.getMbox_sha1sum()) { + mbox_sha1sum.add(element); + } + } + + if (this.openid != null && this.openid.size() > 0) { + ArrayNode openid = mapper.createArrayNode(); + node.put("openid", openid); + + for (String element : this.getOpenid()) { + openid.add(element); + } + } + + if (this.account != null && this.account.size() > 0) { + ArrayNode account = mapper.createArrayNode(); + node.put("account", account); + + for (AgentAccount element : this.getAccount()) { + account.add(element.toJSONNode(version)); + } + } + + return node; + } +} diff --git a/src/main/java/com/rusticisoftware/tincan/RemoteLRS.java b/src/main/java/com/rusticisoftware/tincan/RemoteLRS.java index 5cb1fa9..e135906 100644 --- a/src/main/java/com/rusticisoftware/tincan/RemoteLRS.java +++ b/src/main/java/com/rusticisoftware/tincan/RemoteLRS.java @@ -25,6 +25,7 @@ import com.rusticisoftware.tincan.http.HTTPRequest; import com.rusticisoftware.tincan.http.HTTPResponse; import com.rusticisoftware.tincan.lrsresponses.*; + import lombok.Data; import lombok.NoArgsConstructor; @@ -42,6 +43,7 @@ import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; + import com.rusticisoftware.tincan.exceptions.*; import com.rusticisoftware.tincan.json.Mapper; import com.rusticisoftware.tincan.json.StringOfJSON; @@ -694,6 +696,35 @@ public LRSResponse clearState(Activity activity, Agent agent, UUID registration) return deleteDocument("activities/state", queryParams); } + @Override + public ActivityLRSResponse retrieveActivity(Activity activity) { + HTTPRequest request = new HTTPRequest(); + request.setMethod(HttpMethods.GET); + request.setResource("activities"); + request.setQueryParams(new HashMap()); + request.getQueryParams().put("activityId", activity.getId().toString()); + + HTTPResponse response = makeSyncRequest(request); + int status = response.getStatus(); + + ActivityLRSResponse lrsResponse = new ActivityLRSResponse(request, response); + + if (status == 200) { + lrsResponse.setSuccess(true); + try { + lrsResponse.setContent(new Activity(new StringOfJSON(response.getContent()))); + } catch (Exception ex) { + lrsResponse.setErrMsg("Exception: " + ex.toString()); + lrsResponse.setSuccess(false); + } + } + else { + lrsResponse.setSuccess(false); + } + + return lrsResponse; + } + @Override public ProfileKeysLRSResponse retrieveActivityProfileIds(Activity activity) { HashMap queryParams = new HashMap(); @@ -753,6 +784,35 @@ public LRSResponse deleteActivityProfile(ActivityProfileDocument profile) { return deleteDocument("activities/profile", queryParams); } + @Override + public PersonLRSResponse retrievePerson(Agent agent) { + HTTPRequest request = new HTTPRequest(); + request.setMethod(HttpMethods.GET); + request.setResource("agents"); + request.setQueryParams(new HashMap()); + request.getQueryParams().put("agent", agent.toJSON(this.getVersion(), this.usePrettyJSON())); + + HTTPResponse response = makeSyncRequest(request); + int status = response.getStatus(); + + PersonLRSResponse lrsResponse = new PersonLRSResponse(request, response); + + if (status == 200) { + lrsResponse.setSuccess(true); + try { + lrsResponse.setContent(new Person(new StringOfJSON(response.getContent()))); + } catch (Exception ex) { + lrsResponse.setErrMsg("Exception: " + ex.toString()); + lrsResponse.setSuccess(false); + } + } + else { + lrsResponse.setSuccess(false); + } + + return lrsResponse; + } + @Override public ProfileKeysLRSResponse retrieveAgentProfileIds(Agent agent) { HashMap queryParams = new HashMap(); diff --git a/src/main/java/com/rusticisoftware/tincan/http/HTTPResponse.java b/src/main/java/com/rusticisoftware/tincan/http/HTTPResponse.java index 2747a3e..8ed071f 100644 --- a/src/main/java/com/rusticisoftware/tincan/http/HTTPResponse.java +++ b/src/main/java/com/rusticisoftware/tincan/http/HTTPResponse.java @@ -46,7 +46,14 @@ public String getContent() { } public String getContentType() { return this.getHeader("Content-Type"); } - public String getEtag() { return this.getHeader("ETag").toLowerCase(); } + public String getEtag() { + String etag = this.getHeader("ETag"); + if (etag == null) { + return etag; + } + + return etag.toLowerCase(); + } public DateTime getLastModified() { DateTimeFormatter RFC1123_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC(); diff --git a/src/main/java/com/rusticisoftware/tincan/lrsresponses/ActivityLRSResponse.java b/src/main/java/com/rusticisoftware/tincan/lrsresponses/ActivityLRSResponse.java new file mode 100644 index 0000000..45c9140 --- /dev/null +++ b/src/main/java/com/rusticisoftware/tincan/lrsresponses/ActivityLRSResponse.java @@ -0,0 +1,34 @@ +/* + Copyright 2015 Rustici Software + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.rusticisoftware.tincan.lrsresponses; + +import com.rusticisoftware.tincan.Activity; +import com.rusticisoftware.tincan.http.HTTPRequest; +import com.rusticisoftware.tincan.http.HTTPResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +public class ActivityLRSResponse extends LRSResponse{ + private Activity content; + + public ActivityLRSResponse (HTTPRequest initRequest, HTTPResponse initResponse) { + super(initRequest, initResponse); + } +} diff --git a/src/main/java/com/rusticisoftware/tincan/lrsresponses/PersonLRSResponse.java b/src/main/java/com/rusticisoftware/tincan/lrsresponses/PersonLRSResponse.java new file mode 100644 index 0000000..c407ad8 --- /dev/null +++ b/src/main/java/com/rusticisoftware/tincan/lrsresponses/PersonLRSResponse.java @@ -0,0 +1,34 @@ +/* + Copyright 2015 Rustici Software + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.rusticisoftware.tincan.lrsresponses; + +import com.rusticisoftware.tincan.Person; +import com.rusticisoftware.tincan.http.HTTPRequest; +import com.rusticisoftware.tincan.http.HTTPResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +public class PersonLRSResponse extends LRSResponse{ + private Person content; + + public PersonLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { + super(initRequest, initResponse); + } +} diff --git a/src/test/java/com/rusticisoftware/tincan/LanguageMapTest.java b/src/test/java/com/rusticisoftware/tincan/LanguageMapTest.java index e0d88e9..f75d1e2 100644 --- a/src/test/java/com/rusticisoftware/tincan/LanguageMapTest.java +++ b/src/test/java/com/rusticisoftware/tincan/LanguageMapTest.java @@ -21,6 +21,9 @@ import java.io.IOException; import java.util.Map; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Vector; import org.junit.Test; @@ -28,7 +31,7 @@ * Description */ public class LanguageMapTest { - + @Test public void serializeDeserialize() throws Exception { LanguageMap lm = new LanguageMap(); @@ -50,7 +53,6 @@ public void fillAndIterate() { } String lmContent = lm.toJSON(); - String lmCopyContent = lmCopy.toJSON(); assertEquals(lmContent, lmCopyContent); @@ -58,9 +60,21 @@ public void fillAndIterate() { boolean hasKey = lm.containsKey("und"); boolean hasValue = lm.containsValue("Some english"); Map.Entry entry = lm.findFirstValue("Some espanol"); + ArrayList arrayOfLangs = new ArrayList(); + LinkedList linkedListOfLangs = new LinkedList(); + Vector vectorOfLangs = new Vector(); + lm.populateWithAvailableLanguages(arrayOfLangs); + lm.populateWithAvailableLanguages(linkedListOfLangs); + lm.populateWithAvailableLanguages(vectorOfLangs); assertTrue(hasKey); assertTrue(hasValue); assertEquals(entry.getKey(), "es-ES"); + assertEquals(arrayOfLangs.size(), 3); + assertEquals(linkedListOfLangs.size(), 3); + assertEquals(vectorOfLangs.size(), 3); + for (String s : linkedListOfLangs) { + assertTrue(lm.containsKey(s)); + } } } diff --git a/src/test/java/com/rusticisoftware/tincan/RemoteLRSTest.java b/src/test/java/com/rusticisoftware/tincan/RemoteLRSTest.java index dd03b01..71f3211 100644 --- a/src/test/java/com/rusticisoftware/tincan/RemoteLRSTest.java +++ b/src/test/java/com/rusticisoftware/tincan/RemoteLRSTest.java @@ -26,7 +26,10 @@ import com.rusticisoftware.tincan.documents.StateDocument; import com.rusticisoftware.tincan.lrsresponses.*; import com.rusticisoftware.tincan.json.*; + import lombok.extern.java.Log; + +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; @@ -67,6 +70,7 @@ public static void Init() throws Exception { agent = new Agent(); agent.setMbox("mailto:tincanjava@tincanapi.com"); + agent.setName("Test Agent"); verb = new Verb("http://adlnet.gov/expapi/verbs/experienced"); verb.setDisplay(new LanguageMap()); @@ -518,6 +522,15 @@ public void testClearState() throws Exception { Assert.assertTrue(lrsRes.getSuccess()); } + @Test + public void testRetrieveActivity() throws Exception { + ActivityLRSResponse lrsResponse = lrs.retrieveActivity(activity); + Assert.assertTrue(lrsResponse.getSuccess()); + + Activity returnedActivity = lrsResponse.getContent(); + Assert.assertTrue(activity.getId().toString().equals(returnedActivity.getId().toString())); + } + @Test public void testRetrieveActivityProfileIds() throws Exception { ProfileKeysLRSResponse lrsRes = lrs.retrieveActivityProfileIds(activity); @@ -667,6 +680,16 @@ public void testDeleteActivityProfile() throws Exception { Assert.assertTrue(lrsRes.getSuccess()); } + @Test + public void testRetrievePerson() throws Exception { + PersonLRSResponse lrsResponse = lrs.retrievePerson(agent); + Assert.assertTrue(lrsResponse.getSuccess()); + + Person person = lrsResponse.getContent(); + Assert.assertTrue(agent.getName().equals(person.getName().get(0))); + Assert.assertTrue(agent.getMbox().equals(person.getMbox().get(0))); + } + @Test public void testRetrieveAgentProfileIds() throws Exception { ProfileKeysLRSResponse lrsRes = lrs.retrieveAgentProfileIds(agent);