summaryrefslogtreecommitdiff
path: root/src/com/p4square/grow/backend
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-04-09 14:22:20 -0700
committerJesse Morgan <jesse@jesterpm.net>2016-04-09 15:48:01 -0700
commit3102d8bce3426d9cf41aeaf201c360d342677770 (patch)
tree38c4f1e8828f9af9c4b77a173bee0d312b321698 /src/com/p4square/grow/backend
parentbbf907e51dfcf157bdee24dead1d531122aa25db (diff)
Switching from Ivy+Ant to Maven.
Diffstat (limited to 'src/com/p4square/grow/backend')
-rw-r--r--src/com/p4square/grow/backend/BackendVerifier.java92
-rw-r--r--src/com/p4square/grow/backend/CassandraGrowData.java172
-rw-r--r--src/com/p4square/grow/backend/DynamoGrowData.java180
-rw-r--r--src/com/p4square/grow/backend/GrowBackend.java211
-rw-r--r--src/com/p4square/grow/backend/GrowData.java36
-rw-r--r--src/com/p4square/grow/backend/apiinfo.html41
-rw-r--r--src/com/p4square/grow/backend/db/CassandraCollectionProvider.java109
-rw-r--r--src/com/p4square/grow/backend/db/CassandraDatabase.java212
-rw-r--r--src/com/p4square/grow/backend/db/CassandraKey.java34
-rw-r--r--src/com/p4square/grow/backend/db/CassandraProviderImpl.java37
-rw-r--r--src/com/p4square/grow/backend/db/CassandraTrainingRecordProvider.java71
-rw-r--r--src/com/p4square/grow/backend/dynamo/DbTool.java481
-rw-r--r--src/com/p4square/grow/backend/dynamo/DynamoCollectionProviderImpl.java109
-rw-r--r--src/com/p4square/grow/backend/dynamo/DynamoDatabase.java307
-rw-r--r--src/com/p4square/grow/backend/dynamo/DynamoKey.java56
-rw-r--r--src/com/p4square/grow/backend/dynamo/DynamoProviderImpl.java37
-rw-r--r--src/com/p4square/grow/backend/feed/FeedDataProvider.java33
-rw-r--r--src/com/p4square/grow/backend/feed/ThreadResource.java106
-rw-r--r--src/com/p4square/grow/backend/feed/TopicResource.java117
-rw-r--r--src/com/p4square/grow/backend/resources/AccountResource.java87
-rw-r--r--src/com/p4square/grow/backend/resources/BannerResource.java85
-rw-r--r--src/com/p4square/grow/backend/resources/SurveyResource.java115
-rw-r--r--src/com/p4square/grow/backend/resources/SurveyResultsResource.java253
-rw-r--r--src/com/p4square/grow/backend/resources/TrainingRecordResource.java235
-rw-r--r--src/com/p4square/grow/backend/resources/TrainingResource.java97
25 files changed, 0 insertions, 3313 deletions
diff --git a/src/com/p4square/grow/backend/BackendVerifier.java b/src/com/p4square/grow/backend/BackendVerifier.java
deleted file mode 100644
index 83160a9..0000000
--- a/src/com/p4square/grow/backend/BackendVerifier.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend;
-
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import org.apache.commons.codec.binary.Hex;
-
-import org.restlet.security.SecretVerifier;
-
-import com.p4square.grow.model.UserRecord;
-import com.p4square.grow.provider.Provider;
-
-/**
- * Verify the given credentials against the users with backend access.
- */
-public class BackendVerifier extends SecretVerifier {
-
- private final Provider<String, UserRecord> mUserProvider;
-
- public BackendVerifier(Provider<String, UserRecord> userProvider) {
- mUserProvider = userProvider;
- }
-
- @Override
- public int verify(String identifier, char[] secret) {
- if (identifier == null) {
- throw new IllegalArgumentException("Null identifier");
- }
-
- if (secret == null) {
- throw new IllegalArgumentException("Null secret");
- }
-
- // Does the user exist?
- UserRecord user;
- try {
- user = mUserProvider.get(identifier);
- if (user == null) {
- return RESULT_UNKNOWN;
- }
-
- } catch (IOException e) {
- return RESULT_UNKNOWN;
- }
-
- // Does the user have a backend password?
- String storedHash = user.getBackendPasswordHash();
- if (storedHash == null) {
- // This user doesn't have access
- return RESULT_INVALID;
- }
-
- // Validate the password.
- try {
- String hashedInput = hashPassword(secret);
- if (hashedInput.equals(storedHash)) {
- return RESULT_VALID;
- }
-
- } catch (NoSuchAlgorithmException e) {
- return RESULT_UNSUPPORTED;
- }
-
- // If all else fails, fail.
- return RESULT_INVALID;
- }
-
- /**
- * Hash the given secret.
- */
- public static String hashPassword(char[] secret) throws NoSuchAlgorithmException {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
-
- // Convert the char[] to byte[]
- // FIXME This approach is incorrectly truncating multibyte
- // characters.
- byte[] b = new byte[secret.length];
- for (int i = 0; i < secret.length; i++) {
- b[i] = (byte) secret[i];
- }
-
- md.update(b);
-
- byte[] hash = md.digest();
- return new String(Hex.encodeHex(hash));
- }
-}
diff --git a/src/com/p4square/grow/backend/CassandraGrowData.java b/src/com/p4square/grow/backend/CassandraGrowData.java
deleted file mode 100644
index 22a7716..0000000
--- a/src/com/p4square/grow/backend/CassandraGrowData.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend;
-
-import java.io.IOException;
-
-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.CassandraCollectionProvider;
-import com.p4square.grow.backend.db.CassandraTrainingRecordProvider;
-
-import com.p4square.grow.model.Message;
-import com.p4square.grow.model.MessageThread;
-import com.p4square.grow.model.Playlist;
-import com.p4square.grow.model.Question;
-import com.p4square.grow.model.TrainingRecord;
-import com.p4square.grow.model.UserRecord;
-
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.DelegateCollectionProvider;
-import com.p4square.grow.provider.DelegateProvider;
-import com.p4square.grow.provider.Provider;
-
-/**
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-class CassandraGrowData implements GrowData {
- private static final String DEFAULT_COLUMN = "value";
-
- private final Config mConfig;
- private final CassandraDatabase mDatabase;
-
- private final Provider<String, UserRecord> mUserRecordProvider;
-
- private final Provider<String, Question> mQuestionProvider;
- private final CassandraTrainingRecordProvider mTrainingRecordProvider;
- private final CollectionProvider<String, String, String> mVideoProvider;
-
- private final CollectionProvider<String, String, MessageThread> mFeedThreadProvider;
- private final CollectionProvider<String, String, Message> mFeedMessageProvider;
-
- private final Provider<String, String> mStringProvider;
-
- private final CollectionProvider<String, String, String> mAnswerProvider;
-
- public CassandraGrowData(final Config config) {
- mConfig = config;
- mDatabase = new CassandraDatabase();
-
- mUserRecordProvider = new DelegateProvider<String, CassandraKey, UserRecord>(
- new CassandraProviderImpl<UserRecord>(mDatabase, UserRecord.class)) {
- @Override
- public CassandraKey makeKey(String userid) {
- return new CassandraKey("accounts", userid, DEFAULT_COLUMN);
- }
- };
-
- mQuestionProvider = new DelegateProvider<String, CassandraKey, Question>(
- new CassandraProviderImpl<Question>(mDatabase, Question.class)) {
- @Override
- public CassandraKey makeKey(String questionId) {
- return new CassandraKey("strings", "/questions/" + questionId, DEFAULT_COLUMN);
- }
- };
-
- mFeedThreadProvider = new CassandraCollectionProvider<MessageThread>(mDatabase,
- "feedthreads", MessageThread.class);
- mFeedMessageProvider = new CassandraCollectionProvider<Message>(mDatabase,
- "feedmessages", Message.class);
-
- mTrainingRecordProvider = new CassandraTrainingRecordProvider(mDatabase);
-
- mVideoProvider = new DelegateCollectionProvider<String, String, String, String, String>(
- new CassandraCollectionProvider<String>(mDatabase, "strings", String.class)) {
- @Override
- public String makeCollectionKey(String key) {
- return "/training/" + key;
- }
-
- @Override
- public String makeKey(String key) {
- return key;
- }
-
- @Override
- public String unmakeKey(String key) {
- return key;
- }
- };
-
- mStringProvider = new DelegateProvider<String, CassandraKey, String>(
- new CassandraProviderImpl<String>(mDatabase, String.class)) {
- @Override
- public CassandraKey makeKey(String id) {
- return new CassandraKey("strings", id, DEFAULT_COLUMN);
- }
- };
-
- mAnswerProvider = new CassandraCollectionProvider<String>(
- mDatabase, "assessments", String.class);
- }
-
- @Override
- public void start() throws Exception {
- mDatabase.setClusterName(mConfig.getString("clusterName", "Dev Cluster"));
- mDatabase.setKeyspaceName(mConfig.getString("keyspace", "GROW"));
- mDatabase.init();
- }
-
- @Override
- public void stop() throws Exception {
- mDatabase.close();
- }
-
- /**
- * @return the current database.
- */
- public CassandraDatabase getDatabase() {
- return mDatabase;
- }
-
- @Override
- public Provider<String, UserRecord> getUserRecordProvider() {
- return mUserRecordProvider;
- }
-
- @Override
- public Provider<String, Question> getQuestionProvider() {
- return mQuestionProvider;
- }
-
- @Override
- public Provider<String, TrainingRecord> getTrainingRecordProvider() {
- return mTrainingRecordProvider;
- }
-
- @Override
- public CollectionProvider<String, String, String> getVideoProvider() {
- return mVideoProvider;
- }
-
- @Override
- public Playlist getDefaultPlaylist() throws IOException {
- return mTrainingRecordProvider.getDefaultPlaylist();
- }
-
- @Override
- public CollectionProvider<String, String, MessageThread> getThreadProvider() {
- return mFeedThreadProvider;
- }
-
- @Override
- public CollectionProvider<String, String, Message> getMessageProvider() {
- return mFeedMessageProvider;
- }
-
- @Override
- public Provider<String, String> getStringProvider() {
- return mStringProvider;
- }
-
- @Override
- public CollectionProvider<String, String, String> getAnswerProvider() {
- return mAnswerProvider;
- }
-}
diff --git a/src/com/p4square/grow/backend/DynamoGrowData.java b/src/com/p4square/grow/backend/DynamoGrowData.java
deleted file mode 100644
index 3b38eac..0000000
--- a/src/com/p4square/grow/backend/DynamoGrowData.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend;
-
-import java.io.IOException;
-
-import com.amazonaws.auth.AWSCredentials;
-
-import com.p4square.grow.backend.dynamo.DynamoDatabase;
-import com.p4square.grow.backend.dynamo.DynamoKey;
-import com.p4square.grow.backend.dynamo.DynamoProviderImpl;
-import com.p4square.grow.backend.dynamo.DynamoCollectionProviderImpl;
-
-import com.p4square.grow.config.Config;
-
-import com.p4square.grow.model.Message;
-import com.p4square.grow.model.MessageThread;
-import com.p4square.grow.model.Playlist;
-import com.p4square.grow.model.Question;
-import com.p4square.grow.model.TrainingRecord;
-import com.p4square.grow.model.UserRecord;
-
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.DelegateCollectionProvider;
-import com.p4square.grow.provider.DelegateProvider;
-import com.p4square.grow.provider.Provider;
-import com.p4square.grow.provider.JsonEncodedProvider;
-
-/**
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-class DynamoGrowData implements GrowData {
- private static final String DEFAULT_COLUMN = "value";
- private static final String DEFAULT_PLAYLIST_KEY = "/training/defaultplaylist";
-
- private final Config mConfig;
- private final DynamoDatabase mDatabase;
-
- private final Provider<String, UserRecord> mUserRecordProvider;
-
- private final Provider<String, Question> mQuestionProvider;
- private final Provider<String, TrainingRecord> mTrainingRecordProvider;
- private final CollectionProvider<String, String, String> mVideoProvider;
-
- private final CollectionProvider<String, String, MessageThread> mFeedThreadProvider;
- private final CollectionProvider<String, String, Message> mFeedMessageProvider;
-
- private final Provider<String, String> mStringProvider;
-
- private final CollectionProvider<String, String, String> mAnswerProvider;
-
- public DynamoGrowData(final Config config) {
- mConfig = config;
-
- mDatabase = new DynamoDatabase(config);
-
- mUserRecordProvider = new DelegateProvider<String, DynamoKey, UserRecord>(
- new DynamoProviderImpl<UserRecord>(mDatabase, UserRecord.class)) {
- @Override
- public DynamoKey makeKey(String userid) {
- return DynamoKey.newAttributeKey("accounts", userid, DEFAULT_COLUMN);
- }
- };
-
- mQuestionProvider = new DelegateProvider<String, DynamoKey, Question>(
- new DynamoProviderImpl<Question>(mDatabase, Question.class)) {
- @Override
- public DynamoKey makeKey(String questionId) {
- return DynamoKey.newAttributeKey("strings",
- "/questions/" + questionId,
- DEFAULT_COLUMN);
- }
- };
-
- mFeedThreadProvider = new DynamoCollectionProviderImpl<MessageThread>(
- mDatabase, "feedthreads", MessageThread.class);
- mFeedMessageProvider = new DynamoCollectionProviderImpl<Message>(
- mDatabase, "feedmessages", Message.class);
-
- mTrainingRecordProvider = new DelegateProvider<String, DynamoKey, TrainingRecord>(
- new DynamoProviderImpl<TrainingRecord>(mDatabase, TrainingRecord.class)) {
- @Override
- public DynamoKey makeKey(String userId) {
- return DynamoKey.newAttributeKey("training",
- userId,
- DEFAULT_COLUMN);
- }
- };
-
- mVideoProvider = new DelegateCollectionProvider<String, String, String, String, String>(
- new DynamoCollectionProviderImpl<String>(mDatabase, "strings", String.class)) {
- @Override
- public String makeCollectionKey(String key) {
- return "/training/" + key;
- }
-
- @Override
- public String makeKey(String key) {
- return key;
- }
-
- @Override
- public String unmakeKey(String key) {
- return key;
- }
- };
-
- mStringProvider = new DelegateProvider<String, DynamoKey, String>(
- new DynamoProviderImpl<String>(mDatabase, String.class)) {
- @Override
- public DynamoKey makeKey(String id) {
- return DynamoKey.newAttributeKey("strings", id, DEFAULT_COLUMN);
- }
- };
-
- mAnswerProvider = new DynamoCollectionProviderImpl<String>(
- mDatabase, "assessments", String.class);
- }
-
- @Override
- public void start() throws Exception {
- }
-
- @Override
- public void stop() throws Exception {
- }
-
- @Override
- public Provider<String, UserRecord> getUserRecordProvider() {
- return mUserRecordProvider;
- }
-
- @Override
- public Provider<String, Question> getQuestionProvider() {
- return mQuestionProvider;
- }
-
- @Override
- public Provider<String, TrainingRecord> getTrainingRecordProvider() {
- return mTrainingRecordProvider;
- }
-
- @Override
- public CollectionProvider<String, String, String> getVideoProvider() {
- return mVideoProvider;
- }
-
- @Override
- public Playlist getDefaultPlaylist() throws IOException {
- String blob = mStringProvider.get(DEFAULT_PLAYLIST_KEY);
- if (blob == null) {
- return null;
- }
-
- return JsonEncodedProvider.MAPPER.readValue(blob, Playlist.class);
- }
-
- @Override
- public CollectionProvider<String, String, MessageThread> getThreadProvider() {
- return mFeedThreadProvider;
- }
-
- @Override
- public CollectionProvider<String, String, Message> getMessageProvider() {
- return mFeedMessageProvider;
- }
-
- @Override
- public Provider<String, String> getStringProvider() {
- return mStringProvider;
- }
-
- @Override
- public CollectionProvider<String, String, String> getAnswerProvider() {
- return mAnswerProvider;
- }
-}
diff --git a/src/com/p4square/grow/backend/GrowBackend.java b/src/com/p4square/grow/backend/GrowBackend.java
deleted file mode 100644
index 4091138..0000000
--- a/src/com/p4square/grow/backend/GrowBackend.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2012 Jesse Morgan
- */
-
-package com.p4square.grow.backend;
-
-import java.io.IOException;
-
-import com.codahale.metrics.MetricRegistry;
-
-import org.apache.log4j.Logger;
-
-import org.restlet.Application;
-import org.restlet.Component;
-import org.restlet.Restlet;
-import org.restlet.data.Protocol;
-import org.restlet.data.Reference;
-import org.restlet.resource.Directory;
-import org.restlet.routing.Router;
-
-import com.p4square.grow.config.Config;
-
-import com.p4square.grow.model.Message;
-import com.p4square.grow.model.MessageThread;
-import com.p4square.grow.model.Playlist;
-import com.p4square.grow.model.Question;
-import com.p4square.grow.model.TrainingRecord;
-import com.p4square.grow.model.UserRecord;
-
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.Provider;
-import com.p4square.grow.provider.ProvidesQuestions;
-import com.p4square.grow.provider.ProvidesTrainingRecords;
-import com.p4square.grow.provider.ProvidesUserRecords;
-
-import com.p4square.grow.backend.resources.AccountResource;
-import com.p4square.grow.backend.resources.BannerResource;
-import com.p4square.grow.backend.resources.SurveyResource;
-import com.p4square.grow.backend.resources.SurveyResultsResource;
-import com.p4square.grow.backend.resources.TrainingRecordResource;
-import com.p4square.grow.backend.resources.TrainingResource;
-
-import com.p4square.grow.backend.feed.FeedDataProvider;
-import com.p4square.grow.backend.feed.ThreadResource;
-import com.p4square.grow.backend.feed.TopicResource;
-
-import com.p4square.restlet.metrics.MetricRouter;
-
-/**
- * Main class for the backend application.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class GrowBackend extends Application implements GrowData {
-
- private final static Logger LOG = Logger.getLogger(GrowBackend.class);
-
- private final MetricRegistry mMetricRegistry;
-
- private final Config mConfig;
- private final GrowData mGrowData;
-
- public GrowBackend() {
- this(new Config(), new MetricRegistry());
- }
-
- public GrowBackend(Config config, MetricRegistry metricRegistry) {
- mConfig = config;
-
- mMetricRegistry = metricRegistry;
-
- mGrowData = new DynamoGrowData(config);
- }
-
- public MetricRegistry getMetrics() {
- return mMetricRegistry;
- }
-
- @Override
- public Restlet createInboundRoot() {
- Router router = new MetricRouter(getContext(), mMetricRegistry);
-
- // Account API
- router.attach("/accounts/{userId}", AccountResource.class);
-
- // Survey API
- router.attach("/assessment/question/{questionId}", SurveyResource.class);
-
- router.attach("/accounts/{userId}/assessment", SurveyResultsResource.class);
- router.attach("/accounts/{userId}/assessment/answers/{questionId}",
- SurveyResultsResource.class);
-
- // Training API
- router.attach("/training/{level}", TrainingResource.class);
- router.attach("/training/{level}/videos/{videoId}", TrainingResource.class);
-
- router.attach("/accounts/{userId}/training", TrainingRecordResource.class);
- router.attach("/accounts/{userId}/training/videos/{videoId}",
- TrainingRecordResource.class);
-
- // Misc.
- router.attach("/banner", BannerResource.class);
-
- // Feed
- router.attach("/feed/{topic}", TopicResource.class);
- router.attach("/feed/{topic}/{thread}", ThreadResource.class);
- //router.attach("/feed/{topic/{thread}/{message}", MessageResource.class);
-
- router.attachDefault(new Directory(getContext(), new Reference(getClass().getResource("apiinfo.html"))));
-
- return router;
- }
-
- /**
- * Open the database.
- */
- @Override
- public void start() throws Exception {
- super.start();
-
- mGrowData.start();
- }
-
- /**
- * Close the database.
- */
- @Override
- public void stop() throws Exception {
- LOG.info("Shutting down...");
- mGrowData.stop();
-
- super.stop();
- }
-
- @Override
- public Provider<String, UserRecord> getUserRecordProvider() {
- return mGrowData.getUserRecordProvider();
- }
-
- @Override
- public Provider<String, Question> getQuestionProvider() {
- return mGrowData.getQuestionProvider();
- }
-
- @Override
- public CollectionProvider<String, String, String> getVideoProvider() {
- return mGrowData.getVideoProvider();
- }
-
- @Override
- public Provider<String, TrainingRecord> getTrainingRecordProvider() {
- return mGrowData.getTrainingRecordProvider();
- }
-
- /**
- * @return the Default Playlist.
- */
- public Playlist getDefaultPlaylist() throws IOException {
- return mGrowData.getDefaultPlaylist();
- }
-
- @Override
- public CollectionProvider<String, String, MessageThread> getThreadProvider() {
- return mGrowData.getThreadProvider();
- }
-
- @Override
- public CollectionProvider<String, String, Message> getMessageProvider() {
- return mGrowData.getMessageProvider();
- }
-
- @Override
- public Provider<String, String> getStringProvider() {
- return mGrowData.getStringProvider();
- }
-
- @Override
- public CollectionProvider<String, String, String> getAnswerProvider() {
- return mGrowData.getAnswerProvider();
- }
-
- /**
- * Stand-alone main for testing.
- */
- public static void main(String[] args) throws Exception {
- // Start the HTTP Server
- final Component component = new Component();
- component.getServers().add(Protocol.HTTP, 9095);
- component.getClients().add(Protocol.HTTP);
- component.getDefaultHost().attach(new GrowBackend());
-
- // Setup shutdown hook
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- try {
- component.stop();
- } catch (Exception e) {
- LOG.error("Exception during cleanup", e);
- }
- }
- });
-
- LOG.info("Starting server...");
-
- try {
- component.start();
- } catch (Exception e) {
- LOG.fatal("Could not start: " + e.getMessage(), e);
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/GrowData.java b/src/com/p4square/grow/backend/GrowData.java
deleted file mode 100644
index 293bb88..0000000
--- a/src/com/p4square/grow/backend/GrowData.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend;
-
-import com.p4square.grow.backend.feed.FeedDataProvider;
-import com.p4square.grow.model.Playlist;
-import com.p4square.grow.provider.ProvidesAssessments;
-import com.p4square.grow.provider.ProvidesQuestions;
-import com.p4square.grow.provider.ProvidesStrings;
-import com.p4square.grow.provider.ProvidesTrainingRecords;
-import com.p4square.grow.provider.ProvidesUserRecords;
-import com.p4square.grow.provider.ProvidesVideos;
-
-/**
- * Aggregate of the data provider interfaces.
- *
- * Used by GrowBackend to swap out implementations of the providers.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-interface GrowData extends ProvidesQuestions, ProvidesTrainingRecords, ProvidesVideos,
- FeedDataProvider, ProvidesUserRecords, ProvidesStrings,
- ProvidesAssessments {
-
- /**
- * Start the data provider.
- */
- void start() throws Exception;
-
- /**
- * Stop the data provider.
- */
- void stop() throws Exception;
-}
diff --git a/src/com/p4square/grow/backend/apiinfo.html b/src/com/p4square/grow/backend/apiinfo.html
deleted file mode 100644
index a3637c9..0000000
--- a/src/com/p4square/grow/backend/apiinfo.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<html>
-<head>
-<title>API Info</title>
-</head>
-<body>
-<dl>
-<dt>/backend/accounts/{userId}</dt>
-<dd>GET information about <em>userId</em> or PUT new information.</dd>
-
-<dt>/backend/assessment/question/{questionId}</dt>
-<dd>GET information about <em>questionId</em>. Special <em>questionId</em>s: first identifies first question. count returns total number of questions.</dd>
-
-<dt>/backend/accounts/{userId}/assessment</dt>
-<dd>GET the assessment summary for <em>userId</em> or DELETE <em>userId</em>'s assessment.</dd>
-
-<dt>/backend/accounts/{userId}/assessment/answers/{questionId}</dt>
-<dd>GET <em>userId</em>'s answer to <em>questionId</em>, PUT a new answer, or DELETE an answer.</dd>
-
-<dt>/backend/training/{level}</dt>
-<dd>GET all video information for <em>level</em>.</dd>
-
-<dt>/backend/training/{level}/videos/{videoId}</dt>
-<dd>GET video information for <em>videoId</em> in <em>level</em>.</dd>
-
-<dt>/backend/accounts/{userId}/training</dt>
-<dd>GET training record summary for <em>userId</em>.</dd>
-
-<dt>/backend/accounts/{userId}/training/videos/{videoId}</dt>
-<dd>GET training record for <em>userId</em> and <em>videoId</em> or PUT a new record.</dd>
-
-<dt>/backend/banner</dt>
-<dd>GET the info banner or PUT new banner info.</dd>
-
-<dt>/backend/feed/{topic}</dt>
-<dd>Get all threads for forum <em>topic</em>.</dd>
-
-<dt>/backend/feed/{topic}/{thread}</dt>
-<dd>Get all responses to question <em>thread</em> on forum <em>topic</em>.</dd>
-</dl>
-</body>
-</html>
diff --git a/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java b/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java
deleted file mode 100644
index bfcb48d..0000000
--- a/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.db;
-
-import java.io.IOException;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import com.netflix.astyanax.model.Column;
-import com.netflix.astyanax.model.ColumnList;
-
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.JsonEncodedProvider;
-
-/**
- * CollectionProvider implementation backed by a Cassandra ColumnFamily.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class CassandraCollectionProvider<V> implements CollectionProvider<String, String, V> {
- private final CassandraDatabase mDb;
- private final String mCF;
- private final Class<V> mClazz;
-
- public CassandraCollectionProvider(CassandraDatabase db, String columnFamily, Class<V> clazz) {
- mDb = db;
- mCF = columnFamily;
- mClazz = clazz;
- }
-
- @Override
- public V get(String collection, String key) throws IOException {
- String blob = mDb.getKey(mCF, collection, key);
- return decode(blob);
- }
-
- @Override
- public Map<String, V> query(String collection) throws IOException {
- return query(collection, -1);
- }
-
- @Override
- public Map<String, V> query(String collection, int limit) throws IOException {
- Map<String, V> result = new LinkedHashMap<>();
-
- ColumnList<String> row = mDb.getRow(mCF, collection);
- if (!row.isEmpty()) {
- int count = 0;
- for (Column<String> c : row) {
- if (limit >= 0 && ++count > limit) {
- break; // Limit reached.
- }
-
- String key = c.getName();
- String blob = c.getStringValue();
- V obj = decode(blob);
-
- result.put(key, obj);
- }
- }
-
- return Collections.unmodifiableMap(result);
- }
-
- @Override
- public void put(String collection, String key, V obj) throws IOException {
- String blob = encode(obj);
- mDb.putKey(mCF, collection, key, blob);
- }
-
- /**
- * Encode the object as JSON.
- *
- * @param obj The object to encode.
- * @return The JSON encoding of obj.
- * @throws IOException if the object cannot be encoded.
- */
- protected String encode(V obj) throws IOException {
- if (mClazz == String.class) {
- return (String) obj;
- } else {
- return JsonEncodedProvider.MAPPER.writeValueAsString(obj);
- }
- }
-
- /**
- * Decode the JSON string as an object.
- *
- * @param blob The JSON data to decode.
- * @return The decoded object or null if blob is null.
- * @throws IOException If an object cannot be decoded.
- */
- protected V decode(String blob) throws IOException {
- if (blob == null) {
- return null;
- }
-
- if (mClazz == String.class) {
- return (V) blob;
- }
-
- V obj = JsonEncodedProvider.MAPPER.readValue(blob, mClazz);
- return obj;
- }
-}
diff --git a/src/com/p4square/grow/backend/db/CassandraDatabase.java b/src/com/p4square/grow/backend/db/CassandraDatabase.java
deleted file mode 100644
index b8cb6df..0000000
--- a/src/com/p4square/grow/backend/db/CassandraDatabase.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.db;
-
-import com.netflix.astyanax.AstyanaxContext;
-import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
-import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl;
-import com.netflix.astyanax.connectionpool.impl.CountingConnectionPoolMonitor;
-import com.netflix.astyanax.connectionpool.NodeDiscoveryType;
-import com.netflix.astyanax.connectionpool.OperationResult;
-import com.netflix.astyanax.impl.AstyanaxConfigurationImpl;
-import com.netflix.astyanax.Keyspace;
-import com.netflix.astyanax.ColumnMutation;
-import com.netflix.astyanax.model.Column;
-import com.netflix.astyanax.model.ColumnFamily;
-import com.netflix.astyanax.model.ColumnList;
-import com.netflix.astyanax.ColumnListMutation;
-import com.netflix.astyanax.MutationBatch;
-import com.netflix.astyanax.serializers.StringSerializer;
-import com.netflix.astyanax.thrift.ThriftFamilyFactory;
-
-import org.apache.log4j.Logger;
-
-/**
- * Cassandra Database Abstraction for the Backend.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class CassandraDatabase {
- private static Logger cLog = Logger.getLogger(CassandraDatabase.class);
-
- // Configuration fields.
- private String mClusterName;
- private String mKeyspaceName;
- private String mSeedEndpoint = "127.0.0.1:9160";
- private int mPort = 9160;
-
- private AstyanaxContext<Keyspace> mContext;
- private Keyspace mKeyspace;
-
- /**
- * Connect to Cassandra.
- *
- * Cluster and Keyspace must be set before calling init().
- */
- public void init() {
- mContext = new AstyanaxContext.Builder()
- .forCluster(mClusterName)
- .forKeyspace(mKeyspaceName)
- .withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
- .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
- )
- .withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
- .setPort(mPort)
- .setMaxConnsPerHost(1)
- .setSeeds(mSeedEndpoint)
- )
- .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
- .buildKeyspace(ThriftFamilyFactory.getInstance());
-
- mContext.start();
- mKeyspace = mContext.getClient();
- }
-
- /**
- * Close the database connection.
- */
- public void close() {
- mContext.shutdown();
- }
-
- /**
- * Set the cluster name to connect to.
- */
- public void setClusterName(final String cluster) {
- mClusterName = cluster;
- }
-
- /**
- * Set the name of the keyspace to open.
- */
- public void setKeyspaceName(final String keyspace) {
- mKeyspaceName = keyspace;
- }
-
- /**
- * Change the seed endpoint.
- * The default is 127.0.0.1:9160.
- */
- public void setSeedEndpoint(final String endpoint) {
- mSeedEndpoint = endpoint;
- }
-
- /**
- * Change the port to connect to.
- * The default is 9160.
- */
- public void setPort(final int port) {
- mPort = port;
- }
-
- /**
- * @return The entire row associated with this key.
- */
- public ColumnList<String> getRow(final String cfName, final String key) {
- try {
- ColumnFamily<String, String> cf = new ColumnFamily(cfName,
- StringSerializer.get(),
- StringSerializer.get());
-
- OperationResult<ColumnList<String>> result =
- mKeyspace.prepareQuery(cf)
- .getKey(key)
- .execute();
-
- return result.getResult();
-
- } catch (ConnectionException e) {
- cLog.error("getRow failed due to Connection Exception", e);
- throw new RuntimeException(e);
- }
- }
-
- /**
- * @return The value associated with the given key.
- */
- public String getKey(final String cfName, final String key) {
- return getKey(cfName, key, "value");
- }
-
- /**
- * @return The value associated with the given key, column pair.
- */
- public String getKey(final String cfName, final String key, final String column) {
- final ColumnList<String> row = getRow(cfName, key);
-
- if (row != null) {
- final Column rowColumn = row.getColumnByName(column);
- if (rowColumn != null) {
- return rowColumn.getStringValue();
- }
- }
-
- return null;
- }
-
- /**
- * Assign value to key.
- */
- public void putKey(final String cfName, final String key, final String value) {
- putKey(cfName, key, "value", value);
- }
-
- /**
- * Assign value to the key, column pair.
- */
- public void putKey(final String cfName, final String key,
- final String column, final String value) {
-
- ColumnFamily<String, String> cf = new ColumnFamily(cfName,
- StringSerializer.get(),
- StringSerializer.get());
-
- MutationBatch m = mKeyspace.prepareMutationBatch();
- m.withRow(cf, key).putColumn(column, value);
-
- try {
- m.execute();
- } catch (ConnectionException e) {
- cLog.error("putKey failed due to Connection Exception", e);
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Remove a key, column pair.
- */
- public void deleteKey(final String cfName, final String key, final String column) {
- ColumnFamily<String, String> cf = new ColumnFamily(cfName,
- StringSerializer.get(),
- StringSerializer.get());
-
- try {
- ColumnMutation m = mKeyspace.prepareColumnMutation(cf, key, column);
- m.deleteColumn().execute();
- } catch (ConnectionException e) {
- cLog.error("deleteKey failed due to Connection Exception", e);
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Remove a row
- */
- public void deleteRow(final String cfName, final String key) {
- ColumnFamily<String, String> cf = new ColumnFamily(cfName,
- StringSerializer.get(),
- StringSerializer.get());
-
- try {
- MutationBatch batch = mKeyspace.prepareMutationBatch();
- ColumnListMutation<String> cfm = batch.withRow(cf, key).delete();
- batch.execute();
-
- } catch (ConnectionException e) {
- cLog.error("deleteRow failed due to Connection Exception", e);
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/db/CassandraKey.java b/src/com/p4square/grow/backend/db/CassandraKey.java
deleted file mode 100644
index 853fe96..0000000
--- a/src/com/p4square/grow/backend/db/CassandraKey.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.db;
-
-/**
- * CassandraKey represents a Cassandra key / column pair.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class CassandraKey {
- private final String mColumnFamily;
- private final String mId;
- private final String mColumn;
-
- public CassandraKey(String columnFamily, String id, String column) {
- mColumnFamily = columnFamily;
- mId = id;
- mColumn = column;
- }
-
- public String getColumnFamily() {
- return mColumnFamily;
- }
-
- public String getId() {
- return mId;
- }
-
- public String getColumn() {
- return mColumn;
- }
-}
diff --git a/src/com/p4square/grow/backend/db/CassandraProviderImpl.java b/src/com/p4square/grow/backend/db/CassandraProviderImpl.java
deleted file mode 100644
index da5a9f2..0000000
--- a/src/com/p4square/grow/backend/db/CassandraProviderImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.db;
-
-import java.io.IOException;
-
-import com.p4square.grow.provider.Provider;
-import com.p4square.grow.provider.JsonEncodedProvider;
-
-/**
- * Provider implementation backed by a Cassandra ColumnFamily.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class CassandraProviderImpl<V> extends JsonEncodedProvider<V> implements Provider<CassandraKey, V> {
- private final CassandraDatabase mDb;
-
- public CassandraProviderImpl(CassandraDatabase db, Class<V> clazz) {
- super(clazz);
-
- mDb = db;
- }
-
- @Override
- public V get(CassandraKey key) throws IOException {
- 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(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
deleted file mode 100644
index 4face52..0000000
--- a/src/com/p4square/grow/backend/db/CassandraTrainingRecordProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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/dynamo/DbTool.java b/src/com/p4square/grow/backend/dynamo/DbTool.java
deleted file mode 100644
index 374fa83..0000000
--- a/src/com/p4square/grow/backend/dynamo/DbTool.java
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend.dynamo;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-
-import com.p4square.grow.backend.dynamo.DynamoDatabase;
-import com.p4square.grow.backend.dynamo.DynamoKey;
-import com.p4square.grow.config.Config;
-import com.p4square.grow.model.UserRecord;
-import com.p4square.grow.provider.Provider;
-
-/**
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class DbTool {
- private static final FilenameFilter JSON_FILTER = new JsonFilter();
-
- private static Config mConfig;
- private static DynamoDatabase mDatabase;
-
- public static void usage() {
- System.out.println("java com.p4square.grow.backend.dynamo.DbTool <command>...\n");
- System.out.println("Commands:");
- System.out.println("\t--domain <domain> Set config domain");
- System.out.println("\t--dev Set config domain to dev");
- System.out.println("\t--config <file> Merge in config file");
- System.out.println("\t--list List all tables");
- System.out.println("\t--create <table> <reads> <writes> Create a table");
- System.out.println("\t--update <table> <reads> <writes> Update table throughput");
- System.out.println("\t--drop <table> Delete a table");
- System.out.println("\t--get <table> <key> <attribute> Get a value");
- System.out.println("\t--put <table> <key> <attribute> <value> Put a value");
- System.out.println("\t--delete <table> <key> <attribute> Delete a value");
- System.out.println("\t--scan <table> List all rows");
- System.out.println("\t--scanf <table> <attribute> List all rows");
- System.out.println();
- System.out.println("Bootstrap Commands:");
- System.out.println("\t--bootstrap <data> Create all tables and import all data");
- System.out.println("\t--loadStrings <data> Load all videos and questions");
- System.out.println("\t--destroy Drop all tables");
- System.out.println("\t--addadmin <user> <pass> Add a backend account");
- System.out.println("\t--import <table> <file> Backfill a table");
- }
-
- public static void main(String... args) {
- if (args.length == 0) {
- usage();
- System.exit(1);
- }
-
- mConfig = new Config();
-
- try {
- mConfig.updateConfig(DbTool.class.getResourceAsStream("/grow.properties"));
-
- int offset = 0;
- while (offset < args.length) {
- if ("--domain".equals(args[offset])) {
- mConfig.setDomain(args[offset + 1]);
- mDatabase = null;
- offset += 2;
-
- } else if ("--dev".equals(args[offset])) {
- mConfig.setDomain("dev");
- mDatabase = null;
- offset += 1;
-
- } else if ("--config".equals(args[offset])) {
- mConfig.updateConfig(args[offset + 1]);
- mDatabase = null;
- offset += 2;
-
- } else if ("--list".equals(args[offset])) {
- //offset = list(args, ++offset);
-
- } else if ("--create".equals(args[offset])) {
- offset = create(args, ++offset);
-
- } else if ("--update".equals(args[offset])) {
- offset = update(args, ++offset);
-
- } else if ("--drop".equals(args[offset])) {
- offset = drop(args, ++offset);
-
- } else if ("--get".equals(args[offset])) {
- offset = get(args, ++offset);
-
- } else if ("--put".equals(args[offset])) {
- offset = put(args, ++offset);
-
- } else if ("--delete".equals(args[offset])) {
- offset = delete(args, ++offset);
-
- } else if ("--scan".equals(args[offset])) {
- offset = scan(args, ++offset);
-
- } else if ("--scanf".equals(args[offset])) {
- offset = scanf(args, ++offset);
-
- /* Bootstrap Commands */
- } else if ("--bootstrap".equals(args[offset])) {
- if ("dev".equals(mConfig.getDomain())) {
- offset = bootstrapDevTables(args, ++offset);
- } else {
- offset = bootstrapTables(args, ++offset);
- }
- offset = loadStrings(args, offset);
-
- } else if ("--loadStrings".equals(args[offset])) {
- offset = loadStrings(args, ++offset);
-
- } else if ("--destroy".equals(args[offset])) {
- offset = destroy(args, ++offset);
-
- } else if ("--addadmin".equals(args[offset])) {
- offset = addAdmin(args, ++offset);
-
- } else if ("--import".equals(args[offset])) {
- offset = importTable(args, ++offset);
-
- } else {
- throw new IllegalArgumentException("Unknown command " + args[offset]);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(2);
- }
- }
-
- private static DynamoDatabase getDatabase() {
- if (mDatabase == null) {
- mDatabase = new DynamoDatabase(mConfig);
- }
-
- return mDatabase;
- }
-
- private static int create(String[] args, int offset) {
- String name = args[offset++];
- long reads = Long.parseLong(args[offset++]);
- long writes = Long.parseLong(args[offset++]);
-
- DynamoDatabase db = getDatabase();
-
- db.createTable(name, reads, writes);
-
- return offset;
- }
-
- private static int update(String[] args, int offset) {
- String name = args[offset++];
- long reads = Long.parseLong(args[offset++]);
- long writes = Long.parseLong(args[offset++]);
-
- DynamoDatabase db = getDatabase();
-
- db.updateTable(name, reads, writes);
-
- return offset;
- }
-
- private static int drop(String[] args, int offset) {
- String name = args[offset++];
-
- DynamoDatabase db = getDatabase();
-
- db.deleteTable(name);
-
- return offset;
- }
-
- private static int get(String[] args, int offset) {
- String table = args[offset++];
- String key = args[offset++];
- String attribute = args[offset++];
-
- DynamoDatabase db = getDatabase();
-
- String value = db.getAttribute(DynamoKey.newAttributeKey(table, key, attribute));
-
- if (value == null) {
- value = "<null>";
- }
-
- System.out.printf("%s %s:%s\n%s\n\n", table, key, attribute, value);
-
- return offset;
- }
-
- private static int put(String[] args, int offset) {
- String table = args[offset++];
- String key = args[offset++];
- String attribute = args[offset++];
- String value = args[offset++];
-
- DynamoDatabase db = getDatabase();
-
- db.putAttribute(DynamoKey.newAttributeKey(table, key, attribute), value);
-
- return offset;
- }
-
- private static int delete(String[] args, int offset) {
- String table = args[offset++];
- String key = args[offset++];
- String attribute = args[offset++];
-
- DynamoDatabase db = getDatabase();
-
- db.deleteAttribute(DynamoKey.newAttributeKey(table, key, attribute));
-
- System.out.printf("Deleted %s %s:%s\n\n", table, key, attribute);
-
- return offset;
- }
-
- private static int scan(String[] args, int offset) {
- String table = args[offset++];
-
- DynamoKey key = DynamoKey.newKey(table, null);
-
- doScan(key);
-
- return offset;
- }
-
- private static int scanf(String[] args, int offset) {
- String table = args[offset++];
- String attribute = args[offset++];
-
- DynamoKey key = DynamoKey.newAttributeKey(table, null, attribute);
-
- doScan(key);
-
- return offset;
- }
-
- private static void doScan(DynamoKey key) {
- DynamoDatabase db = getDatabase();
-
- String attributeFilter = key.getAttribute();
-
- while (key != null) {
- Map<DynamoKey, Map<String, String>> result = db.getAll(key);
-
- key = null; // If there are no results, exit
-
- for (Map.Entry<DynamoKey, Map<String, String>> entry : result.entrySet()) {
- key = entry.getKey(); // Save the last key
-
- for (Map.Entry<String, String> attribute : entry.getValue().entrySet()) {
- if (attributeFilter == null || attributeFilter.equals(attribute.getKey())) {
- String keyString = key.getHashKey();
- if (key.getRangeKey() != null) {
- keyString += "(" + key.getRangeKey() + ")";
- }
- System.out.printf("%s %s:%s\n%s\n\n",
- key.getTable(), keyString, attribute.getKey(),
- attribute.getValue());
- }
- }
- }
- }
- }
-
-
- private static int bootstrapTables(String[] args, int offset) {
- DynamoDatabase db = getDatabase();
-
- db.createTable("strings", 5, 1);
- db.createTable("accounts", 5, 1);
- db.createTable("assessments", 5, 5);
- db.createTable("training", 5, 5);
- db.createTable("feedthreads", 5, 1);
- db.createTable("feedmessages", 5, 1);
-
- return offset;
- }
-
- private static int bootstrapDevTables(String[] args, int offset) {
- DynamoDatabase db = getDatabase();
-
- db.createTable("strings", 1, 1);
- db.createTable("accounts", 1, 1);
- db.createTable("assessments", 1, 1);
- db.createTable("training", 1, 1);
- db.createTable("feedthreads", 1, 1);
- db.createTable("feedmessages", 1, 1);
-
- return offset;
- }
-
- private static int loadStrings(String[] args, int offset) throws IOException {
- String data = args[offset++];
- File baseDir = new File(data);
-
- DynamoDatabase db = getDatabase();
-
- insertQuestions(baseDir);
- insertVideos(baseDir);
- insertDefaultPlaylist(baseDir);
-
- return offset;
- }
-
- private static int destroy(String[] args, int offset) {
- DynamoDatabase db = getDatabase();
-
- final String[] tables = { "strings",
- "accounts",
- "assessments",
- "training",
- "feedthreads",
- "feedmessages"
- };
-
- for (String table : tables) {
- try {
- db.deleteTable(table);
- } catch (Exception e) {
- System.err.println("Deleting " + table + ": " + e.getMessage());
- }
- }
-
- return offset;
- }
-
- private static int addAdmin(String[] args, int offset) throws IOException {
- String user = args[offset++];
- String pass = args[offset++];
-
- DynamoDatabase db = getDatabase();
-
- UserRecord record = new UserRecord();
- record.setId(user);
- record.setBackendPassword(pass);
-
- Provider<DynamoKey, UserRecord> provider = new DynamoProviderImpl(db, UserRecord.class);
- provider.put(DynamoKey.newAttributeKey("accounts", user, "value"), record);
-
- return offset;
- }
-
- private static int importTable(String[] args, int offset) throws IOException {
- String table = args[offset++];
- String filename = args[offset++];
-
- DynamoDatabase db = getDatabase();
-
- List<String> lines = Files.readAllLines(new File(filename).toPath(),
- StandardCharsets.UTF_8);
-
- int count = 0;
-
- String key = null;
- Map<String, String> attributes = new HashMap<>();
- for (String line : lines) {
- if (line.length() == 0) {
- if (attributes.size() > 0) {
- db.putKey(DynamoKey.newKey(table, key), attributes);
- count++;
-
- if (count % 50 == 0) {
- System.out.printf("Imported %d records into %s...\n", count, table);
- }
- }
- key = null;
- attributes = new HashMap<>();
- continue;
- }
-
- if (key == null) {
- key = line;
- continue;
- }
-
- int space = line.indexOf(' ');
- String attribute = line.substring(0, space);
- String value = line.substring(space + 1);
-
- attributes.put(attribute, value);
- }
-
- // Finish up the remaining attributes.
- if (key != null && attributes.size() > 0) {
- db.putKey(DynamoKey.newKey(table, key), attributes);
- count++;
- }
-
- System.out.printf("Imported %d records into %s.\n", count, table);
-
- return offset;
- }
-
- private static void insertQuestions(File baseDir) throws IOException {
- DynamoDatabase db = getDatabase();
- File questions = new File(baseDir, "questions");
-
- File[] files = questions.listFiles(JSON_FILTER);
- Arrays.sort(files);
-
- for (File file : files) {
- String filename = file.getName();
- String questionId = filename.substring(0, filename.lastIndexOf('.'));
-
- byte[] encoded = Files.readAllBytes(file.toPath());
- String value = new String(encoded, StandardCharsets.UTF_8);
- db.putAttribute(DynamoKey.newAttributeKey("strings",
- "/questions/" + questionId, "value"), value);
- System.out.println("Inserted /questions/" + questionId);
- }
-
- String filename = files[0].getName();
- String first = filename.substring(0, filename.lastIndexOf('.'));
- int count = files.length;
- String summary = "{\"first\": \"" + first + "\", \"count\": " + count + "}";
- db.putAttribute(DynamoKey.newAttributeKey("strings", "/questions", "value"), summary);
- System.out.println("Inserted /questions");
- }
-
- private static void insertVideos(File baseDir) throws IOException {
- DynamoDatabase db = getDatabase();
- File videos = new File(baseDir, "videos");
-
- for (File topic : videos.listFiles()) {
- if (!topic.isDirectory()) {
- continue;
- }
-
- String topicName = topic.getName();
-
- Map<String, String> attributes = new HashMap<>();
- File[] files = topic.listFiles(JSON_FILTER);
- for (File file : files) {
- String filename = file.getName();
- String videoId = filename.substring(0, filename.lastIndexOf('.'));
-
- byte[] encoded = Files.readAllBytes(file.toPath());
- String value = new String(encoded, StandardCharsets.UTF_8);
-
- attributes.put(videoId, value);
- System.out.println("Found /training/" + topicName + ":" + videoId);
- }
-
- db.putKey(DynamoKey.newKey("strings",
- "/training/" + topicName), attributes);
- System.out.println("Inserted /training/" + topicName);
- }
- }
-
- private static void insertDefaultPlaylist(File baseDir) throws IOException {
- DynamoDatabase db = getDatabase();
- File file = new File(baseDir, "videos/playlist.json");
-
- byte[] encoded = Files.readAllBytes(file.toPath());
- String value = new String(encoded, StandardCharsets.UTF_8);
- db.putAttribute(DynamoKey.newAttributeKey("strings",
- "/training/defaultplaylist", "value"), value);
- System.out.println("Inserted /training/defaultplaylist");
- }
-
- private static class JsonFilter implements FilenameFilter {
- @Override
- public boolean accept(File dir, String name) {
- return name.endsWith(".json");
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/dynamo/DynamoCollectionProviderImpl.java b/src/com/p4square/grow/backend/dynamo/DynamoCollectionProviderImpl.java
deleted file mode 100644
index b53e9f7..0000000
--- a/src/com/p4square/grow/backend/dynamo/DynamoCollectionProviderImpl.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend.dynamo;
-
-import java.io.IOException;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.JsonEncodedProvider;
-
-/**
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class DynamoCollectionProviderImpl<V> implements CollectionProvider<String, String, V> {
- private final DynamoDatabase mDb;
- private final String mTable;
- private final Class<V> mClazz;
-
- public DynamoCollectionProviderImpl(DynamoDatabase db, String table, Class<V> clazz) {
- mDb = db;
- mTable = table;
- mClazz = clazz;
- }
-
- @Override
- public V get(String collection, String key) throws IOException {
- String blob = mDb.getAttribute(DynamoKey.newAttributeKey(mTable, collection, key));
- return decode(blob);
- }
-
- @Override
- public Map<String, V> query(String collection) throws IOException {
- return query(collection, -1);
- }
-
- @Override
- public Map<String, V> query(String collection, int limit) throws IOException {
- Map<String, V> result = new LinkedHashMap<>();
-
- Map<String, String> row = mDb.getKey(DynamoKey.newKey(mTable, collection));
- if (row.size() > 0) {
- int count = 0;
- for (Map.Entry<String, String> c : row.entrySet()) {
- if (limit >= 0 && ++count > limit) {
- break; // Limit reached.
- }
-
- String key = c.getKey();
- String blob = c.getValue();
- V obj = decode(blob);
-
- result.put(key, obj);
- }
- }
-
- return Collections.unmodifiableMap(result);
- }
-
- @Override
- public void put(String collection, String key, V obj) throws IOException {
- if (obj == null) {
- mDb.deleteAttribute(DynamoKey.newAttributeKey(mTable, collection, key));
- } else {
- String blob = encode(obj);
- mDb.putAttribute(DynamoKey.newAttributeKey(mTable, collection, key), blob);
- }
- }
-
- /**
- * Encode the object as JSON.
- *
- * @param obj The object to encode.
- * @return The JSON encoding of obj.
- * @throws IOException if the object cannot be encoded.
- */
- protected String encode(V obj) throws IOException {
- if (mClazz == String.class) {
- return (String) obj;
- } else {
- return JsonEncodedProvider.MAPPER.writeValueAsString(obj);
- }
- }
-
- /**
- * Decode the JSON string as an object.
- *
- * @param blob The JSON data to decode.
- * @return The decoded object or null if blob is null.
- * @throws IOException If an object cannot be decoded.
- */
- protected V decode(String blob) throws IOException {
- if (blob == null) {
- return null;
- }
-
- if (mClazz == String.class) {
- return (V) blob;
- }
-
- V obj = JsonEncodedProvider.MAPPER.readValue(blob, mClazz);
- return obj;
- }
-}
diff --git a/src/com/p4square/grow/backend/dynamo/DynamoDatabase.java b/src/com/p4square/grow/backend/dynamo/DynamoDatabase.java
deleted file mode 100644
index 68a165d..0000000
--- a/src/com/p4square/grow/backend/dynamo/DynamoDatabase.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend.dynamo;
-
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
-import com.amazonaws.regions.Region;
-import com.amazonaws.regions.Regions;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
-import com.amazonaws.services.dynamodbv2.model.AttributeAction;
-import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
-import com.amazonaws.services.dynamodbv2.model.AttributeValue;
-import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;
-import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
-import com.amazonaws.services.dynamodbv2.model.CreateTableResult;
-import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest;
-import com.amazonaws.services.dynamodbv2.model.DeleteItemResult;
-import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest;
-import com.amazonaws.services.dynamodbv2.model.DeleteTableResult;
-import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
-import com.amazonaws.services.dynamodbv2.model.GetItemResult;
-import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
-import com.amazonaws.services.dynamodbv2.model.KeyType;
-import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
-import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
-import com.amazonaws.services.dynamodbv2.model.PutItemResult;
-import com.amazonaws.services.dynamodbv2.model.ScanRequest;
-import com.amazonaws.services.dynamodbv2.model.ScanResult;
-import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest;
-import com.amazonaws.services.dynamodbv2.model.UpdateItemResult;
-import com.amazonaws.services.dynamodbv2.model.UpdateTableRequest;
-import com.amazonaws.services.dynamodbv2.model.UpdateTableResult;
-
-import com.p4square.grow.config.Config;
-
-/**
- * A wrapper around the Dynamo API.
- */
-public class DynamoDatabase {
- private final AmazonDynamoDBClient mClient;
- private final String mTablePrefix;
-
- public DynamoDatabase(final Config config) {
- AWSCredentials creds;
-
- String awsAccessKey = config.getString("awsAccessKey");
- if (awsAccessKey != null) {
- creds = new AWSCredentials() {
- @Override
- public String getAWSAccessKeyId() {
- return config.getString("awsAccessKey");
- }
- @Override
- public String getAWSSecretKey() {
- return config.getString("awsSecretKey");
- }
- };
- } else {
- creds = new DefaultAWSCredentialsProviderChain().getCredentials();
- }
-
- mClient = new AmazonDynamoDBClient(creds);
-
- String endpoint = config.getString("dynamoEndpoint");
- if (endpoint != null) {
- mClient.setEndpoint(endpoint);
- }
-
- String region = config.getString("awsRegion");
- if (region != null) {
- mClient.setRegion(Region.getRegion(Regions.fromName(region)));
- }
-
- mTablePrefix = config.getString("dynamoTablePrefix", "");
- }
-
- public void createTable(String name, long reads, long writes) {
- ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<>();
- attributeDefinitions.add(new AttributeDefinition()
- .withAttributeName("id")
- .withAttributeType("S"));
-
- ArrayList<KeySchemaElement> ks = new ArrayList<>();
- ks.add(new KeySchemaElement().withAttributeName("id").withKeyType(KeyType.HASH));
-
- ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput()
- .withReadCapacityUnits(reads)
- .withWriteCapacityUnits(writes);
-
- CreateTableRequest request = new CreateTableRequest()
- .withTableName(mTablePrefix + name)
- .withAttributeDefinitions(attributeDefinitions)
- .withKeySchema(ks)
- .withProvisionedThroughput(provisionedThroughput);
-
- CreateTableResult result = mClient.createTable(request);
- }
-
- public void updateTable(String name, long reads, long writes) {
- ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput()
- .withReadCapacityUnits(reads)
- .withWriteCapacityUnits(writes);
-
- UpdateTableRequest request = new UpdateTableRequest()
- .withTableName(mTablePrefix + name)
- .withProvisionedThroughput(provisionedThroughput);
-
- UpdateTableResult result = mClient.updateTable(request);
- }
-
- public void deleteTable(String name) {
- DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
- .withTableName(mTablePrefix + name);
-
- DeleteTableResult result = mClient.deleteTable(deleteTableRequest);
- }
-
- /**
- * Get all rows from a table.
- *
- * The key parameter must specify a table. If hash/range key is specified,
- * the scan will begin after that key.
- *
- * @param key Previous key to start with.
- * @return An ordered map of all results.
- */
- public Map<DynamoKey, Map<String, String>> getAll(final DynamoKey key) {
- ScanRequest scanRequest = new ScanRequest().withTableName(mTablePrefix + key.getTable());
-
- if (key.getHashKey() != null) {
- scanRequest.setExclusiveStartKey(generateKey(key));
- }
-
- ScanResult scanResult = mClient.scan(scanRequest);
-
- Map<DynamoKey, Map<String, String>> result = new LinkedHashMap<>();
- for (Map<String, AttributeValue> map : scanResult.getItems()) {
- String id = null;
- String range = null;
- Map<String, String> row = new LinkedHashMap<>();
- for (Map.Entry<String, AttributeValue> entry : map.entrySet()) {
- if ("id".equals(entry.getKey())) {
- id = entry.getValue().getS();
- } else if ("range".equals(entry.getKey())) {
- range = entry.getValue().getS();
- } else {
- row.put(entry.getKey(), entry.getValue().getS());
- }
- }
- result.put(DynamoKey.newRangeKey(key.getTable(), id, range), row);
- }
-
- return result;
- }
-
- public Map<String, String> getKey(final DynamoKey key) {
- GetItemRequest getItemRequest = new GetItemRequest()
- .withTableName(mTablePrefix + key.getTable())
- .withKey(generateKey(key));
-
- GetItemResult getItemResult = mClient.getItem(getItemRequest);
- Map<String, AttributeValue> map = getItemResult.getItem();
-
- Map<String, String> result = new LinkedHashMap<>();
- if (map != null) {
- for (Map.Entry<String, AttributeValue> entry : map.entrySet()) {
- if (!"id".equals(entry.getKey())) {
- result.put(entry.getKey(), entry.getValue().getS());
- }
- }
- }
-
- return result;
- }
-
- public String getAttribute(final DynamoKey key) {
- checkAttributeKey(key);
-
- GetItemRequest getItemRequest = new GetItemRequest()
- .withTableName(mTablePrefix + key.getTable())
- .withKey(generateKey(key))
- .withAttributesToGet(key.getAttribute());
-
- GetItemResult result = mClient.getItem(getItemRequest);
- Map<String, AttributeValue> map = result.getItem();
-
- if (map == null) {
- return null;
- }
-
- AttributeValue value = map.get(key.getAttribute());
- if (value != null) {
- return value.getS();
-
- } else {
- return null;
- }
- }
-
- /**
- * Set all attributes for the given key.
- *
- * @param key The key.
- * @param values Map of attributes to values.
- */
- public void putKey(final DynamoKey key, final Map<String, String> values) {
- Map<String, AttributeValue> item = new HashMap<>();
- for (Map.Entry<String, String> entry : values.entrySet()) {
- item.put(entry.getKey(), new AttributeValue().withS(entry.getValue()));
- }
-
- // Set the Key
- item.putAll(generateKey(key));
-
- PutItemRequest putItemRequest = new PutItemRequest()
- .withTableName(mTablePrefix + key.getTable())
- .withItem(item);
-
- PutItemResult result = mClient.putItem(putItemRequest);
- }
-
- /**
- * Set the particular attributes of the given key.
- *
- * @param key The key.
- * @param value The new value.
- */
- public void putAttribute(final DynamoKey key, final String value) {
- checkAttributeKey(key);
-
- Map<String, AttributeValueUpdate> updateItem = new HashMap<>();
- updateItem.put(key.getAttribute(),
- new AttributeValueUpdate()
- .withAction(AttributeAction.PUT)
- .withValue(new AttributeValue().withS(value)));
-
- UpdateItemRequest updateItemRequest = new UpdateItemRequest()
- .withTableName(mTablePrefix + key.getTable())
- .withKey(generateKey(key))
- .withAttributeUpdates(updateItem);
- // TODO: Check conditions.
-
- UpdateItemResult result = mClient.updateItem(updateItemRequest);
- }
-
- /**
- * Delete the given key.
- *
- * @param key The key.
- */
- public void deleteKey(final DynamoKey key) {
- DeleteItemRequest deleteItemRequest = new DeleteItemRequest()
- .withTableName(mTablePrefix + key.getTable())
- .withKey(generateKey(key));
-
- DeleteItemResult result = mClient.deleteItem(deleteItemRequest);
- }
-
- /**
- * Delete an attribute from the given key.
- *
- * @param key The key.
- */
- public void deleteAttribute(final DynamoKey key) {
- checkAttributeKey(key);
-
- Map<String, AttributeValueUpdate> updateItem = new HashMap<>();
- updateItem.put(key.getAttribute(),
- new AttributeValueUpdate().withAction(AttributeAction.DELETE));
-
- UpdateItemRequest updateItemRequest = new UpdateItemRequest()
- .withTableName(mTablePrefix + key.getTable())
- .withKey(generateKey(key))
- .withAttributeUpdates(updateItem);
-
- UpdateItemResult result = mClient.updateItem(updateItemRequest);
- }
-
- /**
- * Generate a DynamoDB Key Map from the DynamoKey.
- */
- private Map<String, AttributeValue> generateKey(final DynamoKey key) {
- HashMap<String, AttributeValue> keyMap = new HashMap<>();
- keyMap.put("id", new AttributeValue().withS(key.getHashKey()));
-
- String range = key.getRangeKey();
- if (range != null) {
- keyMap.put("range", new AttributeValue().withS(range));
- }
-
- return keyMap;
- }
-
- private void checkAttributeKey(DynamoKey key) {
- if (null == key.getAttribute()) {
- throw new IllegalArgumentException("Attribute must be non-null");
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/dynamo/DynamoKey.java b/src/com/p4square/grow/backend/dynamo/DynamoKey.java
deleted file mode 100644
index 5cdbacd..0000000
--- a/src/com/p4square/grow/backend/dynamo/DynamoKey.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2014 Jesse Morgan
- */
-
-package com.p4square.grow.backend.dynamo;
-
-/**
- * DynamoKey represents a table, hash key, and range key tupl.
- */
-public class DynamoKey {
- private final String mTable;
- private final String mHashKey;
- private final String mRangeKey;
- private final String mAttribute;
-
- public static DynamoKey newKey(final String table, final String hashKey) {
- return new DynamoKey(table, hashKey, null, null);
- }
-
- public static DynamoKey newRangeKey(final String table, final String hashKey,
- final String rangeKey) {
-
- return new DynamoKey(table, hashKey, rangeKey, null);
- }
-
- public static DynamoKey newAttributeKey(final String table, final String hashKey,
- final String attribute) {
-
- return new DynamoKey(table, hashKey, null, attribute);
- }
-
- public DynamoKey(final String table, final String hashKey, final String rangeKey,
- final String attribute) {
-
- mTable = table;
- mHashKey = hashKey;
- mRangeKey = rangeKey;
- mAttribute = attribute;
- }
-
- public String getTable() {
- return mTable;
- }
-
- public String getHashKey() {
- return mHashKey;
- }
-
- public String getRangeKey() {
- return mRangeKey;
- }
-
- public String getAttribute() {
- return mAttribute;
- }
-}
diff --git a/src/com/p4square/grow/backend/dynamo/DynamoProviderImpl.java b/src/com/p4square/grow/backend/dynamo/DynamoProviderImpl.java
deleted file mode 100644
index 93a535f..0000000
--- a/src/com/p4square/grow/backend/dynamo/DynamoProviderImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.dynamo;
-
-import java.io.IOException;
-
-import com.p4square.grow.provider.Provider;
-import com.p4square.grow.provider.JsonEncodedProvider;
-
-/**
- * Provider implementation backed by a DynamoDB Table.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class DynamoProviderImpl<V> extends JsonEncodedProvider<V> implements Provider<DynamoKey, V> {
- private final DynamoDatabase mDb;
-
- public DynamoProviderImpl(DynamoDatabase db, Class<V> clazz) {
- super(clazz);
-
- mDb = db;
- }
-
- @Override
- public V get(DynamoKey key) throws IOException {
- String blob = mDb.getAttribute(key);
- return decode(blob);
- }
-
- @Override
- public void put(DynamoKey key, V obj) throws IOException {
- String blob = encode(obj);
- mDb.putAttribute(key, blob);
- }
-}
diff --git a/src/com/p4square/grow/backend/feed/FeedDataProvider.java b/src/com/p4square/grow/backend/feed/FeedDataProvider.java
deleted file mode 100644
index 6f090c0..0000000
--- a/src/com/p4square/grow/backend/feed/FeedDataProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.feed;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-import com.p4square.grow.model.MessageThread;
-import com.p4square.grow.model.Message;
-import com.p4square.grow.provider.CollectionProvider;
-
-/**
- * Implementing this interface indicates you can provide a data source for the Feed.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public interface FeedDataProvider {
- public static final Collection<String> TOPICS = Collections.unmodifiableCollection(
- Arrays.asList(new String[] { "seeker", "believer", "disciple", "teacher", "leader" }));
-
- /**
- * @return a CollectionProvider of Threads.
- */
- CollectionProvider<String, String, MessageThread> getThreadProvider();
-
- /**
- * @return a CollectionProvider of Messages.
- */
- CollectionProvider<String, String, Message> getMessageProvider();
-}
diff --git a/src/com/p4square/grow/backend/feed/ThreadResource.java b/src/com/p4square/grow/backend/feed/ThreadResource.java
deleted file mode 100644
index e8f46c2..0000000
--- a/src/com/p4square/grow/backend/feed/ThreadResource.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.feed;
-
-import java.io.IOException;
-
-import java.util.Date;
-import java.util.Map;
-
-import org.restlet.data.Status;
-import org.restlet.resource.ServerResource;
-import org.restlet.representation.Representation;
-
-import org.restlet.ext.jackson.JacksonRepresentation;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.model.Message;
-
-/**
- * ThreadResource manages the messages that make up a thread.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class ThreadResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(ThreadResource.class);
-
- private FeedDataProvider mBackend;
- private String mTopic;
- private String mThreadId;
-
- @Override
- public void doInit() {
- super.doInit();
-
- mBackend = (FeedDataProvider) getApplication();
- mTopic = getAttribute("topic");
- mThreadId = getAttribute("thread");
- }
-
- /**
- * GET a list of messages in a thread.
- */
- @Override
- protected Representation get() {
- // If the topic or threadId are missing, return a 404.
- if (mTopic == null || mTopic.length() == 0 ||
- mThreadId == null || mThreadId.length() == 0) {
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
- }
-
- // TODO: Support limit query parameter.
-
- try {
- String collectionKey = mTopic + "/" + mThreadId;
- Map<String, Message> messages = mBackend.getMessageProvider().query(collectionKey);
- return new JacksonRepresentation(messages.values());
-
- } catch (IOException e) {
- LOG.error("Unexpected exception: " + e.getMessage(), e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-
- /**
- * POST a new message to the thread.
- */
- @Override
- protected Representation post(Representation entity) {
- // If the topic and thread are not provided, respond with not allowed.
- // TODO: Check if the thread exists.
- if (mTopic == null || !mBackend.TOPICS.contains(mTopic) ||
- mThreadId == null || mThreadId.length() == 0) {
- setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
- return null;
- }
-
- try {
- JacksonRepresentation<Message> jsonRep = new JacksonRepresentation<Message>(entity, Message.class);
- Message message = jsonRep.getObject();
-
- // Force the thread id and message to be what we expect.
- message.setThreadId(mThreadId);
- message.setId(Message.generateId());
-
- if (message.getCreated() == null) {
- message.setCreated(new Date());
- }
-
- String collectionKey = mTopic + "/" + mThreadId;
- mBackend.getMessageProvider().put(collectionKey, message.getId(), message);
-
- setLocationRef(mThreadId + "/" + message.getId());
- return new JacksonRepresentation(message);
-
- } catch (IOException e) {
- LOG.error("Unexpected exception: " + e.getMessage(), e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/feed/TopicResource.java b/src/com/p4square/grow/backend/feed/TopicResource.java
deleted file mode 100644
index 24b6a92..0000000
--- a/src/com/p4square/grow/backend/feed/TopicResource.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.feed;
-
-import java.io.IOException;
-
-import java.util.Date;
-import java.util.Map;
-
-import org.restlet.data.Status;
-import org.restlet.resource.ServerResource;
-import org.restlet.representation.Representation;
-
-import org.restlet.ext.jackson.JacksonRepresentation;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.model.Message;
-import com.p4square.grow.model.MessageThread;
-
-/**
- * TopicResource manages the threads contained in a topic.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class TopicResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(TopicResource.class);
-
- private FeedDataProvider mBackend;
- private String mTopic;
-
- @Override
- public void doInit() {
- super.doInit();
-
- mBackend = (FeedDataProvider) getApplication();
- mTopic = getAttribute("topic");
- }
-
- /**
- * GET a list of threads in the topic.
- */
- @Override
- protected Representation get() {
- // If no topic is provided, return a list of topics.
- if (mTopic == null || mTopic.length() == 0) {
- return new JacksonRepresentation(FeedDataProvider.TOPICS);
- }
-
- // Parse limit query parameter.
- int limit = -1;
- String limitString = getQueryValue("limit");
- if (limitString != null) {
- try {
- limit = Integer.parseInt(limitString);
- } catch (NumberFormatException e) {
- setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
- return null;
- }
- }
-
- try {
- Map<String, MessageThread> threads = mBackend.getThreadProvider().query(mTopic, limit);
- return new JacksonRepresentation(threads.values());
-
- } catch (IOException e) {
- LOG.error("Unexpected exception: " + e.getMessage(), e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-
- /**
- * POST a new thread to the topic.
- */
- @Override
- protected Representation post(Representation entity) {
- // If no topic is provided, respond with not allowed.
- if (mTopic == null || !mBackend.TOPICS.contains(mTopic)) {
- setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
- return null;
- }
-
- try {
- // Deserialize the incoming message.
- JacksonRepresentation<MessageThread> jsonRep =
- new JacksonRepresentation<MessageThread>(entity, MessageThread.class);
-
- // Get the message from the request.
- // Throw away the wrapping MessageThread because we'll create our own later.
- Message message = jsonRep.getObject().getMessage();
- if (message.getCreated() == null) {
- message.setCreated(new Date());
- }
-
- // Create the new thread.
- MessageThread newThread = MessageThread.createNew();
-
- // Force the thread id and message to be what we expect.
- message.setId(Message.generateId());
- message.setThreadId(newThread.getId());
- newThread.setMessage(message);
-
- mBackend.getThreadProvider().put(mTopic, newThread.getId(), newThread);
-
- setLocationRef(mTopic + "/" + newThread.getId());
- return new JacksonRepresentation(newThread);
-
- } catch (IOException e) {
- LOG.error("Unexpected exception: " + e.getMessage(), e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/resources/AccountResource.java b/src/com/p4square/grow/backend/resources/AccountResource.java
deleted file mode 100644
index 2ac7061..0000000
--- a/src/com/p4square/grow/backend/resources/AccountResource.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-
-import org.restlet.data.Status;
-import org.restlet.resource.ServerResource;
-import org.restlet.representation.Representation;
-
-import org.restlet.ext.jackson.JacksonRepresentation;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.model.UserRecord;
-import com.p4square.grow.provider.Provider;
-import com.p4square.grow.provider.ProvidesUserRecords;
-import com.p4square.grow.provider.JsonEncodedProvider;
-
-/**
- * Stores a document about a user.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class AccountResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(AccountResource.class);
-
- private Provider<String, UserRecord> mUserRecordProvider;
-
- private String mUserId;
-
- @Override
- public void doInit() {
- super.doInit();
-
- final ProvidesUserRecords backend = (ProvidesUserRecords) getApplication();
- mUserRecordProvider = backend.getUserRecordProvider();
-
- mUserId = getAttribute("userId");
- }
-
- /**
- * Handle GET Requests.
- */
- @Override
- protected Representation get() {
- try {
- UserRecord result = mUserRecordProvider.get(mUserId);
-
- if (result == null) {
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
- }
-
- JacksonRepresentation<UserRecord> rep = new JacksonRepresentation<UserRecord>(result);
- rep.setObjectMapper(JsonEncodedProvider.MAPPER);
- return rep;
-
- } catch (IOException e) {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-
- /**
- * Handle PUT requests
- */
- @Override
- protected Representation put(Representation entity) {
- try {
- JacksonRepresentation<UserRecord> representation =
- new JacksonRepresentation<>(entity, UserRecord.class);
- representation.setObjectMapper(JsonEncodedProvider.MAPPER);
- UserRecord record = representation.getObject();
-
- mUserRecordProvider.put(mUserId, record);
- setStatus(Status.SUCCESS_NO_CONTENT);
-
- } catch (IOException e) {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- }
-
- return null;
- }
-}
diff --git a/src/com/p4square/grow/backend/resources/BannerResource.java b/src/com/p4square/grow/backend/resources/BannerResource.java
deleted file mode 100644
index 2b9c8e6..0000000
--- a/src/com/p4square/grow/backend/resources/BannerResource.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-
-import org.restlet.data.Status;
-import org.restlet.ext.jackson.JacksonRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ServerResource;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.backend.GrowBackend;
-import com.p4square.grow.model.Banner;
-import com.p4square.grow.provider.JsonEncodedProvider;
-import com.p4square.grow.provider.Provider;
-
-/**
- * Fetches or sets the banner string.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class BannerResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(BannerResource.class);
-
- public static final ObjectMapper MAPPER = JsonEncodedProvider.MAPPER;
-
- private Provider<String, String> mStringProvider;
-
- @Override
- public void doInit() {
- super.doInit();
-
- final GrowBackend backend = (GrowBackend) getApplication();
- mStringProvider = backend.getStringProvider();
- }
-
- /**
- * Handle GET Requests.
- */
- @Override
- protected Representation get() {
- String result = null;
- try {
- result = mStringProvider.get("banner");
-
- } catch (IOException e) {
- LOG.warn("Exception loading banner: " + e);
- }
-
- if (result == null || result.length() == 0) {
- result = "{\"html\":null}";
- }
-
- return new StringRepresentation(result);
- }
-
- /**
- * Handle PUT requests
- */
- @Override
- protected Representation put(Representation entity) {
- try {
- JacksonRepresentation<Banner> representation =
- new JacksonRepresentation<>(entity, Banner.class);
- representation.setObjectMapper(MAPPER);
-
- Banner banner = representation.getObject();
-
- mStringProvider.put("banner", MAPPER.writeValueAsString(banner));
- setStatus(Status.SUCCESS_NO_CONTENT);
-
- } catch (IOException e) {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- }
-
- return null;
- }
-}
diff --git a/src/com/p4square/grow/backend/resources/SurveyResource.java b/src/com/p4square/grow/backend/resources/SurveyResource.java
deleted file mode 100644
index 8723ee2..0000000
--- a/src/com/p4square/grow/backend/resources/SurveyResource.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-
-import java.util.Map;
-import java.util.HashMap;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.restlet.data.MediaType;
-import org.restlet.data.Status;
-import org.restlet.ext.jackson.JacksonRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ServerResource;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.backend.GrowBackend;
-import com.p4square.grow.model.Question;
-import com.p4square.grow.provider.JsonEncodedProvider;
-import com.p4square.grow.provider.Provider;
-
-/**
- * This resource manages assessment questions.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class SurveyResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(SurveyResource.class);
-
- private static final ObjectMapper MAPPER = JsonEncodedProvider.MAPPER;
-
- private Provider<String, Question> mQuestionProvider;
- private Provider<String, String> mStringProvider;
-
- private String mQuestionId;
-
- @Override
- public void doInit() {
- super.doInit();
-
- final GrowBackend backend = (GrowBackend) getApplication();
- mQuestionProvider = backend.getQuestionProvider();
- mStringProvider = backend.getStringProvider();
-
- mQuestionId = getAttribute("questionId");
- }
-
- /**
- * Handle GET Requests.
- */
- @Override
- protected Representation get() {
- String result = "{}";
-
- if (mQuestionId == null) {
- // TODO: List all question ids
-
- } else if (mQuestionId.equals("first")) {
- // Get the first question id from db?
- Map<?, ?> questionSummary = getQuestionsSummary();
- mQuestionId = (String) questionSummary.get("first");
-
- } else if (mQuestionId.equals("count")) {
- // Get the first question id from db?
- Map<?, ?> questionSummary = getQuestionsSummary();
-
- return new StringRepresentation("{\"count\":" +
- String.valueOf((Integer) questionSummary.get("count")) + "}");
- }
-
- if (mQuestionId != null) {
- // Get a question by id
- Question question = null;
- try {
- question = mQuestionProvider.get(mQuestionId);
- } catch (IOException e) {
- LOG.error("IOException loading question: " + e);
- }
-
- if (question == null) {
- // 404
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
- }
-
- JacksonRepresentation<Question> rep = new JacksonRepresentation<>(question);
- rep.setObjectMapper(MAPPER);
- return rep;
- }
-
- return new StringRepresentation(result);
- }
-
- private Map<?, ?> getQuestionsSummary() {
- try {
- // TODO: This could be better. Quick fix for provider support.
- String json = mStringProvider.get("/questions");
-
- if (json != null) {
- return MAPPER.readValue(json, Map.class);
- }
-
- } catch (IOException e) {
- LOG.info("Exception reading questions summary.", e);
- }
-
- return null;
- }
-}
diff --git a/src/com/p4square/grow/backend/resources/SurveyResultsResource.java b/src/com/p4square/grow/backend/resources/SurveyResultsResource.java
deleted file mode 100644
index 7c15cfd..0000000
--- a/src/com/p4square/grow/backend/resources/SurveyResultsResource.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.HashMap;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.restlet.data.MediaType;
-import org.restlet.data.Status;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ServerResource;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.backend.GrowBackend;
-import com.p4square.grow.model.Answer;
-import com.p4square.grow.model.Question;
-import com.p4square.grow.model.RecordedAnswer;
-import com.p4square.grow.model.Score;
-import com.p4square.grow.model.UserRecord;
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.Provider;
-
-
-/**
- * Store the user's answers to the assessment and generate their score.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class SurveyResultsResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(SurveyResultsResource.class);
-
- private static final ObjectMapper MAPPER = new ObjectMapper();
-
- static enum RequestType {
- ASSESSMENT, ANSWER
- }
-
- private CollectionProvider<String, String, String> mAnswerProvider;
- private Provider<String, Question> mQuestionProvider;
- private Provider<String, UserRecord> mUserRecordProvider;
-
- private RequestType mRequestType;
- private String mUserId;
- private String mQuestionId;
-
- @Override
- public void doInit() {
- super.doInit();
-
- final GrowBackend backend = (GrowBackend) getApplication();
- mAnswerProvider = backend.getAnswerProvider();
- mQuestionProvider = backend.getQuestionProvider();
- mUserRecordProvider = backend.getUserRecordProvider();
-
- mUserId = getAttribute("userId");
- mQuestionId = getAttribute("questionId");
-
- mRequestType = RequestType.ASSESSMENT;
- if (mQuestionId != null) {
- mRequestType = RequestType.ANSWER;
- }
- }
-
- /**
- * Handle GET Requests.
- */
- @Override
- protected Representation get() {
- try {
- String result = null;
-
- switch (mRequestType) {
- case ANSWER:
- result = mAnswerProvider.get(mUserId, mQuestionId);
- break;
-
- case ASSESSMENT:
- result = mAnswerProvider.get(mUserId, "summary");
- if (result == null || result.length() == 0) {
- result = buildAssessment();
- }
- break;
- }
-
- if (result == null) {
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
- }
-
- return new StringRepresentation(result);
- } catch (IOException e) {
- LOG.error("IOException getting answer: ", e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-
- /**
- * Handle PUT requests
- */
- @Override
- protected Representation put(Representation entity) {
- boolean success = false;
-
- switch (mRequestType) {
- case ANSWER:
- try {
- mAnswerProvider.put(mUserId, mQuestionId, entity.getText());
- mAnswerProvider.put(mUserId, "lastAnswered", mQuestionId);
- mAnswerProvider.put(mUserId, "summary", null);
- success = true;
-
- } catch (Exception e) {
- LOG.warn("Caught exception putting answer: " + e.getMessage(), e);
- }
- break;
-
- default:
- setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
- return null;
- }
-
- if (success) {
- setStatus(Status.SUCCESS_NO_CONTENT);
-
- } else {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- }
-
- return null;
- }
-
- /**
- * Clear assessment results.
- */
- @Override
- protected Representation delete() {
- boolean success = false;
-
- switch (mRequestType) {
- case ANSWER:
- try {
- mAnswerProvider.put(mUserId, mQuestionId, null);
- mAnswerProvider.put(mUserId, "summary", null);
- success = true;
-
- } catch (Exception e) {
- LOG.warn("Caught exception putting answer: " + e.getMessage(), e);
- }
- break;
-
- case ASSESSMENT:
- try {
- mAnswerProvider.put(mUserId, "summary", null);
- mAnswerProvider.put(mUserId, "lastAnswered", null);
- // TODO Delete answers
-
- UserRecord record = mUserRecordProvider.get(mUserId);
- if (record != null) {
- record.setLanding("assessment");
- mUserRecordProvider.put(mUserId, record);
- }
-
- success = true;
-
- } catch (Exception e) {
- LOG.warn("Caught exception putting answer: " + e.getMessage(), e);
- }
- break;
-
- default:
- setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
- return null;
- }
-
- if (success) {
- setStatus(Status.SUCCESS_NO_CONTENT);
-
- } else {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- }
-
- return null;
-
- }
-
- /**
- * This method compiles assessment results.
- */
- private String buildAssessment() throws IOException {
- StringBuilder sb = new StringBuilder("{ ");
-
- // Last question answered
- final String lastAnswered = mAnswerProvider.get(mUserId, "lastAnswered");
- if (lastAnswered != null && lastAnswered.length() > 0) {
- sb.append("\"lastAnswered\": \"" + lastAnswered + "\", ");
- }
-
- // Compute score
- Map<String, String> row = mAnswerProvider.query(mUserId);
- if (row.size() > 0) {
- Score score = new Score();
- boolean scoringDone = false;
- int totalAnswers = 0;
- for (Map.Entry<String, String> c : row.entrySet()) {
- if (c.getKey().equals("lastAnswered") || c.getKey().equals("summary")) {
- continue;
- }
-
- try {
- Question question = mQuestionProvider.get(c.getKey());
- RecordedAnswer userAnswer = MAPPER.readValue(c.getValue(), RecordedAnswer.class);
-
- if (question == null) {
- LOG.warn("Answer for unknown question: " + c.getKey());
- continue;
- }
-
- LOG.debug("Scoring questionId: " + c.getKey());
- scoringDone = !question.scoreAnswer(score, userAnswer);
-
- } catch (Exception e) {
- LOG.error("Failed to score question: {userid: \"" + mUserId +
- "\", questionid:\"" + c.getKey() +
- "\", userAnswer:\"" + c.getValue() + "\"}", e);
- }
-
- totalAnswers++;
- }
-
- sb.append("\"score\":" + score.getScore());
- sb.append(", \"sum\":" + score.getSum());
- sb.append(", \"count\":" + score.getCount());
- sb.append(", \"totalAnswers\":" + totalAnswers);
- sb.append(", \"result\":\"" + score.toString() + "\"");
- }
-
- sb.append(" }");
- String summary = sb.toString();
-
- // Persist summary
- mAnswerProvider.put(mUserId, "summary", summary);
-
- return summary;
- }
-}
diff --git a/src/com/p4square/grow/backend/resources/TrainingRecordResource.java b/src/com/p4square/grow/backend/resources/TrainingRecordResource.java
deleted file mode 100644
index 51ba56a..0000000
--- a/src/com/p4square/grow/backend/resources/TrainingRecordResource.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.HashMap;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.restlet.data.MediaType;
-import org.restlet.data.Status;
-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.model.Chapter;
-import com.p4square.grow.model.Playlist;
-import com.p4square.grow.model.VideoRecord;
-import com.p4square.grow.model.TrainingRecord;
-
-import com.p4square.grow.provider.CollectionProvider;
-import com.p4square.grow.provider.JsonEncodedProvider;
-import com.p4square.grow.provider.Provider;
-import com.p4square.grow.provider.ProvidesAssessments;
-import com.p4square.grow.provider.ProvidesTrainingRecords;
-
-import com.p4square.grow.model.Score;
-
-/**
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class TrainingRecordResource extends ServerResource {
- private static final Logger LOG = Logger.getLogger(TrainingRecordResource.class);
- private static final ObjectMapper MAPPER = JsonEncodedProvider.MAPPER;
-
- static enum RequestType {
- SUMMARY, VIDEO
- }
-
- private Provider<String, TrainingRecord> mTrainingRecordProvider;
- private CollectionProvider<String, String, String> mAnswerProvider;
-
- private RequestType mRequestType;
- private String mUserId;
- private String mVideoId;
- private TrainingRecord mRecord;
-
- @Override
- public void doInit() {
- super.doInit();
-
- mTrainingRecordProvider = ((ProvidesTrainingRecords) getApplication()).getTrainingRecordProvider();
- mAnswerProvider = ((ProvidesAssessments) getApplication()).getAnswerProvider();
-
- mUserId = getAttribute("userId");
- mVideoId = getAttribute("videoId");
-
- try {
- Playlist defaultPlaylist = ((ProvidesTrainingRecords) getApplication()).getDefaultPlaylist();
-
- mRecord = mTrainingRecordProvider.get(mUserId);
- if (mRecord == null) {
- mRecord = new TrainingRecord();
- mRecord.setPlaylist(defaultPlaylist);
- skipAssessedChapters(mUserId, mRecord);
- } 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;
- }
- }
-
- /**
- * Handle GET Requests.
- */
- @Override
- protected Representation get() {
- JacksonRepresentation<?> rep = null;
-
- if (mRecord == null) {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
-
- switch (mRequestType) {
- case VIDEO:
- VideoRecord video = mRecord.getPlaylist().find(mVideoId);
- if (video == null) {
- break; // Fall through and return 404
- }
- rep = new JacksonRepresentation<VideoRecord>(video);
- break;
-
- case SUMMARY:
- rep = new JacksonRepresentation<TrainingRecord>(mRecord);
- break;
- }
-
- if (rep == null) {
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
-
- } else {
- rep.setObjectMapper(JsonEncodedProvider.MAPPER);
- return rep;
- }
- }
-
- /**
- * Handle PUT requests
- */
- @Override
- protected Representation put(Representation entity) {
- if (mRecord == null) {
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
-
- switch (mRequestType) {
- case VIDEO:
- try {
- 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);
- }
-
- setStatus(Status.SUCCESS_NO_CONTENT);
-
- } catch (Exception e) {
- LOG.warn("Caught exception updating training record: " + e.getMessage(), e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- }
- break;
-
- default:
- setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
- }
-
- return null;
- }
-
- private Score getAssessedScore(String userId) throws IOException {
- // Get the user's score.
- Score assessedScore = new Score(0, 0);
-
- String summaryString = mAnswerProvider.get(userId, "summary");
- if (summaryString == null) {
- throw new IOException("Asked to create training record for unassessed user " + userId);
- }
-
- Map<?,?> summary = MAPPER.readValue(summaryString, Map.class);
-
- if (summary.containsKey("sum") && summary.containsKey("count")) {
- double sum = (Double) summary.get("sum");
- int count = (Integer) summary.get("count");
- assessedScore = new Score(sum, count);
- }
-
- return assessedScore;
- }
-
- /**
- * Mark the chapters which the user assessed through as not required.
- */
- private void skipAssessedChapters(String userId, TrainingRecord record) {
- // Get the user's score.
- Score assessedScore = new Score(0, 0);
-
- try {
- assessedScore = getAssessedScore(userId);
- } catch (IOException e) {
- LOG.error("IOException fetching assessment record for " + userId, e);
- return;
- }
-
- // Mark the correct videos as not required.
- Playlist playlist = record.getPlaylist();
-
- for (Map.Entry<String, Chapter> entry : playlist.getChaptersMap().entrySet()) {
- String chapterId = entry.getKey();
- Chapter chapter = entry.getValue();
- 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 = assessedScore.floor() <= Score.numericScore(chapterId);
- }
-
- if (!required) {
- for (VideoRecord video : chapter.getVideos().values()) {
- video.setRequired(required);
- }
- }
- }
- }
-}
diff --git a/src/com/p4square/grow/backend/resources/TrainingResource.java b/src/com/p4square/grow/backend/resources/TrainingResource.java
deleted file mode 100644
index 6efdfab..0000000
--- a/src/com/p4square/grow/backend/resources/TrainingResource.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2013 Jesse Morgan
- */
-
-package com.p4square.grow.backend.resources;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.restlet.data.Status;
-import org.restlet.resource.ServerResource;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-
-import org.apache.log4j.Logger;
-
-import com.p4square.grow.backend.GrowBackend;
-import com.p4square.grow.backend.db.CassandraDatabase;
-
-import com.p4square.grow.provider.CollectionProvider;
-/**
- * This resource returns a listing of training items for a particular level.
- *
- * @author Jesse Morgan <jesse@jesterpm.net>
- */
-public class TrainingResource extends ServerResource {
- private final static Logger LOG = Logger.getLogger(TrainingResource.class);
-
- private CollectionProvider<String, String, String> mVideoProvider;
-
- private String mLevel;
- private String mVideoId;
-
- @Override
- public void doInit() {
- super.doInit();
-
- GrowBackend backend = (GrowBackend) getApplication();
- mVideoProvider = backend.getVideoProvider();
-
- mLevel = getAttribute("level");
- mVideoId = getAttribute("videoId");
- }
-
- /**
- * Handle GET Requests.
- */
- @Override
- protected Representation get() {
- String result = null;
-
- if (mLevel == null) {
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
- }
-
- try {
- if (mVideoId == null) {
- // Get all videos
- // TODO: This could be improved, but this is the quickest way to get
- // providers working.
- Map<String, String> videos = mVideoProvider.query(mLevel);
- if (videos.size() > 0) {
- StringBuilder sb = new StringBuilder("{ \"level\": \"" + mLevel + "\"");
- sb.append(", \"videos\": [");
- boolean first = true;
- for (String value : videos.values()) {
- if (!first) {
- sb.append(", ");
- }
- sb.append(value);
- first = false;
- }
- sb.append("] }");
- result = sb.toString();
- }
-
- } else {
- // Get single video
- result = mVideoProvider.get(mLevel, mVideoId);
- }
-
- if (result == null) {
- // 404
- setStatus(Status.CLIENT_ERROR_NOT_FOUND);
- return null;
- }
-
- return new StringRepresentation(result);
-
- } catch (IOException e) {
- LOG.error("IOException fetch video: " + e.getMessage(), e);
- setStatus(Status.SERVER_ERROR_INTERNAL);
- return null;
- }
- }
-}