diff options
| author | Jesse Morgan <jesse@jesterpm.net> | 2016-04-09 15:53:24 -0700 | 
|---|---|---|
| committer | Jesse Morgan <jesse@jesterpm.net> | 2016-04-09 15:53:24 -0700 | 
| commit | 371ccae3d1f31ec38f4af77fb7fcd175d49b3cd5 (patch) | |
| tree | 38c4f1e8828f9af9c4b77a173bee0d312b321698 /src/com/p4square/grow/backend | |
| parent | bbf907e51dfcf157bdee24dead1d531122aa25db (diff) | |
| parent | 3102d8bce3426d9cf41aeaf201c360d342677770 (diff) | |
Merge pull request #10 from PuyallupFoursquare/maven
Switching from Ivy+Ant to Maven.
Diffstat (limited to 'src/com/p4square/grow/backend')
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; -        } -    } -} | 
