From cfb2c5ef6582e51ae9cfdfff35e12b5b7fdc24fb Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Mon, 24 Mar 2014 21:38:02 -0700 Subject: Enabling the Feed and various bug fixes. * Fixing thread ordering. * Adding a limit of 5 threads per topic. * Changing frontend /account references to UserRecord. --- .../backend/db/CassandraCollectionProvider.java | 12 ++-- .../p4square/grow/backend/feed/ThreadResource.java | 5 +- .../p4square/grow/backend/feed/TopicResource.java | 17 ++++-- .../grow/frontend/AccountRedirectResource.java | 64 ++++++---------------- src/com/p4square/grow/frontend/FeedData.java | 15 ++++- .../p4square/grow/frontend/SurveyPageResource.java | 47 ++++++++-------- .../grow/frontend/TrainingPageResource.java | 17 +----- src/com/p4square/grow/model/Message.java | 8 +++ src/com/p4square/grow/model/MessageThread.java | 4 +- src/com/p4square/grow/model/UserRecord.java | 16 ++++++ src/templates/templates/communityfeed.ftl | 3 +- 11 files changed, 106 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java b/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java index cc11828..5e83247 100644 --- a/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java +++ b/src/com/p4square/grow/backend/db/CassandraCollectionProvider.java @@ -7,7 +7,7 @@ package com.p4square.grow.backend.db; import java.io.IOException; import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import com.netflix.astyanax.model.Column; @@ -45,21 +45,21 @@ public class CassandraCollectionProvider implements CollectionProvider query(String collection, int limit) throws IOException { - Map result = new HashMap<>(); + Map result = new LinkedHashMap<>(); ColumnList row = mDb.getRow(mCF, collection); if (!row.isEmpty()) { int count = 0; for (Column 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); - - if (limit >= 0 && ++count > limit) { - break; // Limit reached. - } } } diff --git a/src/com/p4square/grow/backend/feed/ThreadResource.java b/src/com/p4square/grow/backend/feed/ThreadResource.java index c0604a8..e8f46c2 100644 --- a/src/com/p4square/grow/backend/feed/ThreadResource.java +++ b/src/com/p4square/grow/backend/feed/ThreadResource.java @@ -8,7 +8,6 @@ import java.io.IOException; import java.util.Date; import java.util.Map; -import java.util.UUID; import org.restlet.data.Status; import org.restlet.resource.ServerResource; @@ -68,7 +67,7 @@ public class ThreadResource extends ServerResource { } /** - * POST a new thread to the topic. + * POST a new message to the thread. */ @Override protected Representation post(Representation entity) { @@ -86,7 +85,7 @@ public class ThreadResource extends ServerResource { // Force the thread id and message to be what we expect. message.setThreadId(mThreadId); - message.setId(String.format("%x-%s", System.currentTimeMillis(), UUID.randomUUID().toString())); + message.setId(Message.generateId()); if (message.getCreated() == null) { message.setCreated(new Date()); diff --git a/src/com/p4square/grow/backend/feed/TopicResource.java b/src/com/p4square/grow/backend/feed/TopicResource.java index 5826355..24b6a92 100644 --- a/src/com/p4square/grow/backend/feed/TopicResource.java +++ b/src/com/p4square/grow/backend/feed/TopicResource.java @@ -8,7 +8,6 @@ import java.io.IOException; import java.util.Date; import java.util.Map; -import java.util.UUID; import org.restlet.data.Status; import org.restlet.resource.ServerResource; @@ -50,10 +49,20 @@ public class TopicResource extends ServerResource { return new JacksonRepresentation(FeedDataProvider.TOPICS); } - // TODO: Support limit query parameter. + // 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 threads = mBackend.getThreadProvider().query(mTopic); + Map threads = mBackend.getThreadProvider().query(mTopic, limit); return new JacksonRepresentation(threads.values()); } catch (IOException e) { @@ -90,7 +99,7 @@ public class TopicResource extends ServerResource { MessageThread newThread = MessageThread.createNew(); // Force the thread id and message to be what we expect. - message.setId(String.format("%x-%s", System.currentTimeMillis(), UUID.randomUUID().toString())); + message.setId(Message.generateId()); message.setThreadId(newThread.getId()); newThread.setMessage(message); diff --git a/src/com/p4square/grow/frontend/AccountRedirectResource.java b/src/com/p4square/grow/frontend/AccountRedirectResource.java index 25467cd..b363c89 100644 --- a/src/com/p4square/grow/frontend/AccountRedirectResource.java +++ b/src/com/p4square/grow/frontend/AccountRedirectResource.java @@ -14,13 +14,13 @@ import org.restlet.resource.ServerResource; import org.apache.log4j.Logger; -import com.p4square.fmfacade.json.JsonRequestClient; -import com.p4square.fmfacade.json.JsonResponse; -import com.p4square.fmfacade.json.ClientException; - import com.p4square.fmfacade.FreeMarkerPageResource; import com.p4square.grow.config.Config; +import com.p4square.grow.model.UserRecord; +import com.p4square.grow.provider.Provider; +import com.p4square.grow.provider.DelegateProvider; +import com.p4square.grow.provider.JsonEncodedProvider; /** * This resource simply redirects the user to either the assessment @@ -32,7 +32,7 @@ public class AccountRedirectResource extends ServerResource { private static final Logger LOG = Logger.getLogger(AccountRedirectResource.class); private Config mConfig; - private JsonRequestClient mJsonClient; + private Provider mUserRecordProvider; // Fields pertaining to this request. private String mUserId; @@ -44,7 +44,14 @@ public class AccountRedirectResource extends ServerResource { GrowFrontend growFrontend = (GrowFrontend) getApplication(); mConfig = growFrontend.getConfig(); - mJsonClient = new JsonRequestClient(getContext().getClientDispatcher()); + mUserRecordProvider = new DelegateProvider( + new JsonRequestProvider(getContext().getClientDispatcher(), + UserRecord.class)) { + @Override + public String makeKey(String userid) { + return getBackendEndpoint() + "/accounts/" + userid; + } + }; mUserId = getRequest().getClientInfo().getUser().getIdentifier(); } @@ -56,25 +63,17 @@ public class AccountRedirectResource extends ServerResource { protected Representation get() { try { // Fetch account Map. - Map account = new HashMap(); - try { - JsonResponse response = backendGet("/accounts/" + mUserId); - if (response.getStatus().isSuccess()) { - account = response.getMap(); - } - } catch (ClientException e) { - - } + UserRecord user = mUserRecordProvider.get(mUserId); // Check for the new believers cookie String cookie = getRequest().getCookies().getFirstValue(NewBelieverResource.COOKIE_NAME); if (cookie != null && cookie.length() != 0) { - account.put("landing", "training"); - account.put("newbeliever", "true"); - backendPut("/accounts/" + mUserId, account); + user.setLanding("training"); + user.setNewBeliever(true); + mUserRecordProvider.put(mUserId, user); } - String landing = (String) account.get("landing"); + String landing = user.getLanding(); if (landing == null) { landing = "assessment"; } @@ -97,31 +96,4 @@ public class AccountRedirectResource extends ServerResource { private String getBackendEndpoint() { return mConfig.getString("backendUri", "riap://component/backend"); } - - /** - * Helper method to send a GET to the backend. - */ - private JsonResponse backendGet(final String uri) { - LOG.debug("Sending backend GET " + uri); - - final JsonResponse response = mJsonClient.get(getBackendEndpoint() + uri); - final Status status = response.getStatus(); - if (!status.isSuccess() && !Status.CLIENT_ERROR_NOT_FOUND.equals(status)) { - LOG.warn("Error making backend request for '" + uri + "'. status = " + response.getStatus().toString()); - } - - return response; - } - - protected JsonResponse backendPut(final String uri, final Map data) { - LOG.debug("Sending backend PUT " + uri); - - final JsonResponse response = mJsonClient.put(getBackendEndpoint() + uri, data); - final Status status = response.getStatus(); - if (!status.isSuccess() && !Status.CLIENT_ERROR_NOT_FOUND.equals(status)) { - LOG.warn("Error making backend request for '" + uri + "'. status = " + response.getStatus().toString()); - } - - return response; - } } diff --git a/src/com/p4square/grow/frontend/FeedData.java b/src/com/p4square/grow/frontend/FeedData.java index 55e845c..feb03a1 100644 --- a/src/com/p4square/grow/frontend/FeedData.java +++ b/src/com/p4square/grow/frontend/FeedData.java @@ -62,8 +62,15 @@ public class FeedData { mMessageProvider = new JsonRequestProvider(clientDispatcher, Message.class); } - public List getThreads(final String topic) throws IOException { - return mThreadsProvider.get(makeUrl(topic)); + /** + * Get the threads for a topic. + * + * @param topic The topic to request threads for. + * @param limit The maximum number of threads. + * @return A list of MessageThread objects. + */ + public List getThreads(final String topic, final int limit) throws IOException { + return mThreadsProvider.get(makeUrl(limit, topic)); } public List getMessages(final String topic, final String threadId) throws IOException { @@ -91,4 +98,8 @@ public class FeedData { return url; } + + private String makeUrl(int limit, String... parts) { + return makeUrl(parts) + "?limit=" + limit; + } } diff --git a/src/com/p4square/grow/frontend/SurveyPageResource.java b/src/com/p4square/grow/frontend/SurveyPageResource.java index f864014..1f9c56c 100644 --- a/src/com/p4square/grow/frontend/SurveyPageResource.java +++ b/src/com/p4square/grow/frontend/SurveyPageResource.java @@ -29,8 +29,11 @@ import com.p4square.fmfacade.FreeMarkerPageResource; import com.p4square.grow.config.Config; import com.p4square.grow.model.Question; -import com.p4square.grow.provider.QuestionProvider; +import com.p4square.grow.model.UserRecord; +import com.p4square.grow.provider.DelegateProvider; +import com.p4square.grow.provider.JsonEncodedProvider; import com.p4square.grow.provider.Provider; +import com.p4square.grow.provider.QuestionProvider; /** * SurveyPageResource handles rendering the survey and processing user's answers. @@ -49,6 +52,7 @@ public class SurveyPageResource extends FreeMarkerPageResource { private Template mSurveyTemplate; private JsonRequestClient mJsonClient; private Provider mQuestionProvider; + private Provider mUserRecordProvider; // Fields pertaining to this request. private String mQuestionId; @@ -74,6 +78,15 @@ public class SurveyPageResource extends FreeMarkerPageResource { } }; + mUserRecordProvider = new DelegateProvider( + new JsonRequestProvider(getContext().getClientDispatcher(), + UserRecord.class)) { + @Override + public String makeKey(String userid) { + return getBackendEndpoint() + "/accounts/" + userid; + } + }; + mQuestionId = getAttribute("questionId"); mUserId = getRequest().getClientInfo().getUser().getIdentifier(); } @@ -205,24 +218,6 @@ public class SurveyPageResource extends FreeMarkerPageResource { } } - private Map getAccount(String id) { - try { - Map account = null; - - JsonResponse response = backendGet("/accounts/" + id); - if (!response.getStatus().isSuccess()) { - return null; - } - account = response.getMap(); - - return account; - - } catch (ClientException e) { - LOG.warn("Error fetching account.", e); - return null; - } - } - private Question getQuestion(String id) { try { return mQuestionProvider.get(id); @@ -252,12 +247,16 @@ public class SurveyPageResource extends FreeMarkerPageResource { if (nextQuestionId == null) { // Just finished the last question. Update the user's account - Map account = getAccount(mUserId); - if (account == null) { - account = new HashMap(); + try { + UserRecord account = mUserRecordProvider.get(mUserId); + if (account == null) { + account = new UserRecord(); + } + account.setLanding("training"); + mUserRecordProvider.put(mUserId, account); + } catch (IOException e) { + LOG.warn("IOException updating landing for " + mUserId, e); } - account.put("landing", "training"); - backendPut("/accounts/" + mUserId, account); String nextPage = mConfig.getString("dynamicRoot", ""); nextPage += "/account/assessment/results"; diff --git a/src/com/p4square/grow/frontend/TrainingPageResource.java b/src/com/p4square/grow/frontend/TrainingPageResource.java index 0c8f656..ae2f3a7 100644 --- a/src/com/p4square/grow/frontend/TrainingPageResource.java +++ b/src/com/p4square/grow/frontend/TrainingPageResource.java @@ -214,21 +214,8 @@ public class TrainingPageResource extends FreeMarkerPageResource { root.put("videos", videos); root.put("allowUserToSkip", allowUserToSkip); - // Optionally show the feed. - boolean showfeed = "true".equals(getRequest().getCookies().getFirstValue("showfeed")); - if (getQueryValue("showfeed") != null) { - CookieSetting cookie = new CookieSetting("showfeed", "true"); - cookie.setPath("/"); - if ("true".equals(getQueryValue("showfeed"))) { - showfeed = true; - getResponse().getCookieSettings().add(cookie); - } else { - showfeed = false; - cookie.setValue("false"); - cookie.setMaxAge(0); - getResponse().getCookieSettings().add(cookie); - } - } + // Determine if we should show the feed. + boolean showfeed = true; // Don't show the feed if the topic isn't allowed. if (!FeedData.TOPICS.contains(mChapter)) { diff --git a/src/com/p4square/grow/model/Message.java b/src/com/p4square/grow/model/Message.java index ad02af9..9d33320 100644 --- a/src/com/p4square/grow/model/Message.java +++ b/src/com/p4square/grow/model/Message.java @@ -5,6 +5,7 @@ package com.p4square.grow.model; import java.util.Date; +import java.util.UUID; /** * A feed message. @@ -18,6 +19,13 @@ public class Message { private Date mCreated; private String mMessage; + /** + * @return a new message id. + */ + public static String generateId() { + return String.format("%x-%s", System.currentTimeMillis(), UUID.randomUUID().toString()); + } + /** * @return The id of the thread that the message belongs to. */ diff --git a/src/com/p4square/grow/model/MessageThread.java b/src/com/p4square/grow/model/MessageThread.java index 25a46b7..9542a18 100644 --- a/src/com/p4square/grow/model/MessageThread.java +++ b/src/com/p4square/grow/model/MessageThread.java @@ -21,7 +21,9 @@ public class MessageThread { */ public static MessageThread createNew() { MessageThread t = new MessageThread(); - t.setId(String.format("%x-%s", System.currentTimeMillis(), UUID.randomUUID().toString())); + // IDs are keyed to sort lexicographically from latest to oldest. + t.setId(String.format("%016x-%s", Long.MAX_VALUE - System.currentTimeMillis(), + UUID.randomUUID().toString())); return t; } diff --git a/src/com/p4square/grow/model/UserRecord.java b/src/com/p4square/grow/model/UserRecord.java index b5aaa4e..4399282 100644 --- a/src/com/p4square/grow/model/UserRecord.java +++ b/src/com/p4square/grow/model/UserRecord.java @@ -21,6 +21,7 @@ public class UserRecord { private String mLastName; private String mEmail; private String mLanding; + private boolean mNewBeliever; // Backend Access private String mBackendPasswordHash; @@ -116,6 +117,21 @@ public class UserRecord { mLanding = value; } + /** + * @return true if the user came from the New Believer's landing. + */ + public boolean getNewBeliever() { + return mNewBeliever; + } + + /** + * Set the user's new believer flag. + * @param value The new flag. + */ + public void setNewBeliever(final boolean value) { + mNewBeliever = value; + } + /** * @return The user's backend password hash, null if he doesn't have * access. diff --git a/src/templates/templates/communityfeed.ftl b/src/templates/templates/communityfeed.ftl index 7c68771..71b33bc 100644 --- a/src/templates/templates/communityfeed.ftl +++ b/src/templates/templates/communityfeed.ftl @@ -2,7 +2,8 @@

Discussion Forum

- <#assign threads = feeddata.getThreads(chapter)> + <#assign max_threads = 5> + <#assign threads = feeddata.getThreads(chapter, max_threads)> <#list threads as thread> <#assign messages = feeddata.getMessages(chapter, thread.id)>
-- cgit v1.2.3