summaryrefslogtreecommitdiff
path: root/src/com/p4square/grow/backend/resources
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/p4square/grow/backend/resources')
-rw-r--r--src/com/p4square/grow/backend/resources/Playlist.java134
-rw-r--r--src/com/p4square/grow/backend/resources/SurveyResource.java2
-rw-r--r--src/com/p4square/grow/backend/resources/SurveyResultsResource.java2
-rw-r--r--src/com/p4square/grow/backend/resources/TrainingRecordResource.java202
-rw-r--r--src/com/p4square/grow/backend/resources/VideoRecord.java56
5 files changed, 73 insertions, 323 deletions
diff --git a/src/com/p4square/grow/backend/resources/Playlist.java b/src/com/p4square/grow/backend/resources/Playlist.java
deleted file mode 100644
index f3d2f08..0000000
--- a/src/com/p4square/grow/backend/resources/Playlist.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.type.TypeReference;
-
-import com.p4square.grow.backend.db.CassandraDatabase;
-
-/**
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-class Playlist {
- private static final ObjectMapper MAPPER = new ObjectMapper();
-
- /**
- * Load a Playlist from the database.
- */
- public static Playlist load(CassandraDatabase db, String userId) throws IOException {
- String playlistString = db.getKey("training", userId, "playlist");
-
- if (playlistString == null) {
- return null;
- }
-
- Map<String, Map<String, VideoRecord>> playlist =
- MAPPER.readValue(playlistString, new TypeReference<Map<String, Map<String, VideoRecord>>>() { });
-
- return new Playlist(playlist);
-
- }
-
- /**
- * Persist the Playlist for the given user.
- * @return The String serialization of the playlist.
- */
- public static String save(CassandraDatabase db, String userId, Playlist playlist) throws IOException {
- String playlistString = MAPPER.writeValueAsString(playlist.mPlaylist);
- db.putKey("training", userId, "playlist", playlistString);
- return playlistString;
- }
-
-
- private Map<String, Map<String, VideoRecord>> mPlaylist;
-
- /**
- * Construct an empty playlist.
- */
- public Playlist() {
- mPlaylist = new HashMap<String, Map<String, VideoRecord>>();
- }
-
- /**
- * Constructor for database initialization.
- */
- private Playlist(Map<String, Map<String, VideoRecord>> playlist) {
- mPlaylist = playlist;
- }
-
- public VideoRecord find(String videoId) {
- for (Map<String, VideoRecord> chapter : mPlaylist.values()) {
- VideoRecord r = chapter.get(videoId);
-
- if (r != null) {
- return r;
- }
- }
-
- return null;
- }
-
- /**
- * Add a video to the playlist.
- */
- public VideoRecord add(String chapter, String videoId) {
- Map<String, VideoRecord> chapterMap = mPlaylist.get(chapter);
-
- if (chapterMap == null) {
- chapterMap = new HashMap<String, VideoRecord>();
- mPlaylist.put(chapter, chapterMap);
- }
-
- VideoRecord r = new VideoRecord();
- chapterMap.put(videoId, r);
- return r;
- }
-
- /**
- * @return The last chapter to be completed.
- */
- public Map<String, Boolean> getChapterStatuses() {
- Map<String, Boolean> completed = new HashMap<String, Boolean>();
-
- for (String chapter : mPlaylist.keySet()) {
- completed.put(chapter, isChapterComplete(chapter));
- }
-
- return completed;
- }
-
- public boolean isChapterComplete(String chapterId) {
- boolean complete = true;
-
- Map<String, VideoRecord> chapter = mPlaylist.get(chapterId);
- if (chapter != null) {
- for (VideoRecord r : chapter.values()) {
- if (r.getRequired() && !r.getComplete()) {
- return false;
- }
- }
- }
-
- return complete;
- }
-
- @Override
- public String toString() {
- try {
- return MAPPER.writeValueAsString(mPlaylist);
-
- } catch (IOException e) {
- return super.toString();
- }
- }
-
-}
diff --git a/src/com/p4square/grow/backend/resources/SurveyResource.java b/src/com/p4square/grow/backend/resources/SurveyResource.java
index 83c4cad..497978f 100644
--- a/src/com/p4square/grow/backend/resources/SurveyResource.java
+++ b/src/com/p4square/grow/backend/resources/SurveyResource.java
@@ -9,7 +9,7 @@ import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
-import org.codehaus.jackson.map.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
diff --git a/src/com/p4square/grow/backend/resources/SurveyResultsResource.java b/src/com/p4square/grow/backend/resources/SurveyResultsResource.java
index 91d4d0f..e87126d 100644
--- a/src/com/p4square/grow/backend/resources/SurveyResultsResource.java
+++ b/src/com/p4square/grow/backend/resources/SurveyResultsResource.java
@@ -10,7 +10,7 @@ import java.util.HashMap;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.ColumnList;
-import org.codehaus.jackson.map.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
diff --git a/src/com/p4square/grow/backend/resources/TrainingRecordResource.java b/src/com/p4square/grow/backend/resources/TrainingRecordResource.java
index 6de9507..e42456e 100644
--- a/src/com/p4square/grow/backend/resources/TrainingRecordResource.java
+++ b/src/com/p4square/grow/backend/resources/TrainingRecordResource.java
@@ -14,7 +14,7 @@ import java.util.HashMap;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.ColumnList;
-import org.codehaus.jackson.map.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
@@ -22,11 +22,21 @@ import org.restlet.resource.ServerResource;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
+import org.restlet.ext.jackson.JacksonRepresentation;
+
import org.apache.log4j.Logger;
import com.p4square.grow.backend.GrowBackend;
import com.p4square.grow.backend.db.CassandraDatabase;
+import com.p4square.grow.model.Playlist;
+import com.p4square.grow.model.VideoRecord;
+import com.p4square.grow.model.TrainingRecord;
+
+import com.p4square.grow.provider.Provider;
+import com.p4square.grow.provider.ProvidesTrainingRecords;
+import com.p4square.grow.provider.JsonEncodedProvider;
+
import com.p4square.grow.model.Score;
/**
@@ -43,23 +53,41 @@ public class TrainingRecordResource extends ServerResource {
SUMMARY, VIDEO
}
- private GrowBackend mBackend;
private CassandraDatabase mDb;
+ private Provider<String, TrainingRecord> mTrainingRecordProvider;
private RequestType mRequestType;
private String mUserId;
private String mVideoId;
+ private TrainingRecord mRecord;
@Override
public void doInit() {
super.doInit();
- mBackend = (GrowBackend) getApplication();
- mDb = mBackend.getDatabase();
+ mDb = ((GrowBackend) getApplication()).getDatabase();
+ mTrainingRecordProvider = ((ProvidesTrainingRecords) getApplication()).getTrainingRecordProvider();
mUserId = getAttribute("userId");
mVideoId = getAttribute("videoId");
+ try {
+ Playlist defaultPlaylist = ((GrowBackend) getApplication()).getDefaultPlaylist();
+
+ mRecord = mTrainingRecordProvider.get(mUserId);
+ if (mRecord == null) {
+ mRecord = new TrainingRecord();
+ mRecord.setPlaylist(defaultPlaylist);
+ } else {
+ // Merge the playlist with the most recent version.
+ mRecord.getPlaylist().merge(defaultPlaylist);
+ }
+
+ } catch (IOException e) {
+ LOG.error("IOException loading TrainingRecord: " + e.getMessage(), e);
+ mRecord = null;
+ }
+
mRequestType = RequestType.SUMMARY;
if (mVideoId != null) {
mRequestType = RequestType.VIDEO;
@@ -71,24 +99,35 @@ public class TrainingRecordResource extends ServerResource {
*/
@Override
protected Representation get() {
- String result = null;
+ JacksonRepresentation<?> rep = null;
+
+ if (mRecord == null) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
switch (mRequestType) {
case VIDEO:
- result = mDb.getKey("training", mUserId, mVideoId);
+ VideoRecord video = mRecord.getPlaylist().find(mVideoId);
+ if (video == null) {
+ break; // Fall through and return 404
+ }
+ rep = new JacksonRepresentation<VideoRecord>(video);
break;
case SUMMARY:
- result = buildSummary();
+ rep = new JacksonRepresentation<TrainingRecord>(mRecord);
break;
}
- if (result == null) {
+ if (rep == null) {
setStatus(Status.CLIENT_ERROR_NOT_FOUND);
return null;
- }
- return new StringRepresentation(result);
+ } else {
+ rep.setObjectMapper(JsonEncodedProvider.MAPPER);
+ return rep;
+ }
}
/**
@@ -96,27 +135,37 @@ public class TrainingRecordResource extends ServerResource {
*/
@Override
protected Representation put(Representation entity) {
- boolean success = false;
+ if (mRecord == null) {
+ setStatus(Status.SERVER_ERROR_INTERNAL);
+ return null;
+ }
switch (mRequestType) {
case VIDEO:
try {
- mDb.putKey("training", mUserId, mVideoId, entity.getText());
- mDb.putKey("training", mUserId, "lastVideo", mVideoId);
-
- Playlist playlist = Playlist.load(mDb, mUserId);
- if (playlist != null) {
- VideoRecord r = playlist.find(mVideoId);
- if (r != null && !r.getComplete()) {
- r.complete();
- Playlist.save(mDb, mUserId, playlist);
- }
+ JacksonRepresentation<VideoRecord> representation =
+ new JacksonRepresentation<>(entity, VideoRecord.class);
+ representation.setObjectMapper(JsonEncodedProvider.MAPPER);
+ VideoRecord update = representation.getObject();
+ VideoRecord video = mRecord.getPlaylist().find(mVideoId);
+
+ if (video == null) {
+ // TODO: Video isn't on their playlist...
+ LOG.warn("Skipping video completion for video missing from playlist.");
+
+ } else if (update.getComplete() && !video.getComplete()) {
+ // Video was newly completed
+ video.complete();
+ mRecord.setLastVideo(mVideoId);
+
+ mTrainingRecordProvider.put(mUserId, mRecord);
}
- success = true;
+ setStatus(Status.SUCCESS_NO_CONTENT);
} catch (Exception e) {
LOG.warn("Caught exception updating training record: " + e.getMessage(), e);
+ setStatus(Status.SERVER_ERROR_INTERNAL);
}
break;
@@ -124,116 +173,7 @@ public class TrainingRecordResource extends ServerResource {
setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
}
- if (success) {
- setStatus(Status.SUCCESS_NO_CONTENT);
-
- } else {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- }
-
return null;
}
- /**
- * This method compiles the summary of the training completed.
- */
- private String buildSummary() {
- StringBuilder sb = new StringBuilder("{ ");
-
- // Last watch video
- final String lastVideo = mDb.getKey("training", mUserId, "lastVideo");
- if (lastVideo != null) {
- sb.append("\"lastVideo\": \"" + lastVideo + "\", ");
- }
-
- // Get the user's video history
- sb.append("\"videos\": { ");
- ColumnList<String> row = mDb.getRow("training", mUserId);
- if (!row.isEmpty()) {
- boolean first = true;
- for (Column<String> c : row) {
- if ("lastVideo".equals(c.getName()) ||
- "playlist".equals(c.getName())) {
- continue;
- }
-
- if (first) {
- sb.append("\"" + c.getName() + "\": ");
- first = false;
- } else {
- sb.append(", \"" + c.getName() + "\": ");
- }
-
- sb.append(c.getStringValue());
- }
- }
- sb.append(" }");
-
- // Get the user's playlist
- try {
- Playlist playlist = Playlist.load(mDb, mUserId);
- if (playlist == null) {
- playlist = createInitialPlaylist();
- }
-
- sb.append(", \"playlist\": ");
- sb.append(playlist.toString());
-
- // Last Completed Section
- Map<String, Boolean> chapters = playlist.getChapterStatuses();
- String chaptersString = MAPPER.writeValueAsString(chapters);
- sb.append(", \"chapters\":");
- sb.append(chaptersString);
-
-
- } catch (IOException e) {
- LOG.warn("IOException loading playlist for user " + mUserId, e);
- }
-
-
- sb.append(" }");
- return sb.toString();
- }
-
- /**
- * Create the user's initial playlist.
- *
- * @return Returns the String representation of the initial playlist.
- */
- private Playlist createInitialPlaylist() throws IOException {
- Playlist playlist = new Playlist();
-
- // Get assessment score
- String summaryString = mDb.getKey("assessments", mUserId, "summary");
- if (summaryString == null) {
- return null;
- }
- Map<?,?> summary = MAPPER.readValue(summaryString, Map.class);
- double score = (Double) summary.get("score");
-
- // Get videos for each section and build playlist
- for (String chapter : CHAPTERS) {
- boolean required;
-
- if ("introduction".equals(chapter)) {
- // Introduction chapter is always required
- required = true;
- } else {
- // Chapter required if the floor of the score is <= the chapter's numeric value.
- required = score < Score.numericScore(chapter) + 1;
- }
-
- ColumnList<String> row = mDb.getRow("strings", "/training/" + chapter);
- if (!row.isEmpty()) {
- for (Column<String> c : row) {
- VideoRecord r = playlist.add(chapter, c.getName());
- r.setRequired(required);
- }
- }
- }
-
- Playlist.save(mDb, mUserId, playlist);
-
- return playlist;
- }
}
diff --git a/src/com/p4square/grow/backend/resources/VideoRecord.java b/src/com/p4square/grow/backend/resources/VideoRecord.java
deleted file mode 100644
index 2ba28c3..0000000
--- a/src/com/p4square/grow/backend/resources/VideoRecord.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.util.Date;
-
-/**
- * Simple bean containing video completion data.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-class VideoRecord {
- private boolean mComplete;
- private boolean mRequired;
- private Date mCompletionDate;
-
- public VideoRecord() {
- mComplete = false;
- mRequired = true;
- mCompletionDate = null;
- }
-
- public boolean getComplete() {
- return mComplete;
- }
-
- public void setComplete(boolean complete) {
- mComplete = complete;
- }
-
- public boolean getRequired() {
- return mRequired;
- }
-
- public void setRequired(boolean complete) {
- mRequired = complete;
- }
-
- public Date getCompletionDate() {
- return mCompletionDate;
- }
-
- public void setCompletionDate(Date date) {
- mCompletionDate = date;
- }
-
- /**
- * Convenience method to mark a video complete.
- */
- public void complete() {
- mComplete = true;
- mCompletionDate = new Date();
- }
-}