diff --git a/.gwt/.gwt-log b/.gwt/.gwt-log new file mode 100644 index 0000000..e69de29 diff --git a/META-INF/KeySpace Structure.xlsx b/META-INF/KeySpace Structure.xlsx index 9a65883..6ee9994 100644 Binary files a/META-INF/KeySpace Structure.xlsx and b/META-INF/KeySpace Structure.xlsx differ diff --git a/distro/changelog.xml b/distro/changelog.xml index 5d9e105..ee25e78 100644 --- a/distro/changelog.xml +++ b/distro/changelog.xml @@ -1,8 +1,12 @@ + + Added support for hashtags in comments + Added support for job completion notifications - Improved exceptions handling + Improved exceptions handling diff --git a/pom.xml b/pom.xml index fd7f2d1..06a18f1 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.gcube.portal social-networking-library - 1.15.0-SNAPSHOT + 1.16.0-SNAPSHOT gCube Social Networking Library The gCube Social Networking Library is the 'bridge' between your gCube Applications and the social networking facilities. diff --git a/src/main/java/org/gcube/portal/databook/server/CassandraClusterConnection.java b/src/main/java/org/gcube/portal/databook/server/CassandraClusterConnection.java index b44b0f0..47c2386 100644 --- a/src/main/java/org/gcube/portal/databook/server/CassandraClusterConnection.java +++ b/src/main/java/org/gcube/portal/databook/server/CassandraClusterConnection.java @@ -271,6 +271,7 @@ public class CassandraClusterConnection { ColumnFamilyDefinition cfDefVREInvitesTimeline = getDynamicCFDef(DBCassandraAstyanaxImpl.VRE_INVITES); ColumnFamilyDefinition cfDefHashtagsCounter = getDynamicCFDef(DBCassandraAstyanaxImpl.HASHTAGS_COUNTER); ColumnFamilyDefinition cfDefHashtagTimeline = getDynamicCFDef(DBCassandraAstyanaxImpl.HASHTAGGED_FEEDS); + ColumnFamilyDefinition cfDefHashtagCommentsTimeline = getDynamicCFDef(DBCassandraAstyanaxImpl.HASHTAGGED_COMMENTS); ksDef.setName(keyspaceName) @@ -294,7 +295,8 @@ public class CassandraClusterConnection { .addColumnFamily(cfDefEmailInvitesTimeline) .addColumnFamily(cfDefVREInvitesTimeline) .addColumnFamily(cfDefHashtagsCounter) - .addColumnFamily(cfDefHashtagTimeline); + .addColumnFamily(cfDefHashtagTimeline) + .addColumnFamily(cfDefHashtagCommentsTimeline); cluster.addKeyspace(ksDef); } diff --git a/src/main/java/org/gcube/portal/databook/server/DBCassandraAstyanaxImpl.java b/src/main/java/org/gcube/portal/databook/server/DBCassandraAstyanaxImpl.java index 1892db9..f6b59da 100644 --- a/src/main/java/org/gcube/portal/databook/server/DBCassandraAstyanaxImpl.java +++ b/src/main/java/org/gcube/portal/databook/server/DBCassandraAstyanaxImpl.java @@ -85,6 +85,7 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore { public static final String USER_NOTIFICATIONS_PREFERENCES = "USERNotificationsPreferences"; // preferences for notifications public static final String HASHTAGS_COUNTER = "HashtagsCounter"; // count the hashtags per group and type public static final String HASHTAGGED_FEEDS = "HashtaggedFeeds"; // contains hashtags per type associated with vre and feed + public static final String HASHTAGGED_COMMENTS = "HashtaggedComments"; // contains hashtags per type associated with vre and comment public static final String VRE_INVITES = "VREInvites"; //contains the emails that were invited per VRE public static final String EMAIL_INVITES = "EMAILInvites"; //contains the list of invitation per email public static final String ATTACHMENTS = "Attachments"; //contains the list of all the attachments in a feed @@ -154,11 +155,14 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore { HASHTAGS_COUNTER, // Column Family Name StringSerializer.get(), // Key Serializer StringSerializer.get()); // Column Serializer - protected static ColumnFamily cf_HashtagTimeline = new ColumnFamily( + protected static ColumnFamily cf_HashtagTimelineFeed = new ColumnFamily( HASHTAGGED_FEEDS, // Column Family Name StringSerializer.get(), // Key Serializer StringSerializer.get()); // Column Serializer - + protected static ColumnFamily cf_HashtagTimelineComment = new ColumnFamily( + HASHTAGGED_COMMENTS, // Column Family Name + StringSerializer.get(), // Key Serializer + StringSerializer.get()); // Column Serializer private static ColumnFamily cf_VREInvites = new ColumnFamily( VRE_INVITES, // Column Family Name StringSerializer.get(), // Key Serializer @@ -1833,7 +1837,7 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore { MutationBatch m = conn.getKeyspace().prepareMutationBatch(); for (String hashtag : noduplicatesHashtags) { String lowerCaseHashtag = hashtag.toLowerCase(); - m.withRow(cf_HashtagTimeline, lowerCaseHashtag).putColumn(feedid, vreid, null); + m.withRow(cf_HashtagTimelineFeed, lowerCaseHashtag).putColumn(feedid, vreid, null); boolean firstInsert = execute(m); boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, true); if (! (firstInsert && secondInsert)) { @@ -1856,7 +1860,7 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore { MutationBatch m = conn.getKeyspace().prepareMutationBatch(); for (String hashtag : noduplicatesHashtags) { String lowerCaseHashtag = hashtag.toLowerCase(); - m.withRow(cf_HashtagTimeline, lowerCaseHashtag).deleteColumn(feedid); + m.withRow(cf_HashtagTimelineFeed, lowerCaseHashtag).deleteColumn(feedid); boolean firstDelete = execute(m); boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, false); if (! (firstDelete && secondInsert)) { @@ -1870,6 +1874,59 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore { * {@inheritDoc} */ @Override + public boolean saveHashTagsComment(String commentId, String vreid, List hashtags) throws CommentIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting datacommentIdcommentId + MutationBatch m = conn.getKeyspace().prepareMutationBatch(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + m.withRow(cf_HashtagTimelineComment, lowerCaseHashtag).putColumn(commentId, vreid, null); + boolean firstInsert = execute(m); + boolean secondInsert = false; + if(firstInsert) + secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, true); + if (! (firstInsert && secondInsert)) { + _log.error("saveHashTags: Could not save the hashtag(s)"); + return false; + } + } + return true; + } + /** + * {@inheritDoc} + */ + @Override + public boolean deleteHashTagsComment(String commentId, String vreid, List hashtags) throws CommentIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting data + MutationBatch m = conn.getKeyspace().prepareMutationBatch(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + m.withRow(cf_HashtagTimelineComment, lowerCaseHashtag).deleteColumn(commentId); + boolean firstDelete = execute(m); + if(firstDelete){ + boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, false); + if (!(firstDelete && secondInsert)) { + _log.error("deleteHashTags: Could not delete the hashtag(s)"); + return false; + } + }else{ + _log.error("deleteHashTags: Could not delete the hashtag(s)"); + return false; + } + } + return true; + } + /** + * {@inheritDoc} + */ + @Override public Map getVREHashtagsWithOccurrence(String vreid) { OperationResult> result = null; try { @@ -1951,23 +2008,44 @@ public final class DBCassandraAstyanaxImpl implements DatabookStore { @Override public List getVREFeedsByHashtag(String vreid, String hashtag) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { List toReturn = new ArrayList(); - OperationResult> result = null; + OperationResult> resultFeed = null; + OperationResult> resultComment = null; try { - result = conn.getKeyspace().prepareQuery(cf_HashtagTimeline) + resultFeed = conn.getKeyspace().prepareQuery(cf_HashtagTimelineFeed) .getKeySlice(hashtag) .execute(); } catch (ConnectionException e) { e.printStackTrace(); - } - ArrayList feedIds = new ArrayList(); - // Iterate rows and their columns - for (Row row : result.getResult()) { + } + try { + resultComment = conn.getKeyspace().prepareQuery(cf_HashtagTimelineComment) + .getKeySlice(hashtag) + .execute(); + } catch (ConnectionException e) { + e.printStackTrace(); + } + Set feedIds = new HashSet(); + // Iterate rows and their columns (feed) + for (Row row : resultFeed.getResult()) { for (Column column : row.getColumns()) { if (column.getStringValue().compareTo(vreid)==0) feedIds.add(column.getName()); } } - toReturn = getFeedsByIds(feedIds); + // Iterate rows and their columns (comments) + for (Row row : resultComment.getResult()) { + for (Column column : row.getColumns()) { + if (column.getStringValue().compareTo(vreid)==0){ + try { + Comment c = readCommentById(column.getName()); + feedIds.add(c.getFeedid()); + } catch (CommentIDNotFoundException e) { + _log.warn("Failed to fetch comment with id " + column.getName(), e); + } + } + } + } + toReturn = getFeedsByIds(new ArrayList(feedIds)); return toReturn; } /* diff --git a/src/main/java/org/gcube/portal/databook/server/DatabookStore.java b/src/main/java/org/gcube/portal/databook/server/DatabookStore.java index c41acbe..09c8531 100644 --- a/src/main/java/org/gcube/portal/databook/server/DatabookStore.java +++ b/src/main/java/org/gcube/portal/databook/server/DatabookStore.java @@ -372,6 +372,15 @@ public interface DatabookStore { * @throws FeedIDNotFoundException */ boolean saveHashTags(String feedid, String vreid, List hashtags) throws FeedIDNotFoundException; + /** + * + * @param hashtags the hashtag including the '#' + * @param commentId the commentId to which the hashtag is associated + * @param vreid VRE identifier + * @return true if success, false otherwise + * @throws CommentIDNotFoundException + */ + boolean saveHashTagsComment(String commentId, String vreid, List hashtags) throws CommentIDNotFoundException; /** * * @param hashtags the hashtag including the '#' @@ -381,6 +390,15 @@ public interface DatabookStore { * @throws FeedIDNotFoundException */ boolean deleteHashTags(String feedid, String vreid, List hashtags) throws FeedIDNotFoundException; + /** + * + * @param hashtags the hashtag including the '#' + * @param commentId the commentId to which the hashtag is associated + * @param vreid VRE identifier + * @return true if success, false otherwise + * @throws CommentIDNotFoundException + */ + boolean deleteHashTagsComment(String commentId, String vreid, List hashtags) throws CommentIDNotFoundException; /** * get a map of vre hashtags where the key is the hashtag and the value is the occurrence of the hashtag in the VRE * @param vreid vre identifier (scope)