summaryrefslogtreecommitdiff
path: root/src/com/p4square/grow/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/p4square/grow/backend')
-rw-r--r--src/com/p4square/grow/backend/GrowBackend.java30
-rw-r--r--src/com/p4square/grow/backend/db/CassandraKey.java8
-rw-r--r--src/com/p4square/grow/backend/db/CassandraProviderImpl.java12
-rw-r--r--src/com/p4square/grow/backend/db/CassandraTrainingRecordProvider.java71
-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
9 files changed, 181 insertions, 336 deletions
diff --git a/src/com/p4square/grow/backend/GrowBackend.java b/src/com/p4square/grow/backend/GrowBackend.java
index 45e0fa2..195554e 100644
--- a/src/com/p4square/grow/backend/GrowBackend.java
+++ b/src/com/p4square/grow/backend/GrowBackend.java
@@ -4,6 +4,8 @@
package com.p4square.grow.backend;
+import java.io.IOException;
+
import org.apache.log4j.Logger;
import org.restlet.Application;
@@ -17,10 +19,15 @@ import com.p4square.grow.config.Config;
import com.p4square.grow.backend.db.CassandraDatabase;
import com.p4square.grow.backend.db.CassandraKey;
import com.p4square.grow.backend.db.CassandraProviderImpl;
+import com.p4square.grow.backend.db.CassandraTrainingRecordProvider;
import com.p4square.grow.model.Question;
+import com.p4square.grow.model.TrainingRecord;
+import com.p4square.grow.model.Playlist;
import com.p4square.grow.provider.Provider;
+import com.p4square.grow.provider.ProvidesQuestions;
+import com.p4square.grow.provider.ProvidesTrainingRecords;
import com.p4square.grow.provider.QuestionProvider;
import com.p4square.grow.backend.resources.AccountResource;
@@ -35,7 +42,8 @@ import com.p4square.grow.backend.resources.TrainingResource;
*
* @author Jesse Morgan <jesse@jesterpm.net>
*/
-public class GrowBackend extends Application {
+public class GrowBackend extends Application
+ implements ProvidesQuestions, ProvidesTrainingRecords {
private static final String DEFAULT_COLUMN = "value";
private final static Logger LOG = Logger.getLogger(GrowBackend.class);
@@ -44,6 +52,7 @@ public class GrowBackend extends Application {
private final CassandraDatabase mDatabase;
private final Provider<String, Question> mQuestionProvider;
+ private final CassandraTrainingRecordProvider mTrainingRecordProvider;
public GrowBackend() {
this(new Config());
@@ -53,12 +62,14 @@ public class GrowBackend extends Application {
mConfig = config;
mDatabase = new CassandraDatabase();
- mQuestionProvider = new QuestionProvider<CassandraKey>(new CassandraProviderImpl<Question>(mDatabase, "strings", Question.class)) {
+ mQuestionProvider = new QuestionProvider<CassandraKey>(new CassandraProviderImpl<Question>(mDatabase, Question.class)) {
@Override
public CassandraKey makeKey(String questionId) {
- return new CassandraKey("/questions/" + questionId, DEFAULT_COLUMN);
+ return new CassandraKey("strings", "/questions/" + questionId, DEFAULT_COLUMN);
}
};
+
+ mTrainingRecordProvider = new CassandraTrainingRecordProvider(mDatabase);
}
@Override
@@ -120,10 +131,23 @@ public class GrowBackend extends Application {
return mDatabase;
}
+ @Override
public Provider<String, Question> getQuestionProvider() {
return mQuestionProvider;
}
+ @Override
+ public Provider<String, TrainingRecord> getTrainingRecordProvider() {
+ return mTrainingRecordProvider;
+ }
+
+ /**
+ * @return the Default Playlist.
+ */
+ public Playlist getDefaultPlaylist() throws IOException {
+ return mTrainingRecordProvider.getDefaultPlaylist();
+ }
+
/**
* Stand-alone main for testing.
*/
diff --git a/src/com/p4square/grow/backend/db/CassandraKey.java b/src/com/p4square/grow/backend/db/CassandraKey.java
index 8e23087..853fe96 100644
--- a/src/com/p4square/grow/backend/db/CassandraKey.java
+++ b/src/com/p4square/grow/backend/db/CassandraKey.java
@@ -10,14 +10,20 @@ package com.p4square.grow.backend.db;
* @author Jesse Morgan <jesse@jesterpm.net>
*/
public class CassandraKey {
+ private final String mColumnFamily;
private final String mId;
private final String mColumn;
- public CassandraKey(String id, String column) {
+ public CassandraKey(String columnFamily, String id, String column) {
+ mColumnFamily = columnFamily;
mId = id;
mColumn = column;
}
+ public String getColumnFamily() {
+ return mColumnFamily;
+ }
+
public String getId() {
return mId;
}
diff --git a/src/com/p4square/grow/backend/db/CassandraProviderImpl.java b/src/com/p4square/grow/backend/db/CassandraProviderImpl.java
index fb6e34e..c1f6e6d 100644
--- a/src/com/p4square/grow/backend/db/CassandraProviderImpl.java
+++ b/src/com/p4square/grow/backend/db/CassandraProviderImpl.java
@@ -6,10 +6,6 @@ package com.p4square.grow.backend.db;
import java.io.IOException;
-import org.codehaus.jackson.map.DeserializationConfig;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
-
import com.p4square.grow.provider.JsonEncodedProvider;
/**
@@ -19,24 +15,22 @@ import com.p4square.grow.provider.JsonEncodedProvider;
*/
public class CassandraProviderImpl<V> extends JsonEncodedProvider<CassandraKey, V> {
private final CassandraDatabase mDb;
- private final String mColumnFamily;
- public CassandraProviderImpl(CassandraDatabase db, String columnFamily, Class<V> clazz) {
+ public CassandraProviderImpl(CassandraDatabase db, Class<V> clazz) {
super(clazz);
mDb = db;
- mColumnFamily = columnFamily;
}
@Override
public V get(CassandraKey key) throws IOException {
- String blob = mDb.getKey(mColumnFamily, key.getId(), key.getColumn());
+ String blob = mDb.getKey(key.getColumnFamily(), key.getId(), key.getColumn());
return decode(blob);
}
@Override
public void put(CassandraKey key, V obj) throws IOException {
String blob = encode(obj);
- mDb.putKey(mColumnFamily, key.getId(), key.getColumn(), blob);
+ mDb.putKey(key.getColumnFamily(), key.getId(), key.getColumn(), blob);
}
}
diff --git a/src/com/p4square/grow/backend/db/CassandraTrainingRecordProvider.java b/src/com/p4square/grow/backend/db/CassandraTrainingRecordProvider.java
new file mode 100644
index 0000000..4face52
--- /dev/null
+++ b/src/com/p4square/grow/backend/db/CassandraTrainingRecordProvider.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 Jesse Morgan
+ */
+
+package com.p4square.grow.backend.db;
+
+import java.io.IOException;
+
+import com.p4square.grow.model.Playlist;
+import com.p4square.grow.model.TrainingRecord;
+
+import com.p4square.grow.provider.JsonEncodedProvider;
+import com.p4square.grow.provider.Provider;
+
+/**
+ *
+ * @author Jesse Morgan <jesse@jesterpm.net>
+ */
+public class CassandraTrainingRecordProvider implements Provider<String, TrainingRecord> {
+ private static final CassandraKey DEFAULT_PLAYLIST_KEY = new CassandraKey("strings", "defaultPlaylist", "value");
+
+ private static final String COLUMN_FAMILY = "training";
+ private static final String PLAYLIST_KEY = "playlist";
+ private static final String LAST_VIDEO_KEY = "lastVideo";
+
+ private final CassandraDatabase mDb;
+ private final Provider<CassandraKey, Playlist> mPlaylistProvider;
+
+ public CassandraTrainingRecordProvider(CassandraDatabase db) {
+ mDb = db;
+ mPlaylistProvider = new CassandraProviderImpl<>(db, Playlist.class);
+ }
+
+ @Override
+ public TrainingRecord get(String userid) throws IOException {
+ Playlist playlist = mPlaylistProvider.get(new CassandraKey(COLUMN_FAMILY, userid, PLAYLIST_KEY));
+
+ if (playlist == null) {
+ // We consider no playlist to mean no record whatsoever.
+ return null;
+ }
+
+ TrainingRecord r = new TrainingRecord();
+ r.setPlaylist(playlist);
+ r.setLastVideo(mDb.getKey(COLUMN_FAMILY, userid, LAST_VIDEO_KEY));
+
+ return r;
+ }
+
+ @Override
+ public void put(String userid, TrainingRecord record) throws IOException {
+ String lastVideo = record.getLastVideo();
+ Playlist playlist = record.getPlaylist();
+
+ mDb.putKey(COLUMN_FAMILY, userid, LAST_VIDEO_KEY, lastVideo);
+ mPlaylistProvider.put(new CassandraKey(COLUMN_FAMILY, userid, PLAYLIST_KEY), playlist);
+ }
+
+ /**
+ * @return the default playlist stored in the database.
+ */
+ public Playlist getDefaultPlaylist() throws IOException {
+ Playlist playlist = mPlaylistProvider.get(DEFAULT_PLAYLIST_KEY);
+
+ if (playlist == null) {
+ playlist = new Playlist();
+ }
+
+ return playlist;
+ }
+}
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();
- }
-}