Added methods to retrieve most recent liked feeds and most recent comments by user

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portal/social-networking-library@130946 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-08-02 15:25:27 +00:00
parent 0754b015fe
commit bdaf2fef33
3 changed files with 172 additions and 33 deletions

View File

@ -10,6 +10,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.mail.internet.AddressException; import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetAddress;
@ -43,6 +44,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.netflix.astyanax.MutationBatch; import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.RowCallback;
import com.netflix.astyanax.connectionpool.OperationResult; import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException; import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.model.Column; import com.netflix.astyanax.model.Column;
@ -55,9 +57,8 @@ import com.netflix.astyanax.serializers.StringSerializer;
import com.netflix.astyanax.util.RangeBuilder; import com.netflix.astyanax.util.RangeBuilder;
/** /**
* @author Massimiliano Assante ISTI-CNR * @author Massimiliano Assante ISTI-CNR
* * @author Costantino Perciante ISTI-CNR
* This class is used for querying and adding data to Cassandra via Astyanax High Level API * This class is used for querying and adding data to Cassandra via Astyanax High Level API
*
*/ */
public final class DBCassandraAstyanaxImpl implements DatabookStore { public final class DBCassandraAstyanaxImpl implements DatabookStore {
@ -1416,6 +1417,70 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore {
return toReturn; return toReturn;
} }
/**
* {@inheritDoc}
* @throws Exception
*/
@Override
public List<Comment> getRecentCommentsByUserAndDate(final String userid,
final long timeInMillis) throws Exception {
long start = System.currentTimeMillis();
final List<Comment> commentsByUser = new ArrayList<Comment>();
final AtomicInteger maxRetryExecutions = new AtomicInteger(10);
/**
* See https://github.com/Netflix/astyanax/wiki/Reading-Data for more information (Query all with callback)
*/
conn.getKeyspace().prepareQuery(cf_Comments)
.getAllRows()
.setRowLimit(100) // Read in blocks of 100
.withColumnRange(new RangeBuilder().setLimit(10).build())
.executeWithCallback(new RowCallback<String, String>() {
@Override
public void success(Rows<String, String> rows) {
synchronized (commentsByUser) {
nextRow: for (Row<String, String> row : rows) {
for(Column<String> column: row.getColumns())
if(column.getName().equals("Userid"))
if(column.getStringValue().equals(userid)){
try{
Comment c = readCommentById(row.getKey());
Feed f = readFeed(c.getFeedid());
if(c.getTime().getTime() >= timeInMillis &&
(f.getType() == FeedType.TWEET || f.getType() == FeedType.SHARE || f.getType() == FeedType.PUBLISH))
commentsByUser.add(c);
}catch(Exception e){
_log.error("Unable to read comment with id" + row.getKey(), e);
}
continue nextRow;
}
}
}
}
@Override
public boolean failure(ConnectionException e) {
// decrement value
int currentValue = maxRetryExecutions.decrementAndGet();
if(currentValue <= 0){
_log.error("Error while fetching user's recent comments ... repeating operation");
return true;
}else
{
_log.error("Too many errors while fetching user's comments, returning");
return false;
}
}
});
Collections.sort(commentsByUser, Collections.reverseOrder());
_log.debug("Time taken to retrieve most recent user's comments is " + (System.currentTimeMillis() - start));
return commentsByUser;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -1587,6 +1652,57 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore {
return toReturn; return toReturn;
} }
/**
* {@inheritDoc}
*/
@Override
public List<Feed> getRecentLikedFeedsByUserAndDate(String userid,
long timeInMillis) throws IllegalArgumentException {
List<Feed> toReturn = new ArrayList<Feed>();
Date now = new Date();
if (timeInMillis > now.getTime())
throw new IllegalArgumentException("the timeInMillis must be before today");
if(userid == null || userid.isEmpty())
throw new IllegalArgumentException("the userId parameter cannot be null/empty");
// get the list of liked feeds
List<String> likedFeedsIdsByUser = getAllLikedFeedIdsByUser(userid);
if(likedFeedsIdsByUser != null){
for(int i = likedFeedsIdsByUser.size() - 1; i >= 0; i--){
String feedId = likedFeedsIdsByUser.get(i);
try{
// retrieve the feed
Feed toCheck = readFeed(feedId);
boolean isFeedOk = (toCheck.getType() == FeedType.TWEET || toCheck.getType() == FeedType.SHARE || toCheck.getType() == FeedType.PUBLISH);
// retrieve the like of the user for the feed
if(isFeedOk){
List<Like> likes = getAllLikesByFeed(feedId);
for (Like like : likes) {
if(like.getTime().getTime() >= timeInMillis && like.getUserid().equals(userid))
toReturn.add(toCheck);
}
}
}catch(Exception e){
_log.error("Skipped feed with id " + feedId, e);
}
}
}
// please check consider that if a user made like recently to an old post, well it could happen that this
// post comes first than a newer post in the toReturn list. Thus we need to sort it.
Collections.sort(toReturn, Collections.reverseOrder());
return toReturn;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -1732,24 +1848,24 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore {
_log.error("Unable to retrieve the list of feeds for hashtag" + column.getName() + " in vre " + vreid); _log.error("Unable to retrieve the list of feeds for hashtag" + column.getName() + " in vre " + vreid);
continue; continue;
} }
if(feeds.isEmpty()){ if(feeds.isEmpty()){
_log.info("There are no feeds containing hashtag " + column.getName() + " in vre " + vreid); _log.info("There are no feeds containing hashtag " + column.getName() + " in vre " + vreid);
continue; continue;
} }
// retrieve the most recent one among these feeds // retrieve the most recent one among these feeds
Collections.sort(feeds, Collections.reverseOrder()); Collections.sort(feeds, Collections.reverseOrder());
if(feeds.get(0).getTime().getTime() < timestamp){ if(feeds.get(0).getTime().getTime() < timestamp){
continue; continue;
} }
// else.. // else..
int curValue = Integer.parseInt(column.getStringValue()); int curValue = Integer.parseInt(column.getStringValue());
if (curValue > 0) if (curValue > 0)
toReturn.put(column.getName(), curValue); toReturn.put(column.getName(), curValue);
} }

View File

@ -1,24 +1,6 @@
package org.gcube.portal.databook.server; package org.gcube.portal.databook.server;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.ex.ColumnNameNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedTypeNotFoundException;
import org.gcube.portal.databook.shared.ex.PrivacyLevelTypeNotFoundException;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test;
public class DatabookCassandraTest { public class DatabookCassandraTest {
private static DBCassandraAstyanaxImpl store; private static DBCassandraAstyanaxImpl store;
@ -35,6 +17,36 @@ public class DatabookCassandraTest {
} }
// @Test
// public void getRecentCommentsByUserAndDate() throws Exception{
//
// String userid = "costantino.perciante";
// Calendar oneYearAgo = Calendar.getInstance();
// oneYearAgo.set(Calendar.YEAR, oneYearAgo.get(Calendar.YEAR) - 1);
//
// List<Comment> res = store.getRecentCommentsByUserAndDate(userid, oneYearAgo.getTimeInMillis());
//
// for (Comment comment : res) {
// System.out.println("Result is " + comment);
// }
//
//
//
//
// }
// @Test
// public void getRecentLikedFeedsByUser(){
//
// String userid = "costantino.perciante";
// Calendar oneYearAgo = Calendar.getInstance();
// oneYearAgo.set(Calendar.YEAR, oneYearAgo.get(Calendar.YEAR) - 1);
//
// List<Feed> result = store.getRecentLikedFeedsByUserAndDate(userid, oneYearAgo.getTimeInMillis());
//
// for (Feed feed : result) {
// System.out.println("Result is " + feed);
// }
// }
// @Test // @Test
// public void getHashTagsFilteredByTime() throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException{ // public void getHashTagsFilteredByTime() throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException{
// //

View File

@ -32,7 +32,7 @@ import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
/** /**
* @author Massimiliano Assante ISTI-CNR * @author Massimiliano Assante ISTI-CNR
* * @author Costantino Perciante ISTI-CNR
* <class>DatabookStore</class> is the high level interface for querying and adding data to DatabookStore * <class>DatabookStore</class> is the high level interface for querying and adding data to DatabookStore
*/ */
public interface DatabookStore { public interface DatabookStore {
@ -236,7 +236,6 @@ public interface DatabookStore {
* @throws ColumnNameNotFoundException * @throws ColumnNameNotFoundException
*/ */
List<Notification> getUnreadNotificationsByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException; List<Notification> getUnreadNotificationsByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException;
/** /**
* *
* @param userid user identifier * @param userid user identifier
@ -280,7 +279,7 @@ public interface DatabookStore {
* @throws NotificationChannelTypeNotFoundException self explaining * @throws NotificationChannelTypeNotFoundException self explaining
*/ */
Map<NotificationType, NotificationChannelType[]> getUserNotificationPreferences(String userid) throws NotificationTypeNotFoundException, NotificationChannelTypeNotFoundException; Map<NotificationType, NotificationChannelType[]> getUserNotificationPreferences(String userid) throws NotificationTypeNotFoundException, NotificationChannelTypeNotFoundException;
/** /**
* @param commentId comment unique identifier * @param commentId comment unique identifier
* @return the comment belonging to the commentId * @return the comment belonging to the commentId
@ -297,13 +296,18 @@ public interface DatabookStore {
* return all the comments belonging to the feedid * return all the comments belonging to the feedid
*/ */
List<Comment> getAllCommentByFeed(String feedid); List<Comment> getAllCommentByFeed(String feedid);
/**
* @param userid user identifier
* @param timeInMillis time in milliseconds from which you want to start retrieve the feeds
* @return a list of comments (sorted starting from the most recent one) made by the user since timeInMillis up to now
*/
List<Comment> getRecentCommentsByUserAndDate(String userid, long timeInMillis) throws Exception;
/** /**
* edit a comment * edit a comment
* @param commentid the comment identifier to edit * @param commentid the comment identifier to edit
* @return true if success, false otherwise * @return true if success, false otherwise
*/ */
boolean editComment(Comment comment) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, FeedIDNotFoundException; boolean editComment(Comment comment) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, FeedIDNotFoundException;
/** /**
* delete a comment * delete a comment
* @param commentid the comment identifier to delete * @param commentid the comment identifier to delete
@ -341,6 +345,13 @@ public interface DatabookStore {
* return all the feeds a user has liked * return all the feeds a user has liked
*/ */
List<Feed> getAllLikedFeedsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException; List<Feed> getAllLikedFeedsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException;
/**
* @param userid user identifier
* @param timeInMillis time in milliseconds from which you want to start retrieve the feeds
* @return the likes made to feeds in the range from: today to: timeInMillis
*/
List<Feed> getRecentLikedFeedsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException;
/** /**
* @param feedid feed identifier * @param feedid feed identifier
* return all the likes belonging to the feedid * return all the likes belonging to the feedid
@ -428,14 +439,14 @@ public interface DatabookStore {
* @return the list of attachments of the feed feedId, starting from the second one (first attachment is included in Feed instance already) * @return the list of attachments of the feed feedId, starting from the second one (first attachment is included in Feed instance already)
*/ */
List<Attachment> getAttachmentsByFeedId(String feedId) throws FeedIDNotFoundException; List<Attachment> getAttachmentsByFeedId(String feedId) throws FeedIDNotFoundException;
/** /**
* Retrieve all the ids of the vre * Retrieve all the ids of the vre
* @return the set of ids of the vre available or empty list in case of errors. * @return the set of ids of the vre available or empty list in case of errors.
* @throws ConnectionException * @throws ConnectionException
*/ */
public List<String> getAllVREIds() throws ConnectionException; public List<String> getAllVREIds() throws ConnectionException;
/** /**
* close the connection to the underlying database * close the connection to the underlying database
*/ */