From c2dcfac36cf26a204fb954597c39bed848b0be49 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Thu, 16 May 2024 14:43:49 +0200 Subject: [PATCH] second commit --- Dockerfile | 13 + docker/container.ini | 28 + docker/logback.xml | 23 + docker/properties | 2 + enunciate.xml | 26 +- .../extra-resources/WEB-INF/application.yaml | 7 + gcube/extra-resources/WEB-INF/docker.md | 5 + gcube/extra-resources/WEB-INF/web.xml | 20 + pom.xml | 122 +- .../DBCassandraAstyanaxImpl.java | 4084 +++++++++++++++ .../ResourceInitializer.java | 20 - .../social_networking/SocialService.java | 25 + ...a => SocialServiceApplicationManager.java} | 35 +- .../caches/CachesManager.java | 34 + .../social_networking/caches/GroupsCache.java | 54 + .../caches/SocialNetworkingSiteFinder.java | 249 + .../social_networking/caches/UsersCache.java | 83 + .../liferay/ws/GroupManagerWSBuilder.java | 50 + .../liferay/ws/KeycloakAPICredentials.java | 143 + .../liferay/ws/LiferayJSONWsCredentials.java | 175 + .../liferay/ws/RoleManagerWSBuilder.java | 50 + .../liferay/ws/ServletContextClass.java | 39 + .../liferay/ws/UserManagerWSBuilder.java | 50 + .../social_networking/rest/Attachments.java | 26 - .../social_networking/rest/HelloWorld.java | 96 +- .../gcube/social_networking/rest/Invites.java | 35 - .../gcube/social_networking/rest/Likes.java | 35 - .../social_networking/rest/Notifications.java | 40 - .../gcube/social_networking/rest/Posts.java | 113 - .../gcube/social_networking/rest/Users.java | 149 - .../gcube/social_networking/rest/Vres.java | 98 - .../rest/collections/Attachments.java | 87 + .../rest/collections/Collection.java | 276 + .../rest/collections/Comments.java | 63 + .../rest/collections/Entities.java | 210 + .../rest/collections/Invites.java | 63 + .../rest/collections/Likes.java | 87 + .../rest/collections/Notifications.java | 77 + .../rest/collections/Posts.java | 199 + .../rest/collections/Vres.java | 230 + .../server/CassandraCluster.java | 8 +- .../server/SocialDBDatastaxDriver.java | 4613 +++++++++-------- .../server/SocialDBDriver.java | 465 +- .../utils/ParameterNames.java | 15 + .../utils/ResourceNames.java | 19 + .../social_networking/utils/ResponseBean.java | 77 + .../social_networking/ws/WelcomeService.java | 19 + .../ws/docs/DocsGenerator.java | 50 + .../ws/ex/ApplicationException.java | 28 + .../ws/ex/AuthException.java | 16 + .../ws/ex/ValidationException.java | 36 + .../ws/inputs/ApplicationId.java | 42 + .../ws/inputs/CommentInputBean.java | 72 + .../ws/inputs/LikeInputBean.java | 60 + .../social_networking/ws/inputs/PostId.java | 43 + .../ws/inputs/PostInputBean.java | 146 + .../ws/inputs/UserSetNotificationBean.java | 63 + .../ws/mappers/CatalogueEventTypeMapper.java | 28 + .../ws/mappers/JobMapper.java | 64 + .../ws/mappers/WorkspaceItemMapper.java | 57 + .../ws/methods/v2/Comments.java | 233 + .../ws/methods/v2/FullTextSearch.java | 167 + .../ws/methods/v2/HashTags.java | 84 + .../social_networking/ws/methods/v2/Lib.java | 1397 +++++ .../ws/methods/v2/Likes.java | 168 + .../ws/methods/v2/Messages.java | 295 ++ .../ws/methods/v2/Notifications.java | 684 +++ .../ws/methods/v2/People.java | 105 + .../ws/methods/v2/Posts.java | 702 +++ .../ws/methods/v2/Tokens.java | 89 + .../social_networking/ws/methods/v2/VREs.java | 135 + .../ws/outputs/ResponseBean.java | 77 + .../ws/providers/CustomObjectMapper.java | 37 + .../ws/utils/CassandraConnection.java | 50 + .../ws/utils/ElasticSearchConnection.java | 52 + .../ws/utils/ErrorMessages.java | 21 + .../social_networking/ws/utils/Filters.java | 193 + .../ws/utils/SocialUtils.java | 725 +++ .../ws/utils/TokensUtils.java | 82 + .../UserProfileExtendedWithVerifiedEmail.java | 194 + src/main/webapp/WEB-INF/web.xml | 22 +- .../portal/test/GcoreEndpointReader.java | 78 + .../test/ServiceEndPointReaderSocial.java | 103 + 83 files changed, 15578 insertions(+), 3257 deletions(-) create mode 100644 Dockerfile create mode 100644 docker/container.ini create mode 100644 docker/logback.xml create mode 100644 docker/properties create mode 100644 gcube/extra-resources/WEB-INF/application.yaml create mode 100644 gcube/extra-resources/WEB-INF/docker.md create mode 100644 gcube/extra-resources/WEB-INF/web.xml create mode 100644 src/main/java/org/gcube/social_networking/DBCassandraAstyanaxImpl.java delete mode 100644 src/main/java/org/gcube/social_networking/ResourceInitializer.java create mode 100644 src/main/java/org/gcube/social_networking/SocialService.java rename src/main/java/org/gcube/social_networking/{HelloWorldInitializator.java => SocialServiceApplicationManager.java} (59%) create mode 100644 src/main/java/org/gcube/social_networking/caches/CachesManager.java create mode 100644 src/main/java/org/gcube/social_networking/caches/GroupsCache.java create mode 100644 src/main/java/org/gcube/social_networking/caches/SocialNetworkingSiteFinder.java create mode 100644 src/main/java/org/gcube/social_networking/caches/UsersCache.java create mode 100644 src/main/java/org/gcube/social_networking/liferay/ws/GroupManagerWSBuilder.java create mode 100644 src/main/java/org/gcube/social_networking/liferay/ws/KeycloakAPICredentials.java create mode 100644 src/main/java/org/gcube/social_networking/liferay/ws/LiferayJSONWsCredentials.java create mode 100644 src/main/java/org/gcube/social_networking/liferay/ws/RoleManagerWSBuilder.java create mode 100644 src/main/java/org/gcube/social_networking/liferay/ws/ServletContextClass.java create mode 100644 src/main/java/org/gcube/social_networking/liferay/ws/UserManagerWSBuilder.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Attachments.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Invites.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Likes.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Notifications.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Posts.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Users.java delete mode 100644 src/main/java/org/gcube/social_networking/rest/Vres.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Attachments.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Collection.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Comments.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Entities.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Invites.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Likes.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Notifications.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Posts.java create mode 100644 src/main/java/org/gcube/social_networking/rest/collections/Vres.java create mode 100644 src/main/java/org/gcube/social_networking/utils/ParameterNames.java create mode 100644 src/main/java/org/gcube/social_networking/utils/ResourceNames.java create mode 100644 src/main/java/org/gcube/social_networking/utils/ResponseBean.java create mode 100644 src/main/java/org/gcube/social_networking/ws/WelcomeService.java create mode 100644 src/main/java/org/gcube/social_networking/ws/docs/DocsGenerator.java create mode 100644 src/main/java/org/gcube/social_networking/ws/ex/ApplicationException.java create mode 100644 src/main/java/org/gcube/social_networking/ws/ex/AuthException.java create mode 100644 src/main/java/org/gcube/social_networking/ws/ex/ValidationException.java create mode 100644 src/main/java/org/gcube/social_networking/ws/inputs/ApplicationId.java create mode 100644 src/main/java/org/gcube/social_networking/ws/inputs/CommentInputBean.java create mode 100644 src/main/java/org/gcube/social_networking/ws/inputs/LikeInputBean.java create mode 100644 src/main/java/org/gcube/social_networking/ws/inputs/PostId.java create mode 100644 src/main/java/org/gcube/social_networking/ws/inputs/PostInputBean.java create mode 100644 src/main/java/org/gcube/social_networking/ws/inputs/UserSetNotificationBean.java create mode 100644 src/main/java/org/gcube/social_networking/ws/mappers/CatalogueEventTypeMapper.java create mode 100644 src/main/java/org/gcube/social_networking/ws/mappers/JobMapper.java create mode 100644 src/main/java/org/gcube/social_networking/ws/mappers/WorkspaceItemMapper.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Comments.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/FullTextSearch.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/HashTags.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Lib.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Likes.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Messages.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Notifications.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/People.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Posts.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/Tokens.java create mode 100644 src/main/java/org/gcube/social_networking/ws/methods/v2/VREs.java create mode 100644 src/main/java/org/gcube/social_networking/ws/outputs/ResponseBean.java create mode 100644 src/main/java/org/gcube/social_networking/ws/providers/CustomObjectMapper.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/CassandraConnection.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/ElasticSearchConnection.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/ErrorMessages.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/Filters.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/SocialUtils.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/TokensUtils.java create mode 100644 src/main/java/org/gcube/social_networking/ws/utils/UserProfileExtendedWithVerifiedEmail.java create mode 100644 src/test/java/org/gcube/portal/test/GcoreEndpointReader.java create mode 100644 src/test/java/org/gcube/portal/test/ServiceEndPointReaderSocial.java diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5e8fabe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +#FROM d4science/smartgears-distribution:4.0.0-SNAPSHOT-java11-tomcat9 +FROM smartgears-distribution:4.0.0-java11-tomcat9 + +ARG REPOUSER=admin +ARG REPOPWD=admin + +COPY ./target/social-service.war /usr/local/tomcat/webapps/ + +COPY ./docker/logback.xml /etc/ +COPY ./docker/container.ini /etc/ +RUN unzip /usr/local/tomcat/webapps/social-service.war -d /usr/local/tomcat/webapps/social-service +RUN rm /usr/local/tomcat/webapps/social-service.war +EXPOSE 8080 diff --git a/docker/container.ini b/docker/container.ini new file mode 100644 index 0000000..e8cd44e --- /dev/null +++ b/docker/container.ini @@ -0,0 +1,28 @@ +[node] +mode = offline +hostname = socialservice +protocol= http +port = 8080 +infrastructure = gcube +authorizeChildrenContext = true +publicationFrequencyInSeconds = 60 + +[properties] +SmartGearsDistribution = 4.0.0-SNAPSHOT +SmartGearsDistributionBundle = UnBundled + +[site] +country = it +location = pisa + +[authorization] +factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory +factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token +credentials.class = org.gcube.smartgears.security.SimpleCredentials +//for smartgears +credentials.clientID = social-service-hosting-node-client +credentials.secret = 979bd3bc-5cc4-11ec-bf63-0242ac130002 + +//for interacting with alfredo's service +socialservice +yqMpmqwlcu9o2mZTWMyDq0om8QMcjUEb \ No newline at end of file diff --git a/docker/logback.xml b/docker/logback.xml new file mode 100644 index 0000000..f125098 --- /dev/null +++ b/docker/logback.xml @@ -0,0 +1,23 @@ + + + + Ï + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docker/properties b/docker/properties new file mode 100644 index 0000000..2c035d9 --- /dev/null +++ b/docker/properties @@ -0,0 +1,2 @@ +${{adminId}}=social +${{adminPwd}}=social \ No newline at end of file diff --git a/enunciate.xml b/enunciate.xml index 3524ef4..97526b3 100644 --- a/enunciate.xml +++ b/enunciate.xml @@ -2,22 +2,36 @@ - - - + + + + - + + + + + + + + + + - - + + \ No newline at end of file diff --git a/gcube/extra-resources/WEB-INF/application.yaml b/gcube/extra-resources/WEB-INF/application.yaml new file mode 100644 index 0000000..a1502f1 --- /dev/null +++ b/gcube/extra-resources/WEB-INF/application.yaml @@ -0,0 +1,7 @@ +name: ${artifactId} +group: ${groupId} +version: ${version} +description: ${description} +excludes: + - path: /docs.* + - path: /api-docs.* \ No newline at end of file diff --git a/gcube/extra-resources/WEB-INF/docker.md b/gcube/extra-resources/WEB-INF/docker.md new file mode 100644 index 0000000..f83ff28 --- /dev/null +++ b/gcube/extra-resources/WEB-INF/docker.md @@ -0,0 +1,5 @@ +mvn clean package +docker build -t idm . +docker compose up -d --build --force-recreate + +#docker run -it -d -p 9090:8080 --name idm idm diff --git a/gcube/extra-resources/WEB-INF/web.xml b/gcube/extra-resources/WEB-INF/web.xml new file mode 100644 index 0000000..243fb96 --- /dev/null +++ b/gcube/extra-resources/WEB-INF/web.xml @@ -0,0 +1,20 @@ + + + + admin-username + {{adminId}} + + + admin-pwd + {{adminPwd}} + + + org.gcube.social_networking.SocialService + + + + org.gcube.social_networking.SocialService + /social-service/* + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9d1d8d2..3ba5e06 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.gcube.tools maven-parent - 1.1.0 + 1.2.0 org.gcube.social_networking social-service @@ -16,6 +16,9 @@ UTF-8 + 11 + 11 + ${project.basedir}${file.separator}src${file.separator}main${file.separator}webapp${file.separator}WEB-INF 2.14.0 @@ -35,7 +38,7 @@ org.gcube.distribution gcube-smartgears-bom - 2.5.0 + 3.0.1-SNAPSHOT pom import @@ -47,6 +50,7 @@ import + @@ -54,33 +58,46 @@ org.slf4j slf4j-api - - org.gcube.common - authorization-utils - [2.2.0, 3.0.0-SNAPSHOT) - - - org.glassfish.jersey.media - jersey-media-multipart - + + org.glassfish.jersey.containers jersey-container-servlet + + org.glassfish.jersey.containers + jersey-container-servlet-core + + javax.ws.rs javax.ws.rs-api - org.gcube.common.portal - portal-manager - provided + org.gcube.core + common-smartgears-app - + + org.gcube.core + common-smartgears + + + org.gcube.core + common-scope + + + org.gcube.core + common-scope-maps + + + org.gcube.common + authorization-client + + org.gcube.social-networking social-service-model - [1.2.0-SNAPSHOT, 2.0.0) + 2.0.0-SNAPSHOT com.datastax.oss @@ -92,6 +109,11 @@ java-driver-mapper-runtime ${cassandra.driver.oss.version} + + commons-lang + commons-lang + 2.6 + com.sun.mail javax.mail @@ -99,33 +121,9 @@ compile - commons-lang - commons-lang - 2.6 + org.gcube.common.portal + portal-manager - - org.gcube.core - common-smartgears-app - - - - - javax.xml.ws - jaxws-api - provided - - - org.projectlombok - lombok - provided - - - - - org.gcube.core - common-smartgears - - @@ -144,7 +142,6 @@ javax.servlet javax.servlet-api 3.1.0 - provided @@ -152,7 +149,7 @@ junit junit - 4.11 + 4.13.2 test @@ -161,32 +158,12 @@ test - - - - - - kr.motd.maven - sphinx-maven-plugin - 2.10.0 - - - ${project.build.directory}/${project.artifactId}-${project.version}/docs - html - ${basedir}/docs - ${basedir}/docs - - - - process-resources - - generate - - - - - + + ${project.artifactId} + + + + org.apache.maven.plugins maven-resources-plugin @@ -227,7 +203,7 @@ - +--> org.apache.maven.plugins @@ -240,4 +216,4 @@ - + \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/DBCassandraAstyanaxImpl.java b/src/main/java/org/gcube/social_networking/DBCassandraAstyanaxImpl.java new file mode 100644 index 0000000..59f1725 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/DBCassandraAstyanaxImpl.java @@ -0,0 +1,4084 @@ +package org.gcube.social_networking; + +import java.time.Instant; +import java.util.*; +import java.util.stream.Collectors; + +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.print.attribute.standard.MediaSize; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.cql.*; +import com.datastax.oss.driver.api.querybuilder.QueryBuilder; +import org.apache.commons.lang.NullArgumentException; +import org.gcube.portal.databook.shared.*; +import org.gcube.portal.databook.shared.ex.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.gcube.portal.databook.server.CassandraClusterConnection.closeSession; +import static org.gcube.portal.databook.server.Schema.*; +/** + * @author Massimiliano Assante ISTI-CNR + * @author Costantino Perciante ISTI-CNR + * @author Ahmed Ibrahim ISTI-CNR + * This class is used for querying and adding data to Cassandra via Datastax High Level API + */ +public final class DBCassandraAstyanaxImpl implements DatabookStore { + + /** + * logger + */ + private static final Logger _log = LoggerFactory.getLogger(DBCassandraAstyanaxImpl.class); + + /** + * connection instance + */ + private CassandraClusterConnection conn; + + protected CassandraClusterConnection getConnection() { + return conn; + } + /** + * use this constructor carefully from test classes + * @param dropSchema set true if you want do drop the current and set up new one + */ + protected DBCassandraAstyanaxImpl(boolean dropSchema) { + try { + conn = new CassandraClusterConnection(dropSchema); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + /** + * public constructor, no dropping schema is allowed + */ + public DBCassandraAstyanaxImpl() { + try { + conn = new CassandraClusterConnection(false); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * public constructor, no dropping schema is allowed, infrastructureName is given. + */ + public DBCassandraAstyanaxImpl(String infrastructureName) { + try { + conn = new CassandraClusterConnection(false, infrastructureName); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /* + Utility Functions + */ + private static boolean existRecordbyId(CqlSession session, String id, String tableName, String colName) { + PreparedStatement stmt = session.prepare(QueryBuilder + .selectFrom(tableName).column(colName) + .whereColumn(colName) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + return session.execute(stmt.bind(id)).getAvailableWithoutFetching() > 0; + } + + private static boolean existRecordbyCompId(CqlSession session, String col1, String col2, String id1, String id2, String tableName) { + PreparedStatement stmt = session.prepare(QueryBuilder + .selectFrom(tableName).all() + .whereColumn(col1) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(col2) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + return session.execute(stmt.bind(id1, id2)).getAvailableWithoutFetching() > 0; + } + + private static PreparedStatement updatePostEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(POSTS) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static Optional < Post > findPostById(String postid, CqlSession session) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException { + PreparedStatement stmtFindPost = session.prepare(QueryBuilder + .selectFrom(POSTS).all() + .whereColumn(POST_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet rs = session.execute(stmtFindPost.bind(UUID.fromString(postid))); + // We query by the primary key ensuring unicity + Row record = rs.one(); + return (null != record) ? Optional.of(readPostFromRow(record)) :Optional.empty(); + } + + private static Attachment readAttachmentFromRow(Row record) { + Attachment a = new Attachment(); + a.setId(Objects.requireNonNull(record.getUuid(ATTACH_ID)).toString()); + a.setUri(record.getString(URI)); + a.setName(record.getString(NAME)); + a.setDescription(record.getString(DESCRIPTION)); + a.setThumbnailURL(record.getString(URI_THUMBNAIL)); + a.setMimeType(record.getString(MIME_TYPE)); + return a; + } + private static Notification readNotificationFromRow(Row record) throws NotificationTypeNotFoundException { + Notification a = new Notification(); + a.setKey(Objects.requireNonNull(record.getUuid(NOT_ID)).toString()); + a.setType(getNotificationType(Objects.requireNonNull(record.getString(TYPE)))); + a.setUserid(record.getString(USER_ID)); + a.setSubjectid(record.getString(SUBJECT_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setUri(record.getString(URI)); + a.setDescription(record.getString(DESCRIPTION)); + a.setRead(record.getBoolean(IS_READ)); + a.setSenderid(record.getString(SENDER_ID)); + a.setSenderFullName(record.getString(SENDER_FULL_NAME)); + a.setSenderThumbnail(record.getString(SENDER_THUMBNAIL_URL)); + return a; + } + private static Post readPostFromRow(Row record) throws FeedTypeNotFoundException, PrivacyLevelTypeNotFoundException { + Post a = new Post(); + + a.setKey(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setType(getPostType(Objects.requireNonNull(record.getString(TYPE)))); + a.setEntityId(record.getString(ENTITY_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setVreid(record.getString(VRE_ID)); + a.setUri(record.getString(URI)); + a.setUriThumbnail(record.getString(URI_THUMBNAIL)); + a.setDescription(record.getString(DESCRIPTION)); + a.setPrivacy(getPrivacyLevel(Objects.requireNonNull(record.getString(PRIVACY)))); + a.setFullName(record.getString(FULL_NAME)); + a.setEmail(record.getString(EMAIL)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + a.setCommentsNo(String.valueOf(record.getLong(COMMENTS_NO))); + a.setLikesNo(String.valueOf(record.getLong(LIKES_NO))); + a.setLinkDescription(record.getString(LINK_DESCRIPTION)); + a.setLinkTitle(record.getString(LINK_TITLE)); + a.setLinkHost(record.getString(LINK_HOST)); + a.setApplicationFeed(record.getBoolean(IS_APPLICATION_POST)); + a.setMultiFileUpload(record.getBoolean(MULTI_FILE_UPLOAD)); + + return a; + } + private static Like readLikeFromRow(Row record) { + Like a = new Like(); + a.setKey(Objects.requireNonNull(record.getUuid(LIKE_ID)).toString()); + a.setUserid(record.getString(USER_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setFeedid(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setFullName(record.getString(FULL_NAME)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + return a; + } + private static Comment readCommentFromRow(Row record) { + Comment a = new Comment(); + a.setKey(Objects.requireNonNull(record.getUuid(COMMENT_ID)).toString()); + a.setUserid(record.getString(USER_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setFeedid(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setFullName(record.getString(FULL_NAME)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + a.setText(record.getString(COMMENT)); + a.setEdit(!record.isNull(IS_EDIT) && record.getBoolean(IS_EDIT)); + a.setLastEditTime(record.isNull(LAST_EDIT_TIME)? null : Date.from(Objects.requireNonNull(record.getInstant(LAST_EDIT_TIME)))); + return a; + } + private static Invite readAInviteFromRow(Row record) throws InviteStatusNotFoundException { + Invite a = new Invite(); + a.setKey(Objects.requireNonNull(record.getUuid(INVITE_ID)).toString()); + a.setSenderUserId(record.getString(SENDER_USER_ID)); + a.setVreid(record.getString(VRE_ID)); + a.setInvitedEmail(record.getString(EMAIL)); + a.setControlCode(record.getString(CONTROL_CODE)); + a.setStatus(getInviteStatusType(Objects.requireNonNull(record.getString(STATUS)))); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setSenderFullName(record.getString(SENDER_FULL_NAME)); + return a; + } + private static Feed readFeedFromRow(Row record) throws FeedTypeNotFoundException, PrivacyLevelTypeNotFoundException { + Feed a = new Feed(); + + a.setKey(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setType(getFeedType(Objects.requireNonNull(record.getString(TYPE)))); + a.setEntityId(record.getString(ENTITY_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setVreid(record.getString(VRE_ID)); + a.setUri(record.getString(URI)); + a.setUriThumbnail(record.getString(URI_THUMBNAIL)); + a.setDescription(record.getString(DESCRIPTION)); + a.setPrivacy(getPrivacyLevel(Objects.requireNonNull(record.getString(PRIVACY)))); + a.setFullName(record.getString(FULL_NAME)); + a.setEmail(record.getString(EMAIL)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + a.setCommentsNo(String.valueOf(record.getLong(COMMENTS_NO))); + a.setLikesNo(String.valueOf(record.getLong(LIKES_NO))); + a.setLinkDescription(record.getString(LINK_DESCRIPTION)); + a.setLinkTitle(record.getString(LINK_TITLE)); + a.setLinkHost(record.getString(LINK_HOST)); + a.setApplicationFeed(record.getBoolean(IS_APPLICATION_POST)); + a.setMultiFileUpload(record.getBoolean(MULTI_FILE_UPLOAD)); + + return a; + } + + + private static Optional < Feed > findFeedById(String postid, CqlSession session) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException { + PreparedStatement stmtFindPost = session.prepare(QueryBuilder + .selectFrom(POSTS).all() + .whereColumn(POST_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet rs = session.execute(stmtFindPost.bind(UUID.fromString(postid))); + // We query by the primary key ensuring unicity + Row record = rs.one(); + return (null != record) ? Optional.of(readFeedFromRow(record)) :Optional.empty(); + } + private static Optional < Notification > findNotById(String notid, CqlSession session) throws NotificationTypeNotFoundException { + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(NOTIFICATIONS).all() + .whereColumn(NOT_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet rs = session.execute(stmtFind.bind(UUID.fromString(notid))); + // We query by the primary key ensuring unicity + Row record = rs.one(); + return (null != record) ? Optional.of(readNotificationFromRow(record)) :Optional.empty(); + } + + + private static PreparedStatement updateInviteEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(INVITES) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(INVITE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement updateVreInviteEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(VRE_INVITES) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(VRE_ID).isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(INVITE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement deleteHashtagEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(HASHTAGGED_POSTS) + .whereColumn(HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(POST_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteHashtagCommentEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(HASHTAGGED_COMMENTS) + .whereColumn(HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(COMMENT_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteLikeEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(LIKES) + .whereColumn(LIKE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteUserLikeEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(USER_LIKED_POSTS) + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(LIKE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement updateCommentEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(COMMENTS) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(COMMENT_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement deleteCommentEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(COMMENTS) + .whereColumn(COMMENT_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement updateNotificationEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(NOTIFICATIONS) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(NOT_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement deleteUnreadNotEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(USER_NOTIFICATIONS_UNREAD) + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(TIMESTAMP) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static BatchStatement getBatch(){ + return BatchStatement.builder(BatchType.LOGGED).build(); + } + + private static PreparedStatement createPostEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(POSTS) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(LINK_HOST, QueryBuilder.bindMarker()) + .value(DESCRIPTION, QueryBuilder.bindMarker()) + .value(EMAIL, QueryBuilder.bindMarker()) + .value(LIKES_NO, QueryBuilder.bindMarker()) + .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(LINK_DESCRIPTION, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(URI, QueryBuilder.bindMarker()) + .value(IS_APPLICATION_POST, QueryBuilder.bindMarker()) + .value(ENTITY_ID, QueryBuilder.bindMarker()) + .value(PRIVACY, QueryBuilder.bindMarker()) + .value(TYPE, QueryBuilder.bindMarker()) + .value(URI_THUMBNAIL, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(MULTI_FILE_UPLOAD, QueryBuilder.bindMarker()) + .value(FULL_NAME, QueryBuilder.bindMarker()) + .value(COMMENTS_NO, QueryBuilder.bindMarker()) + .value(LINK_TITLE, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createUserTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_TIMELINE_POSTS) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createVreTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(VRE_TIMELINE_POSTS) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createAppTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(APP_TIMELINE_POSTS) + .value(APP_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNotificationEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(NOTIFICATIONS) + .value(NOT_ID, QueryBuilder.bindMarker()) + .value(TYPE, QueryBuilder.bindMarker()) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(SUBJECT_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(DESCRIPTION, QueryBuilder.bindMarker()) + .value(URI, QueryBuilder.bindMarker()) + .value(SENDER_ID, QueryBuilder.bindMarker()) + .value(SENDER_FULL_NAME, QueryBuilder.bindMarker()) + .value(SENDER_THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(IS_READ, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createUserNotificationsEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_NOTIFICATIONS) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(NOT_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createUnreadNotificationEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_NOTIFICATIONS_UNREAD) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(NOT_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNotificationPreferenceEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_NOTIFICATIONS_PREFERENCES) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TYPE, QueryBuilder.bindMarker()) + .value(PREFERENCE, QueryBuilder.bindMarker()) + .build()); + } + + private static PreparedStatement createNewCommentEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(COMMENTS) + .value(COMMENT_ID, QueryBuilder.bindMarker()) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(FULL_NAME, QueryBuilder.bindMarker()) + .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(COMMENT, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(IS_EDIT, QueryBuilder.bindMarker()) + .value(LAST_EDIT_TIME, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewLikeEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(LIKES) + .value(LIKE_ID, QueryBuilder.bindMarker()) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(FULL_NAME, QueryBuilder.bindMarker()) + .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewUserLikesEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_LIKED_POSTS) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(LIKE_ID, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewHashtagTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(HASHTAGGED_POSTS) + .value(HASHTAG, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewHashtagCommentEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(HASHTAGGED_COMMENTS) + .value(HASHTAG, QueryBuilder.bindMarker()) + .value(COMMENT_ID, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewEmailInviteEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(EMAIL_INVITES) + .value(EMAIL, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(INVITE_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewInviteEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(INVITES) + .value(INVITE_ID, QueryBuilder.bindMarker()) + .value(SENDER_USER_ID, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(EMAIL, QueryBuilder.bindMarker()) + .value(CONTROL_CODE, QueryBuilder.bindMarker()) + .value(STATUS, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(SENDER_FULL_NAME, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewVreInviteEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(VRE_INVITES) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(INVITE_ID, QueryBuilder.bindMarker()) + .value(STATUS, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewaAttachEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(ATTACHMENTS) + .value(ATTACH_ID, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(URI, QueryBuilder.bindMarker()) + .value(NAME, QueryBuilder.bindMarker()) + .value(DESCRIPTION, QueryBuilder.bindMarker()) + .value(URI_THUMBNAIL, QueryBuilder.bindMarker()) + .value(MIME_TYPE, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewUHashtagCounterEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(HASHTAGS_COUNTER) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(HASHTAG, QueryBuilder.bindMarker()) + .value(COUNT, QueryBuilder.bindMarker()) + .build()); + } + + + /* + * + ********************** FRIENDSHIPS (CONNECTIONS) *********************** + * + */ + /** + * {@inheritDoc} + */ + @Override + public boolean requestFriendship(String from, String to) { + return true; + } + /** + * {@inheritDoc} + */ + @Override + public boolean approveFriendship(String from, String to) { + return true; + } + /** + * {@inheritDoc} + */ + @Override + public boolean denyFriendship(String from, String to) { + return true; + } + /** + * {@inheritDoc} + */ + @Override + public List getFriends(String userid) { + ArrayList toReturn = new ArrayList(); + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getPendingFriendRequests(String userid) { + ArrayList toReturn = new ArrayList(); + return toReturn; + } + /* + * + ********************** FEEDS *********************** + * + */ + + private static Post feed2post(Feed feed){ + Post post = new Post(); + if (feed.getKey()!=null)post.setKey(feed.getKey()); + if (feed.getType()!=null)post.setType(PostType.valueOf(feed.getType().toString())); + if (feed.getEntityId()!=null)post.setEntityId(feed.getEntityId()); + if (feed.getTime()!=null)post.setTime(feed.getTime()); + if (feed.getVreid()!=null)post.setVreid(feed.getVreid()); + if (feed.getUri()!=null)post.setUri(feed.getUri()); + if (feed.getUriThumbnail()!=null)post.setUriThumbnail(feed.getUriThumbnail()); + if (feed.getDescription()!=null)post.setDescription(feed.getDescription()); + if (feed.getPrivacy()!=null)post.setPrivacy(feed.getPrivacy()); + if (feed.getFullName()!=null)post.setFullName(feed.getFullName()); + if (feed.getEmail()!=null)post.setEmail(feed.getEmail()); + if (feed.getThumbnailURL()!=null)post.setThumbnailURL(feed.getThumbnailURL()); + if (feed.getCommentsNo()!=null)post.setCommentsNo(feed.getCommentsNo()); + if (feed.getLikesNo()!=null)post.setLikesNo(feed.getLikesNo()); + if (feed.getLinkTitle()!=null)post.setLinkTitle(feed.getLinkTitle()); + if (feed.getLinkDescription()!=null)post.setLinkDescription(feed.getLinkDescription()); + if (feed.getLinkHost()!=null)post.setLinkHost(feed.getLinkHost()); + post.setApplicationFeed(feed.isApplicationFeed()); + post.setMultiFileUpload(feed.isMultiFileUpload()); + return post; + } + + private static Feed post2feed(Post post){ + Feed feed = new Feed(); + + if (post.getKey()!=null)feed.setKey(post.getKey()); + if (post.getType()!=null)feed.setType(FeedType.valueOf(post.getType().toString())); + if (post.getEntityId()!=null)feed.setEntityId(post.getEntityId()); + if (post.getTime()!=null)feed.setTime(post.getTime()); + if (post.getVreid()!=null)feed.setVreid(post.getVreid()); + if (post.getUri()!=null)feed.setUri(post.getUri()); + if (post.getUriThumbnail()!=null)feed.setUriThumbnail(post.getUriThumbnail()); + if (post.getDescription()!=null)feed.setDescription(post.getDescription()); + if (post.getPrivacy()!=null)feed.setPrivacy(post.getPrivacy()); + if (post.getFullName()!=null)feed.setFullName(post.getFullName()); + if (post.getEmail()!=null)feed.setEmail(post.getEmail()); + if (post.getThumbnailURL()!=null)feed.setThumbnailURL(post.getThumbnailURL()); + if (post.getCommentsNo()!=null)feed.setCommentsNo(post.getCommentsNo()); + if (post.getLikesNo()!=null)feed.setLikesNo(post.getLikesNo()); + if (post.getLinkTitle()!=null)feed.setLinkTitle(post.getLinkTitle()); + if (post.getLinkDescription()!=null)feed.setLinkDescription(post.getLinkDescription()); + if (post.getLinkHost()!=null)feed.setLinkHost(post.getLinkHost()); + feed.setApplicationFeed(post.isApplicationFeed()); + feed.setMultiFileUpload(post.isMultiFileUpload()); + + return feed; + } + private List insertIntoPosts(CqlSession session, Post post){ + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_HOST, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(EMAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LIKES_NO, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt9 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(IS_APPLICATION_POST, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt10 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(ENTITY_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt11 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(PRIVACY, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt12 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(TYPE, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt13 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(URI_THUMBNAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt14 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(VRE_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt15 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(MULTI_FILE_UPLOAD, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt16 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt17 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(COMMENTS_NO, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt18 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_TITLE, QueryBuilder.bindMarker()).build()); + +/* + PreparedStatement prepStmt1 = session.prepare("INSERT INTO posts("+POST_ID+","+ LINK_HOST+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare("INSERT INTO posts("+POST_ID+","+ DESCRIPTION+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare("INSERT INTO posts("+POST_ID+","+ EMAIL+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare("INSERT INTO posts("+POST_ID+","+ LIKES_NO+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare("INSERT INTO posts("+POST_ID+","+ THUMBNAIL_URL+") values(?, ?)"); + PreparedStatement prepStmt6 = session.prepare("INSERT INTO posts("+POST_ID+","+ LINK_DESCRIPTION+") values(?, ?)"); + PreparedStatement prepStmt7 = session.prepare("INSERT INTO posts("+POST_ID+","+ TIMESTAMP+") values(?, ?)"); + PreparedStatement prepStmt8 = session.prepare("INSERT INTO posts("+POST_ID+","+ URI+") values(?, ?)"); + PreparedStatement prepStmt9 = session.prepare("INSERT INTO posts("+POST_ID+","+ IS_APPLICATION_POST+") values(?, ?)"); + PreparedStatement prepStmt10 = session.prepare("INSERT INTO posts("+POST_ID+","+ ENTITY_ID+") values(?, ?)"); + PreparedStatement prepStmt11 = session.prepare("INSERT INTO posts("+POST_ID+","+ PRIVACY+") values(?, ?)"); + PreparedStatement prepStmt12 = session.prepare("INSERT INTO posts("+POST_ID+","+ TYPE+") values(?, ?)"); + PreparedStatement prepStmt13 = session.prepare("INSERT INTO posts("+POST_ID+","+ URI_THUMBNAIL+") values(?, ?)"); + PreparedStatement prepStmt14 = session.prepare("INSERT INTO posts("+POST_ID+","+ VRE_ID+") values(?, ?)"); + PreparedStatement prepStmt15 = session.prepare("INSERT INTO posts("+POST_ID+","+ MULTI_FILE_UPLOAD+") values(?, ?)"); + PreparedStatement prepStmt16 = session.prepare("INSERT INTO posts("+POST_ID+","+ FULL_NAME+") values(?, ?)"); + PreparedStatement prepStmt17 = session.prepare("INSERT INTO posts("+POST_ID+","+ COMMENTS_NO+") values(?, ?)"); + PreparedStatement prepStmt18 = session.prepare("INSERT INTO posts("+POST_ID+","+ LINK_TITLE+") values(?, ?)"); +*/ + List boundStatements = new ArrayList<>(); + + if(post.getLinkHost()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(post.getKey()), post.getLinkHost())); + } + + if(post.getDescription()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(post.getKey()), post.getDescription())); + } + + if(post.getEmail()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(post.getKey()), post.getEmail())); + } + if(post.getLikesNo()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(post.getKey()), Long.parseLong(post.getLikesNo()))); + }if(post.getThumbnailURL()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(post.getKey()), post.getThumbnailURL())); + }if(post.getLinkDescription()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(post.getKey()), post.getLinkDescription())); + }if(post.getTime()!=null){ + boundStatements.add(prepStmt7.bind(UUID.fromString(post.getKey()), post.getTime().toInstant())); + }if(post.getUri()!=null){ + boundStatements.add(prepStmt8.bind(UUID.fromString(post.getKey()), post.getUri())); + } + boundStatements.add(prepStmt9.bind(UUID.fromString(post.getKey()), post.isApplicationFeed())); + if(post.getEntityId()!=null){ + boundStatements.add(prepStmt10.bind(UUID.fromString(post.getKey()), post.getEntityId())); + }if(post.getPrivacy()!=null){ + boundStatements.add(prepStmt11.bind(UUID.fromString(post.getKey()), post.getPrivacy().toString())); + }if(post.getType()!=null){ + boundStatements.add(prepStmt12.bind(UUID.fromString(post.getKey()), post.getType().toString())); + }if(post.getUriThumbnail()!=null){ + boundStatements.add(prepStmt13.bind(UUID.fromString(post.getKey()), post.getUriThumbnail())); + }if(post.getVreid()!=null){ + boundStatements.add(prepStmt14.bind(UUID.fromString(post.getKey()), post.getVreid())); + } + boundStatements.add(prepStmt15.bind(UUID.fromString(post.getKey()), post.isMultiFileUpload())); + if(post.getFullName()!=null){ + boundStatements.add(prepStmt16.bind(UUID.fromString(post.getKey()), post.getFullName())); + }if(post.getCommentsNo()!=null){ + boundStatements.add(prepStmt17.bind(UUID.fromString(post.getKey()), Long.parseLong(post.getCommentsNo()))); + }if(post.getLinkTitle()!=null){ + boundStatements.add(prepStmt18.bind(UUID.fromString(post.getKey()), post.getLinkTitle())); + } + return boundStatements; + } + + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public boolean saveUserFeed(Feed post) { + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = insertIntoPosts(session, feed2post(post)); + + + //boundStatements.forEach(stmt -> writeBatch.add(stmt)); + + //an entry in posts + /*PreparedStatement stmt1 = createPostEntry(session); + writeBatch.add(stmt1.bind(UUID.fromString(post.getKey()), + post.getLinkHost(), + post.getDescription(), + post.getEmail(), + post.getLikesNo()!=null?Long.parseLong(post.getLikesNo()):null, + post.getThumbnailURL(), + post.getLinkDescription(), + post.getTime()!=null?post.getTime().toInstant():null, + post.getUri(), + post.isApplicationFeed(), + post.getEntityId(), + post.getPrivacy()!=null?post.getPrivacy().toString():null, + post.getType()!=null?post.getType().toString():null, + post.getUriThumbnail(), + post.getVreid(), + post.isMultiFileUpload(), + post.getFullName(), + post.getCommentsNo()!=null?Long.parseLong(post.getCommentsNo()):null, + post.getLinkTitle())); + */ + + //an entry in the user Timeline + BoundStatement stmt2 = createUserTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt2); + //an entry in the VRES Timeline iff vreid field is not empty + if (post.getVreid() != null && post.getVreid().compareTo("") != 0){ + BoundStatement stmt3 = createVreTimelineEntry(session).bind(post.getVreid(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt3); + } + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + Boolean result = session.execute(writeBatch).wasApplied(); + if (result){ + _log.debug("Wrote user post with id " + post.getKey()); + } + + + return result; + } + /** + * {@inheritDoc} + */ + @Override + public boolean saveUserPost(Post post) { + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = insertIntoPosts(session, post); + //boundStatements.forEach(stmt -> writeBatch.add(stmt)); + //an entry in posts + /*PreparedStatement stmt1 = createPostEntry(session); + writeBatch.add(stmt1.bind(UUID.fromString(post.getKey()), + post.getLinkHost(), + post.getDescription(), + post.getEmail(), + post.getLikesNo()!=null?Long.parseLong(post.getLikesNo()):null, + post.getThumbnailURL(), + post.getLinkDescription(), + post.getTime()!=null?post.getTime().toInstant():null, + post.getUri(), + post.isApplicationFeed(), + post.getEntityId(), + post.getPrivacy()!=null?post.getPrivacy().toString():null, + post.getType()!=null?post.getType().toString():null, + post.getUriThumbnail(), + post.getVreid(), + post.isMultiFileUpload(), + post.getFullName(), + post.getCommentsNo()!=null?Long.parseLong(post.getCommentsNo()):null, + post.getLinkTitle()));*/ + + //an entry in the user Timeline + BoundStatement stmt2 = createUserTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt2); + //an entry in the VRES Timeline iff vreid field is not empty + if (post.getVreid() != null && post.getVreid().compareTo("") != 0){ + BoundStatement stmt3 = createVreTimelineEntry(session).bind(post.getVreid(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt3); + } + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + Boolean result = session.execute(writeBatch).wasApplied(); + if (result){ + _log.debug("Wrote user post with id " + post.getKey()); + } + + + return result; + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public boolean saveUserFeed(Feed feed, List attachments) { + if (attachments != null && !attachments.isEmpty()) + feed.setMultiFileUpload(true); + boolean saveFeedResult = saveUserFeed(feed); + if (saveFeedResult) { + String feedKey = feed.getKey(); + for (Attachment attachment : attachments) { + boolean attachSaveResult = saveAttachmentEntry(feedKey, attachment); + if (!attachSaveResult) + _log.warn("Some of the attachments failed to me saved: " + attachment.getName()); + } + return true; + } + else return false; + } + /** + * {@inheritDoc} + */ + @Override + public boolean saveUserPost(Post post, List attachments) { + if (attachments != null && !attachments.isEmpty()) + post.setMultiFileUpload(true); + boolean savePostResult = saveUserPost(post); + if (savePostResult) { + _log.debug("Post has been saved"); + String postkey = post.getKey(); + for (Attachment attachment : attachments) { + boolean attachSaveResult = saveAttachmentEntry(postkey, attachment); + if (!attachSaveResult) + _log.info("Some of the attachments failed to be saved: " + attachment.getName()); + } + return true; + } + else return false; + } + + /** + * {@inheritDoc} + */ + @Override + @Deprecated + public boolean saveAppFeed(Feed post) { + CqlSession session = conn.getKeyspaceSession(); + + List boundStatements = insertIntoPosts(session, feed2post(post)); + //boundStatements.forEach(stmt -> writeBatch.add(stmt)); + //an entry to posts + /*PreparedStatement stmt1 = createPostEntry(session); + writeBatch.add(stmt1.bind(UUID.fromString(post.getKey()), + post.getLinkHost(), + post.getDescription(), + post.getEmail(), + post.getLikesNo()!=null?Long.parseLong(post.getLikesNo()):null, + post.getThumbnailURL(), + post.getLinkDescription(), + post.getTime()!=null?post.getTime().toInstant():null, + post.getUri(), + post.isApplicationFeed(), + post.getEntityId(), + post.getPrivacy()!=null?post.getPrivacy().toString():null, + post.getType()!=null?post.getType().toString():null, + post.getUriThumbnail(), + post.getVreid(), + post.isMultiFileUpload(), + post.getFullName(), + post.getCommentsNo()!=null?Long.parseLong(post.getCommentsNo()):null, + post.getLinkTitle()));*/ + + + //an entry in the Applications Timeline + BoundStatement stmt2 = createAppTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt2); + //an entry in the VRES Timeline iff vreid field is not empty + if (post.getVreid() != null && post.getVreid().compareTo("") != 0){ + BoundStatement stmt3 = createVreTimelineEntry(session).bind(post.getVreid(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt3); + } + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + boolean result = session.execute(writeBatch).wasApplied(); + if (result) + _log.debug("Wrote app post with id " + post.getKey()); + + return result; + } + /** + * {@inheritDoc} + */ + @Override + public boolean saveAppPost(Post post) { + CqlSession session = conn.getKeyspaceSession(); + + List boundStatements = insertIntoPosts(session, post); + //boundStatements.forEach(stmt -> writeBatch.add(stmt)); + //an entry to posts + /*PreparedStatement stmt1 = createPostEntry(session); + writeBatch.add(stmt1.bind(UUID.fromString(post.getKey()), + post.getLinkHost(), + post.getDescription(), + post.getEmail(), + post.getLikesNo()!=null?Long.parseLong(post.getLikesNo()):null, + post.getThumbnailURL(), + post.getLinkDescription(), + post.getTime()!=null?post.getTime().toInstant():null, + post.getUri(), + post.isApplicationFeed(), + post.getEntityId(), + post.getPrivacy()!=null?post.getPrivacy().toString():null, + post.getType()!=null?post.getType().toString():null, + post.getUriThumbnail(), + post.getVreid(), + post.isMultiFileUpload(), + post.getFullName(), + post.getCommentsNo()!=null?Long.parseLong(post.getCommentsNo()):null, + post.getLinkTitle()));*/ + + + //an entry in the Applications Timeline + BoundStatement stmt2 = createAppTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt2); + //an entry in the VRES Timeline iff vreid field is not empty + if (post.getVreid() != null && post.getVreid().compareTo("") != 0){ + BoundStatement stmt3 = createVreTimelineEntry(session).bind(post.getVreid(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + boundStatements.add(stmt3); + } + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + boolean result = session.execute(writeBatch).wasApplied(); + if (result) + _log.debug("Wrote app post with id " + post.getKey()); + + return result; + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public boolean saveAppFeed(Feed feed, List attachments) { + if (attachments != null && !attachments.isEmpty()) + feed.setMultiFileUpload(true); + boolean saveFeedResult = saveAppFeed(feed); + if (saveFeedResult) { + String feedKey = feed.getKey(); + for (Attachment attachment : attachments) { + boolean attachSaveResult = saveAttachmentEntry(feedKey, attachment); + if (!attachSaveResult) + _log.warn("Some of the attachments failed to me saved: " + attachment.getName()); + } + return true; + } + else return false; + } + /** + * {@inheritDoc} + */ + @Override + public boolean saveAppPost(Post post, List attachments) { + if (attachments != null && !attachments.isEmpty()) + post.setMultiFileUpload(true); + boolean saveFeedResult = saveAppPost(post); + if (saveFeedResult) { + String feedKey = post.getKey(); + for (Attachment attachment : attachments) { + boolean attachSaveResult = saveAttachmentEntry(feedKey, attachment); + if (!attachSaveResult) + _log.warn("Some of the attachments failed to be saved: " + attachment.getName()); + } + return true; + } + else return false; + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public boolean saveFeedToVRETimeline(String feedKey, String vreid) throws FeedIDNotFoundException { + Feed toCheck; + try { + toCheck = readFeed(feedKey); + if (toCheck == null) + throw new FeedIDNotFoundException("Could not find Post with id " + feedKey, feedKey); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add( + createVreTimelineEntry(session).bind(vreid, toCheck.getTime().toInstant(), UUID.fromString(toCheck.getKey()))); + + try{ + boolean res = session.execute(writeBatch).wasApplied(); + + return res; + }catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * {@inheritDoc} + */ + @Override + public boolean savePostToVRETimeline(String postKey, String vreid) throws FeedIDNotFoundException { + Post toCheck; + try { + toCheck = readPost(postKey); + if (toCheck == null) + throw new FeedIDNotFoundException("Could not find Post with id " + postKey, postKey); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(createVreTimelineEntry(session).bind(vreid, toCheck.getTime().toInstant(), UUID.fromString(toCheck.getKey()))); + + try{ + boolean res = session.execute(writeBatch).wasApplied(); + + return res; + }catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public Feed readFeed(String feedid) + throws PrivacyLevelTypeNotFoundException, + FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { + CqlSession session = conn.getKeyspaceSession(); + Feed post; + try{ + post = findFeedById(feedid, session).get(); + + } catch (Exception e){ + e.printStackTrace(); + + return null; + } + return post; + } + /** + * {@inheritDoc} + */ + @Override + public Post readPost(String postid) + throws PrivacyLevelTypeNotFoundException, + FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { + CqlSession session = conn.getKeyspaceSession(); + Post post; + try{ + post = findPostById(postid, session).get(); + + } catch (Exception e){ + e.printStackTrace(); + + return null; + } + return post; + } + /** + * {@inheritDoc} + */ + @Override + @Deprecated + public List getRecentFeedsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException { + Date now = new Date(); + if (timeInMillis > now.getTime()) + throw new IllegalArgumentException("the timeInMillis must be before today"); + + ResultSet result = null; + try { + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_TIMELINE_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e) { + e.printStackTrace(); + } + ListtoReturn = new ArrayList<>(); + Listrows=result.all(); + for (Row row: rows){ + Instant postTime = row.getInstant(TIMESTAMP); + if (Date.from(postTime).getTime() > timeInMillis){ + try{ + Feed toCheck = readFeed(row.getUuid(POST_ID).toString()); + if (toCheck.getType() != FeedType.DISABLED) + toReturn.add(toCheck); + } catch (ColumnNameNotFoundException | PrivacyLevelTypeNotFoundException | FeedTypeNotFoundException | + FeedIDNotFoundException e) { + throw new RuntimeException(e); + } + } + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getRecentPostsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException { + Date now = new Date(); + if (timeInMillis > now.getTime()) + throw new IllegalArgumentException("the timeInMillis must be before today"); + + ResultSet result = null; + try { + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_TIMELINE_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e) { + e.printStackTrace(); + } + Listrows = result.all(); + List toReturn = new ArrayList<>(); + for (Row row: rows){ + Instant postTime = row.getInstant(TIMESTAMP); + if (Date.from(postTime).getTime() > timeInMillis){ + try{ + Post toCheck = readPost(row.getUuid(POST_ID).toString()); + if (toCheck.getType() != PostType.DISABLED) + toReturn.add(toCheck); + } catch (ColumnNameNotFoundException | PrivacyLevelTypeNotFoundException | FeedIDNotFoundException | + FeedTypeNotFoundException e) { + throw new RuntimeException(e); + } + } + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public boolean deleteFeed(String feedId) throws FeedIDNotFoundException, PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException { + Feed toDelete = readFeed(feedId); + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updatePostEntry(session, TYPE).bind(FeedType.DISABLED.toString(), UUID.fromString(toDelete.getKey()))); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + _log.error("Delete Post ERROR for postid " + feedId); + + return false; + } + _log.debug("Delete Post OK"); + return true; + } + /** + * {@inheritDoc} + */ + @Override + public boolean deletePost(String postid) throws FeedIDNotFoundException, PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException { + Post toDelete = readPost(postid); + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updatePostEntry(session, TYPE).bind(PostType.DISABLED.toString(), UUID.fromString(toDelete.getKey()))); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + _log.error("Delete Post ERROR for postid " + postid); + + return false; + } + _log.debug("Delete Post OK"); + return true; + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public List getAllFeedsByUser(String userid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + return getFeedsByIds(getUserFeedIds(userid)); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllPostsByUser(String userid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + return getPostsByIds(getUserPostIds(userid)); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllFeedsByApp(String appid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + return getFeedsByIds(getAppFeedIds(appid)); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllPostsByApp(String appid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + return getPostsByIds(getAppPostIds(appid)); + } + /** + * {@inheritDoc} + * @throws Exception + */ + @Deprecated + @Override + public List getRecentCommentedFeedsByUserAndDate(String userid, + long timeInMillis) throws Exception { + + List toReturn = new ArrayList(); + + 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 last comments by the user (it is not needed to get them sorted) + List lastComments = getRecentCommentsByUserAndDateBody(userid, timeInMillis, false); + + // evaluate unique feeds' ids + HashSet postIds = new HashSet(); + + for (Comment comment : lastComments) { + String postId = comment.getFeedid(); + try{ + if(!postIds.contains(postId)){ + postIds.add(postId); + toReturn.add(readFeed(postId)); + } + }catch(Exception e){ + _log.error("Unable to retrieve feed with id " + postId, e); + } + } + + Collections.sort(toReturn, Collections.reverseOrder()); + return toReturn; + } + /** + * {@inheritDoc} + * @throws Exception + */ + @Override + public List getRecentCommentedPostsByUserAndDate(String userid, + long timeInMillis) throws Exception { + + List toReturn = new ArrayList(); + + 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 last comments by the user (it is not needed to get them sorted) + List lastComments = getRecentCommentsByUserAndDateBody(userid, timeInMillis, false); + + // evaluate unique feeds' ids + HashSet postIds = new HashSet(); + + for (Comment comment : lastComments) { + String postId = comment.getFeedid(); + try{ + if(!postIds.contains(postId)){ + postIds.add(postId); + toReturn.add(readPost(postId)); + } + }catch(Exception e){ + _log.error("Unable to retrieve feed with id " + postId, e); + } + } + + Collections.sort(toReturn, Collections.reverseOrder()); + return toReturn; + } + /** + * @deprecated + * helper method that retrieve all the feeds belongin to a list of Ids + * @param feedIds + * @return + * @throws ColumnNameNotFoundException + * @throws FeedIDNotFoundException + * @throws FeedTypeNotFoundException + * @throws PrivacyLevelTypeNotFoundException + */ + private List getFeedsByIds(List feedIds) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { + ArrayList toReturn = new ArrayList(); + for (String feedid : feedIds) { + Feed toAdd = readFeed(feedid); + if (toAdd.getType() == FeedType.TWEET || toAdd.getType() == FeedType.SHARE || toAdd.getType() == FeedType.PUBLISH) + toReturn.add(toAdd); + } + return toReturn; + } + /** + * helper method that retrieve all the feeds belongin to a list of Ids + * @param postIds + * @return + * @throws ColumnNameNotFoundException + * @throws FeedIDNotFoundException + * @throws FeedTypeNotFoundException + * @throws PrivacyLevelTypeNotFoundException + */ + private List getPostsByIds(List postIds) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { + ArrayList toReturn = new ArrayList(); + for (String feedid : postIds) { + Post toAdd = readPost(feedid); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) + toReturn.add(toAdd); + } + return toReturn; + } + /** + * helper method that retrieve all the feed Ids belonging to a user + * @param userid user identifier + * @return simply return a list of user feed UUID in chronological order from the oldest to the more recent + */ + @Deprecated + private ArrayList getUserFeedIds(String userid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_TIMELINE_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + Listrows = result.all(); + ListtoReturn = new ArrayList<>(); + for (Row row: rows){ + try { + String postid = row.getUuid(POST_ID).toString(); + toReturn.add(postid); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + } + return (ArrayList) toReturn; + } + /** + * helper method that retrieve all the post Ids belonging to a user + * @param userid user identifier + * @return simply return a list of user post UUID in chronological order from the oldest to the more recent + */ + private ArrayList getUserPostIds(String userid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_TIMELINE_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + ArrayList toReturn = new ArrayList<>(); + Listrows = result.all(); + for(Row row: rows){ + try { + String postid = row.getUuid(POST_ID).toString(); + toReturn.add(postid); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + } + return toReturn; + } + + /** + * helper method that return whether the user + * @param userid user identifier + * @param postid the feed identifier + * @return true if the feed id liked already + */ + private boolean isPostLiked(String userid, String postid) { + + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_LIKED_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + Listrows = result.all(); + for (Row row: rows){ + if (row.getUuid(POST_ID).toString().equals(postid)){ + return true; + } + } + + return false; + } + + + /** + * helper method that retrieve all the feed Ids belonging to an application + * @param appid application identifier + * @return simply return a list of app feed UUID in chronological order from the oldest to the more recent + */ + @Deprecated + private ArrayList getAppFeedIds(String appid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(APP_TIMELINE_POSTS).all() + .whereColumn(APP_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(appid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + Listrows=result.all(); + ArrayList toReturn=new ArrayList<>(); + for(Row row: rows){ + try { + String postid = row.getUuid(POST_ID).toString(); + toReturn.add(postid); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + } + + + return toReturn; + } + /** + * helper method that retrieve all the post Ids belonging to an application + * @param appid application identifier + * @return simply return a list of app post UUID in chronological order from the oldest to the more recent + */ + private ArrayList getAppPostIds(String appid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(APP_TIMELINE_POSTS).all() + .whereColumn(APP_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(appid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + Listrows=result.all(); + ArrayList toReturn=new ArrayList<>(); + for(Row row: rows){ + try { + String postid = row.getUuid(POST_ID).toString(); + toReturn.add(postid); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + } + + + return toReturn; + } + + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public List getAllPortalPrivacyLevelFeeds() throws FeedTypeNotFoundException, ColumnNameNotFoundException, PrivacyLevelTypeNotFoundException { + //possible error index + ArrayList toReturn = new ArrayList(); + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(POSTS).all() + .whereColumn(PRIVACY).isEqualTo(QueryBuilder.bindMarker()) + .limit(20) + .build()); + try { + result = session.execute(stmtFind.bind(PrivacyLevel.PORTAL.toString())); + + } catch (Exception e){ + e.printStackTrace(); + + } + Listrows=result.all(); + for (Row row: rows) { + Feed toAdd = readFeedFromRow(row); + if (toAdd.getType() == FeedType.TWEET || toAdd.getType() == FeedType.SHARE || toAdd.getType() == FeedType.PUBLISH) + toReturn.add(toAdd); + } + return toReturn; + } + @Override + public List getAllPortalPrivacyLevelPosts() throws FeedTypeNotFoundException, ColumnNameNotFoundException, PrivacyLevelTypeNotFoundException { + //possible error index + ArrayList toReturn = new ArrayList(); + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(POSTS).all() + .whereColumn(PRIVACY).isEqualTo(QueryBuilder.bindMarker()) + .limit(20) + .build()); + try { + result = session.execute(stmtFind.bind(PrivacyLevel.PORTAL.toString())); + + } catch (Exception e){ + e.printStackTrace(); + + } + Listrows=result.all(); + for (Row row: rows) { + Post toAdd = readPostFromRow(row); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) + toReturn.add(toAdd); + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + @Deprecated + public List getRecentFeedsByUser(String userid, int quantity) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList feedIDs = getUserFeedIds(userid); + //check if quantity is greater than user feeds + quantity = (quantity > feedIDs.size()) ? feedIDs.size() : quantity; + + //need them in reverse order + for (int i = feedIDs.size()-1; i >= (feedIDs.size()-quantity); i--) { + Feed toAdd = readFeed(feedIDs.get(i)); + if (toAdd.getType() == FeedType.TWEET || toAdd.getType() == FeedType.SHARE || toAdd.getType() == FeedType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent feed: " + feedIDs.get(i)); + } else { + _log.trace("Read and skipped feed: " + feedIDs.get(i) + " (Removed Feed)"); + quantity += 1; //increase the quantity in case of removed feed + //check if quantity is greater than user feeds + quantity = (quantity > feedIDs.size()) ? feedIDs.size() : quantity; + } + } + return toReturn; + } + @Override + public List getRecentPostsByUser(String userid, int quantity) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList postIDs = getUserPostIds(userid); + //check if quantity is greater than user feeds + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + + //need them in reverse order + for (int i = postIDs.size()-1; i >= (postIDs.size()-quantity); i--) { + Post toAdd = readPost(postIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent post: " + postIDs.get(i)); + } else { + _log.trace("Read and skipped post: " + postIDs.get(i) + " (Removed Post)"); + quantity += 1; //increase the quantity in case of removed post + //check if quantity is greater than user feeds + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + } + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + @Deprecated + public List getAllFeedsByVRE(String vreid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + return getFeedsByIds(getVREFeedIds(vreid)); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllPostsByVRE(String vreid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + return getPostsByIds(getVREPostIds(vreid)); + } + /** + * {@inheritDoc} + */ + @Deprecated + @Override + public List getRecentFeedsByVRE(String vreid, int quantity) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList feedIDs = getVREFeedIds(vreid); + //check if quantity is greater than user feeds + quantity = (quantity > feedIDs.size()) ? feedIDs.size() : quantity; + + //need them in reverse order + for (int i = feedIDs.size()-1; i >= (feedIDs.size()-quantity); i--) { + Feed toAdd = readFeed(feedIDs.get(i)); + if (toAdd.getType() == FeedType.TWEET || toAdd.getType() == FeedType.SHARE || toAdd.getType() == FeedType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent feed: " + feedIDs.get(i)); + } else { + _log.trace("Read and skipped feed: " + feedIDs.get(i) + " (Removed Feed) ."); + quantity += 1; //increase the quantity in case of removed feed + //check if quantity is greater than user feeds + quantity = (quantity > feedIDs.size()) ? feedIDs.size() : quantity; + } + } + return toReturn; + } + @Override + public List getRecentPostsByVRE(String vreid, int quantity) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList postIDs = getVREPostIds(vreid); + //check if quantity is greater than user posts + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + + //need them in reverse order + for (int i = postIDs.size()-1; i >= (postIDs.size()-quantity); i--) { + Post toAdd = readPost(postIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent Post: " + postIDs.get(i)); + } else { + _log.trace("Read and skipped Post: " + postIDs.get(i) + " (Removed Post) ."); + quantity += 1; //increase the quantity in case of removed Post + //check if quantity is greater than user Posts + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + } + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public RangeFeeds getRecentFeedsByVREAndRange(String vreid, int from, int quantity) throws IllegalArgumentException, PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + if (from < 1) { + throw new IllegalArgumentException("From must be greather than 0"); + } + ArrayList feedsToReturn = new ArrayList(); + ArrayList feedIDs = getVREFeedIds(vreid); + + //if from is greater than feeds size return empty + if (from >= feedIDs.size()) { + _log.warn("The starting point of the range is greather than the total number of feeds for this timeline: " + from + " >= " + feedIDs.size()); + return new RangeFeeds(); + } + + int rangeStart = feedIDs.size()-from; + int rangeEnd = rangeStart-quantity; + + //check that you reached the end + if (rangeEnd<1) + rangeEnd = 0; + + _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); + //need them in reverse order + int howMany = from; + for (int i = rangeStart; i > rangeEnd; i--) { + Feed toAdd = readFeed(feedIDs.get(i)); + if (toAdd.getType() == FeedType.TWEET || toAdd.getType() == FeedType.SHARE || toAdd.getType() == FeedType.PUBLISH) { + feedsToReturn.add(toAdd); + _log.trace("Read recent post, i=" + i + " id= " + feedIDs.get(i)); + } else { + _log.trace("Read and skipped post, i=" + i + " id=: " + feedIDs.get(i) + " (Removed post) ."); + rangeEnd -= 1; //increase the upTo in case of removed feed + //check if quantity is greater than user feeds + rangeEnd = (rangeEnd > 0) ? rangeEnd : 0; + } + howMany++; + } + _log.debug("AFTER: starting Point==" + rangeStart + " rangeEnd= " + rangeEnd); + return new RangeFeeds(howMany+1, feedsToReturn); + } + /** + * {@inheritDoc} + */ + @Override + public RangePosts getRecentPostsByVREAndRange(String vreid, int from, int quantity) throws IllegalArgumentException, PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + if (from < 1) { + throw new IllegalArgumentException("From must be greather than 0"); + } + ArrayList feedsToReturn = new ArrayList(); + ArrayList feedIDs = getVREPostIds(vreid); + + //if from is greater than feeds size return empty + if (from >= feedIDs.size()) { + _log.warn("The starting point of the range is greather than the total number of feeds for this timeline: " + from + " >= " + feedIDs.size()); + return new RangePosts(); + } + + int rangeStart = feedIDs.size()-from; + int rangeEnd = rangeStart-quantity; + + //check that you reached the end + if (rangeEnd<1) + rangeEnd = 0; + + _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); + //need them in reverse order + int howMany = from; + for (int i = rangeStart; i > rangeEnd; i--) { + Post toAdd = readPost(feedIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + feedsToReturn.add(toAdd); + _log.trace("Read recent post, i=" + i + " id= " + feedIDs.get(i)); + } else { + _log.trace("Read and skipped post, i=" + i + " id=: " + feedIDs.get(i) + " (Removed post) ."); + rangeEnd -= 1; //increase the upTo in case of removed feed + //check if quantity is greater than user feeds + rangeEnd = (rangeEnd > 0) ? rangeEnd : 0; + } + howMany++; + } + _log.debug("AFTER: starting Point==" + rangeStart + " rangeEnd= " + rangeEnd); + return new RangePosts(howMany+1, feedsToReturn); + } + /** + * @deprecated + * get a list of user vre feed UUIDs in chronological order from the oldest to the more recent + * @param vreid vreid identifier (scope) + * @return simply return a list of user vre feed UUIDs in chronological order from the oldest to the more recent + */ + private ArrayList getVREFeedIds(String vreid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(VRE_TIMELINE_POSTS).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + Listrows=result.all(); + ArrayList toReturn=new ArrayList<>(); + for(Row row: rows){ + try { + String postid = row.getUuid(POST_ID).toString(); + toReturn.add(postid); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + } + + return toReturn; + } + /** + * get a list of user vre post UUIDs in chronological order from the oldest to the more recent + * @param vreid vreid identifier (scope) + * @return simply return a list of user vre post UUIDs in chronological order from the oldest to the more recent + */ + private ArrayList getVREPostIds(String vreid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(VRE_TIMELINE_POSTS).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + Listrows=result.all(); + ArrayList toReturn=new ArrayList<>(); + for(Row row: rows){ + try { + String postid = row.getUuid(POST_ID).toString(); + toReturn.add(postid); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + } + + + return toReturn; + } + /* + * + ********************** NOTIFICATIONS *********************** + * + */ + private List insertIntoNotifications(CqlSession session, Notification notification){ + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(TYPE, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SUBJECT_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_FULL_NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt9 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt10 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(IS_READ, QueryBuilder.bindMarker()).build()); + + /* + PreparedStatement prepStmt1 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ TYPE+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ USER_ID+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ SUBJECT_ID+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ TIMESTAMP+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ DESCRIPTION+") values(?, ?)"); + PreparedStatement prepStmt6 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ URI+") values(?, ?)"); + PreparedStatement prepStmt7 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ SENDER_ID+") values(?, ?)"); + PreparedStatement prepStmt8 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ SENDER_FULL_NAME+") values(?, ?)"); + PreparedStatement prepStmt9 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ SENDER_THUMBNAIL_URL+") values(?, ?)"); + PreparedStatement prepStmt10 = session.prepare("INSERT INTO notifications("+NOT_ID+","+ IS_READ+") values(?, ?)"); +*/ + List boundStatements = new ArrayList<>(); + + if(notification.getType()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(notification.getKey()),notification.getType().toString())); + } + + if(notification.getUserid()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(notification.getKey()), notification.getUserid())); + } + + if(notification.getSubjectid()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(notification.getKey()), notification.getSubjectid())); + } + if(notification.getTime()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(notification.getKey()),notification.getTime().toInstant())); + } + if(notification.getDescription()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(notification.getKey()),notification.getDescription())); + }if(notification.getUri()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(notification.getKey()),notification.getUri())); + }if(notification.getSenderid()!=null){ + boundStatements.add(prepStmt7.bind(UUID.fromString(notification.getKey()),notification.getSenderid())); + }if(notification.getSenderFullName()!=null){ + boundStatements.add(prepStmt8.bind(UUID.fromString(notification.getKey()),notification.getSenderFullName())); + }if(notification.getSenderThumbnail()!=null){ + boundStatements.add(prepStmt9.bind(UUID.fromString(notification.getKey()),notification.getSenderThumbnail())); + } + + boundStatements.add(prepStmt10.bind(UUID.fromString(notification.getKey()),notification.isRead())); + + return boundStatements; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean saveNotification(Notification n) { + CqlSession session = conn.getKeyspaceSession(); + + List boundStatements = insertIntoNotifications(session, n); + //boundStatements.forEach(stmt -> writeBatch.add(stmt)); + + /* + //notification entry + PreparedStatement stmt1 = createNotificationEntry(session); + writeBatch.add(stmt1.bind(UUID.fromString(n.getKey()), + n.getType().toString(), + n.getUserid(), + n.getSubjectid(), + n.getTime().toInstant(), + n.getDescription(), + n.getUri(), + n.getSenderid(), + n.getSenderFullName(), + n.getSenderThumbnail(), + n.isRead())); +*/ + + //an entry in the user Notifications Timeline + BoundStatement stmt2 = createUserNotificationsEntry(session).bind(n.getUserid(), n.getTime().toInstant(), UUID.fromString(n.getKey())); + boundStatements.add(stmt2); + + // save key in the unread notifications column family too + BoundStatement stmt3 = createUnreadNotificationEntry(session).bind(n.getUserid(), n.getTime().toInstant(), UUID.fromString(n.getKey())); + boundStatements.add(stmt3); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + try{ + boolean res = session.execute(writeBatch).wasApplied(); + + return res; + }catch (Exception e){ + e.printStackTrace(); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Notification readNotification(String notificationid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { + Notification toReturn = new Notification(); + CqlSession session = conn.getKeyspaceSession(); + try { + toReturn = findNotById(notificationid, session).get(); + + } + catch (Exception e) { + e.printStackTrace(); + + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public boolean setNotificationRead(String notificationidToSet) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { + Notification toSet = readNotification(notificationidToSet); + if (toSet == null) + throw new NotificationIDNotFoundException("The specified notification to set Read with id: " + notificationidToSet + " does not exist"); + + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch() + + //update the entry in notifications + .add(updateNotificationEntry(session,IS_READ).bind(true,UUID.fromString(notificationidToSet))) + + // delete the notification's key from the unread notifications column family + .add(deleteUnreadNotEntry(session).bind(toSet.getUserid(), toSet.getTime().toInstant())); + + // execute the operations + try { + boolean res = session.execute(writeBatch).wasApplied(); + + return res; + } catch (Exception e) { + _log.error("ERROR while setting Notification " + notificationidToSet + " to read."); + return false; + } + } + /** + * + * @param userid user identifier + * @return simply return a list of user notifications UUID in chronological order from the oldest to the more recent + */ + private ArrayList getUserNotificationsIds(String userid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_NOTIFICATIONS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + ArrayList toReturn = new ArrayList(); + + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + toReturn.add(row.getUuid(NOT_ID).toString()); + } + return toReturn; + } + /** + * Return a list of not read notifications by user userid (messages as well as other notifications) + * @param userid user identifier + * @return simply return a list of not read user notifications UUID in chronological order from the oldest to the more recent + */ + private ArrayList getUnreadUserNotificationsIds(String userid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_NOTIFICATIONS_UNREAD).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + ArrayList toReturn = new ArrayList(); + + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + toReturn.add(row.getUuid(NOT_ID).toString()); + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getAllNotificationByUser(String userid, int limit) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList notificationsIDs = getUserNotificationsIds(userid); + //check if quantity is greater than user feeds + limit = (limit > notificationsIDs.size()) ? notificationsIDs.size() : limit; + + //need them in reverse order + for (int i = notificationsIDs.size()-1; i >= (notificationsIDs.size()-limit); i--) { + Notification toAdd = null; + try { + toAdd = readNotification(notificationsIDs.get(i)); + toReturn.add(toAdd); + } catch (NotificationIDNotFoundException e) { + _log.error("Notification not found id=" + notificationsIDs.get(i)); + } + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getUnreadNotificationsByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList notificationsIDs = getUnreadUserNotificationsIds(userid); + + //need them in reverse order + for (int i = notificationsIDs.size()-1; i >= 0; i--) { + try{ + toReturn.add(readNotification(notificationsIDs.get(i))); + }catch(Exception e){ + _log.error("Unable to read notification with key " + notificationsIDs.get(i)); + } + } + + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getRangeNotificationsByUser(String userid,int from, int quantity) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException { + if (from < 1) { + throw new IllegalArgumentException("From must be greather than 0"); + } + ArrayList toReturn = new ArrayList(); + ArrayList notificationsIDs = getUserNotificationsIds(userid); + + //if from is greater than feeds size return empty + if (from >= notificationsIDs.size()) { + _log.warn("The starting point of the range is greather than the total number of feeds for this timeline: " + from + " >= " + notificationsIDs.size()); + return new ArrayList(); + } + + int rangeStart = notificationsIDs.size()-from; + int rangeEnd = rangeStart-quantity; + + //check that you reached the end + if (rangeEnd<1) + rangeEnd = 0; + + _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); + //need them in reverse order + for (int i = rangeStart; i > rangeEnd; i--) { + Notification toAdd = readNotification(notificationsIDs.get(i)); + toReturn.add(toAdd); + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public boolean setAllNotificationReadByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { + + // get the list of unread notifications + ArrayList notificationsIDs = getUnreadUserNotificationsIds(userid); + + for (int i = notificationsIDs.size()-1; i >= 0; i--) { + try{ + + // set to read (and automatically remove from the unread column family) + setNotificationRead(notificationsIDs.get(i)); + + } catch (NotificationIDNotFoundException e) { + _log.error("Could not set read notification with id =" + notificationsIDs.get(i)); + } + } + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean checkUnreadNotifications(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { + + ArrayList unreadNotifications = getUnreadUserNotificationsIds(userid); + + for (int i = unreadNotifications.size() - 1; i >= 0; i--) { + Notification toAdd; + try { + toAdd = readNotification(unreadNotifications.get(i)); + if (toAdd.getType() != NotificationType.MESSAGE) + return true; + } catch (NotificationIDNotFoundException e) { + _log.error("Notification not found with id = " + unreadNotifications.get(i)); + } + } + + return false; + } + /** + * {@inheritDoc} + */ + @Override + public boolean checkUnreadMessagesNotifications(String userid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { + + ArrayList unreadNotifications = getUnreadUserNotificationsIds(userid); + + for (int i = unreadNotifications.size() - 1; i >= 0; i--) { + Notification toAdd; + try { + toAdd = readNotification(unreadNotifications.get(i)); + if (toAdd.getType() == NotificationType.MESSAGE) + return true; + } catch (NotificationIDNotFoundException e) { + _log.error("Notification not found with id = " + unreadNotifications.get(i)); + } + } + + return false; + } + /* + * + ********************** NOTIFICATION SETTINGS *********************** + * + */ + /** + * {@inheritDoc} + */ + @Override + public List getUserNotificationChannels(String userid, NotificationType notificationType) throws NotificationChannelTypeNotFoundException, NotificationTypeNotFoundException { + _log.debug("Asking for Single Notification preference of " + userid + " Type: " + notificationType); + List toReturn = new ArrayList(); + Map userNotPref = getUserNotificationPreferences(userid); + if(userNotPref!=null){ + if(userNotPref.containsKey(notificationType)){ + NotificationChannelType[] toProcess = userNotPref.get(notificationType); + //_log.debug("size of user notification preferences" + toProcess.length); + if (toProcess == null) { + _log.debug("Single Notification preference of " + userid + " Type: " + notificationType + " not existing ... creating default"); + return createNewNotificationType(userid, notificationType); + } + else if (toProcess.length == 0){ + _log.debug("size of user notification preferences " + 0); + return toReturn; + } + else + { + _log.debug("size of user notification preferences " + toProcess.length); + for (int i = 0; i < toProcess.length; i++) { + toReturn.add(toProcess[i]); + } + return toReturn; + } + } + return toReturn; + } + return toReturn; + + } + /** + * called when you add new notification types where the setting does not exist yet + * please note: by default we set all notifications + */ + private List createNewNotificationType(String userid, NotificationType notificationType) { + List toReturn = new ArrayList(); + _log.debug("Create new notification type"); + CqlSession session = conn.getKeyspaceSession(); + + String valueToInsert = ""; + NotificationChannelType[] wpTypes = NotificationChannelType.values(); + + for (int i = 0; i < wpTypes.length; i++) { + valueToInsert += wpTypes[i]; + if (i < wpTypes.length-1) + valueToInsert += ","; + toReturn.add(wpTypes[i]); //add the new added notification type + } + + BatchStatement writeBatch = getBatch().add( + createNotificationPreferenceEntry(session).bind(userid, notificationType.toString(), valueToInsert) + ); + boolean res = false; + try{ + res = session.execute(writeBatch).wasApplied(); + + } catch (Exception e){ + e.printStackTrace(); + + } + + if (res) { + _log.debug("Set New Notification Setting for " + userid + " OK"); + _log.debug("toreturn:" + toReturn.toString()); + return toReturn; + } + _log.debug("empty list"); + return new ArrayList(); //no notification if sth fails + } + /** + * {@inheritDoc} + */ + @Override + public boolean setUserNotificationPreferences(String userid, Map enabledChannels) { + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = new ArrayList<>(); + + for (NotificationType nType : enabledChannels.keySet()) { + String valueToInsert = ""; + _log.debug("Type: " + nType.toString()); + int channelsNo = (enabledChannels.get(nType) != null) ? enabledChannels.get(nType).length : 0; + for (int i = 0; i < channelsNo; i++) { + _log.debug(enabledChannels.get(nType)[i].toString()); + valueToInsert += NotificationChannelType.valueOf(enabledChannels.get(nType)[i].toString()); + if (i < channelsNo-1) + valueToInsert += ","; + } + if (channelsNo == 0) { //in case no channels were selected + valueToInsert = ""; + _log.trace("No Channels selected for " + nType + " by " + userid); + } + + boundStatements.add(createNotificationPreferenceEntry(session).bind(userid, nType.toString(), valueToInsert)); + } + + BatchStatement writeBatch = getBatch().addAll(boundStatements); + boolean overAllresult = session.execute(writeBatch).wasApplied(); + if (overAllresult) + _log.debug("Set Notification Map for " + userid + " OK"); + else + _log.debug("Set Notification Map for " + userid + " FAILED"); + return overAllresult; + } + /** + * {@inheritDoc} + * + * by default Workspace and Calendar Notifications are set to Portal + */ + @Override + public Map getUserNotificationPreferences(String userid) throws NotificationTypeNotFoundException, NotificationChannelTypeNotFoundException { + _log.debug("Asking for Notification preferences of " + userid); + Map toReturn = new HashMap(); + + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_NOTIFICATIONS_PREFERENCES).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + //if there are no settings for this user create an entry and put all of them at true + List results = new ArrayList<>(); + if(result!=null) results = result.all(); + //_log.debug("Result set empty? " + results.isEmpty()); + if (results.isEmpty()) { + _log.debug("Userid " + userid + " settings not found, initiating its preferences..."); + HashMap toCreate = new HashMap(); + + for (int i = 0; i < NotificationType.values().length; i++) { + //TODO: Potential bug in NotificationType for workspace are refactored + //create a map with all notification enabled except for workspace notifications (They start with WP_) it was the only quick way + if (NotificationType.values()[i].toString().startsWith("WP_")) { + NotificationChannelType[] wpTypes = { NotificationChannelType.PORTAL }; + toCreate.put(NotificationType.values()[i], wpTypes); + } + else + toCreate.put(NotificationType.values()[i], NotificationChannelType.values()); + } + setUserNotificationPreferences(userid, toCreate); //commit the map + + return toCreate; + } + else { + _log.debug("Notification preferences Found for " + userid + " : " + results.size()) ; + for (Row row: results){ + String[] channels = row.getString(PREFERENCE).split(","); + //_log.debug("Row : " + row.getString(PREFERENCE)); + if (channels != null && channels.length == 1 && channels[0].toString().equals("") ) { //it is empty, preference is set to no notification at all + //_log.debug("adding CHANNELS NULL: " + getNotificationType(row.getString(TYPE)) + ", " + new NotificationChannelType[0]); + toReturn.put(getNotificationType(row.getString(TYPE)), new NotificationChannelType[0]); + } else { + NotificationChannelType[] toAdd = new NotificationChannelType[channels.length]; + for (int i = 0; i < channels.length; i++) { + if (channels[i].compareTo("") != 0) { + toAdd[i] = (getChannelType(channels[i])); + } + } + //_log.debug("adding channels not null: " + getNotificationType(row.getString(TYPE)) + ", " + toAdd.toString()); + toReturn.put(getNotificationType(row.getString(TYPE)), toAdd); + } + } + } + _log.debug("Returning:"+toReturn.size()); + return toReturn; + } + /* + * + ********************** COMMENTS *********************** + * + */ + private List insertIntoComments(CqlSession session, Comment comment){ + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); + // "INSERT INTO comments("+COMMENT_ID+","+ USER_ID+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ FULL_NAME+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ THUMBNAIL_URL+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(COMMENT, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ COMMENT+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ POST_ID+") values(?, ?)"); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ TIMESTAMP+") values(?, ?)"); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(IS_EDIT, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ TIMESTAMP+") values(?, ?)"); + PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(LAST_EDIT_TIME, QueryBuilder.bindMarker()).build()); + + List boundStatements = new ArrayList<>(); + + if(comment.getUserid()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(comment.getKey()),comment.getUserid())); + } + + if(comment.getFullName()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(comment.getKey()), comment.getFullName())); + } + + if(comment.getThumbnailURL()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(comment.getKey()), comment.getThumbnailURL())); + } + if(comment.getText()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(comment.getKey()),comment.getText())); + } + if(comment.getFeedid()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(comment.getKey()),UUID.fromString(comment.getFeedid()))); + }if(comment.getTime()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(comment.getKey()),comment.getTime().toInstant())); + } + boundStatements.add(prepStmt7.bind(UUID.fromString(comment.getKey()),comment.isEdit())); + + if(comment.getLastEditTime()!=null){ + boundStatements.add(prepStmt8.bind(UUID.fromString(comment.getKey()),comment.getLastEditTime().toInstant())); + } + + return boundStatements; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean addComment(Comment comment) throws FeedIDNotFoundException { + Feed toComment = null; + if (comment == null) + throw new NullArgumentException("Comment must be not null"); + if (comment.getFeedid() == null) + throw new NullArgumentException("Comment feed id must be not null"); + + String postid = comment.getFeedid(); + try { + toComment = readFeed(postid); + if (toComment == null) + throw new FeedIDNotFoundException("Could not find Feed with id " + postid + " to associate this comment", postid); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + _log.debug("Writing comment : {}", comment.toString()); + CqlSession session = conn.getKeyspaceSession(); + + List boundStatements = insertIntoComments(session, comment); + //boundStatements.forEach(stmt->writeBatch.add(stmt)); + + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + try { + ResultSet res = session.execute(writeBatch); + for (ExecutionInfo ex: res.getExecutionInfos()){ + _log.debug("Writing comment result errors: {}", ex.getErrors()); + _log.debug("Writing comment result payload: {}", ex.getIncomingPayload()); + } + _log.debug("Writing comment result executed?: {}", res.wasApplied()); + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + //update the comment count + boolean updateCommentNoResult = updateFeedCommentsCount(toComment, true); + return updateCommentNoResult; + } + /** + * {@inheritDoc} + */ + public Comment readCommentById(String commentId) throws CommentIDNotFoundException { + Comment toReturn = null; + + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(COMMENTS).all() + .whereColumn(COMMENT_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(UUID.fromString(commentId))); + toReturn = readCommentFromRow(result.one()); + if (toReturn==null) { + throw new CommentIDNotFoundException("The requested commentId: " + commentId + " is not existing"); + } + + } catch (Exception e){ + e.printStackTrace(); + } + + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + @Deprecated + public List getAllCommentByFeed(String feedid) { + return getAllCommentByPost(feedid); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllCommentByPost(String postid) { + //possible error index + List toReturn = new ArrayList(); + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare("SELECT * FROM comments WHERE postid=?"); + /*PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(COMMENTS).all() + .where + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) + .build());*/ + try { + result = session.execute(stmtFind.bind(UUID.fromString(postid))); + Listrows=result.all(); + for (Row row : rows) { + Comment toAdd = readCommentFromRow(row); + toReturn.add(toAdd); + } + } catch (Exception e){ + e.printStackTrace(); + + } + + return toReturn; + } + + /** + * {@inheritDoc} + * @throws Exception + */ + @Override + public List getRecentCommentsByUserAndDate(final String userid, + final long timeInMillis) throws Exception { + + final List commentsByUser; + + 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"); + + + commentsByUser = getRecentCommentsByUserAndDateBody(userid, timeInMillis, true); + + return commentsByUser; } + + /** + * Private method that allows also to specify if the returned list must be sorted or not + * @param userid the user id + * @param timeInMillis the initial time to consider + * @param sort a boolean value to specify if the returned list must be sorted (from the most recent to the oldest comment) + * @return a list of comments recently made by the user + */ + private List getRecentCommentsByUserAndDateBody(final String userid, + final long timeInMillis, boolean sort){ + + //possible error + final List commentsByUser = new ArrayList(); + + CqlSession session = conn.getKeyspaceSession(); + + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(COMMENTS) + .all() + .build()); + try { + result = session.execute(stmtFind.bind()); + + List results = result.all(); + if (!results.isEmpty()){ + results.parallelStream().forEach( row->{ + if(row.getString(USER_ID).equals(userid)){ + try{ + Comment c = readCommentById(row.getUuid(COMMENT_ID).toString()); + Post p = readPost(c.getFeedid()); + if(c.getTime().getTime() >= timeInMillis && + (p.getType() == PostType.TWEET || p.getType() == PostType.SHARE || p.getType() == PostType.PUBLISH)) + commentsByUser.add(c); + }catch(Exception e){ + _log.error("Unable to read comment with id" + row.getString(COMMENT_ID), e); + } + } + } + ); + } + } catch (Exception e){ + e.printStackTrace(); + + } + + if(sort) + Collections.sort(commentsByUser, Collections.reverseOrder()); + return commentsByUser; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean editComment(Comment comment2Edit) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, FeedIDNotFoundException { + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updateCommentEntry(session, COMMENT).bind(comment2Edit.getText(), UUID.fromString(comment2Edit.getKey()))) + .add(updateCommentEntry(session, IS_EDIT).bind(true, UUID.fromString(comment2Edit.getKey()))) + .add(updateCommentEntry(session, LAST_EDIT_TIME).bind(new Date().toInstant(), UUID.fromString(comment2Edit.getKey()))); + + try { + boolean res = session.execute(writeBatch).wasApplied(); + + _log.debug("Comments update OK to: " + comment2Edit.getText()); + return res; + } catch (Exception e) { + + _log.error("Comments update NOT OK "); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deleteComment(String commentid, String feedid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, FeedIDNotFoundException { + Feed toUpdate = readFeed(feedid); + boolean updateCommentNoResult = false; + + updateCommentNoResult = updateFeedCommentsCount(toUpdate, false); + if (updateCommentNoResult) { + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(deleteCommentEntry(session).bind(UUID.fromString(commentid))); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + + _log.error("Comment Delete FAILED for " + commentid + " from Feed " + feedid); + e.printStackTrace(); + } + _log.trace("Comment Deleted " + commentid + " from Feed " + feedid); + } + + + return updateCommentNoResult; + } + + private List insertIntoLikes(CqlSession session, Like like){ + + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); + // "INSERT INTO comments("+COMMENT_ID+","+ USER_ID+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ FULL_NAME+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ THUMBNAIL_URL+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ POST_ID+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + //"INSERT INTO comments("+COMMENT_ID+","+ TIMESTAMP+") values(?, ?)"); + + + /*PreparedStatement prepStmt1 = session.prepare("INSERT INTO likes("+LIKE_ID+","+ USER_ID+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare("INSERT INTO likes("+LIKE_ID+","+ FULL_NAME+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare("INSERT INTO likes("+LIKE_ID+","+ THUMBNAIL_URL+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare("INSERT INTO likes("+LIKE_ID+","+ POST_ID+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare("INSERT INTO likes("+LIKE_ID+","+ TIMESTAMP+") values(?, ?)"); + */ + List boundStatements = new ArrayList<>(); + + if(like.getUserid()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(like.getKey()),like.getUserid())); + } + + if(like.getFullName()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(like.getKey()), like.getFullName())); + } + + if(like.getThumbnailURL()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(like.getKey()), like.getThumbnailURL())); + } + + if(like.getFeedid()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(like.getKey()),UUID.fromString(like.getFeedid()))); + }if(like.getTime()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(like.getKey()),like.getTime().toInstant())); + } + + return boundStatements; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean like(Like like) throws FeedIDNotFoundException { + Feed toLike = null; + if (like == null) + throw new NullArgumentException("Like must be not null"); + if (like.getFeedid() == null) + throw new NullArgumentException("Like feed id must be not null"); + + String feedId = like.getFeedid(); + try { + toLike = readFeed(feedId); + if (toLike == null) + throw new FeedIDNotFoundException("Could not find Feed with id " + feedId + " to associate this like", feedId); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + if (isPostLiked(like.getUserid(), feedId)) { + _log.debug("User " + like.getUserid() + " already liked Feed " + feedId); + return true; + } + else { + CqlSession session = conn.getKeyspaceSession(); + // Inserting data + //an entry in the feed CF + //and an entry in the UserLikesCF + List boundStatements = insertIntoLikes(session,like); + BoundStatement stmt2 = createNewUserLikesEntry(session).bind(like.getUserid(), UUID.fromString(like.getKey()), UUID.fromString(like.getFeedid())); + boundStatements.add(stmt2); + + //boundStatements.forEach(stmt->writeBatch.add(stmt)); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return updateFeedLikesCount(toLike, true); + } + } + /** + * {@inheritDoc} + */ + @Override + public boolean unlike(String userid, String likeid, String feedid) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, LikeIDNotFoundException, FeedIDNotFoundException { + Feed toUpdate = readFeed(feedid); + boolean updateLikeNoResult = false; + + updateLikeNoResult = updateFeedLikesCount(toUpdate, false); //this remove 1 from the Feed CF LikeNO + if (updateLikeNoResult) { + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(deleteLikeEntry(session).bind(UUID.fromString(likeid))) + .add(deleteUserLikeEntry(session).bind(userid, UUID.fromString(likeid))); + try { + session.execute(writeBatch); + + } catch (Exception e) { + + _log.error("Like Delete FAILED for " + likeid + " from Feed " + feedid); + e.printStackTrace(); + } + _log.trace("Unlike ok for " + likeid + " from Feed " + feedid); + } + return updateLikeNoResult; + + } + /** + * {@inheritDoc} + */ + @Override + @Deprecated + public List getAllLikedFeedIdsByUser(String userid) { + return getAllLikedPostIdsByUser(userid); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllLikedPostIdsByUser(String userid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_LIKED_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + ArrayList toReturn = new ArrayList(); + for (Row row: result){ + toReturn.add(row.getUuid(POST_ID).toString()); + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getAllLikedFeedsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + ArrayList toReturn = new ArrayList<>(); + List likedPostIDs = getAllLikedPostIdsByUser(userid); + + //check if quantity is greater than user feeds + limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; + + //need them in reverse order + for (int i = likedPostIDs.size()-1; i >= (likedPostIDs.size()-limit); i--) { + Feed toAdd = readFeed(likedPostIDs.get(i)); + if (toAdd.getType() == FeedType.TWEET || toAdd.getType() == FeedType.SHARE || toAdd.getType() == FeedType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent post: " + likedPostIDs.get(i)); + } else { + _log.trace("Read and skipped post: " + likedPostIDs.get(i) + " (Removed post)"); + limit += 1; //increase the quantity in case of removed feed + //check if quantity is greater than user feeds + limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; + } + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getAllLikedPostsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, ColumnNameNotFoundException, FeedIDNotFoundException { + ArrayList toReturn = new ArrayList(); + List likedPostIDs = getAllLikedPostIdsByUser(userid); + + //check if quantity is greater than user feeds + limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; + + //need them in reverse order + for (int i = likedPostIDs.size()-1; i >= (likedPostIDs.size()-limit); i--) { + Post toAdd = readPost(likedPostIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent post: " + likedPostIDs.get(i)); + } else { + _log.trace("Read and skipped post: " + likedPostIDs.get(i) + " (Removed post)"); + limit += 1; //increase the quantity in case of removed feed + //check if quantity is greater than user feeds + limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; + } + } + return toReturn; + } + + /** + * {@inheritDoc} + */ + @Override + public List getRecentLikedFeedsByUserAndDate(String userid, + long timeInMillis) throws IllegalArgumentException { + + List toReturn = new ArrayList<>(); + + 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 likedPostsIdsByUser = getAllLikedFeedIdsByUser(userid); + + if(likedPostsIdsByUser != null && !likedPostsIdsByUser.isEmpty()){ + for(int i = likedPostsIdsByUser.size() - 1; i >= 0; i--){ + String postid = likedPostsIdsByUser.get(i); + try{ + + // retrieve the Post + Feed toCheck = readFeed(postid); + boolean isPostOk = (toCheck.getType() == FeedType.TWEET || toCheck.getType() == FeedType.SHARE || toCheck.getType() == FeedType.PUBLISH); + + // retrieve the like of the user for the post + if(isPostOk){ + List likes = getAllLikesByFeed(postid); + for (Like like : likes) { + if(like.getTime().getTime() >= timeInMillis && like.getUserid().equals(userid)) + toReturn.add(toCheck); + } + } + + }catch(Exception e){ + _log.error("Skipped post with id " + postid, 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} + */ + @Override + public List getRecentLikedPostsByUserAndDate(String userid, + long timeInMillis) throws IllegalArgumentException { + + List toReturn = new ArrayList<>(); + + 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 likedPostsIdsByUser = getAllLikedPostIdsByUser(userid); + + if(likedPostsIdsByUser != null && !likedPostsIdsByUser.isEmpty()){ + for(int i = likedPostsIdsByUser.size() - 1; i >= 0; i--){ + String postid = likedPostsIdsByUser.get(i); + try{ + + // retrieve the Post + Post toCheck = readPost(postid); + boolean isPostOk = (toCheck.getType() == PostType.TWEET || toCheck.getType() == PostType.SHARE || toCheck.getType() == PostType.PUBLISH); + + // retrieve the like of the user for the post + if(isPostOk){ + List likes = getAllLikesByPost(postid); + for (Like like : likes) { + if(like.getTime().getTime() >= timeInMillis && like.getUserid().equals(userid)) + toReturn.add(toCheck); + } + } + + }catch(Exception e){ + _log.error("Skipped post with id " + postid, 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} + */ + @Deprecated + @Override + public List getAllLikesByFeed(String feedid) { + return getAllLikesByPost(feedid); + } + /** + * {@inheritDoc} + */ + @Override + public List getAllLikesByPost(String postid) { + //possible error index + + List toReturn = new ArrayList(); + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(LIKES).all() + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(UUID.fromString(postid))); + for (Row row: result) { + Like toAdd = readLikeFromRow(row); + toReturn.add(toAdd); + } + + } catch (Exception e){ + e.printStackTrace(); + + } + return toReturn; + } + /* + * + ********************** HASHTAGS *********************** + * + */ + /** + * {@inheritDoc} + */ + @Override + public boolean saveHashTags(String feedid, String vreid, List hashtags) throws FeedIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting data + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstInsert = session.execute((createNewHashtagTimelineEntry(session).bind(lowerCaseHashtag, UUID.fromString(feedid), vreid))).wasApplied(); + boolean 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 deleteHashTags(String feedid, String vreid, List hashtags) throws FeedIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting data + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstDelete = session.execute(deleteHashtagEntry(session).bind(lowerCaseHashtag, UUID.fromString(feedid))).wasApplied(); + boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, false); + if (! (firstDelete && secondInsert)) { + _log.error("deleteHashTags: Could not delete the hashtag(s)"); + + return false; + + } + } + + return true; + } + /** + * {@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 + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstInsert = session.execute(createNewHashtagCommentEntry(session).bind(hashtag, UUID.fromString(commentId), vreid)).wasApplied(); + 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 + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstDelete = session.execute(deleteHashtagCommentEntry(session).bind(lowerCaseHashtag, UUID.fromString(commentId))).wasApplied(); + 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) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(HASHTAGS_COUNTER).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + + HashMap toReturn = new HashMap (); + + List rows = result.all(); + // Iterate rows and their columns + for (Row row : rows) { + Integer curValue = (int) row.getLong(COUNT); + if (curValue > 0) + toReturn.put(row.getString(HASHTAG), curValue); + } + + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public Map getVREHashtagsWithOccurrenceFilteredByTime(String vreid, long timestamp){ + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(HASHTAGS_COUNTER).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + HashMap toReturn = new HashMap (); + List rows = result.all(); + // Iterate rows and their columns + for (Row row : rows) { + // retrieve the feeds list for this hashtag + List feeds = null; + try{ + feeds = getVREPostsByHashtag(vreid, row.getString(HASHTAG)); + }catch(Exception e){ + _log.error("Unable to retrieve the list of feeds for hashtag" + row.getString(HASHTAG) + " in vre " + vreid); + continue; + } + + if(feeds.isEmpty()){ + + _log.debug("There are no feeds containing hashtag " + row.getString(HASHTAG) + " in vre " + vreid); + continue; + + } + + // retrieve the most recent one among these feeds + Collections.sort(feeds, Collections.reverseOrder()); + + if(feeds.get(0).getTime().getTime() < timestamp){ + continue; + } + + // else.. + int curValue = (int) row.getLong(COUNT); + + if (curValue > 0) + toReturn.put(row.getString(HASHTAG), curValue); + } + return toReturn; + } + + /** + * {@inheritDoc} + */ + @Override + public List getVREFeedsByHashtag(String vreid, String hashtag) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { + List toReturn = new ArrayList<>(); + CqlSession session = conn.getKeyspaceSession(); + + ResultSet resultPost = null; + PreparedStatement stmtFind1 = session.prepare(QueryBuilder + .selectFrom(HASHTAGGED_POSTS).all() + .whereColumn(HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + resultPost = session.execute(stmtFind1.bind(hashtag)); + } catch (Exception e){ + e.printStackTrace(); + + } + + PreparedStatement stmtFind2 = session.prepare(QueryBuilder + .selectFrom(HASHTAGGED_COMMENTS).all() + .whereColumn(HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet resultComment = null; + try { + resultComment = session.execute(stmtFind2.bind(hashtag)); + } catch (Exception e){ + e.printStackTrace(); + + } + + Set postIds = new HashSet<>(); + // Iterate rows and their columns (feed) + ListrowsPost=resultPost.all(); + for (Row row : rowsPost) { + if (row.getString(VRE_ID).compareTo(vreid)==0) + postIds.add(row.getUuid(POST_ID).toString()); + } + // Iterate rows and their columns (comments) + ListrowsComment=resultComment.all(); + for (Row row : rowsComment) { + if (row.getString(VRE_ID).compareTo(vreid)==0){ + try { + Comment c = readCommentById(row.getUuid(COMMENT_ID).toString()); + postIds.add(c.getFeedid()); + } catch (CommentIDNotFoundException e) { + _log.warn("Failed to fetch comment with id " + row.getString(COMMENT_ID)); + } + } + } + toReturn = getFeedsByIds(new ArrayList<>(postIds)); + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public List getVREPostsByHashtag(String vreid, String hashtag) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException { + List toReturn = new ArrayList<>(); + CqlSession session = conn.getKeyspaceSession(); + + ResultSet resultPost = null; + PreparedStatement stmtFind1 = session.prepare(QueryBuilder + .selectFrom(HASHTAGGED_POSTS).all() + .whereColumn(HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + resultPost = session.execute(stmtFind1.bind(hashtag)); + } catch (Exception e){ + e.printStackTrace(); + + } + + PreparedStatement stmtFind2 = session.prepare(QueryBuilder + .selectFrom(HASHTAGGED_COMMENTS).all() + .whereColumn(HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet resultComment = null; + try { + resultComment = session.execute(stmtFind2.bind(hashtag)); + } catch (Exception e){ + e.printStackTrace(); + + } + + Set postIds = new HashSet<>(); + // Iterate rows and their columns (feed) + ListrowsPost=resultPost.all(); + for (Row row : rowsPost) { + if (row.getString(VRE_ID).compareTo(vreid)==0) + postIds.add(row.getUuid(POST_ID).toString()); + } + // Iterate rows and their columns (comments) + ListrowsComment=resultComment.all(); + for (Row row : rowsComment) { + if (row.getString(VRE_ID).compareTo(vreid)==0){ + try { + Comment c = readCommentById(row.getUuid(COMMENT_ID).toString()); + postIds.add(c.getFeedid()); + } catch (CommentIDNotFoundException e) { + _log.warn("Failed to fetch comment with id " + row.getString(COMMENT_ID)); + } + } + } + toReturn = getPostsByIds(new ArrayList<>(postIds)); + return toReturn; + } + /* + * + ********************** Invites *********************** + * + */ + private List insertIntoInvites(CqlSession session, Invite invite){ + + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(SENDER_USER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(VRE_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(EMAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(CONTROL_CODE, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(STATUS, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(SENDER_FULL_NAME, QueryBuilder.bindMarker()).build()); + + /*PreparedStatement prepStmt1 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ SENDER_USER_ID+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ VRE_ID+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ EMAIL+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ CONTROL_CODE+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ STATUS+") values(?, ?)"); + PreparedStatement prepStmt6 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ TIMESTAMP+") values(?, ?)"); + PreparedStatement prepStmt7 = session.prepare("INSERT INTO invites("+INVITE_ID+","+ SENDER_FULL_NAME+") values(?, ?)"); +*/ + List boundStatements = new ArrayList<>(); + + if(invite.getSenderUserId()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(invite.getKey()),invite.getSenderUserId())); + } + + if(invite.getVreid()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(invite.getKey()), invite.getVreid())); + } + + if(invite.getInvitedEmail()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(invite.getKey()), invite.getInvitedEmail())); + } + + if(invite.getControlCode()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(invite.getKey()),invite.getControlCode())); + } + if(invite.getStatus()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(invite.getKey()),invite.getStatus().toString())); + } + if(invite.getTime()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(invite.getKey()),invite.getTime().toInstant())); + } + + if(invite.getSenderFullName()!=null){ + boundStatements.add(prepStmt7.bind(UUID.fromString(invite.getKey()),invite.getSenderFullName())); + } + + return boundStatements; + } + + /** + * common part to save a invite + * @param invite + * @return the partial mutation batch instance + */ + private List initSaveInvite(Invite invite, CqlSession session) { + List boundStatements = insertIntoInvites(session, invite); + + + if (invite == null) + throw new NullArgumentException("Invite instance is null"); + //insertIntoInvites(session,invite).forEach(stmt->writeBatch.add(stmt)); + //BatchStatement writeBatch = getBatch().addAll(boundStatements); + // Inserting data + /*writeBatch.add(createNewInviteEntry(session).bind( + UUID.fromString(invite.getKey()), + invite.getSenderUserId(), + invite.getVreid(), + invite.getInvitedEmail(), + invite.getControlCode(), + invite.getStatus().toString(), + invite.getTime().toInstant(), + invite.getSenderFullName() + ));*/ + + + return boundStatements; + } + + /** + * {@inheritDoc} + */ + @Override + public String isExistingInvite(String vreid, String email) { + CqlSession session = conn.getKeyspaceSession(); + + ResultSet result = null; + PreparedStatement stmtFind1 = session.prepare(QueryBuilder + .selectFrom(EMAIL_INVITES).all() + .whereColumn(EMAIL) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind1.bind(email)); + } catch (Exception e){ + e.printStackTrace(); + + } + + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + if (row.getString(VRE_ID).compareTo(vreid)==0) + return row.getUuid(INVITE_ID).toString(); + + } + return null; + } + /** + * {@inheritDoc} + */ + @Override + public InviteOperationResult saveInvite(Invite invite) throws AddressException { + if (invite == null) + throw new NullArgumentException("Invite instance is null"); + String email = invite.getInvitedEmail(); + if (! verifyEmail(email)) + throw new AddressException("Email is not valid ->" + email); + if (invite.getVreid() == null || invite.getVreid().equals("")) + throw new NullArgumentException("VREId is null or empty"); + _log.debug("isExistingInvite? " + invite.getInvitedEmail() + " in " + invite.getVreid()); + if (isExistingInvite(invite.getVreid(), invite.getInvitedEmail()) != null) + return InviteOperationResult.ALREADY_INVITED; + _log.debug("Invite not found, proceed to save it ..."); + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = initSaveInvite(invite, session); + //an entry in the VRE Invites + boundStatements.add(createNewVreInviteEntry(session).bind(invite.getVreid(), UUID.fromString(invite.getKey()), InviteStatus.PENDING.toString())); + //an entry in the EMAIL Invites + boundStatements.add(createNewEmailInviteEntry(session).bind(email, invite.getVreid(), UUID.fromString(invite.getKey()))); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + boolean result = session.execute(writeBatch).wasApplied(); + + return result ? InviteOperationResult.SUCCESS : InviteOperationResult.FAILED; + } + /** + * {@inheritDoc} + */ + @Override + public Invite readInvite(String inviteid) throws InviteIDNotFoundException, InviteStatusNotFoundException { + Invite toReturn = null; + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(INVITES).all() + .whereColumn(INVITE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(UUID.fromString(inviteid))); + toReturn = readAInviteFromRow(result.one()); + if (toReturn == null) { + throw new InviteStatusNotFoundException("The requested inviteid: " + inviteid + " is not existing"); + } + //toReturn = readAInviteFromRow(result.all().get(0)); + + } catch (Exception e){ + e.printStackTrace(); + + } + return toReturn; + } + /** + * helper method that retrieve all the Invites belonging to a list of Ids + * @param inviteIds the lisf of invites UUID + * @return all the invites belonging to a list of Ids + * @throws InviteIDNotFoundException + * @throws InviteStatusNotFoundException + */ + private List getInvitesById(List inviteIds) throws InviteIDNotFoundException, InviteStatusNotFoundException { + ArrayList toReturn = new ArrayList(); + for (String inviteid : inviteIds) + toReturn.add(readInvite(inviteid)); + + return toReturn; + } + /** + * {@inheritDoc} + * @throws InviteStatusNotFoundException + */ + @Override + public boolean setInviteStatus(String vreid, String email, InviteStatus status) throws InviteIDNotFoundException, InviteStatusNotFoundException { + String inviteid = isExistingInvite(vreid, email); + Invite toSet = readInvite(inviteid); + if (toSet == null) + throw new InviteIDNotFoundException("The specified invite to set with id: " + inviteid + " does not exist"); + + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updateInviteEntry(session, STATUS).bind(status.toString(), UUID.fromString(inviteid))) + .add(updateVreInviteEntry(session, STATUS).bind(status.toString(), vreid, UUID.fromString(inviteid))); + try { + session.execute(writeBatch); + + } catch (Exception e) { + _log.error("ERROR while setting Invite " + inviteid + " to " + status.toString()); + + return false; + } + _log.trace("Invite Status Set to " + status.toString() + " OK"); + return true; + } + /** + * {@inheritDoc} + */ + @Override + public List getInvitedEmailsByVRE(String vreid, InviteStatus... status) throws InviteIDNotFoundException, InviteStatusNotFoundException{ + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(VRE_INVITES).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + ArrayList invitesIds = new ArrayList(); + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + if (status != null) { + for (int i = 0; i < status.length; i++) { + if (row.getString(STATUS).compareTo(status[i].toString())==0) + invitesIds.add(row.getUuid(INVITE_ID).toString()); + } + } + else { + invitesIds.add(row.getUuid(INVITE_ID).toString()); + } + } + return getInvitesById(invitesIds); + } + /** + * {@inheritDoc} + */ + @Override + public List getAttachmentsByFeedId(String feedId) throws FeedIDNotFoundException { + //index error + Post toCheck = null; + try { + toCheck = readPost(feedId); + if (toCheck == null) + throw new FeedIDNotFoundException("Could not find Feed with id " + feedId, feedId); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + List toReturn = new ArrayList(); + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(ATTACHMENTS).all() + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet result = null; + try { + result = session.execute(stmtFind.bind(UUID.fromString(feedId))); + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + _log.trace("Reading attachment if feed=" + row.getUuid(POST_ID).toString()); + Attachment toAdd = readAttachmentFromRow(row); + toReturn.add(toAdd); + } + + } catch (Exception e) { + e.printStackTrace(); + + return null; + } + return toReturn; + } + /** + * {@inheritDoc} + */ + @Override + public void closeConnection() { + conn.closeConnection(); + } + /* + * + ********************** Helper methods *********************** + * + */ + private List insertIntoAttachments(CqlSession session, Attachment attachment, String feedId){ + + + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(URI_THUMBNAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(MIME_TYPE, QueryBuilder.bindMarker()).build()); + + /*PreparedStatement prepStmt1 = session.prepare("INSERT INTO attachments("+ATTACH_ID+","+ POST_ID+") values(?, ?)"); + PreparedStatement prepStmt2 = session.prepare("INSERT INTO attachments("+ATTACH_ID+","+ URI+") values(?, ?)"); + PreparedStatement prepStmt3 = session.prepare("INSERT INTO attachments("+ATTACH_ID+","+ NAME+") values(?, ?)"); + PreparedStatement prepStmt4 = session.prepare("INSERT INTO attachments("+ATTACH_ID+","+ DESCRIPTION+") values(?, ?)"); + PreparedStatement prepStmt5 = session.prepare("INSERT INTO attachments("+ATTACH_ID+","+ URI_THUMBNAIL+") values(?, ?)"); + PreparedStatement prepStmt6 = session.prepare("INSERT INTO attachments("+ATTACH_ID+","+ MIME_TYPE+") values(?, ?)"); +*/ + List boundStatements = new ArrayList<>(); + + boundStatements.add(prepStmt1.bind(UUID.fromString(attachment.getId()),UUID.fromString(feedId))); + + + if(attachment.getUri()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(attachment.getId()), attachment.getUri())); + } + + if(attachment.getName()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(attachment.getId()), attachment.getName())); + } + + if(attachment.getDescription()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(attachment.getId()),attachment.getDescription())); + } + if(attachment.getThumbnailURL()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(attachment.getId()),attachment.getThumbnailURL())); + } + if(attachment.getMimeType()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(attachment.getId()),attachment.getMimeType())); + } + + + return boundStatements; + } + /** + * {@inheritDoc} + */ + @Override + public boolean saveAttachmentEntry(String feedId, Attachment toSave) { + // Inserting data + CqlSession session = conn.getKeyspaceSession(); + //an entry in the Attachment CF + try { + List boundStatements = insertIntoAttachments(session, toSave, feedId); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + //boundStatements.forEach(stmt->writeBatch.add(stmt)); + ResultSet res = session.execute(writeBatch); + _log.debug(res.getExecutionInfos().toString()); + _log.debug(""+res.wasApplied()); + /* + session.execute(createNewaAttachEntry(session).bind( + UUID.fromString(toSave.getId()), + UUID.fromString(feedId), + toSave.getUri(), + toSave.getName(), + toSave.getDescription(), + toSave.getThumbnailURL(), + toSave.getMimeType() + ));*/ + + } catch (Exception e) { + + e.printStackTrace(); + return false; + } + return true; + } + + + /** + * simply return an enum representing the privacy level + * @return correct enum representing the privacy level + * @throws NotificationChannelTypeNotFoundException + * @throws FeedTypeNotFoundException + */ + private NotificationChannelType getChannelType(String channelName) throws NotificationChannelTypeNotFoundException { + if (channelName.compareTo("PORTAL") == 0) + return NotificationChannelType.PORTAL; + else if (channelName.compareTo("EMAIL") == 0) + return NotificationChannelType.EMAIL; + else if (channelName.compareTo("TWITTER") == 0) + return NotificationChannelType.TWITTER; + else + throw new NotificationChannelTypeNotFoundException("The Notification Channel Type was not recognized should be one of " + NotificationChannelType.values() + " asked for: " + channelName); + } + + /** + * simply return an enum representing the privacy level + * @param privacyLevel . + * @return correct enum representing the privacy level + * @throws FeedTypeNotFoundException + */ + private static PrivacyLevel getPrivacyLevel(String privacyLevel) throws PrivacyLevelTypeNotFoundException { + if (privacyLevel.compareTo("CONNECTION") == 0) + return PrivacyLevel.CONNECTION; + else if (privacyLevel.compareTo("PRIVATE") == 0) + return PrivacyLevel.PRIVATE; + else if (privacyLevel.compareTo("PUBLIC") == 0) + return PrivacyLevel.PUBLIC; + else if (privacyLevel.compareTo("VRES") == 0) + return PrivacyLevel.VRES; + else if (privacyLevel.compareTo("SINGLE_VRE") == 0) + return PrivacyLevel.SINGLE_VRE; + else if (privacyLevel.compareTo("PORTAL") == 0) + return PrivacyLevel.PORTAL; + else + throw new PrivacyLevelTypeNotFoundException("The Privacy Level was not recognized should be one of " + PrivacyLevel.values() + " asked for: " + privacyLevel); + } + /** + * simply return an enum representing the feed type + * @param type . + * @return correct enum representing the feed type + * @throws FeedTypeNotFoundException . + */ + private static FeedType getFeedType(String type) throws FeedTypeNotFoundException { + if (type.compareTo("TWEET") == 0) { + return FeedType.TWEET; + } + else if (type.compareTo("JOIN") == 0) { + return FeedType.JOIN; + } + else if (type.compareTo("PUBLISH") == 0) { + return FeedType.PUBLISH; + } + else if (type.compareTo("SHARE") == 0) { + return FeedType.SHARE; + } + else if (type.compareTo("ACCOUNTING") == 0) { + return FeedType.ACCOUNTING; + } + else if (type.compareTo("DISABLED") == 0) { + return FeedType.DISABLED; + } + else + throw new FeedTypeNotFoundException("The Feed Type was not recognized should be one of " + FeedType.values() + " asked for: " + type); + } + /** + * simply return an enum representing the feed type + * @param type . + * @return correct enum representing the feed type + * @throws FeedTypeNotFoundException . + */ + private static PostType getPostType(String type) throws FeedTypeNotFoundException { + if (type.compareTo("TWEET") == 0) { + return PostType.TWEET; + } + else if (type.compareTo("JOIN") == 0) { + return PostType.JOIN; + } + else if (type.compareTo("PUBLISH") == 0) { + return PostType.PUBLISH; + } + else if (type.compareTo("SHARE") == 0) { + return PostType.SHARE; + } + else if (type.compareTo("ACCOUNTING") == 0) { + return PostType.ACCOUNTING; + } + else if (type.compareTo("DISABLED") == 0) { + return PostType.DISABLED; + } + else + throw new FeedTypeNotFoundException("The Feed Type was not recognized should be one of " + PostType.values() + " asked for: " + type); + } + + /** + * simply return an enum representing the invite status type + * @param type . + * @return correct enum representing the feed type + * @throws InviteStatusNotFoundException . + */ + private static InviteStatus getInviteStatusType(String type) throws InviteStatusNotFoundException { + switch (type) { + case "PENDING": + return InviteStatus.PENDING; + case "ACCEPTED": + return InviteStatus.ACCEPTED; + case "REJECTED": + return InviteStatus.REJECTED; + case "RETRACTED": + return InviteStatus.RETRACTED; + default: + throw new InviteStatusNotFoundException("The Invite Status was not recognized should be one of " + InviteStatus.values() + " asked for: " + type); + } + + } + + /** + * simply return an enum representing the feed type + * @param type . + * @return correct enum representing the feed type + * @throws NotificationTypeNotFoundException . + */ + private static NotificationType getNotificationType(String type) throws NotificationTypeNotFoundException { + if (type.compareTo("WP_FOLDER_SHARE") == 0) { + return NotificationType.WP_FOLDER_SHARE; + } + else if (type.compareTo("WP_FOLDER_UNSHARE") == 0) { + return NotificationType.WP_FOLDER_UNSHARE; + } + else if (type.compareTo("WP_ADMIN_UPGRADE") == 0) { + return NotificationType.WP_ADMIN_UPGRADE; + } + else if (type.compareTo("WP_ADMIN_DOWNGRADE") == 0) { + return NotificationType.WP_ADMIN_DOWNGRADE; + } + else if (type.compareTo("WP_FOLDER_RENAMED") == 0) { + return NotificationType.WP_FOLDER_RENAMED; + } + else if (type.compareTo("WP_FOLDER_ADDEDUSER") == 0) { + return NotificationType.WP_FOLDER_ADDEDUSER; + } + else if (type.compareTo("WP_FOLDER_REMOVEDUSER") == 0) { + return NotificationType.WP_FOLDER_REMOVEDUSER; + } + else if (type.compareTo("WP_ITEM_DELETE") == 0) { + return NotificationType.WP_ITEM_DELETE; + } + else if (type.compareTo("WP_ITEM_UPDATED") == 0) { + return NotificationType.WP_ITEM_UPDATED; + } + else if (type.compareTo("WP_ITEM_NEW") == 0) { + return NotificationType.WP_ITEM_NEW; + } + else if (type.compareTo("WP_ITEM_RENAMED") == 0) { + return NotificationType.WP_ITEM_RENAMED; + } + else if (type.compareTo("OWN_COMMENT") == 0) { + return NotificationType.OWN_COMMENT; + } + else if (type.compareTo("COMMENT") == 0) { + return NotificationType.COMMENT; + } + else if (type.compareTo("MENTION") == 0) { + return NotificationType.MENTION; + } + else if (type.compareTo("LIKE") == 0) { + return NotificationType.LIKE; + } + else if (type.compareTo("CALENDAR_ADDED_EVENT") == 0) { + return NotificationType.CALENDAR_ADDED_EVENT; + } + else if (type.compareTo("CALENDAR_UPDATED_EVENT") == 0) { + return NotificationType.CALENDAR_UPDATED_EVENT; + } + else if (type.compareTo("CALENDAR_DELETED_EVENT") == 0) { + return NotificationType.CALENDAR_DELETED_EVENT; + } + else if (type.compareTo("CALENDAR_ADDED_EVENT") == 0) { + return NotificationType.CALENDAR_ADDED_EVENT; + } + else if (type.compareTo("CALENDAR_UPDATED_EVENT") == 0) { + return NotificationType.CALENDAR_UPDATED_EVENT; + } + else if (type.compareTo("CALENDAR_DELETED_EVENT") == 0) { + return NotificationType.CALENDAR_DELETED_EVENT; + } + else if (type.compareTo("MESSAGE") == 0) { + return NotificationType.MESSAGE; + } + else if (type.compareTo("POST_ALERT") == 0) { + return NotificationType.POST_ALERT; + } + else if (type.compareTo("REQUEST_CONNECTION") == 0) { + return NotificationType.REQUEST_CONNECTION; + } + else if (type.compareTo("JOB_COMPLETED_NOK") == 0) { + return NotificationType.JOB_COMPLETED_NOK; + } + else if (type.compareTo("JOB_COMPLETED_OK") == 0) { + return NotificationType.JOB_COMPLETED_OK; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_EDIT") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_EDIT; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_VIEW") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_VIEW; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_FORWARD_STEP_COMPLETED_OWNER") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_FORWARD_STEP_COMPLETED_OWNER; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_STEP_FORWARD_PEER") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_STEP_FORWARD_PEER; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_STEP_REQUEST_TASK") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_STEP_REQUEST_TASK; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_USER_FORWARD_TO_OWNER") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_USER_FORWARD_TO_OWNER; + } + else if (type.compareTo("DOCUMENT_WORKFLOW_FIRST_STEP_REQUEST_INVOLVMENT") == 0) { + return NotificationType.DOCUMENT_WORKFLOW_FIRST_STEP_REQUEST_INVOLVMENT; + } + else if (type.compareTo("TDM_TAB_RESOURCE_SHARE") == 0) { + return NotificationType.TDM_TAB_RESOURCE_SHARE; + } + else if (type.compareTo("TDM_RULE_SHARE") == 0) { + return NotificationType.TDM_RULE_SHARE; + } + else if (type.compareTo("TDM_TEMPLATE_SHARE") == 0) { + return NotificationType.TDM_TEMPLATE_SHARE; + } + else if (type.compareTo("CAT_ITEM_SUBMITTED") == 0) { + return NotificationType.CAT_ITEM_SUBMITTED; + } + else if (type.compareTo("CAT_ITEM_REJECTED") == 0) { + return NotificationType.CAT_ITEM_REJECTED; + } + else if (type.compareTo("CAT_ITEM_PUBLISHED") == 0) { + return NotificationType.CAT_ITEM_PUBLISHED; + } + else if (type.compareTo("CAT_ITEM_UPDATED") == 0) { + return NotificationType.CAT_ITEM_UPDATED; + } + else if (type.compareTo("CAT_ITEM_DELETE") == 0) { + return NotificationType.CAT_ITEM_DELETE; + } + else if (type.compareTo("GENERIC") == 0) { + return NotificationType.GENERIC; + } + + else + throw new NotificationTypeNotFoundException("The Notification Type was not recognized should be one of " + NotificationType.values() + " asked for: " + type); + } + /** + * + * @param time in milliseconds + * @return a Date object + */ + private Date getDateFromTimeInMillis(String time) { + Long timeInMillis = Long.parseLong(time); + Calendar toSet = Calendar.getInstance(); + toSet.setTimeInMillis(timeInMillis); + return toSet.getTime(); + } + /** + * update the feed by incrementing or decrementing by (1) the CommentsNo + * used when adding or removing a comment to a feed + * @param toUpdate the feedid + * @param increment set true if you want to add 1, false to subtract 1. + */ + private boolean updateFeedCommentsCount(Feed toUpdate, boolean increment) { + int newCount = 0; + try { + int current = Integer.parseInt(toUpdate.getCommentsNo()); + newCount = increment ? current+1 : current-1; + } + catch (NumberFormatException e) { + _log.error("Comments Number found is not a number: " + toUpdate.getCommentsNo()); + } + CqlSession session = conn.getKeyspaceSession(); + //an entry in the feed CF + try { + session.execute(updatePostEntry(session, COMMENTS_NO).bind((long) newCount, UUID.fromString(toUpdate.getKey()))); + + } catch (Exception e) { + _log.error("CommentsNo update NOT OK "); + + return false; + } + _log.debug("CommentsNo update OK to: " + newCount); + return true; + } + + /** + * update the feed by incrementing or decrementing by (1) the LikesNo + * used when adding or removing a comment to a feed + * @param toUpdate the feedid + * @param increment set true if you want to add 1, false to subtract 1. + */ + private boolean updateFeedLikesCount(Feed toUpdate, boolean increment) { + int newCount = 0; + try { + int current = Integer.parseInt(toUpdate.getLikesNo()); + newCount = increment ? current+1 : current-1; + } + catch (NumberFormatException e) { + _log.error("Likes Number found is not a number: " + toUpdate.getLikesNo()); + } + CqlSession session = conn.getKeyspaceSession(); + //an entry in the feed CF + try { + session.execute(updatePostEntry(session, LIKES_NO).bind((long)newCount, UUID.fromString(toUpdate.getKey()))); + + } catch (Exception e) { + _log.error("LikesNo update NOT OK "); + + return false; + } + _log.debug("LikesNo update OK to: " + newCount); + return true; + } + + /** + * update the hashtag count by incrementing or decrementing it by (1) + * used when adding or removing a hashtag in a feed + * @param vreid the vreid + * @param hashtag the hashtag + * @param increment set true if you want to add 1, false to subtract 1. + */ + private boolean updateVREHashtagCount(String vreid, String hashtag, boolean increment) { + Map vreHashtags = getVREHashtagsWithOccurrence(vreid); + //if the hashtag not yet exist + int newCount = 0; + + if (!vreHashtags.containsKey(hashtag)) { + newCount = 1; + } + else { + try { + int current = vreHashtags.get(hashtag); + newCount = increment ? current+1 : current-1; + } + catch (NumberFormatException e) { + _log.error("Hashtag Number found is not a number: " + newCount); + } + } + _log.debug("Updating counter for " + hashtag + " to " + newCount); + CqlSession session = conn.getKeyspaceSession(); + BoundStatement stmt; + + if (existRecordbyCompId(session, HASHTAG, VRE_ID, hashtag, vreid, HASHTAGS_COUNTER)){ + stmt = session.prepare(QueryBuilder.update(HASHTAGS_COUNTER) + .setColumn(COUNT, QueryBuilder.bindMarker()) + .whereColumn(HASHTAG).isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(VRE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()).bind((long)newCount, hashtag, vreid); + } + else{ + stmt = createNewUHashtagCounterEntry(session).bind(vreid, hashtag, (long)newCount); + } + BatchStatement writeBatch = getBatch().add(stmt); + try { + session.execute(writeBatch); + + } catch (Exception e) { + _log.error("Hashtag Count update NOT OK "); + + return false; + } + _log.debug("Hashtag Count update OK to: " + newCount); + return true; + } + /** + * verify an email address + * @param email + * @return true or false + */ + private boolean verifyEmail(String email) { + boolean isValid = false; + try { + InternetAddress internetAddress = new InternetAddress(email); + internetAddress.validate(); + isValid = true; + } catch (AddressException e) { + _log.error("Validation Exception Occurred for email: " + email); + } + return isValid; + } + + + @Override + public List getAllVREIds(){ + + Set ids = new HashSet<>(); + + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(VRE_TIMELINE_POSTS).column(VRE_ID).all() + .build()); + try { + result = session.execute(stmtFind.bind()); + + } catch (Exception e){ + e.printStackTrace(); + + } + + Listrows=result.all(); + for (Row row : rows) { + ids.add(row.getString(VRE_ID)); + } + List toReturn = new ArrayList<>(); + toReturn.addAll(ids); + _log.debug("VRE ids are " + ids); + + return toReturn; + } +} diff --git a/src/main/java/org/gcube/social_networking/ResourceInitializer.java b/src/main/java/org/gcube/social_networking/ResourceInitializer.java deleted file mode 100644 index ab21eb5..0000000 --- a/src/main/java/org/gcube/social_networking/ResourceInitializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.gcube.social_networking; - -import javax.ws.rs.ApplicationPath; - -import org.gcube.smartgears.annotations.ManagedBy; -import org.gcube.social_networking.rest.HelloWorld; -import org.glassfish.jersey.server.ResourceConfig; - -/** - * @author Luca Frosini (ISTI - CNR) - */ -@ApplicationPath("/") -@ManagedBy(HelloWorldInitializator.class) -public class ResourceInitializer extends ResourceConfig { - - public ResourceInitializer() { - packages(HelloWorld.class.getPackage().toString()); - } - -} diff --git a/src/main/java/org/gcube/social_networking/SocialService.java b/src/main/java/org/gcube/social_networking/SocialService.java new file mode 100644 index 0000000..e7fcdcc --- /dev/null +++ b/src/main/java/org/gcube/social_networking/SocialService.java @@ -0,0 +1,25 @@ +package org.gcube.social_networking; + +import javax.ws.rs.Path; +import javax.ws.rs.core.Application; +import org.gcube.social_networking.rest.HelloWorld; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.Set; + +@Path("social-service") +public class SocialService extends Application { + private static Logger logger = LoggerFactory.getLogger(SocialService.class); + + @Override + public Set> getClasses() { + logger.info("/social-service/ here"); + final Set> classes = new HashSet>(); + // register resources and features + classes.add(HelloWorld.class); + return classes; + } + +} diff --git a/src/main/java/org/gcube/social_networking/HelloWorldInitializator.java b/src/main/java/org/gcube/social_networking/SocialServiceApplicationManager.java similarity index 59% rename from src/main/java/org/gcube/social_networking/HelloWorldInitializator.java rename to src/main/java/org/gcube/social_networking/SocialServiceApplicationManager.java index 5e0ddda..8cd921a 100644 --- a/src/main/java/org/gcube/social_networking/HelloWorldInitializator.java +++ b/src/main/java/org/gcube/social_networking/SocialServiceApplicationManager.java @@ -1,6 +1,6 @@ package org.gcube.social_networking; -import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.smartgears.ApplicationManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,12 +8,12 @@ import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ -public class HelloWorldInitializator implements ApplicationManager { +public class SocialServiceApplicationManager implements ApplicationManager { /** * Logger */ - private static Logger logger = LoggerFactory.getLogger(HelloWorldInitializator.class); + private static Logger logger = LoggerFactory.getLogger(SocialServiceApplicationManager.class); public static boolean initialised; @@ -22,24 +22,25 @@ public class HelloWorldInitializator implements ApplicationManager { */ @Override public synchronized void onInit() { + + logger.info("Starting social service"); + try{ + String context = SecretManagerProvider.instance.get().getContext(); + logger.info( + "\n-------------------------------------------------------\n" + + "Social Service is Starting on context {}\n" + + "-------------------------------------------------------", + context); + }catch (Throwable e) { + logger.error("unexpected error initiliazing storagehub",e); + } + - String context = SecretManagerProvider.instance.get().getContext(); - - logger.trace( - "\n-------------------------------------------------------\n" - + "Hello World Service is Starting on context {}\n" - + "-------------------------------------------------------", - context); + // ApplicationContext applicationContext = ContextProvider.get(); // String helloWorldEServiceID = applicationContext.id(); - - logger.trace( - "\n-------------------------------------------------------\n" - + "Hello World Service Started Successfully on context {}\n" - + "-------------------------------------------------------", - context); - + } /** diff --git a/src/main/java/org/gcube/social_networking/caches/CachesManager.java b/src/main/java/org/gcube/social_networking/caches/CachesManager.java new file mode 100644 index 0000000..6fe5f80 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/caches/CachesManager.java @@ -0,0 +1,34 @@ +package org.gcube.social_networking.caches; + +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.Ehcache; + +/** + * Handle caches via Ehcache + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class CachesManager { + + private static CacheManager cacheManager; + public static final CachesManager singleton = new CachesManager(); + + // the following caches are declared within the ehcache.xml (no default is available) + public static final String SOCIAL_NETWORKING_SITES_CACHE = "social_networking_site_cache"; + public static final String USERS_CACHE = "users_cache"; + public static final String GROUPS_CACHE = "groups_cache"; + + private CachesManager(){ + cacheManager = CacheManager.newInstance(); + } + + public static Ehcache getCache(String name){ + return cacheManager.getEhcache(name); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + cacheManager.shutdown(); + } + +} diff --git a/src/main/java/org/gcube/social_networking/caches/GroupsCache.java b/src/main/java/org/gcube/social_networking/caches/GroupsCache.java new file mode 100644 index 0000000..def0a52 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/caches/GroupsCache.java @@ -0,0 +1,54 @@ +package org.gcube.social_networking.caches; + +import net.sf.ehcache.Ehcache; +import net.sf.ehcache.Element; + +import org.gcube.vomanagement.usermanagement.model.GCubeGroup; +import org.slf4j.LoggerFactory; + +public class GroupsCache { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(GroupsCache.class); + private static GroupsCache singleton = new GroupsCache(); + + /** + * Private constructor: build the cache + * @return + */ + private GroupsCache(){ + + logger.debug("Building cache"); + CachesManager.getCache(CachesManager.GROUPS_CACHE); + + } + + /** + * Get the singleton object + */ + public static GroupsCache getSingleton() { + return singleton; + } + + /** + * Retrieve an entry + * @param groupId + * @return user associated to the user + */ + public GCubeGroup getGroup(long groupId){ + Ehcache groupsCache = CachesManager.getCache(CachesManager.GROUPS_CACHE); + if(groupsCache.get(groupId) != null) + return (GCubeGroup) groupsCache.get(groupId).getObjectValue(); + else + return null; + } + + /** + * Save an entry into the cache + * @param id + * @param group + */ + public void pushEntry(long id, GCubeGroup group){ + Ehcache groupsCache = CachesManager.getCache(CachesManager.GROUPS_CACHE); + groupsCache.put(new Element(id, group)); + } + +} diff --git a/src/main/java/org/gcube/social_networking/caches/SocialNetworkingSiteFinder.java b/src/main/java/org/gcube/social_networking/caches/SocialNetworkingSiteFinder.java new file mode 100644 index 0000000..61665ce --- /dev/null +++ b/src/main/java/org/gcube/social_networking/caches/SocialNetworkingSiteFinder.java @@ -0,0 +1,249 @@ +package org.gcube.social_networking.caches; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.io.InputStream; +import java.util.List; +import java.util.Properties; + +import net.sf.ehcache.Ehcache; +import net.sf.ehcache.Element; + +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; +import org.gcube.common.portal.GCubePortalConstants; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.model.GCubeGroup; +import org.gcube.vomanagement.usermanagement.model.VirtualGroup; +import org.slf4j.LoggerFactory; + +/** + * When a notification needs to be sent, this class offers utility to discover (starting from the scope) + * the site information needed to build up the SocialNetworkingSite object (which, for instance, contains the + * portal email). + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class SocialNetworkingSiteFinder { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SocialNetworkingSiteFinder.class); + + private static final String EMAIL_SENDER_SITE_CUSTOM_FIELD = "Emailsender"; + private static final String CATEGORY = "Portal"; + + // these properties could be overwritten by the ones read from config.properties + private static String PROD_FALLBACK_GATEWAY = "D4Science.org Gateway"; + private static String DEV_FALLBACK_GATEWAY = "gCube Snapshot Gateway"; + private static String PREPROD_FALLBACK_GATEWAY = "D4Science Preproduction Gateway"; + + /** + * Singleton object + */ + private static SocialNetworkingSiteFinder singleton = new SocialNetworkingSiteFinder(); + + /** + * Build the singleton instance + */ + private SocialNetworkingSiteFinder(){ + + // read fallback properties + try{ + logger.debug("Trying to read config.properties"); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream input = classLoader.getResourceAsStream("config.properties"); + Properties properties = new Properties(); + properties.load(input); + PROD_FALLBACK_GATEWAY = properties.getProperty("PROD_FALLBACK_GATEWAY"); + DEV_FALLBACK_GATEWAY = properties.getProperty("DEV_FALLBACK_GATEWAY"); + PREPROD_FALLBACK_GATEWAY = properties.getProperty("PREPROD_FALLBACK_GATEWAY"); + }catch(Exception e){ + logger.warn("Failed to read config.properties...", e); + } + + } + + /** + * Retrieve the singleton instance + */ + public static SocialNetworkingSiteFinder getInstance(){ + + return singleton; + + } + + /** + * Retrieve the SocialNetworkingSite given the scope + * @param scope + * @return + */ + public static SocialNetworkingSite getSocialNetworkingSiteFromScope(String scope){ + + Ehcache socialSitesCache = CachesManager.getCache(CachesManager.SOCIAL_NETWORKING_SITES_CACHE); + + if(scope == null || scope.isEmpty()) + throw new IllegalArgumentException("Scope cannot be null/empty"); + + if(socialSitesCache != null && socialSitesCache.get(scope) != null) + return (SocialNetworkingSite) socialSitesCache.get(scope).getObjectValue(); + else{ + SocialNetworkingSite site = discoverSite(scope); + if(socialSitesCache != null && site != null) + socialSitesCache.put(new Element(scope, site)); + return site; + } + + } + + /** + * Discover the site for this scope + * @param scope + * @return + */ + private static SocialNetworkingSite discoverSite(String scope) { + + try{ + + logger.info("Requested site for scope " + scope); + GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + long groupId = groupManager.getGroupIdFromInfrastructureScope(scope); + + GCubeGroup matchingGateway = null; + + if(groupManager.isVRE(groupId)){ + + // get the Virtual groups for the groupid related to the scope + + List virtualGroupsOfGroup = groupManager.getVirtualGroups(groupId); + + if(virtualGroupsOfGroup == null || virtualGroupsOfGroup.isEmpty()) + throw new Exception("It seems that the VRE is not linked to any VirtualGroups"); + + // get the gateways + List gateways = groupManager.getGateways(); + + if(gateways == null || gateways.isEmpty()) + throw new Exception("It seems there is no gateway here!"); + + logger.info("Retrieved Gateways are " + gateways); + + // now, retrieve the virtual groups for each gateway and stop when a VG matches with one of the group + // then, it is the gateway of interest + ext_loop: for (GCubeGroup gateway : gateways) { + List gatewayVirtualGroups = groupManager.getVirtualGroups(gateway.getGroupId()); + if(gatewayVirtualGroups != null && !gatewayVirtualGroups.isEmpty()){ + for (VirtualGroup gatewayVirtualGroup : gatewayVirtualGroups) { + if(virtualGroupsOfGroup.contains(gatewayVirtualGroup)){ + logger.debug("Matching gateway for scope " + scope + " is " + gateway); + matchingGateway = gateway; + break ext_loop; + } + } + } + } + + }else{ + + List gateways = groupManager.getGateways(); + + // vo and root vo cases are treated separately: in production environment services.d4science.org is used, instead + // in dev next.d4science.org is used TODO better way... + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + String rootContext = "/"+ctx.container().configuration().infrastructure(); + String matchingGatewayName = null; + if(isDevOrPreprod(rootContext)){ + matchingGatewayName = DEV_FALLBACK_GATEWAY; + }else{ + matchingGatewayName = PROD_FALLBACK_GATEWAY; + } + + // find the matching one among the gateways + for (GCubeGroup gateway : gateways) { + if(gateway.getGroupName().equals(matchingGatewayName)){ + matchingGateway = gateway; + break; + } + } + + if(matchingGateway == null && isDevOrPreprod(rootContext)){ + + logger.warn("Checking if it is the preprod environment"); + matchingGatewayName = PREPROD_FALLBACK_GATEWAY; + // find the matching one among the gateways + for (GCubeGroup gateway : gateways) { + if(gateway.getGroupName().equals(matchingGatewayName)){ + matchingGateway = gateway; + break; + } + } + + } + + } + + if(matchingGateway == null){ + logger.warn("There is no gateway for such scope. Returning null"); + return null; + }else{ + String siteName = matchingGateway.getGroupName(); + String emailSender = (String)groupManager.readCustomAttr(matchingGateway.getGroupId(), EMAIL_SENDER_SITE_CUSTOM_FIELD); + emailSender = emailSender.replace("\"", ""); //this is because otherwise it would contains double quotes and postfix would use it as first part before @ e.g. senderEmail="aginfra@d4science.org"@d4science.org + String siteLandingPagePath = GCubePortalConstants.PREFIX_GROUP_URL + matchingGateway.getFriendlyURL(); + String siteUrl = discoverHostOfServiceEndpoint(siteName); + SocialNetworkingSite site = new SocialNetworkingSite(siteName, emailSender, siteUrl, siteLandingPagePath); + logger.info("Site is " + site); + return site; + } + + }catch(Exception e){ + logger.error("Failed to determine the SocialNetworkingSite for scope " + scope, e); + } + + return null; + } + + private static boolean isDevOrPreprod(String rootContext) { + return (rootContext.equals("/gcube") || rootContext.equals("/pred4s")); + } + + /** + * Retrieve endpoint host from IS for this gateway + * @return the host for the gateway + * @throws Exception + */ + private static String discoverHostOfServiceEndpoint(String gatewayName){ + + String currentScope = ScopeProvider.instance.get(); + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + ScopeProvider.instance.set("/"+ctx.container().configuration().infrastructure()); + String host = null; + try{ + + SimpleQuery query = queryFor(ServiceEndpoint.class); + query.addCondition("$resource/Profile/Name/text() eq '"+ gatewayName +"'"); + query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'"); + DiscoveryClient client = clientFor(ServiceEndpoint.class); + List toReturn = client.submit(query); + for (ServiceEndpoint serviceEndpoint : toReturn) { + host = "https://" + serviceEndpoint.profile().runtime().hostedOn(); + logger.info("Gateway host is " + host); + break; + } + + }catch(Exception e){ + logger.error("Error while retrieving host for the gateway " + gatewayName); + }finally{ + ScopeProvider.instance.set(currentScope); + } + + return host; + + } + +} diff --git a/src/main/java/org/gcube/social_networking/caches/UsersCache.java b/src/main/java/org/gcube/social_networking/caches/UsersCache.java new file mode 100644 index 0000000..5c9de82 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/caches/UsersCache.java @@ -0,0 +1,83 @@ +package org.gcube.social_networking.caches; + +import java.util.List; + +import net.sf.ehcache.Ehcache; +import net.sf.ehcache.Element; + +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.LoggerFactory; + +/** + * This cache will store GCubeUser of the users of the infrastructure as couples {user-id, user screename} + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class UsersCache{ + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UsersCache.class); + private static UsersCache singleton = new UsersCache(); + + /** + * Private constructor: build the cache + * @return + */ + private UsersCache(){ + + // create a thread to build the cache + new Thread(){ + public void run() { + try{ + logger.debug("Fetching users and putting them into cache"); + Ehcache usersCache = CachesManager.getCache(CachesManager.USERS_CACHE); + GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager(); + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + List users = userManager.listUsersByGroup(groupManager.getGroupIdFromInfrastructureScope("/"+ctx.container().configuration().infrastructure())); + for (GCubeUser gCubeUser : users) { + usersCache.put(new Element(gCubeUser.getUserId(), gCubeUser)); + } + }catch(Exception e){ + logger.error("Unable to retrieve user's usernames. Other users will be discovered later on", e); + } + } + }.start(); + + } + + /** + * Get the singleton object + */ + public static UsersCache getSingleton() { + return singleton; + } + + /** + * Retrieve an entry + * @param userId + * @return user associated to the user + */ + public GCubeUser getUser(long userId){ + Ehcache usersCache = CachesManager.getCache(CachesManager.USERS_CACHE); + if(usersCache.get(userId) != null) + return (GCubeUser) usersCache.get(userId).getObjectValue(); + else + return null; + } + + /** + * Save an entry into the cache + * @param id + * @param user + */ + public void pushEntry(long id, GCubeUser user){ + Ehcache usersCache = CachesManager.getCache(CachesManager.USERS_CACHE); + usersCache.put(new Element(id, user)); + } + +} diff --git a/src/main/java/org/gcube/social_networking/liferay/ws/GroupManagerWSBuilder.java b/src/main/java/org/gcube/social_networking/liferay/ws/GroupManagerWSBuilder.java new file mode 100644 index 0000000..7906fc1 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/liferay/ws/GroupManagerWSBuilder.java @@ -0,0 +1,50 @@ +package org.gcube.social_networking.liferay.ws; + +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.impl.ws.LiferayWSGroupManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class that builds a (singleton) GroupManagerWS object. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class GroupManagerWSBuilder { + + private static final Logger logger = LoggerFactory.getLogger(GroupManagerWSBuilder.class); + private static GroupManagerWSBuilder singleton = new GroupManagerWSBuilder(); + private static GroupManager groupManagerWs; + + private GroupManagerWSBuilder(){ + + logger.debug("Building GroupManager please wait"); + + try{ + groupManagerWs = new LiferayWSGroupManager( + LiferayJSONWsCredentials.getSingleton().getUser(), + LiferayJSONWsCredentials.getSingleton().getPassword(), + LiferayJSONWsCredentials.getSingleton().getHost(), + LiferayJSONWsCredentials.getSingleton().getSchema(), + LiferayJSONWsCredentials.getSingleton().getPort()); + }catch(Exception e){ + logger.error("Failed to build the GroupManager. ", e); + return; + } + + logger.debug("GroupManager instance built"); + + } + + /** + * Get the user manager instance + * @return + */ + public GroupManager getGroupManager(){ + return groupManagerWs; + } + + public static GroupManagerWSBuilder getInstance(){ + return singleton; + } + +} diff --git a/src/main/java/org/gcube/social_networking/liferay/ws/KeycloakAPICredentials.java b/src/main/java/org/gcube/social_networking/liferay/ws/KeycloakAPICredentials.java new file mode 100644 index 0000000..887b520 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/liferay/ws/KeycloakAPICredentials.java @@ -0,0 +1,143 @@ +package org.gcube.social_networking.liferay.ws; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.gcube.common.encryption.encrypter.StringEncrypter; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.Property; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class KeycloakAPICredentials { + + private static final Logger logger = LoggerFactory.getLogger(KeycloakAPICredentials.class); + + // the singleton obj + private static KeycloakAPICredentials singleton = new KeycloakAPICredentials(); + + // properties that it contains + private String keycloakURL; + private String realm; + private String clientid; + private String password; + + + // Service endpoint properties + private final static String RUNTIME_RESOURCE_NAME = "IAM"; + private final static String CATEGORY = "Service"; + + /** + * Private constructor + */ + private KeycloakAPICredentials() { + logger.debug("Building KeycloakAPICredentials object"); + + lookupPropertiesFromIs(); + logger.debug("KeycloakAPICredentials object built"); + } + + /** + * Read the properties from the infrastructure + */ + private void lookupPropertiesFromIs() { + + logger.debug("Starting creating KeycloakAPICredentials"); + + String oldContext = ScopeProvider.instance.get(); + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + ScopeProvider.instance.set("/"+ctx.container().configuration().infrastructure()); + logger.debug("Discovering liferay user's credentials in context " + ctx.container().configuration().infrastructure()); + + try{ + List resources = getConfigurationFromIS(); + if (resources.size() == 0){ + logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope."); + throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope."); + } + else { + for (ServiceEndpoint res : resources) { + Iterator accessPointIterator = res.profile().accessPoints().iterator(); + while (accessPointIterator.hasNext()) { + ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator + .next(); + + if(accessPoint.name().equals("d4science")){ + keycloakURL = accessPoint.address(); + realm = accessPoint.name(); + clientid = accessPoint.username(); + password = StringEncrypter.getEncrypter().decrypt(accessPoint.password()); + logger.info("Found accesspoint URL = " + keycloakURL); + } + } + } + } + }catch(Exception e){ + logger.error("Unable to retrieve such service endpoint information!", e); + return; + }finally{ + if(oldContext != null) + ScopeProvider.instance.set(oldContext); + } + + logger.debug("Bean built " + toString()); + } + + /** + * Retrieve endpoints information from IS for DB + * @return list of endpoints for ckan database + * @throws Exception + */ + private List getConfigurationFromIS() throws Exception{ + + SimpleQuery query = queryFor(ServiceEndpoint.class); + query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'"); + query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'"); + DiscoveryClient client = clientFor(ServiceEndpoint.class); + List toReturn = client.submit(query); + return toReturn; + + } + + public static KeycloakAPICredentials getSingleton() { + if (singleton == null) + singleton = new KeycloakAPICredentials(); + return singleton; + } + + public String getServerURL() { + return keycloakURL; + } + + public String getClientid() { + return clientid; + } + + public String getPassword() { + return password; + } + + public String getRealm() { + return realm; + } + + @Override + public String toString() { + return "KeycloakAPICredentials [keycloakURL=" + keycloakURL + ", realm=" + realm + ", clientid=" + clientid + + ", password=**************]"; + } + + +} diff --git a/src/main/java/org/gcube/social_networking/liferay/ws/LiferayJSONWsCredentials.java b/src/main/java/org/gcube/social_networking/liferay/ws/LiferayJSONWsCredentials.java new file mode 100644 index 0000000..dee46d1 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/liferay/ws/LiferayJSONWsCredentials.java @@ -0,0 +1,175 @@ +package org.gcube.social_networking.liferay.ws; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.gcube.common.encryption.encrypter.StringEncrypter; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.Property; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +/** + * This is a singleton bean instantiated at service start up. It contains + * the credentials of the user who is allowed to perform calls to Liferay. + * Its credentials are looked up from the infrastructure. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class LiferayJSONWsCredentials { + + private static final Logger logger = LoggerFactory.getLogger(LiferayJSONWsCredentials.class); + + // the singleton obj + private static LiferayJSONWsCredentials singleton = new LiferayJSONWsCredentials(); + + // properties that it contains + private String host; + private String schema; + private String user; + private String password; + private int port; + + // The token of the user used to send notifications/messages when an application token is provided. (will be read from web.xml) + private String notifierUserToken; + + // Service endpoint properties + private final static String RUNTIME_RESOURCE_NAME = "D4Science Infrastructure Gateway"; + private final static String CATEGORY = "Portal"; + + /** + * Private constructor + */ + private LiferayJSONWsCredentials() { + logger.debug("Building LiferayJSONWsCredentials object"); + loadNotifierToken(); + lookupPropertiesFromIs(); + logger.debug("LiferayJSONWsCredentials object built"); + } + + /** + * Load the token of the notifier user + */ + private void loadNotifierToken() { + try{ + notifierUserToken = ServletContextClass.getNotifierToken(); + logger.debug("Token read " + notifierUserToken.substring(0, 5)+ "*********************"); + }catch(Exception e){ + logger.error("Failed to read notifier user token!", e); + } + } + + /** + * Read the properties from the infrastructure + */ + private void lookupPropertiesFromIs() { + + logger.debug("Starting creating LiferayJSONWsCredentials"); + + String oldContext = ScopeProvider.instance.get(); + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + ScopeProvider.instance.set("/"+ctx.container().configuration().infrastructure()); + logger.info("Discovering liferay user's credentials in context " + ctx.container().configuration().infrastructure()); + + try{ + List resources = getConfigurationFromIS(); + if (resources.size() == 0){ + logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope."); + throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope."); + } + else { + for (ServiceEndpoint res : resources) { + Iterator accessPointIterator = res.profile().accessPoints().iterator(); + while (accessPointIterator.hasNext()) { + ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator + .next(); + + if(accessPoint.name().equals("JSONWSUser")){ + // get base path + Map properties = accessPoint.propertyMap(); + host = accessPoint.address(); + schema = (String)properties.get("schema").value(); + user = StringEncrypter.getEncrypter().decrypt((String)properties.get("username").value()); + password = StringEncrypter.getEncrypter().decrypt((String)properties.get("password").value()); + port = Integer.valueOf(properties.get("port").value()); + + // break + break; + } + } + } + } + }catch(Exception e){ + logger.error("Unable to retrieve such service endpoint information!", e); + return; + }finally{ + if(oldContext != null) + ScopeProvider.instance.set(oldContext); + } + + logger.debug("Bean built " + toString()); + } + + /** + * Retrieve endpoints information from IS for DB + * @return list of endpoints for ckan database + * @throws Exception + */ + private List getConfigurationFromIS() throws Exception{ + + SimpleQuery query = queryFor(ServiceEndpoint.class); + query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'"); + query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'"); + DiscoveryClient client = clientFor(ServiceEndpoint.class); + List toReturn = client.submit(query); + return toReturn; + + } + + public static LiferayJSONWsCredentials getSingleton() { + return singleton; + } + + public String getHost() { + return host; + } + + public String getSchema() { + return schema; + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + + public int getPort() { + return port; + } + + public String getNotifierUserToken() { + return notifierUserToken; + } + + @Override + public String toString() { + return "LiferayJSONWsCredentials [host=" + host + ", schema=" + schema + + ", user=" + user + ", password=" + password + ", port=" + + port + ", notifierUserToken=" + notifierUserToken + "]"; + } + +} diff --git a/src/main/java/org/gcube/social_networking/liferay/ws/RoleManagerWSBuilder.java b/src/main/java/org/gcube/social_networking/liferay/ws/RoleManagerWSBuilder.java new file mode 100644 index 0000000..fdc0c55 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/liferay/ws/RoleManagerWSBuilder.java @@ -0,0 +1,50 @@ +package org.gcube.social_networking.liferay.ws; + +import org.gcube.vomanagement.usermanagement.RoleManager; +import org.gcube.vomanagement.usermanagement.impl.ws.LiferayWSRoleManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class that builds a (singleton) UserManagerWS object. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class RoleManagerWSBuilder { + + private static final Logger logger = LoggerFactory.getLogger(UserManagerWSBuilder.class); + private static RoleManagerWSBuilder singleton = new RoleManagerWSBuilder(); + private RoleManager roleManagerWs; + + private RoleManagerWSBuilder(){ + + logger.debug("Building UserManager please wait"); + + try{ + roleManagerWs = new LiferayWSRoleManager( + LiferayJSONWsCredentials.getSingleton().getUser(), + LiferayJSONWsCredentials.getSingleton().getPassword(), + LiferayJSONWsCredentials.getSingleton().getHost(), + LiferayJSONWsCredentials.getSingleton().getSchema(), + LiferayJSONWsCredentials.getSingleton().getPort()); + }catch(Exception e){ + logger.error("Failed to build the UserManager. ", e); + return; + } + + logger.debug("UserManager instance built"); + + } + + /** + * Get the role manager instance + * @return + */ + public RoleManager getRoleManager(){ + return roleManagerWs; + } + + public static RoleManagerWSBuilder getInstance(){ + return singleton; + } + +} diff --git a/src/main/java/org/gcube/social_networking/liferay/ws/ServletContextClass.java b/src/main/java/org/gcube/social_networking/liferay/ws/ServletContextClass.java new file mode 100644 index 0000000..9c5cf7a --- /dev/null +++ b/src/main/java/org/gcube/social_networking/liferay/ws/ServletContextClass.java @@ -0,0 +1,39 @@ +package org.gcube.social_networking.liferay.ws; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.gcube.social_networking.caches.UsersCache; + +/** + * Loaded at start up. This class performs some init - to be done once - operations. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ServletContextClass implements ServletContextListener +{ + + private static String notifierToken; + + public void contextInitialized(ServletContextEvent arg0) { + + // get the token and save it + notifierToken = arg0.getServletContext().getInitParameter("NOTIFIER_TOKEN"); + + // start the thread to retrieve infrastructure users (which is, build up the singleton) + //UsersCache.getSingleton(); + + } + + @Override + public void contextDestroyed(ServletContextEvent arg0){ + // on shutdown + } + + /** + * Returns the token of the Liferay's User. + * @return + */ + public static String getNotifierToken() { + return notifierToken; + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/liferay/ws/UserManagerWSBuilder.java b/src/main/java/org/gcube/social_networking/liferay/ws/UserManagerWSBuilder.java new file mode 100644 index 0000000..6f69c62 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/liferay/ws/UserManagerWSBuilder.java @@ -0,0 +1,50 @@ +package org.gcube.social_networking.liferay.ws; + +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.impl.ws.LiferayWSUserManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class that builds a (singleton) UserManagerWS object. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class UserManagerWSBuilder { + + private static final Logger logger = LoggerFactory.getLogger(UserManagerWSBuilder.class); + private static UserManagerWSBuilder singleton = new UserManagerWSBuilder(); + private UserManager userManagerWs; + + private UserManagerWSBuilder(){ + + logger.debug("Building UserManager please wait"); + + try{ + userManagerWs = new LiferayWSUserManager( + LiferayJSONWsCredentials.getSingleton().getUser(), + LiferayJSONWsCredentials.getSingleton().getPassword(), + LiferayJSONWsCredentials.getSingleton().getHost(), + LiferayJSONWsCredentials.getSingleton().getSchema(), + LiferayJSONWsCredentials.getSingleton().getPort()); + }catch(Exception e){ + logger.error("Failed to build the UserManager. ", e); + return; + } + + logger.debug("UserManager instance built"); + + } + + /** + * Get the user manager instance + * @return + */ + public UserManager getUserManager(){ + return userManagerWs; + } + + public static UserManagerWSBuilder getInstance(){ + return singleton; + } + +} diff --git a/src/main/java/org/gcube/social_networking/rest/Attachments.java b/src/main/java/org/gcube/social_networking/rest/Attachments.java deleted file mode 100644 index 7c21ff3..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Attachments.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.Attachment; -import org.gcube.social_networking.socialnetworking.model.shared.Like; - -import javax.ws.rs.*; - -@Path("attachments") -@ResourceGroup("Attachments APIs") -@ResourceLabel("Attachments APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Attachments { - @POST - @Path("/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveAttachmentEntry(Attachment toSave) { - - } -} diff --git a/src/main/java/org/gcube/social_networking/rest/HelloWorld.java b/src/main/java/org/gcube/social_networking/rest/HelloWorld.java index 011b04f..05acbb5 100644 --- a/src/main/java/org/gcube/social_networking/rest/HelloWorld.java +++ b/src/main/java/org/gcube/social_networking/rest/HelloWorld.java @@ -1,94 +1,26 @@ package org.gcube.social_networking.rest; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; +import org.gcube.smartgears.annotations.ManagedBy; +import org.gcube.social_networking.SocialServiceApplicationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; +import javax.ws.rs.core.MediaType; -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import com.webcohesion.enunciate.metadata.rs.ResponseCode; -import com.webcohesion.enunciate.metadata.rs.StatusCodes; -import org.gcube.social_networking.server.CassandraConnection; -import org.gcube.social_networking.socialnetworking.model.shared.Comment; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.CommentIDNotFoundException; - -@Path("comments") -@ResourceGroup("Comments APIs") -@ResourceLabel("Comments APIs") -@RequestHeaders ({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) +@Path("test") +@ManagedBy(SocialServiceApplicationManager.class) public class HelloWorld { - - @POST - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void addComment(Comment comment) { - - } + private static Logger logger = LoggerFactory.getLogger(HelloWorld.class); @GET - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void readComment(@PathParam("id") String id) { - + @Path("/") + @Produces(MediaType.APPLICATION_JSON) + public String test(){ + logger.info("/social-service/test/ here"); + return "{\"result\":\"funziona!!!\"}"; } - @PUT - @Path("/{id}") - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void editComment(@PathParam("id") String id, Comment comment) { - - } - - @DELETE - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void deleteComment(@PathParam("id") String id) { - - } - - @POST - @Produces("application/json;charset=UTF-8") - @Consumes("application/json;charset=UTF-8") - public String create(String json) { - //Greeting g = new Greeting(); - //return g.create(json); - return "{\"text\":\"hi\"}"; - - } - - @PUT - @Path("/{greeting_name}") - @Consumes("application/json;charset=UTF-8") - @Produces("application/json;charset=UTF-8") - @StatusCodes ({ - @ResponseCode ( code = 200, condition = "The greeting has been updated successfully.") - }) -// @AuthorizationControl(allowedRoles={"boss"}, exception=NotAuthorizedException.class) - public String update(@PathParam("greeting_name") String name, String json) { - return "{}"; - } - - - @DELETE - @Path("/{greeting_name}") - @StatusCodes ({ - @ResponseCode ( code = 204, condition = "The item has been deleted successfully."), - @ResponseCode ( code = 404, condition = "The item was not found.") - }) - public String delete(@PathParam("greeting_name") String name) { - return "{}"; - } } diff --git a/src/main/java/org/gcube/social_networking/rest/Invites.java b/src/main/java/org/gcube/social_networking/rest/Invites.java deleted file mode 100644 index faaa095..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Invites.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.Invite; -import org.gcube.social_networking.socialnetworking.model.shared.Notification; - -import javax.ws.rs.*; - -@Path("invites") -@ResourceGroup("Invites APIs") -@ResourceLabel("Invites APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Invites { - - @POST - @Path("/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveInvite(Invite invite) { - - } - - @GET - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void readInvite(@PathParam("id") String inviteid) { - - } - -} diff --git a/src/main/java/org/gcube/social_networking/rest/Likes.java b/src/main/java/org/gcube/social_networking/rest/Likes.java deleted file mode 100644 index b896e2c..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Likes.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.Like; -import org.gcube.social_networking.socialnetworking.model.shared.Notification; - -import javax.ws.rs.*; - -@Path("likes") -@ResourceGroup("Likes APIs") -@ResourceLabel("Likes APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Likes { - @POST - @Path("/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void like(Like like) { - - } - - //had other params why? - @DELETE - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void unlike(@PathParam("id") String likeid) { - - } - -} diff --git a/src/main/java/org/gcube/social_networking/rest/Notifications.java b/src/main/java/org/gcube/social_networking/rest/Notifications.java deleted file mode 100644 index 285ed04..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Notifications.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.Notification; -import org.gcube.social_networking.socialnetworking.model.shared.Post; - -import javax.ws.rs.*; - -@Path("notifications") -@ResourceGroup("Notifications APIs") -@ResourceLabel("Notifications APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Notifications { - @POST - @Path("/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveNotification(Notification notification) { - - } - - @PUT - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void setNotificationRead(@PathParam("id") String notid) { - - } - - @GET - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void readNotification(@PathParam("id") String notid) { - - } -} diff --git a/src/main/java/org/gcube/social_networking/rest/Posts.java b/src/main/java/org/gcube/social_networking/rest/Posts.java deleted file mode 100644 index f987ef0..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Posts.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.Attachment; -import org.gcube.social_networking.socialnetworking.model.shared.Comment; -import org.gcube.social_networking.socialnetworking.model.shared.Post; - -import javax.ws.rs.*; -import java.util.List; - -@Path("posts") -@ResourceGroup("Posts APIs") -@ResourceLabel("Posts APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Posts { - @POST - @Path("/postuser") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveUserPost(Post post) { - - } - - @POST - @Path("/postuser") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveUserPost(Post post, List attachments){ - - } - - @PUT - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void deletePost(@PathParam("id") String postid) { - - } - - @POST - @Path("/postapp") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveAppPost(Post post) { - - } - - @POST - @Path("/postapp/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveAppPost(Post post, List attachments){ - - } - - @GET - @Path("/{id}/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void readPost(@PathParam("id") String postid){ - - } - - @GET - @Path("/portalprivacy") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllPortalPrivacyLevelPosts(){ - - } - - @GET - @Path("/{id}/comments") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllCommentByPost(@PathParam("id") String postid){ - - } - - @GET - @Path("/{id}/likes") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllLikesByPost(@PathParam("id") String postid){ - - } - - - //the following two methods had vreid why? - @POST - @Path("/{id}/hashtags") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void saveHashTags(@PathParam("id") String postid, List hashtags) { - - } - - @DELETE - @Path("/{id}/hashtags") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void deleteHashTagsComment(@PathParam("id") String postid, List hashtags) { - - } - - @GET - @Path("/{id}/attachments") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAttachmentsByPostId(@PathParam("id") String postid) { - - } - -} diff --git a/src/main/java/org/gcube/social_networking/rest/Users.java b/src/main/java/org/gcube/social_networking/rest/Users.java deleted file mode 100644 index 14e578c..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Users.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.InviteStatus; -import org.gcube.social_networking.socialnetworking.model.shared.NotificationChannelType; -import org.gcube.social_networking.socialnetworking.model.shared.NotificationType; -import org.gcube.social_networking.socialnetworking.model.shared.Post; - -import javax.ws.rs.*; -import java.util.Map; - -@Path("entities") -@ResourceGroup("Users & Apps APIs") -@ResourceLabel("Users & Apps APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Users { - - @GET - @Path("users/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllPostsByUser(@PathParam("id") String userid) { - - } - - @GET - @Path("apps/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllPostsByApp(@PathParam("id") String appid) { - - } - - @GET - @Path("users/{id}/posts/comments") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentCommentedPostsByUserAndDate(@PathParam("id") String userid, @QueryParam("time") long timeInMillis) { - - } - - @GET - @Path("users/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentPostsByUser(@PathParam("id") String userid, @QueryParam("limit") int limit) { - - } - - @GET - @Path("users/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentPostsByUser(@PathParam("id") String userid, @QueryParam("time") long timeInMillis) { - - } - - @PUT - @Path("users/{id}/notifications") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void setAllNotificationReadByUser(@PathParam("id") String userid) { - - } - - @GET - @Path("users/{id}/notifications") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getUnreadNotificationsByUser(@PathParam("id") String userid) { - - } - - @GET - @Path("users/{id}/notificationchannels") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getUserNotificationChannels(@PathParam("id") String userid, @QueryParam("type") NotificationType notificationType) { - - } - - @PUT - @Path("users/{id}/notificationpreferences") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void setUserNotificationPreferences(@PathParam("id") String userid, Map enabledChannels) { - - } - - @GET - @Path("users/{id}/notificationpreferences") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getUserNotificationPreferences(@PathParam("id") String userid) { - - } - - @GET - @Path("users/{id}/comments") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentCommentsByUserAndDate(@PathParam("id") String userid, @QueryParam("time") long timeInMillis) { - - } - - @GET - @Path("users/{id}/likes") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllLikedPostIdsByUser(@PathParam("id") String userid) { - - } - - @GET - @Path("users/{id}/likes") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllLikedPostsByUser(@PathParam("id") String userid, @QueryParam("limit") int limit) { - - } - - @GET - @Path("users/{id}/posts/likes") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentLikedPostsByUserAndDate(@PathParam("id") String userid, @QueryParam("time") long timeInMillis) { - - } - - @GET - @Path("users/{id}/notifications") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllNotificationByUser(@PathParam("id") String userid, @QueryParam("limit") int limit) { - - } - - @GET - @Path("users/{id}/notifications") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRangeNotificationsByUser(@PathParam("id") String userid, @QueryParam("limit") int limit, @QueryParam("from") int from) { - - } - - @GET - @Path("users/{id}/notifications/unread") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void checkUnreadNotifications(@PathParam("id") String userid) { - - } - - @GET - @Path("users/{id}/notifications/unread/messages") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void checkUnreadMessagesNotifications(@PathParam("id") String userid) { - - } -} diff --git a/src/main/java/org/gcube/social_networking/rest/Vres.java b/src/main/java/org/gcube/social_networking/rest/Vres.java deleted file mode 100644 index 53f9183..0000000 --- a/src/main/java/org/gcube/social_networking/rest/Vres.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.gcube.social_networking.rest; - -import com.webcohesion.enunciate.metadata.rs.RequestHeader; -import com.webcohesion.enunciate.metadata.rs.RequestHeaders; -import com.webcohesion.enunciate.metadata.rs.ResourceGroup; -import com.webcohesion.enunciate.metadata.rs.ResourceLabel; -import org.gcube.social_networking.socialnetworking.model.shared.InviteStatus; -import org.gcube.social_networking.socialnetworking.model.shared.Post; - -import javax.ws.rs.*; - -@Path("vres") -@ResourceGroup("VREs APIs") -@ResourceLabel("VREs APIs") -@RequestHeaders({ - @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") -}) -public class Vres { - @POST - @Path("/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void savePostToVRETimeline(@PathParam("id") String vreid, Post post) { - - } - - @GET - @Path("/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllPostsByVRE(@PathParam("id") String vreid) { - - } - - @GET - @Path("/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentPostsByVRE(@PathParam("id") String vreid, @QueryParam("limit") int limit) { - - } - - @GET - @Path("/{id}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getRecentPostsByVREAndRange(@PathParam("id") String vreid, @QueryParam("limit") int limit, @QueryParam("from") int from) { - - } - - @GET - @Path("/{id}/hashtags") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getVREHashtagsWithOccurrence(@PathParam("id") String vreid) { - - } - - @GET - @Path("/{id}/hashtags") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getVREHashtagsWithOccurrenceFilteredByTime(@PathParam("id") String vreid, @QueryParam("time") long timestamp) { - - } - - @GET - @Path("/{id}/hashtags/{hashtag}/posts") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getVREPostsByHashtag(@PathParam("id") String vreid, @PathParam("hashtag") String hashtag) { - - } - - @GET - @Path("/{id}/email/{email}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void isExistingInvite(@PathParam("id") String vreid, @PathParam("email") String email) { - - } - - @PUT - @Path("/{id}/email/{email}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void setInviteStatus(@PathParam("id") String vreid, @PathParam("email") String email, InviteStatus status) { - - } - - @GET - @Path("/{id}") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getInvitedEmailsByVRE(@PathParam("id") String vreid, InviteStatus... status) { - - } - - @GET - @Path("/") - @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) - public void getAllVREIds() { - - } -} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Attachments.java b/src/main/java/org/gcube/social_networking/rest/collections/Attachments.java new file mode 100644 index 0000000..638458f --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Attachments.java @@ -0,0 +1,87 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.Attachment; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("attachments") +@ResourceGroup("Attachments APIs") +@ResourceLabel("Attachments APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Attachments extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Attachments.class); + + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" attachment {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createAttachment(Attachment attachment) { + try{ + logger.info("Creating attachment with id {}.", attachment.getId()); + return super.create(attachment); + }catch(Exception e){ + return ErrorHandler(e, "create",attachment.getId()); + } + } + + @GET + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response readAttachment(@NotNull @PathParam("id") String id) { + try{ + logger.info("Reading attachment with id {}.", id); + return super.read(id, ResourceNames.Attachment); + }catch(Exception e){ + return ErrorHandler(e, "fetch",id); + } + } + + @DELETE + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response deleteAttachment(@NotNull @PathParam("id") String id) { + try{ + logger.info("Deleting attachment with id {}.", id); + return super.delete(id,ResourceNames.Attachment); + }catch(Exception e){ + return ErrorHandler(e, "delete",id); + } + } + + @PUT + @Path("/{id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateAttachment(@NotNull @PathParam("id") String id, @NotNull Attachment attachment) { + try{ + logger.info("Updating attachment with id {}", id); + return super.update(id, attachment); + }catch(Exception e){ + return ErrorHandler(e, "update",id); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Collection.java b/src/main/java/org/gcube/social_networking/rest/collections/Collection.java new file mode 100644 index 0000000..7d53e1f --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Collection.java @@ -0,0 +1,276 @@ +package org.gcube.social_networking.rest.collections; + +import org.gcube.social_networking.server.CassandraConnection; +import org.gcube.social_networking.socialnetworking.model.shared.Invite; +import org.gcube.social_networking.socialnetworking.model.shared.InviteOperationResult; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.gcube.social_networking.socialnetworking.model.shared.Resource; + +import javax.mail.internet.AddressException; +import javax.ws.rs.core.Response; +import java.util.List; + +public class Collection { + + //Create + public Response create(Resource resource) { + String resourceName = resource.getClass().getSimpleName(); + if (resourceName.equals(ResourceNames.INVITE)){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + InviteOperationResult result; + try { + result = CassandraConnection.getInstance().getDatabookStore().saveInvite((Invite)resource); + } catch (AddressException e) { + throw new RuntimeException(e); + } + status = (result == InviteOperationResult.SUCCESS) ? Response.Status.CREATED : (result == InviteOperationResult.ALREADY_INVITED)? Response.Status.FOUND : Response.Status.INTERNAL_SERVER_ERROR; + responseBean.setResult(result); + responseBean.setMessage((result == InviteOperationResult.SUCCESS) ? resourceName + " {" + resource.getId() + "} Created Successfully" : (result == InviteOperationResult.ALREADY_INVITED) ? resourceName + " {" + resource.getId() + "} already exists" : "Error"); + responseBean.setSuccess(result==InviteOperationResult.SUCCESS); + return Response.status(status).entity(responseBean).build(); + } + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().create(resource); + status = result ? Response.Status.CREATED : Response.Status.FOUND; + responseBean.setResult(result); + responseBean.setMessage(result ? resourceName + " {" + resource.getId() + "} Created Successfully" : resourceName + " {" + resource.getId() + "} already exists"); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + + } + + public Response createChildOf(String parentid, Resource childResource, String parentResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + String childResourceName = childResource.getClass().getSimpleName(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().createChildOf(parentid, childResource, parentResourceName); + status = result ? Response.Status.CREATED : Response.Status.FOUND; + responseBean.setResult(result); + responseBean.setMessage(result ? childResourceName + " {" + childResource.getId() + "} Created Successfully for " + parentResourceName + "{" + parentid + "}." + : childResourceName + " {" + childResource.getId() + "} already exists"); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + + } + + public Response BatchCreateChildOfWithParameter(String parentid, String parameterName, String parameterValue, List childResource, String parentResourceName, String childResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().BatchCreateChildOfWithParameter(parentid, parameterName, parameterValue, childResource, parentResourceName, childResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " created Successfully" : childResourceName + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + + //Read + public Response read(String id, String resourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Resource resource = CassandraConnection.getInstance().getDatabookStore().read(id, resourceName); + status = resource != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(resource != null ? resourceName + " {" + id + "} fetched Successfully" : resourceName + " {" + id + "} cannot be found"); + responseBean.setSuccess(resource != null); + responseBean.setResult(resource); + return Response.status(status).entity(responseBean).build(); + } + + public Response check(String id, String parameterName, String parameterValue, String resourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().check(id, parameterName, parameterValue, resourceName); + status = result != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result != null ? resourceName + " {" + id + "} checked Successfully" : resourceName + " {" + id + "} cannot be found"); + responseBean.setSuccess(result != null); + responseBean.setResult(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response checkChildOf(String parentid, String parameterName, String parameterValue, String parentResourceName, String childResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().checkChildOf(parentid, parameterName, parameterValue, parentResourceName, childResourceName); + status = result != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result != null ? childResourceName + " {" + parentid + "} checked Successfully" : childResourceName + " {" + parentid + "} cannot be found"); + responseBean.setSuccess(result != null); + responseBean.setResult(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response readAll(String resourceName) { + ResponseBean> responseBean = new ResponseBean<>(); + Response.Status status; + List resources = CassandraConnection.getInstance().getDatabookStore().readAll(resourceName); + status = resources != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(resources != null ? resourceName + "s {" + "} fetched Successfully" : resourceName + "s {" + "} cannot be found"); + responseBean.setSuccess(resources != null); + responseBean.setResult(resources); + return Response.status(status).entity(responseBean).build(); + } + + public Response readChildOf(String parentid, String parentResourceName, String childResourceName) { + ResponseBean> responseBean = new ResponseBean<>(); + Response.Status status; + List resources = CassandraConnection.getInstance().getDatabookStore().readChildOf(parentid, parentResourceName, childResourceName); + status = resources != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(resources != null ? childResourceName + " of " + parentResourceName + " {" + parentid + "} fetched Successfully" + : parentResourceName + " {" + parentid + "} cannot be found"); + responseBean.setSuccess(resources != null); + responseBean.setResult(resources); + return Response.status(status).entity(responseBean).build(); + } + + public Response readWithParameter(String parameterName, String parameterValue, String resourceName) { + ResponseBean> responseBean = new ResponseBean<>(); + Response.Status status; + List resources = CassandraConnection.getInstance().getDatabookStore().readWithParameter(parameterName, parameterValue, resourceName); + status = resources != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(resources != null ? resourceName + "with " + parameterName + "=" + parameterValue + " fetched Successfully" + : resourceName + "with " + parameterName + "=" + parameterValue + " cannot be found"); + responseBean.setSuccess(resources != null); + responseBean.setResult(resources); + return Response.status(status).entity(responseBean).build(); + } + + public Response readChildOfWithParameter(String parentid, String parameterName, String parameterValue, + String parentResourceName, String childResourceName) { + ResponseBean> responseBean = new ResponseBean<>(); + Response.Status status; + List resources = CassandraConnection.getInstance().getDatabookStore().readChildOfWithParameter(parentid, parameterName, parameterValue, parentResourceName, childResourceName); + status = resources != null ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(resources != null ? childResourceName + " of " + parentResourceName + "{" + parentid + "}" + "with " + parameterName + "=" + parameterValue + " fetched Successfully" + : childResourceName + " of " + parentResourceName + "{" + parentid + "}" + "with " + parameterName + "=" + parameterValue + " cannot be found"); + responseBean.setSuccess(resources != null); + responseBean.setResult(resources); + return Response.status(status).entity(responseBean).build(); + } + + //Update + public Response update(String id, Resource resource) { + ResponseBean responseBean = new ResponseBean<>(); + String resourceName = resource.getClass().getSimpleName(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().update(resource); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? resourceName + " {" + id + "} updated Successfully" : resourceName + " {" + id + "} cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response updateChildOf(String parentid, String childid, Resource childResource, String parentResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + String childResourceName = childResource.getClass().getSimpleName(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().updateChildOf(parentid, childid, childResource, parentResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " {" + childid + "} updated Successfully" : childResourceName + " {" + childid + "} cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response BatchUpdateChildOf(String parentid, List childResource, String parentResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + String childResourceName = childResource.get(0).getClass().getSimpleName(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().BatchUpdateChildOf(parentid, childResource, parentResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " updated Successfully" : childResourceName + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response updateWithParameter(String parameterName, String parameterValue, Resource resource) { + ResponseBean responseBean = new ResponseBean<>(); + String resourceName = resource.getClass().getSimpleName(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().updateWithParameter(parameterName, parameterValue, resource); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? resourceName + " with" + parameterName + "=" + parameterValue + " updated Successfully" + : resourceName + " with" + parameterName + "=" + parameterValue + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response updateChildOfWithParameter(String parentid, String parameterName, String parameterValue, + Resource childResource, String parentResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + String childResourceName = childResource.getClass().getSimpleName(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().updateChildOfWithParameter(parentid, parameterName, parameterValue, childResource, parentResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " of " + parentResourceName + "{" + parentid + "}" + "with " + parameterName + "=" + parameterValue + " updated Successfully" + : childResourceName + " of " + parentResourceName + "{" + parentid + "}" + "with " + parameterName + "=" + parameterValue + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + //Delete + public Response delete(String id, String resourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().delete(id, resourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? resourceName + " {" + id + "} deleted Successfully" : resourceName + " {" + id + "} cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response deleteChildOf(String parentid, String childid, String parentResourceName, String childResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().deleteChildOf(parentid, childid, childResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " {" + childid + "} deleted Successfully for " + parentResourceName + "{" + parentid + "}." + : childResourceName + " {" + childid + "} cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response deleteWithParameter(String parameterName, String parameterValue, String resourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().deleteWithParameter(parameterName, parameterValue, resourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? resourceName + " with" + parameterName + "=" + parameterValue + " deleted Successfully" + : resourceName + " with" + parameterName + "=" + parameterValue + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response deleteChildOfWithParameter(String parentid, String childid, String parameterName, String parameterValue, String parentResourceName, String childResourceName) { + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().deleteChildOfWithParameter(parentid, childid, parameterName, parameterValue, parentResourceName, childResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " of " + parentResourceName + "{" + parentid + "}" + "with " + parameterName + "=" + parameterValue + " deleted Successfully" + : childResourceName + " of " + parentResourceName + "{" + parentid + "}" + "with " + parameterName + "=" + parameterValue + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } + + public Response BatchDeleteChildOfWithParameter (String parentid, String parameterName, String + parameterValue, List < Resource > childResource, String parentResourceName, String childResourceName){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + Boolean result = CassandraConnection.getInstance().getDatabookStore().BatchDeleteChildOfWithParameter(parentid, parameterName, parameterValue, childResource, parentResourceName, childResourceName); + status = result ? Response.Status.OK : Response.Status.NOT_FOUND; + responseBean.setMessage(result ? childResourceName + " deleted Successfully" : childResourceName + " cannot be found"); + responseBean.setResult(result); + responseBean.setSuccess(result); + return Response.status(status).entity(responseBean).build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Comments.java b/src/main/java/org/gcube/social_networking/rest/collections/Comments.java new file mode 100644 index 0000000..298f813 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Comments.java @@ -0,0 +1,63 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.Comment; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("comments") +@ResourceGroup("Comments APIs") +@ResourceLabel("Comments APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Comments extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Comments.class); + + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" comment {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response readComment(@NotNull @PathParam("id") String id) { + try{ + logger.info("Reading comment with id {}.", id); + return super.read(id, ResourceNames.COMMENT); + }catch(Exception e){ + return ErrorHandler(e, "fetch",id); + } + } + + + @PUT + @Path("/{id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateComment(@NotNull @PathParam("id") String id, @NotNull Comment comment) { + try{ + logger.info("Updating comment with id {}", id); + return super.update(id, comment); + }catch(Exception e){ + return ErrorHandler(e, "update",id); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Entities.java b/src/main/java/org/gcube/social_networking/rest/collections/Entities.java new file mode 100644 index 0000000..2dff65f --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Entities.java @@ -0,0 +1,210 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.*; +import org.gcube.social_networking.utils.ParameterNames; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + + +@Path("entities") +@ResourceGroup("Entities APIs") +@ResourceLabel("Entities APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Entities extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Entities.class); + private Response ErrorHandler(Exception e, String entity, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+ " " + entity + " {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Path("users/{id}/posts") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getAllPostsByUser(@NotNull @PathParam("id") String id, + @QueryParam("liked") boolean liked, + @QueryParam("limit") int limit){ + String action = "fetch posts of"; + try{ + if(liked){ + action = "fetch liked posts of"; + logger.info("Getting all liked posts of user: "+id); + return super.readChildOfWithParameter(id, ParameterNames.ALL_LIKE, String.valueOf(limit),ResourceNames.USER, ResourceNames.POST); + } + logger.info("Getting all posts of user: " + id); + return super.readChildOf(id, ResourceNames.USER, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "user", action,id); + } + } + + @GET + @Path("apps/{id}/posts") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getAllPostsByApp(@NotNull @PathParam("id") String id){ + try{ + logger.info("Getting all posts of app: " + id); + return super.readChildOf(id, ResourceNames.APP, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "app", "fetch posts of",id); + } + } + + @GET + @Path("users/{id}/posts/") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getRecentPosts(@NotNull @PathParam("id") String id, + @NotNull @QueryParam("recent_comment") boolean recent_comment, + @NotNull @QueryParam("recent_like") boolean recent_like, + @NotNull @QueryParam("recent_limit") boolean recent_limit, + @QueryParam("time") long time, + @QueryParam("limit") int limit){ + String action = "fetch recent posts of"; + try{ + if (recent_comment){ + action = "fetch recently commented posts of"; + logger.info("Getting recently commented posts of user: " + id); + return super.readChildOfWithParameter(id, ParameterNames.RECENT_COMMENT, String.valueOf(time), ResourceNames.USER, ResourceNames.POST); + } else if (recent_like){ + action = "fetch recently liked posts of"; + logger.info("Getting recently liked posts of user: " + id); + return super.readChildOfWithParameter(id, ParameterNames.RECENT_LIKE, String.valueOf(time), ResourceNames.USER, ResourceNames.POST); + }else{ + if(recent_limit){ + action = "fetch n recent posts of"; + logger.info("Getting recent {} posts of user {}", limit, id); + return super.readChildOfWithParameter(id, ParameterNames.RECENT_LIMIT, String.valueOf(limit), ResourceNames.USER, ResourceNames.POST); + } else{ + action = "fetch filtered_recent posts of"; + logger.info("Getting recent posts of user {}", id); + return super.readChildOfWithParameter(id, ParameterNames.TIME, String.valueOf(time), ResourceNames.USER, ResourceNames.POST); + } + } + + }catch(Exception e){ + return ErrorHandler(e, "user", action,id); + } + } + + @GET + @Path("users/{id}/comments/") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getRecentComments(@NotNull @PathParam("id") String id, + @QueryParam("time") long time){ + String action = "fetch recent comments of"; + try{ + logger.info("Getting recent comments of user {}", id); + return super.readChildOfWithParameter(id, ParameterNames.TIME, String.valueOf(time), ResourceNames.USER, ResourceNames.COMMENT); + }catch(Exception e){ + return ErrorHandler(e, "user", action,id); + } + } + + + + @GET + @Path("users/{id}/notifications") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getAllNotificationByUser(@NotNull @PathParam("id") String id, + @QueryParam("limit") @DefaultValue("10") int limit, + @QueryParam("unread") boolean unread, + @QueryParam("check") boolean check, + @QueryParam("message") boolean message){ + String action = "fetch notifications of"; + try{ + if(unread){ + if(check){ + if(message){ + action = "check unread message notifications of"; + logger.info("Checking unread message notifications of user: "+id); + return super.checkChildOf(id, ParameterNames.UNREAD_MESSAGE, String.valueOf(true), ResourceNames.USER, ResourceNames.NOTIFICATION); + } + action = "check unread notifications of"; + logger.info("Checking unread notifications of user: " + id); + return super.checkChildOf(id, ParameterNames.UNREAD, String.valueOf(true),ResourceNames.USER, ResourceNames.NOTIFICATION); + } + action = "fetch unread notifications of"; + logger.info("Getting all unread notifications of user: " + id); + return super.readChildOfWithParameter(id, ParameterNames.UNREAD, "", ResourceNames.USER, ResourceNames.NOTIFICATION); + } + logger.info("Getting all notifications of user: " + id); + return super.readChildOfWithParameter(id, ParameterNames.RECENT_LIMIT, String.valueOf(limit), ResourceNames.USER, ResourceNames.NOTIFICATION); + }catch(Exception e){ + return ErrorHandler(e, "user", action,id); + } + } + + @PUT + @Path("users/{id}/notifications") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response setAllNotificationReadByUser(@NotNull @PathParam("id") String id){ + try{ + logger.info("Setting all notifications to read of user: " + id); + Notification notification = new Notification(); + notification.setRead(true); + return super.updateChildOf(id, "", notification, ResourceNames.USER); + }catch(Exception e){ + return ErrorHandler(e, "user", "mark notifications read of",id); + } + } + + + @GET + @Path("users/{id}/notifications/channels") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getUserNotificationChannels(@NotNull @PathParam("id") String id, + @NotNull NotificationType notificationType){ + try{ + logger.info("Getting notification channels of user {} with type {} ", id, notificationType.toString()); + return super.readChildOfWithParameter(id, ParameterNames.NOTIFICATION_TYPE, String.valueOf(notificationType), ResourceNames.USER, ResourceNames.NOTIFICATION); + }catch(Exception e){ + return ErrorHandler(e, "user", "read notification channels of",id); + } + } + + @GET + @Path("users/{id}/notifications/preferences") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getUserNotificationPreferences(@NotNull @PathParam("id") String id){ + try{ + logger.info("Getting notification preferences of user {}", id); + return super.readChildOf(id, ResourceNames.USER, ResourceNames.NOTIFICATION_PREFERENCES); + }catch(Exception e){ + return ErrorHandler(e, "user", "read notification preferences of",id); + } + } + + @PUT + @Path("users/{id}/notifications/preferences") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response setUserNotificationPreferences(@NotNull @PathParam("id") String id, @NotNull List notificationPreferences){ + try{ + logger.info("Setting notification preferences of user {}", id); + return super.BatchUpdateChildOf(id, new ArrayList<>(notificationPreferences), ResourceNames.USER); + }catch(Exception e){ + return ErrorHandler(e, "user", "set notification preferences of",id); + } + } + + +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Invites.java b/src/main/java/org/gcube/social_networking/rest/collections/Invites.java new file mode 100644 index 0000000..f44692d --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Invites.java @@ -0,0 +1,63 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.Invite; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("invites") +@ResourceGroup("Invites APIs") +@ResourceLabel("Invites APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Invites extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Invites.class); + + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" invite {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response readInvite(@NotNull @PathParam("id") String id) { + try{ + logger.info("Reading invite with id {}.", id); + return super.read(id, ResourceNames.INVITE); + }catch(Exception e){ + return ErrorHandler(e, "fetch",id); + } + } + + @POST + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response saveInvite(@NotNull Invite invite) { + try{ + logger.info("Saving invite with id {}.", invite.getId()); + return super.create(invite); + }catch(Exception e){ + return ErrorHandler(e, "create",invite.getId()); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Likes.java b/src/main/java/org/gcube/social_networking/rest/collections/Likes.java new file mode 100644 index 0000000..833852b --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Likes.java @@ -0,0 +1,87 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.Like; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("likes") +@ResourceGroup("Likes APIs") +@ResourceLabel("Likes APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Likes extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Likes.class); + + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" like {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createLike(Like like) { + try{ + logger.info("Creating like with id {}.", like.getKey()); + return super.create(like); + }catch(Exception e){ + return ErrorHandler(e, "create",like.getKey()); + } + } + + @GET + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response readLike(@NotNull @PathParam("id") String id) { + try{ + logger.info("Reading like with id {}.", id); + return super.read(id, ResourceNames.LIKE); + }catch(Exception e){ + return ErrorHandler(e, "fetch",id); + } + } + + @DELETE + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response deleteLike(@NotNull @PathParam("id") String id) { + try{ + logger.info("Deleting like with id {}.", id); + return super.delete(id,ResourceNames.LIKE); + }catch(Exception e){ + return ErrorHandler(e, "delete",id); + } + } + + @PUT + @Path("/{id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateLike(@NotNull @PathParam("id") String id, @NotNull Like like) { + try{ + logger.info("Updating like with id {}", id); + return super.update(id, like); + }catch(Exception e){ + return ErrorHandler(e, "update",id); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Notifications.java b/src/main/java/org/gcube/social_networking/rest/collections/Notifications.java new file mode 100644 index 0000000..bfa2e52 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Notifications.java @@ -0,0 +1,77 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.Notification; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("notifications") +@ResourceGroup("Notifications APIs") +@ResourceLabel("Notifications APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Notifications extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Notifications.class); + + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" notification {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createNotification(Notification notification) { + try{ + logger.info("Creating notification with id {}.", notification.getId()); + return super.create(notification); + }catch(Exception e){ + return ErrorHandler(e, "create",notification.getId()); + } + } + + @PUT + @Path("/{id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response setNotificationToRead(@NotNull @PathParam("id") String id) { + try{ + logger.info("Setting notification with id {} to read.", id); + Notification notification = new Notification(); + notification.setKey(id); + return super.update(id, notification); + }catch(Exception e){ + return ErrorHandler(e, "update",id); + } + } + + @GET + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response readNotification(@NotNull @PathParam("id") String id) { + try{ + logger.info("Reading notification with id {}.", id); + return super.read(id, ResourceNames.NOTIFICATION); + }catch(Exception e){ + return ErrorHandler(e, "fetch",id); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Posts.java b/src/main/java/org/gcube/social_networking/rest/collections/Posts.java new file mode 100644 index 0000000..0692186 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Posts.java @@ -0,0 +1,199 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.*; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.gcube.social_networking.utils.Schema; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("posts") +@ResourceGroup("Posts APIs") +@ResourceLabel("Posts APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Posts extends Collection { + private static final Logger logger = LoggerFactory.getLogger(Posts.class); + + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" post {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + //Posts + @POST + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createPost(PostWithAttachment postWithAttachment) { + try{ + logger.info("Creating post with id {}.", postWithAttachment.getId()); + return super.create(postWithAttachment); + }catch(Exception e){ + return ErrorHandler(e, "create",postWithAttachment.getId()); + } + } + + @GET + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response readPost(@NotNull @PathParam("id") String id) { + try{ + logger.info("Reading post with id {}.", id); + return super.read(id, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "fetch",id); + } + } + + @GET + @Path("") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response readPostsWithPrivacyLevel(@QueryParam("privacy") String privacyLevel){ + try{ + if (privacyLevel == null || privacyLevel.isEmpty()){ + privacyLevel = PrivacyLevel.PORTAL.toString(); + } + logger.info("Reading post with privacy level = " + privacyLevel ); + return super.readWithParameter(Schema.PRIVACY, privacyLevel, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "fetch","portal privacy level"); + } + } + + @DELETE + @Path("/{id}") + @Produces(MediaType.APPLICATION_JSON) + public Response deletePost(@NotNull @PathParam("id") String id) { + try{ + logger.info("Deleting post with id {}.", id); + return super.delete(id,ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "delete",id); + } + } + + + //comments + @POST + @Path("/{id}/comments") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createComment(@NotNull @PathParam("id") String id, @NotNull Comment comment) { + try{ + logger.info("Creating comment with id {}.", comment.getId()); + return super.createChildOf(id, comment, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "create comment to post",id); + } + } + + @GET + @Path("/{id}/comments") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getCommentsOfPost(@NotNull @PathParam("id") String id){ + try{ + logger.info("Reading comments of post with id " + id); + return super.readChildOf(id, ResourceNames.POST, ResourceNames.COMMENT); + }catch(Exception e){ + return ErrorHandler(e, "fetch comments of",id); + } + } + + @DELETE + @Path("/{id}/comments/{commentid}") + @Produces(MediaType.APPLICATION_JSON) + public Response deleteCommentOfPost(@NotNull @PathParam("id") String id, @NotNull @PathParam("commentid") String commentid) { + try{ + logger.info("Deleting comment of post with id {}.", id); + return super.deleteChildOf(id, commentid, ResourceNames.POST, ResourceNames.COMMENT); + }catch(Exception e){ + return ErrorHandler(e, "delete comment of",id); + } + } + + //Likes + @POST + @Path("/{id}/likes") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createLike(@NotNull @PathParam("id") String id, @NotNull Like like) { + try{ + logger.info("Creating like with id {}.", like.getId()); + return super.createChildOf(id, like, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "create like to post",id); + } + } + + + @GET + @Path("/{id}/likes") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getLikesOfPost(@NotNull @PathParam("id") String id){ + try{ + logger.info("Reading likes of post with id " + id); + return super.readChildOf(id, ResourceNames.POST, ResourceNames.LIKE); + }catch(Exception e){ + return ErrorHandler(e, "fetch likes of",id); + } + } + + + + + @GET + @Path("/{id}/attachments") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getAttachmentsOfPost(@NotNull @PathParam("id") String id){ + try{ + logger.info("Reading attachments of post with id " + id); + return super.readChildOf(id, ResourceNames.POST, ResourceNames.Attachment); + }catch(Exception e){ + return ErrorHandler(e, "fetch attachments of",id); + } + } + + + @PUT + @Path("/{id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updatePost(@NotNull @PathParam("id") String id, @NotNull Post post) { + try{ + logger.info("Updating post with id {}", id); + return super.update(id, post); + }catch(Exception e){ + return ErrorHandler(e, "update",id); + } + } + + @DELETE + @Path("/{id}/likes/{likeid}") + @Produces(MediaType.APPLICATION_JSON) + public Response unlikePost(@NotNull @PathParam("id") String id, @NotNull @PathParam("likeid") String likeid) { + try{ + String username = ""; //get username somehow + logger.info("Unliking post with id {}", id); + return super.deleteChildOfWithParameter(id, likeid, ResourceNames.USER, username, ResourceNames.POST, ResourceNames.LIKE); + }catch(Exception e){ + return ErrorHandler(e, "unlike",id); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/rest/collections/Vres.java b/src/main/java/org/gcube/social_networking/rest/collections/Vres.java new file mode 100644 index 0000000..08b416a --- /dev/null +++ b/src/main/java/org/gcube/social_networking/rest/collections/Vres.java @@ -0,0 +1,230 @@ +package org.gcube.social_networking.rest.collections; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResourceGroup; +import com.webcohesion.enunciate.metadata.rs.ResourceLabel; +import org.gcube.social_networking.socialnetworking.model.shared.*; +import org.gcube.social_networking.utils.ParameterNames; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.ResponseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.util.*; + + +@Path("vres") +@ResourceGroup("Vres APIs") +@ResourceLabel("Vres APIs") +@RequestHeaders({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") +}) +public class Vres extends Collection { + + private static final Logger logger = LoggerFactory.getLogger(Vres.class); + private Response ErrorHandler(Exception e, String action, String id){ + ResponseBean responseBean = new ResponseBean<>(); + Response.Status status; + logger.info("Unable to "+action+" vre {}.", id); + logger.info(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Response.Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Path("/{id}/posts") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getAllPostsByVre(@NotNull @PathParam("id") String id){ + try{ + logger.info("Getting all posts of VRE: " + id); + return super.readChildOf(id, ResourceNames.VRE, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "fetch posts of",id); + } + } + + @GET + @Path("/") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getAllVreIds(){ + try{ + logger.info("Getting all VRE IDs"); + List ids = new ArrayList<>(); + List vres = super.readAll(ResourceNames.VRE).readEntity(new GenericType>>(){}).getResult(); + for(Vre vre: vres){ + ids.add(vre.getId()); + } + Response.Status status = Response.Status.OK; + ResponseBean > responseBean = new ResponseBean<>(); + responseBean.setMessage("vre ids fetched Successfully"); + responseBean.setSuccess(true); + responseBean.setResult(ids); + return Response.status(status).entity(responseBean).build(); + }catch(Exception e){ + return ErrorHandler(e, "fetch ids of",""); + } + } + + @GET + @Path("/{id}/posts") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getRecentPostsByVre(@NotNull @PathParam("id") String id, @QueryParam("limit") @DefaultValue("10") int limit){ + try{ + logger.info("Getting most recent {} posts of VRE {} " , limit, id); + return super.readChildOfWithParameter(id, ParameterNames.RECENT_LIMIT, String.valueOf(limit), ResourceNames.VRE, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "fetch recent posts of",id); + } + } + + @POST + @Path("/{id}/posts") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response savePostToVRETimeline(@NotNull @PathParam("id") String id, @NotNull Post post){ + try{ + logger.info("saving post {} to VRE {} " , post.getKey(), id); + return super.createChildOf(id, post, ResourceNames.VRE); + }catch(Exception e){ + return ErrorHandler(e, "save post to",id); + } + } + + @GET + @Path("/{id}/hashtags") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getVREHashtagsWithOccurrence(@NotNull @PathParam("id") String id){ + try{ + logger.info("getting hashtags of VRE {} " , id); + return super.readChildOf(id, ResourceNames.VRE, ResourceNames.HASHTAG); + }catch(Exception e){ + return ErrorHandler(e, "get hashtags of",id); + } + } + + + @GET + @Path("/{id}/hashtags") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getVREHashtagsWithOccurrenceFilteredByTime(@NotNull @PathParam("id") String id, @NotNull @QueryParam("time") long timestamp){ + try{ + logger.info("getting hashtags of VRE {} starting {} " , id, timestamp); + return super.readChildOfWithParameter(id, ParameterNames.TIME, String.valueOf(timestamp), ResourceNames.VRE, ResourceNames.HASHTAG); + }catch(Exception e){ + return ErrorHandler(e, "get time_filtered hashtags of",id); + } + } + + @GET + @Path("/{id}/hashtags/{hashtag}/posts") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getVREPostsByHashtag(@NotNull @PathParam("id") String id, @NotNull @PathParam("hashtag") String hashtag){ + try{ + logger.info("getting posts containing hashtags in VRE {}" , id); + return super.readChildOfWithParameter(id, ParameterNames.HASHTAG, hashtag, ResourceNames.VRE, ResourceNames.POST); + }catch(Exception e){ + return ErrorHandler(e, "get posts containing hashtag in",id); + } + } + + @GET + @Path("/{id}/invites/") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response getInvitedEmailsByVRE(@NotNull @PathParam("id") String id, @NotNull InviteStatus... status){ + try{ + logger.info("getting invites in VRE {}" , id); + return super.readChildOfWithParameter(id, ParameterNames.STATUS, Arrays.toString(status), ResourceNames.VRE, ResourceNames.INVITE); + }catch(Exception e){ + return ErrorHandler(e, "get invites in",id); + } + } + + @GET + @Path("/{id}/invites/{email}") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response isExistingInvite(@NotNull @PathParam("id") String id, @NotNull @PathParam("email")String email){ + try{ + logger.info("checking if invite {} exists in VRE {}" , email, id); + return super.readChildOfWithParameter(id, ParameterNames.EMAIL, email, ResourceNames.VRE, ResourceNames.INVITE); + }catch(Exception e){ + return ErrorHandler(e, "check invite in",id); + } + } + + @PUT + @Path("/{id}/invites/{email}") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response setInviteStatus(@NotNull @PathParam("id") String id, @NotNull @PathParam("email")String email, @NotNull InviteStatus inviteStatus){ + try{ + logger.info("setting invite {} status in VRE {}" , email, id); + Invite invite = new Invite(); + invite.setStatus(inviteStatus); + return super.updateChildOfWithParameter(id, ParameterNames.EMAIL, email, invite, ResourceNames.VRE); + }catch(Exception e){ + return ErrorHandler(e, "set invite status in",id); + } + } + + + @POST + @Path("/{id}/posts/{postid}/hashtags") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response saveHashTags(@NotNull @PathParam("id") String id, @NotNull @PathParam("postid") String postid, @NotNull Listhashtags){ + try{ + logger.info("saving post hashtags to VRE {} ", id); + return super.BatchCreateChildOfWithParameter(id, ResourceNames.POST, postid, new ArrayList<>(hashtags), ResourceNames.VRE, ResourceNames.HASHTAG); + }catch(Exception e){ + return ErrorHandler(e, "save post hashtags to",id); + } + } + + @DELETE + @Path("/{id}/posts/{postid}/hashtags") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response deleteHashTags(@NotNull @PathParam("id") String id, @NotNull @PathParam("postid") String postid, @NotNull Listhashtags){ + try{ + logger.info("deleting post hashtags from VRE {} " , id); + return super.BatchDeleteChildOfWithParameter(id, ResourceNames.POST, postid, new ArrayList<>(hashtags), ResourceNames.VRE, ResourceNames.HASHTAG); + }catch(Exception e){ + return ErrorHandler(e, "delete post hashtags from",id); + } + } + + + @POST + @Path("/{id}/comments/{commentid}/hashtags") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response saveHashTagsComment(@NotNull @PathParam("id") String id, @NotNull @PathParam("commentid") String commentid, @NotNull Listhashtags){ + try{ + logger.info("saving comment hashtags to VRE {} ", id); + return super.BatchCreateChildOfWithParameter(id, ResourceNames.COMMENT, commentid, new ArrayList<>(hashtags), ResourceNames.VRE, ResourceNames.HASHTAG); + }catch(Exception e){ + return ErrorHandler(e, "save comment hashtags to",id); + } + } + + @DELETE + @Path("/{id}/comments/{commentid}/hashtags") + @Produces({"application/json;charset=UTF-8", "application/vnd.api+json"}) + @Consumes({"application/json;charset=UTF-8", "application/vnd.api+json"}) + public Response deleteHashTagsComment(@NotNull @PathParam("id") String id, @NotNull @PathParam("commentid") String commentid, @NotNull Listhashtags){ + try{ + logger.info("deleting comment hashtags from VRE {} " , id); + return super.BatchDeleteChildOfWithParameter(id, ResourceNames.COMMENT, commentid, new ArrayList<>(hashtags), ResourceNames.VRE, ResourceNames.HASHTAG); + }catch(Exception e){ + return ErrorHandler(e, "delete comment hashtags from",id); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/server/CassandraCluster.java b/src/main/java/org/gcube/social_networking/server/CassandraCluster.java index f637f7f..fd365bf 100644 --- a/src/main/java/org/gcube/social_networking/server/CassandraCluster.java +++ b/src/main/java/org/gcube/social_networking/server/CassandraCluster.java @@ -16,7 +16,7 @@ import org.gcube.common.portal.GCubePortalConstants; import org.gcube.common.portal.PortalContext; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; -import org.gcube.common.scope.api.ScopeProvider; +//import org.gcube.common.scope.api.ScopeProvider; import org.gcube.social_networking.socialnetworking.model.shared.exceptions.TooManyRunningClustersException; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; @@ -122,15 +122,15 @@ class CassandraCluster implements Serializable { scope += readInfrastructureName(); _log.debug("infrastrucute name is null, setting root scope=" + scope); } - String currScope = ScopeProvider.instance.get(); + /*String currScope = ScopeProvider.instance.get(); ScopeProvider.instance.set(scope); SimpleQuery query = queryFor(ServiceEndpoint.class); query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'"); query.addCondition("$resource/Profile/Platform/Name/text() eq '"+ PLATFORM_NAME +"'"); DiscoveryClient client = clientFor(ServiceEndpoint.class); List toReturn = client.submit(query); - ScopeProvider.instance.set(currScope); - return toReturn; + ScopeProvider.instance.set(currScope);*/ + return null; } private String readInfrastructureName() { diff --git a/src/main/java/org/gcube/social_networking/server/SocialDBDatastaxDriver.java b/src/main/java/org/gcube/social_networking/server/SocialDBDatastaxDriver.java index df4ba1a..4c4287d 100644 --- a/src/main/java/org/gcube/social_networking/server/SocialDBDatastaxDriver.java +++ b/src/main/java/org/gcube/social_networking/server/SocialDBDatastaxDriver.java @@ -13,21 +13,23 @@ import org.apache.commons.lang.NullArgumentException; import org.gcube.social_networking.socialnetworking.model.shared.*; import org.gcube.social_networking.socialnetworking.model.shared.exceptions.*; +import org.gcube.social_networking.utils.ParameterNames; +import org.gcube.social_networking.utils.ResourceNames; +import org.gcube.social_networking.utils.Schema; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.gcube.social_networking.utils.Schema.*; +import static org.gcube.social_networking.utils.ResourceNames.*; + /** * @author Massimiliano Assante ISTI-CNR * @author Costantino Perciante ISTI-CNR * @author Ahmed Ibrahim ISTI-CNR * This class is used for querying and adding data to Cassandra via Datastax High Level API */ -public final class SocialDBDatastaxDriver implements SocialDBDriver { +public final class SocialDBDatastaxDriver implements SocialDBDriver{ - /** - * logger - */ private static final Logger _log = LoggerFactory.getLogger(SocialDBDatastaxDriver.class); /** @@ -71,575 +73,928 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { } } + /* - Utility Functions - */ - private static boolean existRecordbyId(CqlSession session, String id, String tableName, String colName) { - PreparedStatement stmt = session.prepare(QueryBuilder - .selectFrom(tableName).column(colName) - .whereColumn(colName) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - return session.execute(stmt.bind(id)).getAvailableWithoutFetching() > 0; + * + ********************** Generic CRUD *********************** + * + */ + @Override + public Boolean create(Resource resource) { + String resourceName = resource.getClass().getSimpleName(); + if(resourceName.equals(ResourceNames.POST)){ + try { + return savePost((PostWithAttachment) resource); + } catch (PostTypeNotFoundException | ColumnNameNotFoundException | PostIDNotFoundException | + PrivacyLevelTypeNotFoundException e) { + throw new RuntimeException(e); + } + } else if(resourceName.equals(ResourceNames.NOTIFICATION)) { + return saveNotification((Notification) resource); + } + else{ + return null; + } } - private static boolean existRecordbyCompId(CqlSession session, String col1, String col2, String id1, String id2, String tableName) { - PreparedStatement stmt = session.prepare(QueryBuilder - .selectFrom(tableName).all() - .whereColumn(col1) - .isEqualTo(QueryBuilder.bindMarker()) - .whereColumn(col2) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - return session.execute(stmt.bind(id1, id2)).getAvailableWithoutFetching() > 0; + @Override + public Boolean createChildOf(String parentid, Resource childResource, String parentResourceName){ + String resourceName = childResource.getClass().getSimpleName(); + if(parentResourceName.equals(ResourceNames.VRE)) { + if(resourceName.equals(ResourceNames.POST)){ + try { + savePostToVRETimeline(parentid, (Post) childResource); + } catch (PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } + + }else { + + if (resourceName.equals(ResourceNames.COMMENT)) { + try { + return saveComment(parentid, (Comment) childResource); + } catch (PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } else if (resourceName.equals(ResourceNames.LIKE)) { + try { + return like(parentid, (Like) childResource); + } catch (PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } + } + return null; + } - private static PreparedStatement updatePostEntry(CqlSession session, String colName){ - return session.prepare(QueryBuilder.update(POSTS) - .setColumn(colName, QueryBuilder.bindMarker()) - .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); + @Override + public Boolean BatchCreateChildOfWithParameter(String parentid, String parameterName, String parameterValue, List childResource, String parentResourceName, String childResourceName){ + if(parentResourceName.equals(ResourceNames.VRE)){ + if(childResourceName.equals(ResourceNames.HASHTAG)){ + List hashtags = new ArrayList<>(); + for(Resource r: childResource){ + Hashtag h = (Hashtag) r; + hashtags.add(h.getHashtag()); + } + if(parameterName.equals(ResourceNames.POST)){ + try { + return saveHashTags(parameterValue, parentid, hashtags); + } catch (PostIDNotFoundException e) { + throw new RuntimeException(e); + } + }else if(parameterName.equals(ResourceNames.COMMENT)){ + try { + return saveHashTagsComment(parameterValue, parentid, hashtags); + } catch (CommentIDNotFoundException e) { + throw new RuntimeException(e); + } + } + } + } + return null; } - private static Attachment readAttachmentFromRow(Row record) { - Attachment a = new Attachment(); - a.setId(Objects.requireNonNull(record.getUuid(ATTACH_ID)).toString()); - a.setUri(record.getString(URI)); - a.setName(record.getString(NAME)); - a.setDescription(record.getString(DESCRIPTION)); - a.setThumbnailURL(record.getString(URI_THUMBNAIL)); - a.setMimeType(record.getString(MIME_TYPE)); - return a; - } - private static Notification readNotificationFromRow(Row record) throws NotificationTypeNotFoundException { - Notification a = new Notification(); - a.setKey(Objects.requireNonNull(record.getUuid(NOT_ID)).toString()); - a.setType(getNotificationType(Objects.requireNonNull(record.getString(TYPE)))); - a.setUserid(record.getString(USER_ID)); - a.setSubjectid(record.getString(SUBJECT_ID)); - a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); - a.setUri(record.getString(URI)); - a.setDescription(record.getString(DESCRIPTION)); - a.setRead(record.getBoolean(IS_READ)); - a.setSenderid(record.getString(SENDER_ID)); - a.setSenderFullName(record.getString(SENDER_FULL_NAME)); - a.setSenderThumbnail(record.getString(SENDER_THUMBNAIL_URL)); - return a; - } - private static Post readPostFromRow(Row record) throws PostTypeNotFoundException, PrivacyLevelTypeNotFoundException { - Post a = new Post(); + @Override + public Resource read(String id, String resourceName) { + if(resourceName.equals(ResourceNames.POST)){ + try { + return readPost(id); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | PostIDNotFoundException | + ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } else if (resourceName.equals(ResourceNames.NOTIFICATION)) { + try { + return readNotification(id); + } catch (NotificationIDNotFoundException | NotificationTypeNotFoundException | ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + }else if (resourceName.equals(ResourceNames.COMMENT)) { + try { + return readComment(id); + } catch (CommentIDNotFoundException e) { + throw new RuntimeException(e); + } - a.setKey(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); - a.setType(getPostType(Objects.requireNonNull(record.getString(TYPE)))); - a.setEntityId(record.getString(ENTITY_ID)); - a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); - a.setVreid(record.getString(VRE_ID)); - a.setUri(record.getString(URI)); - a.setUriThumbnail(record.getString(URI_THUMBNAIL)); - a.setDescription(record.getString(DESCRIPTION)); - a.setPrivacy(getPrivacyLevel(Objects.requireNonNull(record.getString(PRIVACY)))); - a.setFullName(record.getString(FULL_NAME)); - a.setEmail(record.getString(EMAIL)); - a.setThumbnailURL(record.getString(THUMBNAIL_URL)); - a.setCommentsNo(String.valueOf(record.getLong(COMMENTS_NO))); - a.setLikesNo(String.valueOf(record.getLong(LIKES_NO))); - a.setLinkDescription(record.getString(LINK_DESCRIPTION)); - a.setLinkTitle(record.getString(LINK_TITLE)); - a.setLinkHost(record.getString(LINK_HOST)); - a.setApplicationPost(record.getBoolean(IS_APPLICATION_POST)); - a.setMultiFileUpload(record.getBoolean(MULTI_FILE_UPLOAD)); - - return a; - } - private static Like readLikeFromRow(Row record) { - Like a = new Like(); - a.setKey(Objects.requireNonNull(record.getUuid(LIKE_ID)).toString()); - a.setUserid(record.getString(USER_ID)); - a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); - a.setPostid(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); - a.setFullName(record.getString(FULL_NAME)); - a.setThumbnailURL(record.getString(THUMBNAIL_URL)); - return a; - } - private static Comment readCommentFromRow(Row record) { - Comment a = new Comment(); - a.setKey(Objects.requireNonNull(record.getUuid(COMMENT_ID)).toString()); - a.setUserid(record.getString(USER_ID)); - a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); - a.setPostid(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); - a.setFullName(record.getString(FULL_NAME)); - a.setThumbnailURL(record.getString(THUMBNAIL_URL)); - a.setText(record.getString(COMMENT)); - a.setEdit(!record.isNull(IS_EDIT) && record.getBoolean(IS_EDIT)); - a.setLastEditTime(record.isNull(LAST_EDIT_TIME)? null : Date.from(Objects.requireNonNull(record.getInstant(LAST_EDIT_TIME)))); - return a; - } - private static Invite readAInviteFromRow(Row record) throws InviteStatusNotFoundException { - Invite a = new Invite(); - a.setKey(Objects.requireNonNull(record.getUuid(INVITE_ID)).toString()); - a.setSenderUserId(record.getString(SENDER_USER_ID)); - a.setVreid(record.getString(VRE_ID)); - a.setInvitedEmail(record.getString(EMAIL)); - a.setControlCode(record.getString(CONTROL_CODE)); - a.setStatus(getInviteStatusType(Objects.requireNonNull(record.getString(STATUS)))); - a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); - a.setSenderFullName(record.getString(SENDER_FULL_NAME)); - return a; + }else if(resourceName.equals(ResourceNames.INVITE)){ + try { + return readInvite(id); + } catch (InviteIDNotFoundException | InviteStatusNotFoundException e) { + throw new RuntimeException(e); + } + } + else{ + return null; + } } - private static Optional < Post > findPostById(String postid, CqlSession session) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException { - PreparedStatement stmtFindPost = session.prepare(QueryBuilder - .selectFrom(POSTS).all() - .whereColumn(POST_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - ResultSet rs = session.execute(stmtFindPost.bind(UUID.fromString(postid))); - // We query by the primary key ensuring unicity - Row record = rs.one(); - return (null != record) ? Optional.of(readPostFromRow(record)) :Optional.empty(); + @Override + public Boolean check(String id, String parameterName, String parameterValue, String resourceName) { + return null; } - private static Optional < Notification > findNotById(String notid, CqlSession session) throws NotificationTypeNotFoundException { - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(NOTIFICATIONS).all() - .whereColumn(NOT_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - ResultSet rs = session.execute(stmtFind.bind(UUID.fromString(notid))); - // We query by the primary key ensuring unicity - Row record = rs.one(); - return (null != record) ? Optional.of(readNotificationFromRow(record)) :Optional.empty(); + + @Override + public Boolean checkChildOf(String parentid, String parameterName, String parameterValue, String parentResourceName, String childResourceName){ + if(parentResourceName.equals(ResourceNames.USER)){ + if(childResourceName.equals(ResourceNames.NOTIFICATION)){ + if(parameterName.equals(ParameterNames.UNREAD_MESSAGE)){ + if(parameterValue.equals(String.valueOf(true))){ + try { + return checkUnreadMessagesNotifications(parentid); + } catch (NotificationIDNotFoundException | NotificationTypeNotFoundException | + ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } + } else if(parameterName.equals(ParameterNames.UNREAD)){ + if(parameterValue.equals(String.valueOf(true))){ + try { + return checkUnreadNotifications(parentid); + } catch (NotificationTypeNotFoundException | ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } + } + + } + } + return null; + } + + @Override + public List readAll(String resourceName) { + if(resourceName.equals(ResourceNames.VRE)){ + return new ArrayList<>(getAllVREIds()); + } + else{ + return null; + } + } + @Override + public ListreadChildOf(String parentid, String parentResourceName, String childResourceName){ + if (parentResourceName.equals(ResourceNames.POST)){ + if(childResourceName.equals(ResourceNames.COMMENT)){ + return getAllChildrenByPost(parentid, COMMENTS); + } else if (childResourceName.equals(ResourceNames.LIKE)){ + return getAllChildrenByPost(parentid, LIKES); + } else if (childResourceName.equals(ResourceNames.Attachment)){ + return getAllChildrenByPost(parentid, ATTACHMENTS); + } + }else if (parentResourceName.equals(VRE)){ + if(childResourceName.equals(ResourceNames.POST)){ + try { + return new ArrayList<>(getAllPostsByVRE(parentid)); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | ColumnNameNotFoundException | + PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } else if(childResourceName.equals(ResourceNames.HASHTAG)){ + return new ArrayList<>(getVREHashtagsWithOccurrence(parentid)); + } + }else if (parentResourceName.equals(ResourceNames.USER)) { + if (childResourceName.equals(ResourceNames.POST)) { + try { + return new ArrayList<>(getAllPostsByUser(parentid)); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | ColumnNameNotFoundException | + PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } else if (childResourceName.equals(ResourceNames.NOTIFICATION_PREFERENCES)) { + try { + return new ArrayList<>(getUserNotificationPreferences(parentid)); + }catch (NotificationChannelTypeNotFoundException | NotificationTypeNotFoundException e) { + throw new RuntimeException(e); + } + } + + }else if (parentResourceName.equals(ResourceNames.APP)) { + if (childResourceName.equals(ResourceNames.POST)) { + try { + return new ArrayList<>(getAllPostsByApp(parentid)); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | ColumnNameNotFoundException | + PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } + } + return null; + } + + @Override + public List readChildOfWithParameter(String parentid, String parameterName, String parameterValue, String parentResourceName, String childResourceName){ + if(parentResourceName.equals(ResourceNames.VRE)) { + if (childResourceName.equals(ResourceNames.POST)) { + if (parameterName.equals(ParameterNames.RECENT_LIMIT)) { + try { + return new ArrayList<>(getRecentPostsByVRE(parentid, Integer.parseInt(parameterValue))); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | + ColumnNameNotFoundException | PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } else if (parameterName.equals(ParameterNames.HASHTAG)) { + try { + return new ArrayList<>(getVREPostsByHashtag(parentid, parameterValue)); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | PostIDNotFoundException | + ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } + } else if (childResourceName.equals(ResourceNames.HASHTAG)) { + if (parameterName.equals(ParameterNames.TIME)) { + return new ArrayList<>(getVREHashtagsWithOccurrenceFilteredByTime(parentid, Long.parseLong(parameterValue))); + } + } else if (childResourceName.equals(ResourceNames.INVITE)){ + if (parameterName.equals(ParameterNames.STATUS)) { + String status = parameterValue.replace("[", ""); + status = status.replace("]", ""); + status = status.replace(" ", ""); + String [] statusArray = status.split(","); + List inviteStatusList = new ArrayList<>(); + for (String s: statusArray){ + inviteStatusList.add(InviteStatus.valueOf(s)); + } + try { + return new ArrayList<>(getInvitedEmailsByVRE(parentid, inviteStatusList)); + } catch (InviteIDNotFoundException | InviteStatusNotFoundException e) { + throw new RuntimeException(e); + } + + } else if (parameterName.equals(ParameterNames.EMAIL)) { + List toReturn = new ArrayList<>(); + toReturn.add(isExistingInvite(parentid, parameterValue)); + return new ArrayList<>(toReturn); + } + } + }else if(parentResourceName.equals(ResourceNames.USER)){ + if (childResourceName.equals(ResourceNames.POST)){ + if (parameterName.equals(ParameterNames.RECENT_COMMENT)){ + try { + return new ArrayList<>(getRecentCommentedPostsByUserAndDate(parentid, Long.parseLong(parameterValue))); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (parameterName.equals(ParameterNames.RECENT_LIKE)){ + return new ArrayList<>(getRecentLikedPostsByUserAndDate(parentid, Integer.parseInt(parameterValue))); + + } else if (parameterName.equals(ParameterNames.ALL_LIKE)){ + try { + return new ArrayList<>(getAllLikedPostsByUser(parentid, Integer.parseInt(parameterValue))); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | + ColumnNameNotFoundException | PostIDNotFoundException e) { + throw new RuntimeException(e); + } + + }else if (parameterName.equals(ParameterNames.RECENT_LIMIT)){ + try { + return new ArrayList<>(getRecentPostsByUser(parentid, Integer.parseInt(parameterValue))); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | + ColumnNameNotFoundException | PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } else if (parameterName.equals(ParameterNames.TIME)){ + return new ArrayList<>(getRecentPostsByUserAndDate(parentid, Long.parseLong(parameterValue))); + } + } else if (childResourceName.equals(ResourceNames.NOTIFICATION)){ + if (parameterName.equals(ParameterNames.RECENT_LIMIT)){ + try { + return new ArrayList<>(getAllNotificationByUser(parentid, Integer.parseInt(parameterValue))); + } catch (NotificationTypeNotFoundException | ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } else if (parameterName.equals(ParameterNames.UNREAD)){ + try { + return new ArrayList<>(getUnreadNotificationsByUser(parentid)); + } catch (NotificationTypeNotFoundException | ColumnNameNotFoundException | + NotificationIDNotFoundException e) { + throw new RuntimeException(e); + } + }else if (parameterName.equals(ParameterNames.NOTIFICATION_TYPE)) { + try { + List resources = new ArrayList<>(); + List notificationChannelTypes = getUserNotificationChannels(parentid, NotificationType.valueOf(parameterName)); + for (NotificationChannelType n: notificationChannelTypes) { + Resource x = new Resource() { + String notChannel = n.toString(); + @Override + public String getId() { + return notChannel; + } + }; + resources.add(x); + } + + return resources; + } catch (NotificationChannelTypeNotFoundException | NotificationTypeNotFoundException e) { + throw new RuntimeException(e); + } + } + + }else if (childResourceName.equals(ResourceNames.COMMENT)){ + if (parameterName.equals(ParameterNames.TIME)){ + try { + return new ArrayList<>(getRecentCommentsByUserAndDate(parentid, Integer.parseInt(parameterValue))); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } + return null; + } + + @Override + public List readWithParameter(String parameterName, String parameterValue, String resourceName) { + if(resourceName.equals(Post.class.getSimpleName())){ + try { + if(parameterName.equals(PRIVACY)){ + return new ArrayList<>(getAllPostsWithPrivacy(parameterValue)); + } + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | + ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } + else{ + return null; + } + return null; + } + + @Override + public Boolean delete(String id, String resourceName) { + if(resourceName.equals(Post.class.getSimpleName())){ + try { + return deletePost(id); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | PostIDNotFoundException | + ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } + else{ + return null; + } + } + + @Override + public Boolean deleteChildOf(String parentid, String childid, String childResourceName) { + if(childResourceName.equals(Comment.class.getSimpleName())){ + try { + return deleteComment(parentid, childid); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | PostIDNotFoundException | + ColumnNameNotFoundException | CommentIDNotFoundException e) { + throw new RuntimeException(e); + } + } + else{ + return null; + } + } + + @Override + public Boolean deleteWithParameter(String parameterName, String parameterValue, String resourceName) { + return null; + } + + @Override + public Boolean BatchDeleteChildOfWithParameter(String parentid, String parameterName, String parameterValue, List childResource, String parentResourceName, String childResourceName){ + if(parentResourceName.equals(ResourceNames.VRE)){ + if(childResourceName.equals(ResourceNames.HASHTAG)){ + List hashtags = new ArrayList<>(); + for(Resource r: childResource){ + Hashtag h = (Hashtag) r; + hashtags.add(h.getHashtag()); + } + if(parameterName.equals(ResourceNames.POST)){ + try { + return deleteHashTags(parameterValue, parentid, hashtags); + } catch (PostIDNotFoundException e) { + throw new RuntimeException(e); + } + }else if(parameterName.equals(ResourceNames.COMMENT)){ + try { + return deleteHashTagsComment(parameterValue, parentid, hashtags); + } catch (CommentIDNotFoundException e) { + throw new RuntimeException(e); + } + } + } + } + return null; + } + @Override + public Boolean deleteChildOfWithParameter(String parentid, String childid, String parameterName, String parameterValue, String parentResourceName, String childResourceName){ + if(parentResourceName.equals(ResourceNames.POST)){ + if(childResourceName.equals(ResourceNames.LIKE)){ + if(parameterName.equals(ResourceNames.USER)){ + try { + return unlike(parameterValue, childid, parentid); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | + ColumnNameNotFoundException | LikeIDNotFoundException | PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } + } + } + return null; + } + + @Override + public Boolean update(Resource resource) { + String resourceName = resource.getClass().getSimpleName(); + + if(resourceName.equals(Notification.class.getSimpleName())){ + try { + return setNotificationRead(resource.getId()); + } catch (NotificationIDNotFoundException | ColumnNameNotFoundException | NotificationTypeNotFoundException e) { + throw new RuntimeException(e); + } + } + else if(resourceName.equals(Comment.class.getSimpleName())){ + try { + return editComment((Comment) resource); + } catch (PrivacyLevelTypeNotFoundException | PostTypeNotFoundException | ColumnNameNotFoundException | + CommentIDNotFoundException | PostIDNotFoundException e) { + throw new RuntimeException(e); + } + } + else{ + return null; + } + } + + @Override + public Boolean updateChildOf(String parentid, String childid, Resource childResource, String parentResourceName){ + if(parentResourceName.equals(ResourceNames.USER)) { + String childResourceName = childResource.getClass().getSimpleName(); + if (childResourceName.equals(ResourceNames.NOTIFICATION)){ + Notification notification = (Notification) childResource; + try { + if(notification.isRead()) { + return setAllNotificationReadByUser(parentid); + } + } catch (NotificationTypeNotFoundException | ColumnNameNotFoundException e) { + throw new RuntimeException(e); + } + } + } + + return null; + } + @Override + public Boolean BatchUpdateChildOf(String parentid, List childResource, String parentResourceName){ + if(parentResourceName.equals(ResourceNames.USER)) { + String childResourceName = childResource.get(0).getClass().getSimpleName(); + if (childResourceName.equals(NOTIFICATION_PREFERENCES)){ + List notificationPreferences = new ArrayList<>(); + for(Resource r: childResource){ + notificationPreferences.add((NotificationPreference) r); + } + return setUserNotificationPreferences(parentid, notificationPreferences); + } + } + return null; + } + + @Override + public Boolean updateWithParameter(String parameterName, String parameterValue, Resource resource) { + return null; + } + + @Override + public Boolean updateChildOfWithParameter(String parentid, String parameterName, String parameterValue, Resource childResource, String parentResourceName){ + if(parentResourceName.equals(ResourceNames.VRE)){ + String childResourceName = childResource.getClass().getSimpleName(); + if(childResourceName.equals(ResourceNames.INVITE)){ + if(parameterName.equals(ParameterNames.EMAIL)){ + Invite invite = (Invite) childResource; + try { + return setInviteStatus(parentid, parameterValue, invite.getStatus()); + } catch (InviteIDNotFoundException | InviteStatusNotFoundException e) { + throw new RuntimeException(e); + } + } + } + } + + return null; } - private static PreparedStatement updateInviteEntry(CqlSession session, String colName){ - return session.prepare(QueryBuilder.update(INVITES) - .setColumn(colName, QueryBuilder.bindMarker()) - .whereColumn(INVITE_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement updateVreInviteEntry(CqlSession session, String colName){ - return session.prepare(QueryBuilder.update(VRE_INVITES) - .setColumn(colName, QueryBuilder.bindMarker()) - .whereColumn(VRE_ID).isEqualTo(QueryBuilder.bindMarker()) - .whereColumn(INVITE_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement deleteHashtagEntry(CqlSession session){ - return session.prepare(QueryBuilder.deleteFrom(HASHTAGGED_POSTS) - .whereColumn(HASHTAG) - .isEqualTo(QueryBuilder.bindMarker()) - .whereColumn(POST_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement deleteHashtagCommentEntry(CqlSession session){ - return session.prepare(QueryBuilder.deleteFrom(HASHTAGGED_COMMENTS) - .whereColumn(HASHTAG) - .isEqualTo(QueryBuilder.bindMarker()) - .whereColumn(COMMENT_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement deleteLikeEntry(CqlSession session){ - return session.prepare(QueryBuilder.deleteFrom(LIKES) - .whereColumn(LIKE_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement deleteUserLikeEntry(CqlSession session){ - return session.prepare(QueryBuilder.deleteFrom(USER_LIKED_POSTS) - .whereColumn(USER_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .whereColumn(LIKE_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement updateCommentEntry(CqlSession session, String colName){ - return session.prepare(QueryBuilder.update(COMMENTS) - .setColumn(colName, QueryBuilder.bindMarker()) - .whereColumn(COMMENT_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement deleteCommentEntry(CqlSession session){ - return session.prepare(QueryBuilder.deleteFrom(COMMENTS) - .whereColumn(COMMENT_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement updateNotificationEntry(CqlSession session, String colName){ - return session.prepare(QueryBuilder.update(NOTIFICATIONS) - .setColumn(colName, QueryBuilder.bindMarker()) - .whereColumn(NOT_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement deleteUnreadNotEntry(CqlSession session){ - return session.prepare(QueryBuilder.deleteFrom(USER_NOTIFICATIONS_UNREAD) - .whereColumn(USER_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .whereColumn(TIMESTAMP) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - } - private static BatchStatement getBatch(){ - return BatchStatement.builder(BatchType.LOGGED).build(); - } - - private static PreparedStatement createPostEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(POSTS) - .value(POST_ID, QueryBuilder.bindMarker()) - .value(LINK_HOST, QueryBuilder.bindMarker()) - .value(DESCRIPTION, QueryBuilder.bindMarker()) - .value(EMAIL, QueryBuilder.bindMarker()) - .value(LIKES_NO, QueryBuilder.bindMarker()) - .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) - .value(LINK_DESCRIPTION, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(URI, QueryBuilder.bindMarker()) - .value(IS_APPLICATION_POST, QueryBuilder.bindMarker()) - .value(ENTITY_ID, QueryBuilder.bindMarker()) - .value(PRIVACY, QueryBuilder.bindMarker()) - .value(TYPE, QueryBuilder.bindMarker()) - .value(URI_THUMBNAIL, QueryBuilder.bindMarker()) - .value(VRE_ID, QueryBuilder.bindMarker()) - .value(MULTI_FILE_UPLOAD, QueryBuilder.bindMarker()) - .value(FULL_NAME, QueryBuilder.bindMarker()) - .value(COMMENTS_NO, QueryBuilder.bindMarker()) - .value(LINK_TITLE, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createUserTimelineEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(USER_TIMELINE_POSTS) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createVreTimelineEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(VRE_TIMELINE_POSTS) - .value(VRE_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createAppTimelineEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(APP_TIMELINE_POSTS) - .value(APP_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNotificationEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(NOTIFICATIONS) - .value(NOT_ID, QueryBuilder.bindMarker()) - .value(TYPE, QueryBuilder.bindMarker()) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(SUBJECT_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(DESCRIPTION, QueryBuilder.bindMarker()) - .value(URI, QueryBuilder.bindMarker()) - .value(SENDER_ID, QueryBuilder.bindMarker()) - .value(SENDER_FULL_NAME, QueryBuilder.bindMarker()) - .value(SENDER_THUMBNAIL_URL, QueryBuilder.bindMarker()) - .value(IS_READ, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createUserNotificationsEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(USER_NOTIFICATIONS) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(NOT_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createUnreadNotificationEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(USER_NOTIFICATIONS_UNREAD) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(NOT_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNotificationPreferenceEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(USER_NOTIFICATIONS_PREFERENCES) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(TYPE, QueryBuilder.bindMarker()) - .value(PREFERENCE, QueryBuilder.bindMarker()) - .build()); - } - - private static PreparedStatement createNewCommentEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(COMMENTS) - .value(COMMENT_ID, QueryBuilder.bindMarker()) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(FULL_NAME, QueryBuilder.bindMarker()) - .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) - .value(COMMENT, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(IS_EDIT, QueryBuilder.bindMarker()) - .value(LAST_EDIT_TIME, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewLikeEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(LIKES) - .value(LIKE_ID, QueryBuilder.bindMarker()) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(FULL_NAME, QueryBuilder.bindMarker()) - .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewUserLikesEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(USER_LIKED_POSTS) - .value(USER_ID, QueryBuilder.bindMarker()) - .value(LIKE_ID, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewHashtagTimelineEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(HASHTAGGED_POSTS) - .value(HASHTAG, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .value(VRE_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewHashtagCommentEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(HASHTAGGED_COMMENTS) - .value(HASHTAG, QueryBuilder.bindMarker()) - .value(COMMENT_ID, QueryBuilder.bindMarker()) - .value(VRE_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewEmailInviteEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(EMAIL_INVITES) - .value(EMAIL, QueryBuilder.bindMarker()) - .value(VRE_ID, QueryBuilder.bindMarker()) - .value(INVITE_ID, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewInviteEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(INVITES) - .value(INVITE_ID, QueryBuilder.bindMarker()) - .value(SENDER_USER_ID, QueryBuilder.bindMarker()) - .value(VRE_ID, QueryBuilder.bindMarker()) - .value(EMAIL, QueryBuilder.bindMarker()) - .value(CONTROL_CODE, QueryBuilder.bindMarker()) - .value(STATUS, QueryBuilder.bindMarker()) - .value(TIMESTAMP, QueryBuilder.bindMarker()) - .value(SENDER_FULL_NAME, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewVreInviteEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(VRE_INVITES) - .value(VRE_ID, QueryBuilder.bindMarker()) - .value(INVITE_ID, QueryBuilder.bindMarker()) - .value(STATUS, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewaAttachEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(ATTACHMENTS) - .value(ATTACH_ID, QueryBuilder.bindMarker()) - .value(POST_ID, QueryBuilder.bindMarker()) - .value(URI, QueryBuilder.bindMarker()) - .value(NAME, QueryBuilder.bindMarker()) - .value(DESCRIPTION, QueryBuilder.bindMarker()) - .value(URI_THUMBNAIL, QueryBuilder.bindMarker()) - .value(MIME_TYPE, QueryBuilder.bindMarker()) - .build()); - } - private static PreparedStatement createNewUHashtagCounterEntry(CqlSession session){ - return session.prepare( - QueryBuilder.insertInto(HASHTAGS_COUNTER) - .value(VRE_ID, QueryBuilder.bindMarker()) - .value(HASHTAG, QueryBuilder.bindMarker()) - .value(COUNT, QueryBuilder.bindMarker()) - .build()); - } /* * ********************** POSTS *********************** * */ - private List insertIntoPosts(CqlSession session, Post post){ - PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_HOST, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(EMAIL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LIKES_NO, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_DESCRIPTION, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt9 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(IS_APPLICATION_POST, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt10 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(ENTITY_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt11 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(PRIVACY, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt12 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(TYPE, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt13 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(URI_THUMBNAIL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt14 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(VRE_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt15 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(MULTI_FILE_UPLOAD, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt16 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt17 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(COMMENTS_NO, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt18 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_TITLE, QueryBuilder.bindMarker()).build()); - List boundStatements = new ArrayList<>(); + private boolean savePost(PostWithAttachment postWithAttachment) throws PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException, PrivacyLevelTypeNotFoundException { + Post post = postWithAttachment.getPost(); + List attachments = postWithAttachment.getAttachments(); + if (attachments != null && !attachments.isEmpty()) + post.setMultiFileUpload(true); - if(post.getLinkHost()!=null){ - boundStatements.add(prepStmt1.bind(UUID.fromString(post.getKey()), post.getLinkHost())); - }if(post.getDescription()!=null){ - boundStatements.add(prepStmt2.bind(UUID.fromString(post.getKey()), post.getDescription())); - }if(post.getEmail()!=null){ - boundStatements.add(prepStmt3.bind(UUID.fromString(post.getKey()), post.getEmail())); - }if(post.getLikesNo()!=null){ - boundStatements.add(prepStmt4.bind(UUID.fromString(post.getKey()), Long.parseLong(post.getLikesNo()))); - }if(post.getThumbnailURL()!=null){ - boundStatements.add(prepStmt5.bind(UUID.fromString(post.getKey()), post.getThumbnailURL())); - }if(post.getLinkDescription()!=null){ - boundStatements.add(prepStmt6.bind(UUID.fromString(post.getKey()), post.getLinkDescription())); - }if(post.getTime()!=null){ - boundStatements.add(prepStmt7.bind(UUID.fromString(post.getKey()), post.getTime().toInstant())); - }if(post.getUri()!=null){ - boundStatements.add(prepStmt8.bind(UUID.fromString(post.getKey()), post.getUri())); - } - boundStatements.add(prepStmt9.bind(UUID.fromString(post.getKey()), post.isApplicationPost())); - if(post.getEntityId()!=null){ - boundStatements.add(prepStmt10.bind(UUID.fromString(post.getKey()), post.getEntityId())); - }if(post.getPrivacy()!=null){ - boundStatements.add(prepStmt11.bind(UUID.fromString(post.getKey()), post.getPrivacy().toString())); - }if(post.getType()!=null){ - boundStatements.add(prepStmt12.bind(UUID.fromString(post.getKey()), post.getType().toString())); - }if(post.getUriThumbnail()!=null){ - boundStatements.add(prepStmt13.bind(UUID.fromString(post.getKey()), post.getUriThumbnail())); - }if(post.getVreid()!=null){ - boundStatements.add(prepStmt14.bind(UUID.fromString(post.getKey()), post.getVreid())); - } - boundStatements.add(prepStmt15.bind(UUID.fromString(post.getKey()), post.isMultiFileUpload())); - if(post.getFullName()!=null){ - boundStatements.add(prepStmt16.bind(UUID.fromString(post.getKey()), post.getFullName())); - }if(post.getCommentsNo()!=null){ - boundStatements.add(prepStmt17.bind(UUID.fromString(post.getKey()), Long.parseLong(post.getCommentsNo()))); - }if(post.getLinkTitle()!=null){ - boundStatements.add(prepStmt18.bind(UUID.fromString(post.getKey()), post.getLinkTitle())); - } - return boundStatements; - } - /** - * @inheritDoc - */ - @Override - public boolean saveUserPost(Post post) { CqlSession session = conn.getKeyspaceSession(); + if(existRecordbyId(session, post.getKey(), POSTS, POST_ID)){ + return false; + } + //save into posts List boundStatements = insertIntoPosts(session, post); - //boundStatements.forEach(stmt -> writeBatch.add(stmt)); - //an entry in posts - //an entry in the user Timeline - BoundStatement stmt2 = createUserTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + //save into usertimeline or apptimeline + BoundStatement stmt2 = post.isApplicationPost()? createAppTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())) + : createUserTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); boundStatements.add(stmt2); //an entry in the VRES Timeline iff vreid field is not empty if (post.getVreid() != null && post.getVreid().compareTo("") != 0){ BoundStatement stmt3 = createVreTimelineEntry(session).bind(post.getVreid(), post.getTime().toInstant(), UUID.fromString(post.getKey())); boundStatements.add(stmt3); } + //add attachments if any + for(Attachment attachment: attachments){ + boundStatements.addAll(insertIntoAttachments(session, attachment, post.getKey())); + } + //execute the write BatchStatement writeBatch = getBatch().addAll(boundStatements); - - Boolean result = session.execute(writeBatch).wasApplied(); - if (result){ - _log.info("Wrote user post with id " + post.getKey()); - } - - - return result; - } - /** - * @inheritDoc - */ - @Override - public boolean saveUserPost(Post post, List attachments) { - if (attachments != null && !attachments.isEmpty()) - post.setMultiFileUpload(true); - boolean savePostResult = saveUserPost(post); - if (savePostResult) { - _log.info("Post has been saved"); - String postkey = post.getKey(); + boolean savePostResult; + try{ + savePostResult = session.execute(writeBatch).wasApplied(); + return savePostResult; + }catch (Exception e){ + _log.error("Failed to save post with id {} because {} " , post.getKey(), e.getMessage()); + _log.info("Cleaning the mess"); + List cleanMess = new ArrayList<>(); + if(existRecordbyId(session, post.getKey(), POSTS, POST_ID)) + cleanMess.add(deletePostEntry(session).bind(UUID.fromString(post.getKey()))); for (Attachment attachment : attachments) { - boolean attachSaveResult = saveAttachmentEntry(postkey, attachment); - if (!attachSaveResult) - _log.info("Some of the attachments failed to be saved: " + attachment.getName()); + if(existRecordbyId(session, attachment.getId(), ATTACHMENTS, ATTACH_ID)) + cleanMess.add(deleteAttachmentEntry(session).bind(UUID.fromString(attachment.getId()))); } - return true; + BatchStatement cleanMessBatch = getBatch().addAll(cleanMess); + boolean clean = false; + while(!clean) { + clean = session.execute(cleanMessBatch).wasApplied(); + } + e.printStackTrace(); + return false; } - else return false; } - /** - * @inheritDoc + private Post readPost(String postid) + throws PrivacyLevelTypeNotFoundException, + PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException { + CqlSession session = conn.getKeyspaceSession(); + Post post; + try{ + post = findPostById(postid, session).get(); + + } catch (Exception e){ + e.printStackTrace(); + + return null; + } + return post; + } + + private List getAllPostsWithPrivacy(String privacyLevel) throws PostTypeNotFoundException, ColumnNameNotFoundException, PrivacyLevelTypeNotFoundException { + //possible error index + ArrayList toReturn = new ArrayList(); + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(POSTS).all() + .whereColumn(PRIVACY).isEqualTo(QueryBuilder.bindMarker()) + .limit(20) + .build()); + try { + result = session.execute(stmtFind.bind(privacyLevel)); + + } catch (Exception e){ + e.printStackTrace(); + + } + Listrows=result.all(); + for (Row row: rows) { + Post toAdd = readPostFromRow(row); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) + toReturn.add(toAdd); + } + return toReturn; + } + private boolean deletePost(String postid) throws PostIDNotFoundException, PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException { + Post toDelete = readPost(postid); + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updatePostEntry(session, TYPE).bind(PostType.DISABLED.toString(), UUID.fromString(toDelete.getKey()))); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + _log.error("Delete Post ERROR for postid " + postid); + + return false; + } + _log.info("Delete Post OK"); + return true; + } + private List getAllChildrenByPost(String postid,String childType){ + ResultSet result = null; + List toReturn = new ArrayList<>(); + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(childType).all() + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(UUID.fromString(postid))); + for (Row row: result) { + Resource toAdd = childType.equals(LIKES) ? readLikeFromRow(row) : + childType.equals(COMMENTS)? readCommentFromRow(row) : + childType.equals(ATTACHMENTS)?readAttachmentFromRow(row) : null; + if(toAdd == null) throw new Exception("No child resource named " + childType); + toReturn.add(toAdd); + } + } catch (Exception e){ + e.printStackTrace(); + } + return toReturn; + } + + /* + * + ********************** NOTIFICATIONS *********************** + * */ - @Override - public boolean saveAppPost(Post post) { + private boolean saveNotification(Notification n) { CqlSession session = conn.getKeyspaceSession(); - List boundStatements = insertIntoPosts(session, post); - //an entry in the Applications Timeline - BoundStatement stmt2 = createAppTimelineEntry(session).bind(post.getEntityId(), post.getTime().toInstant(), UUID.fromString(post.getKey())); + List boundStatements = insertIntoNotifications(session, n); + + //an entry in the user Notifications Timeline + BoundStatement stmt2 = createUserNotificationsEntry(session).bind(n.getUserid(), n.getTime().toInstant(), UUID.fromString(n.getKey())); boundStatements.add(stmt2); - //an entry in the VRES Timeline iff vreid field is not empty - if (post.getVreid() != null && post.getVreid().compareTo("") != 0){ - BoundStatement stmt3 = createVreTimelineEntry(session).bind(post.getVreid(), post.getTime().toInstant(), UUID.fromString(post.getKey())); - boundStatements.add(stmt3); - } + + // save key in the unread notifications column family too + BoundStatement stmt3 = createUnreadNotificationEntry(session).bind(n.getUserid(), n.getTime().toInstant(), UUID.fromString(n.getKey())); + boundStatements.add(stmt3); BatchStatement writeBatch = getBatch().addAll(boundStatements); + try{ + boolean res = session.execute(writeBatch).wasApplied(); - boolean result = session.execute(writeBatch).wasApplied(); - if (result) - _log.info("Wrote app post with id " + post.getKey()); - - return result; + return res; + }catch (Exception e){ + e.printStackTrace(); + return false; + } } - /** - * @inheritDoc + private Notification readNotification(String notificationid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { + Notification toReturn = new Notification(); + CqlSession session = conn.getKeyspaceSession(); + try { + toReturn = findNotById(notificationid, session).get(); + + } + catch (Exception e) { + e.printStackTrace(); + + } + return toReturn; + } + private boolean setNotificationRead(String notificationidToSet) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { + Notification toSet = readNotification(notificationidToSet); + if (toSet == null) + throw new NotificationIDNotFoundException("The specified notification to set Read with id: " + notificationidToSet + " does not exist"); + + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch() + + //update the entry in notifications + .add(updateNotificationEntry(session,IS_READ).bind(true,UUID.fromString(notificationidToSet))) + + // delete the notification's key from the unread notifications column family + .add(deleteUnreadNotEntry(session).bind(toSet.getUserid(), toSet.getTime().toInstant())); + + // execute the operations + try { + boolean res = session.execute(writeBatch).wasApplied(); + + return res; + } catch (Exception e) { + _log.error("ERROR while setting Notification " + notificationidToSet + " to read."); + return false; + } + } + + /* + * + ********************** COMMENTS *********************** + * */ - @Override - public boolean saveAppPost(Post post, List attachments) { - if (attachments != null && !attachments.isEmpty()) - post.setMultiFileUpload(true); - boolean savePostResult = saveAppPost(post); - if (savePostResult) { - String PostKey = post.getKey(); - for (Attachment attachment : attachments) { - boolean attachSaveResult = saveAttachmentEntry(PostKey, attachment); - if (!attachSaveResult) - _log.warn("Some of the attachments failed to be saved: " + attachment.getName()); + + private boolean saveComment(String postid, Comment comment) throws PostIDNotFoundException { + Post toComment = null; + comment.setPostid(postid); + try { + toComment = readPost(postid); + if (toComment == null) + throw new PostIDNotFoundException("Could not find Post with id " + postid + " to associate this comment", postid); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + _log.info("Writing comment : {}", comment.toString()); + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = insertIntoComments(session, comment); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + try { + ResultSet res = session.execute(writeBatch); + for (ExecutionInfo ex: res.getExecutionInfos()){ + _log.info("Writing comment result errors: {}", ex.getErrors()); + _log.info("Writing comment result payload: {}", ex.getIncomingPayload()); } + _log.info("Writing comment result executed?: {}", res.wasApplied()); + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + //update the comment count + boolean updateCommentNoResult = updatePostCommentsCount(toComment, true); + return updateCommentNoResult; + } + private Comment readComment(String commentId) throws CommentIDNotFoundException { + Comment toReturn = null; + + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(COMMENTS).all() + .whereColumn(COMMENT_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(UUID.fromString(commentId))); + toReturn = readCommentFromRow(result.one()); + if (toReturn==null) { + throw new CommentIDNotFoundException("The requested commentId: " + commentId + " is not existing"); + } + + } catch (Exception e){ + e.printStackTrace(); + } + + return toReturn; + } + private boolean editComment(Comment comment2Edit) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, PostIDNotFoundException { + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updateCommentEntry(session, Schema.COMMENT).bind(comment2Edit.getText(), UUID.fromString(comment2Edit.getKey()))) + .add(updateCommentEntry(session, IS_EDIT).bind(true, UUID.fromString(comment2Edit.getKey()))) + .add(updateCommentEntry(session, LAST_EDIT_TIME).bind(new Date().toInstant(), UUID.fromString(comment2Edit.getKey()))); + + try { + boolean res = session.execute(writeBatch).wasApplied(); + + _log.info("Comments update OK to: " + comment2Edit.getText()); + return res; + } catch (Exception e) { + + _log.error("Comments update NOT OK "); + return false; + } + } + private boolean deleteComment(String Postid, String commentid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, PostIDNotFoundException { + Post toUpdate = readPost(Postid); + boolean updateCommentNoResult = false; + + updateCommentNoResult = updatePostCommentsCount(toUpdate, false); + if (updateCommentNoResult) { + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(deleteCommentEntry(session).bind(UUID.fromString(commentid))); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + + _log.error("Comment Delete FAILED for " + commentid + " from Post " + Postid); + e.printStackTrace(); + } + _log.trace("Comment Deleted " + commentid + " from Post " + Postid); + } + + + return updateCommentNoResult; + } + + /* + * + ********************** Likes *********************** + * + */ + + private boolean like(String postid, Like like) throws PostIDNotFoundException { + Post toLike = null; + like.setPostid(postid); + try { + toLike = readPost(postid); + if (toLike == null) + throw new PostIDNotFoundException("Could not find post with id " + postid + " to associate this like", postid); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + if (isPostLiked(like.getUserid(), postid)) { + _log.info("User " + like.getUserid() + " already liked post " + postid); return true; } - else return false; + else { + CqlSession session = conn.getKeyspaceSession(); + // Inserting data + //an entry in the post CF + //and an entry in the UserLikesCF + List boundStatements = insertIntoLikes(session,like); + BoundStatement stmt2 = createNewUserLikesEntry(session).bind(like.getUserid(), UUID.fromString(like.getKey()), UUID.fromString(like.getPostid())); + boundStatements.add(stmt2); + + //boundStatements.forEach(stmt->writeBatch.add(stmt)); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + + try { + session.execute(writeBatch); + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return updatePostLikesCount(toLike, true); + } } - /** - * @inheritDoc + private boolean unlike(String userid, String likeid, String postId) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, LikeIDNotFoundException, PostIDNotFoundException { + Post toUpdate = readPost(postId); + boolean updateLikeNoResult = false; + + updateLikeNoResult = updatePostLikesCount(toUpdate, false); //this remove 1 from the post CF LikeNO + if (updateLikeNoResult) { + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(deleteLikeEntry(session).bind(UUID.fromString(likeid))) + .add(deleteUserLikeEntry(session).bind(userid, UUID.fromString(likeid))); + try { + session.execute(writeBatch); + + } catch (Exception e) { + + _log.error("Like Delete FAILED for " + likeid + " from post " + postId); + e.printStackTrace(); + } + _log.trace("Unlike ok for " + likeid + " from post " + postId); + } + return updateLikeNoResult; + + } + + /* + * + ********************** VRE *********************** + * */ - @Override - public boolean savePostToVRETimeline(String postKey, String vreid) throws PostIDNotFoundException { + private List getAllPostsByVRE(String vreid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + return getPostsByIds(getVREPostIds(vreid)); + } + private List getAllVREIds(){ + + Set ids = new HashSet<>(); + + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(VRE_TIMELINE_POSTS).column(VRE_ID).all() + .build()); + try { + result = session.execute(stmtFind.bind()); + + } catch (Exception e){ + e.printStackTrace(); + + } + + Listrows=result.all(); + for (Row row : rows) { + ids.add(row.getString(VRE_ID)); + } + + List toReturn = new ArrayList<>(); + for (String id: ids){ + Vre vre = new Vre(id); + toReturn.add(vre); + } + + _log.debug("VRE ids are " + ids); + + return toReturn; + } + private boolean savePostToVRETimeline(String vreid, Post post) throws PostIDNotFoundException { Post toCheck; try { - toCheck = readPost(postKey); + toCheck = readPost(post.getKey()); if (toCheck == null) - throw new PostIDNotFoundException("Could not find Post with id " + postKey, postKey); + throw new PostIDNotFoundException("Could not find Post with id " + post.getKey(), post.getKey()); } catch (Exception e) { e.printStackTrace(); return false; @@ -656,30 +1011,351 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { return false; } } - /** - * @inheritDoc - */ - @Override - public Post readPost(String postid) - throws PrivacyLevelTypeNotFoundException, - PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException { + private List getVREHashtagsWithOccurrence(String vreid) { + ResultSet result = null; CqlSession session = conn.getKeyspaceSession(); - Post post; - try{ - post = findPostById(postid, session).get(); + + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(HASHTAGS_COUNTER).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); } catch (Exception e){ e.printStackTrace(); - return null; } - return post; + + + //HashMap toReturn = new HashMap (); + List toReturn = new ArrayList<>(); + List rows = result.all(); + // Iterate rows and their columns + for (Row row : rows) { + Integer curValue = (int) row.getLong(COUNT); + if (curValue > 0){ + Hashtag hashtag = new Hashtag(row.getString(Schema.HASHTAG)); + hashtag.setOccurrence(curValue); + //toReturn.put(row.getString(Schema.HASHTAG), curValue); + toReturn.add(hashtag); + } + + } + return toReturn; } - /** - * @inheritDoc + private List getVREHashtagsWithOccurrenceFilteredByTime(String vreid, long timestamp){ + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(HASHTAGS_COUNTER).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + HashMap check = new HashMap (); + List toReturn = new ArrayList<>(); + List rows = result.all(); + // Iterate rows and their columns + for (Row row : rows) { + String hashtag = row.getString(Schema.HASHTAG); + // retrieve the posts list for this hashtag + List posts = null; + try{ + posts = getVREPostsByHashtag(vreid, hashtag); + }catch(Exception e){ + _log.error("Unable to retrieve the list of posts for hashtag" + hashtag + " in vre " + vreid); + continue; + } + + if(posts.isEmpty()){ + + _log.info("There are no posts containing hashtag " + hashtag + " in vre " + vreid); + continue; + + } + + // retrieve the most recent one among these posts + Collections.sort(posts, Collections.reverseOrder()); + + if(posts.get(0).getTime().getTime() < timestamp){ + continue; + } + + + // else.. + int curValue = (int) row.getLong(COUNT); + + if (curValue > 0) + check.put(row.getString(Schema.HASHTAG), curValue); + } + Set keys = check.keySet(); + for(String key: keys){ + toReturn.add(new Hashtag(key, check.get(key))); + } + return toReturn; + } + private List getRecentPostsByVRE(String vreid, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList postIDs = getVREPostIds(vreid); + //check if quantity is greater than user posts + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + + //need them in reverse order + for (int i = postIDs.size()-1; i >= (postIDs.size()-quantity); i--) { + Post toAdd = readPost(postIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent Post: " + postIDs.get(i)); + } else { + _log.trace("Read and skipped Post: " + postIDs.get(i) + " (Removed Post) ."); + quantity += 1; //increase the quantity in case of removed Post + //check if quantity is greater than user Posts + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + } + } + return toReturn; + } + private List getVREPostsByHashtag(String vreid, String hashtag) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException { + List toReturn = new ArrayList<>(); + CqlSession session = conn.getKeyspaceSession(); + + ResultSet resultPost = null; + PreparedStatement stmtFind1 = session.prepare(QueryBuilder + .selectFrom(HASHTAGGED_POSTS).all() + .whereColumn(Schema.HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + resultPost = session.execute(stmtFind1.bind(hashtag)); + } catch (Exception e){ + e.printStackTrace(); + + } + + PreparedStatement stmtFind2 = session.prepare(QueryBuilder + .selectFrom(HASHTAGGED_COMMENTS).all() + .whereColumn(Schema.HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet resultComment = null; + try { + resultComment = session.execute(stmtFind2.bind(hashtag)); + } catch (Exception e){ + e.printStackTrace(); + + } + + Set postIds = new HashSet<>(); + // Iterate rows and their columns (post) + ListrowsPost=resultPost.all(); + for (Row row : rowsPost) { + if (row.getString(VRE_ID).compareTo(vreid)==0) + postIds.add(row.getUuid(POST_ID).toString()); + } + // Iterate rows and their columns (comments) + ListrowsComment=resultComment.all(); + for (Row row : rowsComment) { + if (row.getString(VRE_ID).compareTo(vreid)==0){ + try { + Comment c = readComment(row.getUuid(COMMENT_ID).toString()); + postIds.add(c.getPostid()); + } catch (CommentIDNotFoundException e) { + _log.warn("Failed to fetch comment with id " + row.getString(COMMENT_ID)); + } + } + } + toReturn = getPostsByIds(new ArrayList<>(postIds)); + return toReturn; + } + private List getInvitedEmailsByVRE(String vreid, List status) throws InviteIDNotFoundException, InviteStatusNotFoundException{ + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(VRE_INVITES).all() + .whereColumn(VRE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(vreid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + ArrayList invitesIds = new ArrayList(); + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + if (status != null) { + for (int i = 0; i < status.size(); i++) { + if (row.getString(STATUS).compareTo(status.get(i).toString())==0) + invitesIds.add(row.getUuid(INVITE_ID).toString()); + } + } + else { + invitesIds.add(row.getUuid(INVITE_ID).toString()); + } + } + return getInvitesById(invitesIds); + } + private Invite isExistingInvite(String vreid, String email) { + CqlSession session = conn.getKeyspaceSession(); + + ResultSet result = null; + PreparedStatement stmtFind1 = session.prepare(QueryBuilder + .selectFrom(EMAIL_INVITES).all() + .whereColumn(EMAIL) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind1.bind(email)); + } catch (Exception e){ + e.printStackTrace(); + + } + + // Iterate rows and their columns + Listrows=result.all(); + for (Row row : rows) { + if (row.getString(VRE_ID).compareTo(vreid)==0) { + Invite invite = new Invite(); + invite.setVreid(vreid); + invite.setInvitedEmail(email); + invite.setKey(row.getUuid(INVITE_ID).toString()); + return invite; + } + } + return null; + } + private boolean setInviteStatus(String vreid, String email, InviteStatus status) throws InviteIDNotFoundException, InviteStatusNotFoundException { + String inviteid = isExistingInvite(vreid, email).getId(); + Invite toSet = readInvite(inviteid); + if (toSet == null) + throw new InviteIDNotFoundException("The specified invite to set with id: " + inviteid + " does not exist"); + + CqlSession session = conn.getKeyspaceSession(); + BatchStatement writeBatch = getBatch().add(updateInviteEntry(session, STATUS).bind(status.toString(), UUID.fromString(inviteid))) + .add(updateVreInviteEntry(session, STATUS).bind(status.toString(), vreid, UUID.fromString(inviteid))); + try { + session.execute(writeBatch); + + } catch (Exception e) { + _log.error("ERROR while setting Invite " + inviteid + " to " + status.toString()); + + return false; + } + _log.trace("Invite Status Set to " + status.toString() + " OK"); + return true; + } + private boolean saveHashTags(String postId, String vreid, List hashtags) throws PostIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting data + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstInsert = session.execute((createNewHashtagTimelineEntry(session).bind(lowerCaseHashtag, UUID.fromString(postId), vreid))).wasApplied(); + boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, true); + if (! (firstInsert && secondInsert)) { + _log.error("saveHashTags: Could not save the hashtag(s)"); + + return false; + } + } + + return true; + } + private boolean deleteHashTags(String postId, String vreid, List hashtags) throws PostIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting data + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstDelete = session.execute(deleteHashtagEntry(session).bind(lowerCaseHashtag, UUID.fromString(postId))).wasApplied(); + boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, false); + if (! (firstDelete && secondInsert)) { + _log.error("deleteHashTags: Could not delete the hashtag(s)"); + + return false; + + } + } + + return true; + } + private boolean saveHashTagsComment(String commentId, String vreid, List hashtags) throws CommentIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting datacommentIdcommentId + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstInsert = session.execute(createNewHashtagCommentEntry(session).bind(hashtag, UUID.fromString(commentId), vreid)).wasApplied(); + 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; + } + private boolean deleteHashTagsComment(String commentId, String vreid, List hashtags) throws CommentIDNotFoundException { + Set noduplicatesHashtags = null; + if (hashtags != null && !hashtags.isEmpty()) { + noduplicatesHashtags = new HashSet(hashtags); + } + // Inserting data + CqlSession session = conn.getKeyspaceSession(); + for (String hashtag : noduplicatesHashtags) { + String lowerCaseHashtag = hashtag.toLowerCase(); + boolean firstDelete = session.execute(deleteHashtagCommentEntry(session).bind(lowerCaseHashtag, UUID.fromString(commentId))).wasApplied(); + 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; + } + + /* + * + ********************** USER *********************** + * */ - @Override - public List getRecentPostsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException { + private List getAllPostsByUser(String userid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + return getPostsByIds(getUserPostIds(userid)); + } + private List getRecentPostsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException { Date now = new Date(); if (timeInMillis > now.getTime()) throw new IllegalArgumentException("the timeInMillis must be before today"); @@ -714,47 +1390,29 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { } return toReturn; } - /** - * @inheritDoc - */ - @Override - public boolean deletePost(String postid) throws PostIDNotFoundException, PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException { - Post toDelete = readPost(postid); - CqlSession session = conn.getKeyspaceSession(); - BatchStatement writeBatch = getBatch().add(updatePostEntry(session, TYPE).bind(PostType.DISABLED.toString(), UUID.fromString(toDelete.getKey()))); + private List getRecentPostsByUser(String userid, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList postIDs = getUserPostIds(userid); + //check if quantity is greater than user posts + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; - try { - session.execute(writeBatch); - - } catch (Exception e) { - _log.error("Delete Post ERROR for postid " + postid); - - return false; + //need them in reverse order + for (int i = postIDs.size()-1; i >= (postIDs.size()-quantity); i--) { + Post toAdd = readPost(postIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent post: " + postIDs.get(i)); + } else { + _log.trace("Read and skipped post: " + postIDs.get(i) + " (Removed Post)"); + quantity += 1; //increase the quantity in case of removed post + //check if quantity is greater than user posts + quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; + } } - _log.info("Delete Post OK"); - return true; + return toReturn; } - /** - * @inheritDoc - */ - @Override - public List getAllPostsByUser(String userid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - return getPostsByIds(getUserPostIds(userid)); - } - /** - * @inheritDoc - */ - @Override - public List getAllPostsByApp(String appid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - return getPostsByIds(getAppPostIds(appid)); - } - /** - * @inheritDoc - * @throws Exception - */ - @Override - public List getRecentCommentedPostsByUserAndDate(String userid, - long timeInMillis) throws Exception { + private List getRecentCommentedPostsByUserAndDate(String userid, + long timeInMillis) throws Exception { List toReturn = new ArrayList(); @@ -786,6 +1444,421 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { Collections.sort(toReturn, Collections.reverseOrder()); return toReturn; } + private List getUnreadNotificationsByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList notificationsIDs = getUnreadUserNotificationsIds(userid); + + //need them in reverse order + for (int i = notificationsIDs.size()-1; i >= 0; i--) { + try{ + toReturn.add(readNotification(notificationsIDs.get(i))); + }catch(Exception e){ + _log.error("Unable to read notification with key " + notificationsIDs.get(i)); + } + } + + return toReturn; + } + private boolean setAllNotificationReadByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { + + // get the list of unread notifications + ArrayList notificationsIDs = getUnreadUserNotificationsIds(userid); + + for (int i = notificationsIDs.size()-1; i >= 0; i--) { + try{ + + // set to read (and automatically remove from the unread column family) + setNotificationRead(notificationsIDs.get(i)); + + } catch (NotificationIDNotFoundException e) { + _log.error("Could not set read notification with id =" + notificationsIDs.get(i)); + } + } + return true; + } + private List getAllNotificationByUser(String userid, int limit) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { + ArrayList toReturn = new ArrayList(); + ArrayList notificationsIDs = getUserNotificationsIds(userid); + //check if quantity is greater than user posts + limit = (limit > notificationsIDs.size()) ? notificationsIDs.size() : limit; + + //need them in reverse order + for (int i = notificationsIDs.size()-1; i >= (notificationsIDs.size()-limit); i--) { + Notification toAdd = null; + try { + toAdd = readNotification(notificationsIDs.get(i)); + toReturn.add(toAdd); + } catch (NotificationIDNotFoundException e) { + _log.error("Notification not found id=" + notificationsIDs.get(i)); + } + } + return toReturn; + } + private List getRecentLikedPostsByUserAndDate(String userid, + long timeInMillis) throws IllegalArgumentException { + + List toReturn = new ArrayList<>(); + + 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 posts + List likedPostsIdsByUser = getAllLikedPostIdsByUser(userid); + + if(likedPostsIdsByUser != null && !likedPostsIdsByUser.isEmpty()){ + for(int i = likedPostsIdsByUser.size() - 1; i >= 0; i--){ + String postid = likedPostsIdsByUser.get(i); + try{ + + // retrieve the Post + Post toCheck = readPost(postid); + boolean isPostOk = (toCheck.getType() == PostType.TWEET || toCheck.getType() == PostType.SHARE || toCheck.getType() == PostType.PUBLISH); + + // retrieve the like of the user for the post + if(isPostOk){ + List likes = getAllChildrenByPost(postid, LIKES); + for (Resource x : likes) { + Like like = (Like) x; + if(like.getTime().getTime() >= timeInMillis && like.getUserid().equals(userid)) + toReturn.add(toCheck); + } + } + + }catch(Exception e){ + _log.error("Skipped post with id " + postid, 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; + } + private boolean checkUnreadNotifications(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { + + ArrayList unreadNotifications = getUnreadUserNotificationsIds(userid); + + for (int i = unreadNotifications.size() - 1; i >= 0; i--) { + Notification toAdd; + try { + toAdd = readNotification(unreadNotifications.get(i)); + if (toAdd.getType() != NotificationType.MESSAGE) + return true; + } catch (NotificationIDNotFoundException e) { + _log.error("Notification not found with id = " + unreadNotifications.get(i)); + } + } + + return false; + } + private boolean checkUnreadMessagesNotifications(String userid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { + + ArrayList unreadNotifications = getUnreadUserNotificationsIds(userid); + + for (int i = unreadNotifications.size() - 1; i >= 0; i--) { + Notification toAdd; + try { + toAdd = readNotification(unreadNotifications.get(i)); + if (toAdd.getType() == NotificationType.MESSAGE) + return true; + } catch (NotificationIDNotFoundException e) { + _log.error("Notification not found with id = " + unreadNotifications.get(i)); + } + } + + return false; + } + private List getAllLikedPostIdsByUser(String userid) { + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_LIKED_POSTS).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + ArrayList toReturn = new ArrayList(); + for (Row row: result){ + toReturn.add(row.getUuid(POST_ID).toString()); + } + return toReturn; + } //not implemented in REST + private List getAllLikedPostsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + ArrayList toReturn = new ArrayList(); + List likedPostIDs = getAllLikedPostIdsByUser(userid); + + //check if quantity is greater than user posts + limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; + + //need them in reverse order + for (int i = likedPostIDs.size()-1; i >= (likedPostIDs.size()-limit); i--) { + Post toAdd = readPost(likedPostIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + toReturn.add(toAdd); + _log.trace("Read recent post: " + likedPostIDs.get(i)); + } else { + _log.trace("Read and skipped post: " + likedPostIDs.get(i) + " (Removed post)"); + limit += 1; //increase the quantity in case of removed post + //check if quantity is greater than user posts + limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; + } + } + return toReturn; + } + private List getRecentCommentsByUserAndDate(final String userid, final long timeInMillis) throws Exception { + + final List commentsByUser; + + 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"); + + + commentsByUser = getRecentCommentsByUserAndDateBody(userid, timeInMillis, true); + + return commentsByUser; } + private List getUserNotificationChannels(String userid, NotificationType notificationType) throws NotificationChannelTypeNotFoundException, NotificationTypeNotFoundException { + _log.info("Asking for Single Notification preference of " + userid + " Type: " + notificationType); + List toReturn = new ArrayList(); + List notificationPreferences = getUserNotificationPreferences(userid); + NotificationPreference notificationPreference = new NotificationPreference(); + for(NotificationPreference notPref: notificationPreferences){ + if(notPref.getNotificationType().equals(notificationType.toString())){ + notificationPreference = notPref; + break; + } + } + + String[] toProcess = notificationPreference.getNotificationChannelType(); + _log.info("size of user notification preferences" + toProcess.length); + if (toProcess == null) { + _log.info("Single Notification preference of " + userid + " Type: " + notificationType + " not existing ... creating default"); + return createNewNotificationType(userid, notificationType); + } + else if (toProcess.length == 0) + return toReturn; + else + for (int i = 0; i < toProcess.length; i++) { + toReturn.add(NotificationChannelType.valueOf(toProcess[i])); + } + return toReturn; + } + private List getUserNotificationPreferences(String userid) throws NotificationTypeNotFoundException, NotificationChannelTypeNotFoundException { + _log.trace("Asking for Notification preferences of " + userid); + List notificationPreferences = new ArrayList<>(); + Map toReturn = new HashMap(); + + ResultSet result = null; + CqlSession session = conn.getKeyspaceSession(); + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(USER_NOTIFICATIONS_PREFERENCES).all() + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(userid)); + + } catch (Exception e){ + e.printStackTrace(); + + } + + //if there are no settings for this user create an entry and put all of them at true + List results = result.all(); + if (results.isEmpty()) { + _log.info("Userid " + userid + " settings not found, initiating its preferences..."); + HashMap toCreate = new HashMap(); + + for (int i = 0; i < NotificationType.values().length; i++) { + //TODO: Potential bug in NotificationType for workspace are refactored + //create a map with all notification enabled except for workspace notifications (They start with WP_) it was the only quick way + if (NotificationType.values()[i].toString().startsWith("WP_")) { + NotificationChannelType[] wpTypes = { NotificationChannelType.PORTAL }; + toCreate.put(NotificationType.values()[i], wpTypes); + } + else + toCreate.put(NotificationType.values()[i], NotificationChannelType.values()); + } + Set keys = toCreate.keySet(); + for(NotificationType k: keys){ + NotificationChannelType[] notChannels = toCreate.get(k); + String[] notChannelsString = new String[notChannels.length]; + for(int i = 0; i < notChannels.length; i++){ + notChannelsString[i] = notChannels[i].toString(); + } + NotificationPreference notPreference = new NotificationPreference(k.toString(), notChannelsString); + notificationPreferences.add(notPreference); + } + setUserNotificationPreferences(userid, notificationPreferences); //commit the map + + return notificationPreferences; + } + else { + _log.trace("Notification preferences Found for " + userid); + for (Row row: results){ + String[] channels = row.getString(PREFERENCE).split(","); + if (channels != null && channels.length == 1 && channels[0].toString().equals("") ) { //it is empty, preference is set to no notification at all + toReturn.put(getNotificationType(row.getString(TYPE)), new NotificationChannelType[0]); + } else { + NotificationChannelType[] toAdd = new NotificationChannelType[channels.length]; + for (int i = 0; i < channels.length; i++) { + if (channels[i].compareTo("") != 0) { + toAdd[i] = (getChannelType(channels[i])); + } + } + toReturn.put(getNotificationType(row.getString(TYPE)), toAdd); + } + } + } + Set keys = toReturn.keySet(); + for(NotificationType k: keys){ + NotificationChannelType[] notChannels = toReturn.get(k); + String[] notChannelsString = new String[notChannels.length]; + for(int i = 0; i < notChannels.length; i++){ + notChannelsString[i] = notChannels[i].toString(); + } + NotificationPreference notPreference = new NotificationPreference(k.toString(), notChannelsString); + notificationPreferences.add(notPreference); + } + return notificationPreferences; + } + private boolean setUserNotificationPreferences(String userid, List notificationPreferences) { + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = new ArrayList<>(); + Map enabledChannels = new HashMap<>(); + for(NotificationPreference notPref: notificationPreferences){ + NotificationChannelType[] notChannels = new NotificationChannelType[notPref.getNotificationChannelType().length]; + for (int i = 0; i getAllPostsByApp(String appid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + return getPostsByIds(getAppPostIds(appid)); + } + + /* + * + ********************** Invites *********************** + * + */ + private Invite readInvite(String inviteid) throws InviteIDNotFoundException, InviteStatusNotFoundException { + Invite toReturn = null; + CqlSession session = conn.getKeyspaceSession(); + ResultSet result = null; + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(INVITES).all() + .whereColumn(INVITE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + try { + result = session.execute(stmtFind.bind(UUID.fromString(inviteid))); + toReturn = readAInviteFromRow(result.one()); + if (toReturn == null) { + throw new InviteStatusNotFoundException("The requested inviteid: " + inviteid + " is not existing"); + } + //toReturn = readAInviteFromRow(result.all().get(0)); + + } catch (Exception e){ + e.printStackTrace(); + + } + return toReturn; + } + + + + @Override + public InviteOperationResult saveInvite(Invite invite) throws AddressException { + if (invite == null) + throw new NullArgumentException("Invite instance is null"); + String email = invite.getInvitedEmail(); + if (! verifyEmail(email)) + throw new AddressException("Email is not valid ->" + email); + if (invite.getVreid() == null || invite.getVreid().equals("")) + throw new NullArgumentException("VREId is null or empty"); + _log.debug("isExistingInvite? " + invite.getInvitedEmail() + " in " + invite.getVreid()); + if (isExistingInvite(invite.getVreid(), invite.getInvitedEmail()) != null) + return InviteOperationResult.ALREADY_INVITED; + _log.debug("Invite not found, proceed to save it ..."); + CqlSession session = conn.getKeyspaceSession(); + List boundStatements = initSaveInvite(invite, session); + //an entry in the VRE Invites + boundStatements.add(createNewVreInviteEntry(session).bind(invite.getVreid(), UUID.fromString(invite.getKey()), InviteStatus.PENDING.toString())); + //an entry in the EMAIL Invites + boundStatements.add(createNewEmailInviteEntry(session).bind(email, invite.getVreid(), UUID.fromString(invite.getKey()))); + BatchStatement writeBatch = getBatch().addAll(boundStatements); + boolean result = session.execute(writeBatch).wasApplied(); + + return result ? InviteOperationResult.SUCCESS : InviteOperationResult.FAILED; + } + + + + + + /** + * @inheritDoc + */ + @Override + public void closeConnection() { + conn.closeConnection(); + } + /* + * + ********************** Helper methods *********************** + * + */ + /** * helper method that retrieve all the posts belongin to a list of Ids * @param postIds @@ -906,129 +1979,56 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { return toReturn; } - @Override - public List getAllPortalPrivacyLevelPosts() throws PostTypeNotFoundException, ColumnNameNotFoundException, PrivacyLevelTypeNotFoundException { - //possible error index - ArrayList toReturn = new ArrayList(); - ResultSet result = null; + /** + * Private method that allows also to specify if the returned list must be sorted or not + * @param userid the user id + * @param timeInMillis the initial time to consider + * @param sort a boolean value to specify if the returned list must be sorted (from the most recent to the oldest comment) + * @return a list of comments recently made by the user + */ + private List getRecentCommentsByUserAndDateBody(final String userid, + final long timeInMillis, boolean sort){ + + //possible error + final List commentsByUser = new ArrayList(); + CqlSession session = conn.getKeyspaceSession(); + + ResultSet result = null; PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(POSTS).all() - .whereColumn(PRIVACY).isEqualTo(QueryBuilder.bindMarker()) - .limit(20) + .selectFrom(COMMENTS) + .all() .build()); try { - result = session.execute(stmtFind.bind(PrivacyLevel.PORTAL.toString())); + result = session.execute(stmtFind.bind()); + List results = result.all(); + if (!results.isEmpty()){ + results.parallelStream().forEach( row->{ + if(row.getString(USER_ID).equals(userid)){ + try{ + Comment c = readComment(row.getUuid(COMMENT_ID).toString()); + Post p = readPost(c.getPostid()); + if(c.getTime().getTime() >= timeInMillis && + (p.getType() == PostType.TWEET || p.getType() == PostType.SHARE || p.getType() == PostType.PUBLISH)) + commentsByUser.add(c); + }catch(Exception e){ + _log.error("Unable to read comment with id" + row.getString(COMMENT_ID), e); + } + } + } + ); + } } catch (Exception e){ e.printStackTrace(); } - Listrows=result.all(); - for (Row row: rows) { - Post toAdd = readPostFromRow(row); - if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) - toReturn.add(toAdd); - } - return toReturn; + + if(sort) + Collections.sort(commentsByUser, Collections.reverseOrder()); + return commentsByUser; } - /** - * @inheritDoc - */ - @Override - public List getRecentPostsByUser(String userid, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - ArrayList toReturn = new ArrayList(); - ArrayList postIDs = getUserPostIds(userid); - //check if quantity is greater than user posts - quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; - //need them in reverse order - for (int i = postIDs.size()-1; i >= (postIDs.size()-quantity); i--) { - Post toAdd = readPost(postIDs.get(i)); - if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { - toReturn.add(toAdd); - _log.trace("Read recent post: " + postIDs.get(i)); - } else { - _log.trace("Read and skipped post: " + postIDs.get(i) + " (Removed Post)"); - quantity += 1; //increase the quantity in case of removed post - //check if quantity is greater than user posts - quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; - } - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public List getAllPostsByVRE(String vreid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - return getPostsByIds(getVREPostIds(vreid)); - } - @Override - public List getRecentPostsByVRE(String vreid, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - ArrayList toReturn = new ArrayList(); - ArrayList postIDs = getVREPostIds(vreid); - //check if quantity is greater than user posts - quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; - - //need them in reverse order - for (int i = postIDs.size()-1; i >= (postIDs.size()-quantity); i--) { - Post toAdd = readPost(postIDs.get(i)); - if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { - toReturn.add(toAdd); - _log.trace("Read recent Post: " + postIDs.get(i)); - } else { - _log.trace("Read and skipped Post: " + postIDs.get(i) + " (Removed Post) ."); - quantity += 1; //increase the quantity in case of removed Post - //check if quantity is greater than user Posts - quantity = (quantity > postIDs.size()) ? postIDs.size() : quantity; - } - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public RangePosts getRecentPostsByVREAndRange(String vreid, int from, int quantity) throws IllegalArgumentException, PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - if (from < 1) { - throw new IllegalArgumentException("From must be greather than 0"); - } - ArrayList postsToReturn = new ArrayList(); - ArrayList postIDs = getVREPostIds(vreid); - - //if from is greater than posts size return empty - if (from >= postIDs.size()) { - _log.warn("The starting point of the range is greather than the total number of posts for this timeline: " + from + " >= " + postIDs.size()); - return new RangePosts(); - } - - int rangeStart = postIDs.size()-from; - int rangeEnd = rangeStart-quantity; - - //check that you reached the end - if (rangeEnd<1) - rangeEnd = 0; - - _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); - //need them in reverse order - int howMany = from; - for (int i = rangeStart; i > rangeEnd; i--) { - Post toAdd = readPost(postIDs.get(i)); - if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { - postsToReturn.add(toAdd); - _log.trace("Read recent post, i=" + i + " id= " + postIDs.get(i)); - } else { - _log.trace("Read and skipped post, i=" + i + " id=: " + postIDs.get(i) + " (Removed post) ."); - rangeEnd -= 1; //increase the upTo in case of removed post - //check if quantity is greater than user posts - rangeEnd = (rangeEnd > 0) ? rangeEnd : 0; - } - howMany++; - } - _log.debug("AFTER: starting Point==" + rangeStart + " rangeEnd= " + rangeEnd); - return new RangePosts(howMany+1, postsToReturn); - } /** * get a list of user vre post UUIDs in chronological order from the oldest to the more recent * @param vreid vreid identifier (scope) @@ -1064,129 +2064,7 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { return toReturn; } - /* - * - ********************** NOTIFICATIONS *********************** - * - */ - private List insertIntoNotifications(CqlSession session, Notification notification){ - PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(TYPE, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SUBJECT_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_FULL_NAME, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt9 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt10 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(IS_READ, QueryBuilder.bindMarker()).build()); - List boundStatements = new ArrayList<>(); - - if(notification.getType()!=null){ - boundStatements.add(prepStmt1.bind(UUID.fromString(notification.getKey()),notification.getType().toString())); - } - - if(notification.getUserid()!=null){ - boundStatements.add(prepStmt2.bind(UUID.fromString(notification.getKey()), notification.getUserid())); - } - - if(notification.getSubjectid()!=null){ - boundStatements.add(prepStmt3.bind(UUID.fromString(notification.getKey()), notification.getSubjectid())); - } - if(notification.getTime()!=null){ - boundStatements.add(prepStmt4.bind(UUID.fromString(notification.getKey()),notification.getTime().toInstant())); - } - if(notification.getDescription()!=null){ - boundStatements.add(prepStmt5.bind(UUID.fromString(notification.getKey()),notification.getDescription())); - }if(notification.getUri()!=null){ - boundStatements.add(prepStmt6.bind(UUID.fromString(notification.getKey()),notification.getUri())); - }if(notification.getSenderid()!=null){ - boundStatements.add(prepStmt7.bind(UUID.fromString(notification.getKey()),notification.getSenderid())); - }if(notification.getSenderFullName()!=null){ - boundStatements.add(prepStmt8.bind(UUID.fromString(notification.getKey()),notification.getSenderFullName())); - }if(notification.getSenderThumbnail()!=null){ - boundStatements.add(prepStmt9.bind(UUID.fromString(notification.getKey()),notification.getSenderThumbnail())); - } - - boundStatements.add(prepStmt10.bind(UUID.fromString(notification.getKey()),notification.isRead())); - - return boundStatements; - } - - - /** - * @inheritDoc - */ - @Override - public boolean saveNotification(Notification n) { - CqlSession session = conn.getKeyspaceSession(); - - List boundStatements = insertIntoNotifications(session, n); - - //an entry in the user Notifications Timeline - BoundStatement stmt2 = createUserNotificationsEntry(session).bind(n.getUserid(), n.getTime().toInstant(), UUID.fromString(n.getKey())); - boundStatements.add(stmt2); - - // save key in the unread notifications column family too - BoundStatement stmt3 = createUnreadNotificationEntry(session).bind(n.getUserid(), n.getTime().toInstant(), UUID.fromString(n.getKey())); - boundStatements.add(stmt3); - BatchStatement writeBatch = getBatch().addAll(boundStatements); - try{ - boolean res = session.execute(writeBatch).wasApplied(); - - return res; - }catch (Exception e){ - e.printStackTrace(); - return false; - } - } - - /** - * @inheritDoc - */ - @Override - public Notification readNotification(String notificationid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { - Notification toReturn = new Notification(); - CqlSession session = conn.getKeyspaceSession(); - try { - toReturn = findNotById(notificationid, session).get(); - - } - catch (Exception e) { - e.printStackTrace(); - - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public boolean setNotificationRead(String notificationidToSet) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { - Notification toSet = readNotification(notificationidToSet); - if (toSet == null) - throw new NotificationIDNotFoundException("The specified notification to set Read with id: " + notificationidToSet + " does not exist"); - - CqlSession session = conn.getKeyspaceSession(); - BatchStatement writeBatch = getBatch() - - //update the entry in notifications - .add(updateNotificationEntry(session,IS_READ).bind(true,UUID.fromString(notificationidToSet))) - - // delete the notification's key from the unread notifications column family - .add(deleteUnreadNotEntry(session).bind(toSet.getUserid(), toSet.getTime().toInstant())); - - // execute the operations - try { - boolean res = session.execute(writeBatch).wasApplied(); - - return res; - } catch (Exception e) { - _log.error("ERROR while setting Notification " + notificationidToSet + " to read."); - return false; - } - } /** * * @param userid user identifier @@ -1247,169 +2125,6 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { } return toReturn; } - /** - * @inheritDoc - */ - @Override - public List getAllNotificationByUser(String userid, int limit) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { - ArrayList toReturn = new ArrayList(); - ArrayList notificationsIDs = getUserNotificationsIds(userid); - //check if quantity is greater than user posts - limit = (limit > notificationsIDs.size()) ? notificationsIDs.size() : limit; - - //need them in reverse order - for (int i = notificationsIDs.size()-1; i >= (notificationsIDs.size()-limit); i--) { - Notification toAdd = null; - try { - toAdd = readNotification(notificationsIDs.get(i)); - toReturn.add(toAdd); - } catch (NotificationIDNotFoundException e) { - _log.error("Notification not found id=" + notificationsIDs.get(i)); - } - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public List getUnreadNotificationsByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException { - ArrayList toReturn = new ArrayList(); - ArrayList notificationsIDs = getUnreadUserNotificationsIds(userid); - - //need them in reverse order - for (int i = notificationsIDs.size()-1; i >= 0; i--) { - try{ - toReturn.add(readNotification(notificationsIDs.get(i))); - }catch(Exception e){ - _log.error("Unable to read notification with key " + notificationsIDs.get(i)); - } - } - - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public List getRangeNotificationsByUser(String userid,int from, int quantity) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException { - if (from < 1) { - throw new IllegalArgumentException("From must be greather than 0"); - } - ArrayList toReturn = new ArrayList(); - ArrayList notificationsIDs = getUserNotificationsIds(userid); - - //if from is greater than posts size return empty - if (from >= notificationsIDs.size()) { - _log.warn("The starting point of the range is greather than the total number of posts for this timeline: " + from + " >= " + notificationsIDs.size()); - return new ArrayList(); - } - - int rangeStart = notificationsIDs.size()-from; - int rangeEnd = rangeStart-quantity; - - //check that you reached the end - if (rangeEnd<1) - rangeEnd = 0; - - _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); - //need them in reverse order - for (int i = rangeStart; i > rangeEnd; i--) { - Notification toAdd = readNotification(notificationsIDs.get(i)); - toReturn.add(toAdd); - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public boolean setAllNotificationReadByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { - - // get the list of unread notifications - ArrayList notificationsIDs = getUnreadUserNotificationsIds(userid); - - for (int i = notificationsIDs.size()-1; i >= 0; i--) { - try{ - - // set to read (and automatically remove from the unread column family) - setNotificationRead(notificationsIDs.get(i)); - - } catch (NotificationIDNotFoundException e) { - _log.error("Could not set read notification with id =" + notificationsIDs.get(i)); - } - } - return true; - } - - /** - * @inheritDoc - */ - @Override - public boolean checkUnreadNotifications(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException { - - ArrayList unreadNotifications = getUnreadUserNotificationsIds(userid); - - for (int i = unreadNotifications.size() - 1; i >= 0; i--) { - Notification toAdd; - try { - toAdd = readNotification(unreadNotifications.get(i)); - if (toAdd.getType() != NotificationType.MESSAGE) - return true; - } catch (NotificationIDNotFoundException e) { - _log.error("Notification not found with id = " + unreadNotifications.get(i)); - } - } - - return false; - } - /** - * @inheritDoc - */ - @Override - public boolean checkUnreadMessagesNotifications(String userid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException { - - ArrayList unreadNotifications = getUnreadUserNotificationsIds(userid); - - for (int i = unreadNotifications.size() - 1; i >= 0; i--) { - Notification toAdd; - try { - toAdd = readNotification(unreadNotifications.get(i)); - if (toAdd.getType() == NotificationType.MESSAGE) - return true; - } catch (NotificationIDNotFoundException e) { - _log.error("Notification not found with id = " + unreadNotifications.get(i)); - } - } - - return false; - } - /* - * - ********************** NOTIFICATION SETTINGS *********************** - * - */ - /** - * @inheritDoc - */ - @Override - public List getUserNotificationChannels(String userid, NotificationType notificationType) throws NotificationChannelTypeNotFoundException, NotificationTypeNotFoundException { - _log.info("Asking for Single Notification preference of " + userid + " Type: " + notificationType); - List toReturn = new ArrayList(); - NotificationChannelType[] toProcess = getUserNotificationPreferences(userid).get(notificationType); - _log.info("size of user notification preferences" + toProcess.length); - if (toProcess == null) { - _log.info("Single Notification preference of " + userid + " Type: " + notificationType + " not existing ... creating default"); - return createNewNotificationType(userid, notificationType); - } - else if (toProcess.length == 0) - return toReturn; - else - for (int i = 0; i < toProcess.length; i++) { - toReturn.add(toProcess[i]); - } - return toReturn; - } /** * called when you add new notification types where the setting does not exist yet * please note: by default we set all notifications @@ -1449,995 +2164,6 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { _log.info("empty list"); return new ArrayList(); //no notification if sth fails } - /** - * @inheritDoc - */ - @Override - public boolean setUserNotificationPreferences(String userid, Map enabledChannels) { - CqlSession session = conn.getKeyspaceSession(); - List boundStatements = new ArrayList<>(); - - for (NotificationType nType : enabledChannels.keySet()) { - String valueToInsert = ""; - _log.info("Type: " + nType.toString()); - int channelsNo = (enabledChannels.get(nType) != null) ? enabledChannels.get(nType).length : 0; - for (int i = 0; i < channelsNo; i++) { - _log.info(enabledChannels.get(nType)[i].toString()); - valueToInsert += NotificationChannelType.valueOf(enabledChannels.get(nType)[i].toString()); - if (i < channelsNo-1) - valueToInsert += ","; - } - if (channelsNo == 0) { //in case no channels were selected - valueToInsert = ""; - _log.trace("No Channels selected for " + nType + " by " + userid); - } - - boundStatements.add(createNotificationPreferenceEntry(session).bind(userid, nType.toString(), valueToInsert)); - } - - BatchStatement writeBatch = getBatch().addAll(boundStatements); - boolean overAllresult = session.execute(writeBatch).wasApplied(); - if (overAllresult) - _log.info("Set Notification Map for " + userid + " OK"); - else - _log.info("Set Notification Map for " + userid + " FAILED"); - return overAllresult; - } - /** - * @inheritDoc - * - * by default Workspace and Calendar Notifications are set to Portal - */ - @Override - public Map getUserNotificationPreferences(String userid) throws NotificationTypeNotFoundException, NotificationChannelTypeNotFoundException { - _log.trace("Asking for Notification preferences of " + userid); - Map toReturn = new HashMap(); - - ResultSet result = null; - CqlSession session = conn.getKeyspaceSession(); - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(USER_NOTIFICATIONS_PREFERENCES).all() - .whereColumn(USER_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(userid)); - - } catch (Exception e){ - e.printStackTrace(); - - } - - //if there are no settings for this user create an entry and put all of them at true - List results = result.all(); - if (results.isEmpty()) { - _log.info("Userid " + userid + " settings not found, initiating its preferences..."); - HashMap toCreate = new HashMap(); - - for (int i = 0; i < NotificationType.values().length; i++) { - //TODO: Potential bug in NotificationType for workspace are refactored - //create a map with all notification enabled except for workspace notifications (They start with WP_) it was the only quick way - if (NotificationType.values()[i].toString().startsWith("WP_")) { - NotificationChannelType[] wpTypes = { NotificationChannelType.PORTAL }; - toCreate.put(NotificationType.values()[i], wpTypes); - } - else - toCreate.put(NotificationType.values()[i], NotificationChannelType.values()); - } - setUserNotificationPreferences(userid, toCreate); //commit the map - - return toCreate; - } - else { - _log.trace("Notification preferences Found for " + userid); - for (Row row: results){ - String[] channels = row.getString(PREFERENCE).split(","); - if (channels != null && channels.length == 1 && channels[0].toString().equals("") ) { //it is empty, preference is set to no notification at all - toReturn.put(getNotificationType(row.getString(TYPE)), new NotificationChannelType[0]); - } else { - NotificationChannelType[] toAdd = new NotificationChannelType[channels.length]; - for (int i = 0; i < channels.length; i++) { - if (channels[i].compareTo("") != 0) { - toAdd[i] = (getChannelType(channels[i])); - } - } - toReturn.put(getNotificationType(row.getString(TYPE)), toAdd); - } - } - } - return toReturn; - } - /* - * - ********************** COMMENTS *********************** - * - */ - private List insertIntoComments(CqlSession session, Comment comment){ - PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(COMMENT, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(IS_EDIT, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(LAST_EDIT_TIME, QueryBuilder.bindMarker()).build()); - - List boundStatements = new ArrayList<>(); - - if(comment.getUserid()!=null){ - boundStatements.add(prepStmt1.bind(UUID.fromString(comment.getKey()),comment.getUserid())); - } - - if(comment.getFullName()!=null){ - boundStatements.add(prepStmt2.bind(UUID.fromString(comment.getKey()), comment.getFullName())); - } - - if(comment.getThumbnailURL()!=null){ - boundStatements.add(prepStmt3.bind(UUID.fromString(comment.getKey()), comment.getThumbnailURL())); - } - if(comment.getText()!=null){ - boundStatements.add(prepStmt4.bind(UUID.fromString(comment.getKey()),comment.getText())); - } - if(comment.getPostid()!=null){ - boundStatements.add(prepStmt5.bind(UUID.fromString(comment.getKey()),UUID.fromString(comment.getPostid()))); - }if(comment.getTime()!=null){ - boundStatements.add(prepStmt6.bind(UUID.fromString(comment.getKey()),comment.getTime().toInstant())); - } - boundStatements.add(prepStmt7.bind(UUID.fromString(comment.getKey()),comment.isEdit())); - - if(comment.getLastEditTime()!=null){ - boundStatements.add(prepStmt8.bind(UUID.fromString(comment.getKey()),comment.getLastEditTime().toInstant())); - } - - return boundStatements; - } - - /** - * @inheritDoc - */ - @Override - public boolean addComment(Comment comment) throws PostIDNotFoundException { - Post toComment = null; - if (comment == null) - throw new NullArgumentException("Comment must be not null"); - if (comment.getPostid() == null) - throw new NullArgumentException("Comment post id must be not null"); - - String postid = comment.getPostid(); - try { - toComment = readPost(postid); - if (toComment == null) - throw new PostIDNotFoundException("Could not find Post with id " + postid + " to associate this comment", postid); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - _log.info("Writing comment : {}", comment.toString()); - CqlSession session = conn.getKeyspaceSession(); - - List boundStatements = insertIntoComments(session, comment); - - BatchStatement writeBatch = getBatch().addAll(boundStatements); - - try { - ResultSet res = session.execute(writeBatch); - for (ExecutionInfo ex: res.getExecutionInfos()){ - _log.info("Writing comment result errors: {}", ex.getErrors()); - _log.info("Writing comment result payload: {}", ex.getIncomingPayload()); - } - _log.info("Writing comment result executed?: {}", res.wasApplied()); - - } catch (Exception e) { - e.printStackTrace(); - return false; - } - //update the comment count - boolean updateCommentNoResult = updatePostCommentsCount(toComment, true); - return updateCommentNoResult; - } - /** - * @inheritDoc - */ - public Comment readCommentById(String commentId) throws CommentIDNotFoundException { - Comment toReturn = null; - - ResultSet result = null; - CqlSession session = conn.getKeyspaceSession(); - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(COMMENTS).all() - .whereColumn(COMMENT_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(UUID.fromString(commentId))); - toReturn = readCommentFromRow(result.one()); - if (toReturn==null) { - throw new CommentIDNotFoundException("The requested commentId: " + commentId + " is not existing"); - } - - } catch (Exception e){ - e.printStackTrace(); - } - - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public List getAllCommentByPost(String postid) { - //possible error index - List toReturn = new ArrayList(); - ResultSet result = null; - CqlSession session = conn.getKeyspaceSession(); - PreparedStatement stmtFind = session.prepare("SELECT * FROM comments WHERE postid=?"); - try { - result = session.execute(stmtFind.bind(UUID.fromString(postid))); - Listrows=result.all(); - for (Row row : rows) { - Comment toAdd = readCommentFromRow(row); - toReturn.add(toAdd); - } - } catch (Exception e){ - e.printStackTrace(); - - } - - return toReturn; - } - - /** - * @inheritDoc - * @throws Exception - */ - @Override - public List getRecentCommentsByUserAndDate(final String userid, - final long timeInMillis) throws Exception { - - final List commentsByUser; - - 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"); - - - commentsByUser = getRecentCommentsByUserAndDateBody(userid, timeInMillis, true); - - return commentsByUser; } - - /** - * Private method that allows also to specify if the returned list must be sorted or not - * @param userid the user id - * @param timeInMillis the initial time to consider - * @param sort a boolean value to specify if the returned list must be sorted (from the most recent to the oldest comment) - * @return a list of comments recently made by the user - */ - private List getRecentCommentsByUserAndDateBody(final String userid, - final long timeInMillis, boolean sort){ - - //possible error - final List commentsByUser = new ArrayList(); - - CqlSession session = conn.getKeyspaceSession(); - - ResultSet result = null; - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(COMMENTS) - .all() - .build()); - try { - result = session.execute(stmtFind.bind()); - - List results = result.all(); - if (!results.isEmpty()){ - results.parallelStream().forEach( row->{ - if(row.getString(USER_ID).equals(userid)){ - try{ - Comment c = readCommentById(row.getUuid(COMMENT_ID).toString()); - Post p = readPost(c.getPostid()); - if(c.getTime().getTime() >= timeInMillis && - (p.getType() == PostType.TWEET || p.getType() == PostType.SHARE || p.getType() == PostType.PUBLISH)) - commentsByUser.add(c); - }catch(Exception e){ - _log.error("Unable to read comment with id" + row.getString(COMMENT_ID), e); - } - } - } - ); - } - } catch (Exception e){ - e.printStackTrace(); - - } - - if(sort) - Collections.sort(commentsByUser, Collections.reverseOrder()); - return commentsByUser; - } - - /** - * @inheritDoc - */ - @Override - public boolean editComment(Comment comment2Edit) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, PostIDNotFoundException { - CqlSession session = conn.getKeyspaceSession(); - BatchStatement writeBatch = getBatch().add(updateCommentEntry(session, COMMENT).bind(comment2Edit.getText(), UUID.fromString(comment2Edit.getKey()))) - .add(updateCommentEntry(session, IS_EDIT).bind(true, UUID.fromString(comment2Edit.getKey()))) - .add(updateCommentEntry(session, LAST_EDIT_TIME).bind(new Date().toInstant(), UUID.fromString(comment2Edit.getKey()))); - - try { - boolean res = session.execute(writeBatch).wasApplied(); - - _log.info("Comments update OK to: " + comment2Edit.getText()); - return res; - } catch (Exception e) { - - _log.error("Comments update NOT OK "); - return false; - } - } - - /** - * @inheritDoc - */ - @Override - public boolean deleteComment(String commentid, String Postid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, PostIDNotFoundException { - Post toUpdate = readPost(Postid); - boolean updateCommentNoResult = false; - - updateCommentNoResult = updatePostCommentsCount(toUpdate, false); - if (updateCommentNoResult) { - CqlSession session = conn.getKeyspaceSession(); - BatchStatement writeBatch = getBatch().add(deleteCommentEntry(session).bind(UUID.fromString(commentid))); - - try { - session.execute(writeBatch); - - } catch (Exception e) { - - _log.error("Comment Delete FAILED for " + commentid + " from Post " + Postid); - e.printStackTrace(); - } - _log.trace("Comment Deleted " + commentid + " from Post " + Postid); - } - - - return updateCommentNoResult; - } - - private List insertIntoLikes(CqlSession session, Like like){ - - PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); - - List boundStatements = new ArrayList<>(); - - if(like.getUserid()!=null){ - boundStatements.add(prepStmt1.bind(UUID.fromString(like.getKey()),like.getUserid())); - } - - if(like.getFullName()!=null){ - boundStatements.add(prepStmt2.bind(UUID.fromString(like.getKey()), like.getFullName())); - } - - if(like.getThumbnailURL()!=null){ - boundStatements.add(prepStmt3.bind(UUID.fromString(like.getKey()), like.getThumbnailURL())); - } - - if(like.getPostid()!=null){ - boundStatements.add(prepStmt4.bind(UUID.fromString(like.getKey()),UUID.fromString(like.getPostid()))); - }if(like.getTime()!=null){ - boundStatements.add(prepStmt5.bind(UUID.fromString(like.getKey()),like.getTime().toInstant())); - } - - return boundStatements; - } - - /** - * @inheritDoc - */ - @Override - public boolean like(Like like) throws PostIDNotFoundException { - Post toLike = null; - if (like == null) - throw new NullArgumentException("Like must be not null"); - if (like.getPostid() == null) - throw new NullArgumentException("Like post id must be not null"); - - String postId = like.getPostid(); - try { - toLike = readPost(postId); - if (toLike == null) - throw new PostIDNotFoundException("Could not find post with id " + postId + " to associate this like", postId); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - if (isPostLiked(like.getUserid(), postId)) { - _log.info("User " + like.getUserid() + " already liked post " + postId); - return true; - } - else { - CqlSession session = conn.getKeyspaceSession(); - // Inserting data - //an entry in the post CF - //and an entry in the UserLikesCF - List boundStatements = insertIntoLikes(session,like); - BoundStatement stmt2 = createNewUserLikesEntry(session).bind(like.getUserid(), UUID.fromString(like.getKey()), UUID.fromString(like.getPostid())); - boundStatements.add(stmt2); - - //boundStatements.forEach(stmt->writeBatch.add(stmt)); - BatchStatement writeBatch = getBatch().addAll(boundStatements); - - try { - session.execute(writeBatch); - - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return updatePostLikesCount(toLike, true); - } - } - /** - * @inheritDoc - */ - @Override - public boolean unlike(String userid, String likeid, String postId) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, LikeIDNotFoundException, PostIDNotFoundException { - Post toUpdate = readPost(postId); - boolean updateLikeNoResult = false; - - updateLikeNoResult = updatePostLikesCount(toUpdate, false); //this remove 1 from the post CF LikeNO - if (updateLikeNoResult) { - CqlSession session = conn.getKeyspaceSession(); - BatchStatement writeBatch = getBatch().add(deleteLikeEntry(session).bind(UUID.fromString(likeid))) - .add(deleteUserLikeEntry(session).bind(userid, UUID.fromString(likeid))); - try { - session.execute(writeBatch); - - } catch (Exception e) { - - _log.error("Like Delete FAILED for " + likeid + " from post " + postId); - e.printStackTrace(); - } - _log.trace("Unlike ok for " + likeid + " from post " + postId); - } - return updateLikeNoResult; - - } - /** - * @inheritDoc - */ - @Override - public List getAllLikedPostIdsByUser(String userid) { - ResultSet result = null; - CqlSession session = conn.getKeyspaceSession(); - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(USER_LIKED_POSTS).all() - .whereColumn(USER_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(userid)); - - } catch (Exception e){ - e.printStackTrace(); - - } - - ArrayList toReturn = new ArrayList(); - for (Row row: result){ - toReturn.add(row.getUuid(POST_ID).toString()); - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public List getAllLikedPostsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { - ArrayList toReturn = new ArrayList(); - List likedPostIDs = getAllLikedPostIdsByUser(userid); - - //check if quantity is greater than user posts - limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; - - //need them in reverse order - for (int i = likedPostIDs.size()-1; i >= (likedPostIDs.size()-limit); i--) { - Post toAdd = readPost(likedPostIDs.get(i)); - if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { - toReturn.add(toAdd); - _log.trace("Read recent post: " + likedPostIDs.get(i)); - } else { - _log.trace("Read and skipped post: " + likedPostIDs.get(i) + " (Removed post)"); - limit += 1; //increase the quantity in case of removed post - //check if quantity is greater than user posts - limit = (limit > likedPostIDs.size()) ? likedPostIDs.size() : limit; - } - } - return toReturn; - } - - /** - * @inheritDoc - */ - @Override - public List getRecentLikedPostsByUserAndDate(String userid, - long timeInMillis) throws IllegalArgumentException { - - List toReturn = new ArrayList<>(); - - 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 posts - List likedPostsIdsByUser = getAllLikedPostIdsByUser(userid); - - if(likedPostsIdsByUser != null && !likedPostsIdsByUser.isEmpty()){ - for(int i = likedPostsIdsByUser.size() - 1; i >= 0; i--){ - String postid = likedPostsIdsByUser.get(i); - try{ - - // retrieve the Post - Post toCheck = readPost(postid); - boolean isPostOk = (toCheck.getType() == PostType.TWEET || toCheck.getType() == PostType.SHARE || toCheck.getType() == PostType.PUBLISH); - - // retrieve the like of the user for the post - if(isPostOk){ - List likes = getAllLikesByPost(postid); - for (Like like : likes) { - if(like.getTime().getTime() >= timeInMillis && like.getUserid().equals(userid)) - toReturn.add(toCheck); - } - } - - }catch(Exception e){ - _log.error("Skipped post with id " + postid, 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 - */ - @Override - public List getAllLikesByPost(String postid) { - //possible error index - - List toReturn = new ArrayList(); - ResultSet result = null; - CqlSession session = conn.getKeyspaceSession(); - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(LIKES).all() - .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(UUID.fromString(postid))); - for (Row row: result) { - Like toAdd = readLikeFromRow(row); - toReturn.add(toAdd); - } - - } catch (Exception e){ - e.printStackTrace(); - - } - return toReturn; - } - /* - * - ********************** HASHTAGS *********************** - * - */ - /** - * @inheritDoc - */ - @Override - public boolean saveHashTags(String postId, String vreid, List hashtags) throws PostIDNotFoundException { - Set noduplicatesHashtags = null; - if (hashtags != null && !hashtags.isEmpty()) { - noduplicatesHashtags = new HashSet(hashtags); - } - // Inserting data - CqlSession session = conn.getKeyspaceSession(); - for (String hashtag : noduplicatesHashtags) { - String lowerCaseHashtag = hashtag.toLowerCase(); - boolean firstInsert = session.execute((createNewHashtagTimelineEntry(session).bind(lowerCaseHashtag, UUID.fromString(postId), vreid))).wasApplied(); - boolean 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 deleteHashTags(String postId, String vreid, List hashtags) throws PostIDNotFoundException { - Set noduplicatesHashtags = null; - if (hashtags != null && !hashtags.isEmpty()) { - noduplicatesHashtags = new HashSet(hashtags); - } - // Inserting data - CqlSession session = conn.getKeyspaceSession(); - for (String hashtag : noduplicatesHashtags) { - String lowerCaseHashtag = hashtag.toLowerCase(); - boolean firstDelete = session.execute(deleteHashtagEntry(session).bind(lowerCaseHashtag, UUID.fromString(postId))).wasApplied(); - boolean secondInsert = updateVREHashtagCount(vreid, lowerCaseHashtag, false); - if (! (firstDelete && secondInsert)) { - _log.error("deleteHashTags: Could not delete the hashtag(s)"); - - return false; - - } - } - - return true; - } - /** - * @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 - CqlSession session = conn.getKeyspaceSession(); - for (String hashtag : noduplicatesHashtags) { - String lowerCaseHashtag = hashtag.toLowerCase(); - boolean firstInsert = session.execute(createNewHashtagCommentEntry(session).bind(hashtag, UUID.fromString(commentId), vreid)).wasApplied(); - 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 - CqlSession session = conn.getKeyspaceSession(); - for (String hashtag : noduplicatesHashtags) { - String lowerCaseHashtag = hashtag.toLowerCase(); - boolean firstDelete = session.execute(deleteHashtagCommentEntry(session).bind(lowerCaseHashtag, UUID.fromString(commentId))).wasApplied(); - 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) { - ResultSet result = null; - CqlSession session = conn.getKeyspaceSession(); - - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(HASHTAGS_COUNTER).all() - .whereColumn(VRE_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(vreid)); - - } catch (Exception e){ - e.printStackTrace(); - - } - - - HashMap toReturn = new HashMap (); - - List rows = result.all(); - // Iterate rows and their columns - for (Row row : rows) { - Integer curValue = (int) row.getLong(COUNT); - if (curValue > 0) - toReturn.put(row.getString(HASHTAG), curValue); - } - - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public Map getVREHashtagsWithOccurrenceFilteredByTime(String vreid, long timestamp){ - CqlSession session = conn.getKeyspaceSession(); - ResultSet result = null; - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(HASHTAGS_COUNTER).all() - .whereColumn(VRE_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(vreid)); - - } catch (Exception e){ - e.printStackTrace(); - - } - - HashMap toReturn = new HashMap (); - List rows = result.all(); - // Iterate rows and their columns - for (Row row : rows) { - // retrieve the posts list for this hashtag - List posts = null; - try{ - posts = getVREPostsByHashtag(vreid, row.getString(HASHTAG)); - }catch(Exception e){ - _log.error("Unable to retrieve the list of posts for hashtag" + row.getString(HASHTAG) + " in vre " + vreid); - continue; - } - - if(posts.isEmpty()){ - - _log.info("There are no posts containing hashtag " + row.getString(HASHTAG) + " in vre " + vreid); - continue; - - } - - // retrieve the most recent one among these posts - Collections.sort(posts, Collections.reverseOrder()); - - if(posts.get(0).getTime().getTime() < timestamp){ - continue; - } - - // else.. - int curValue = (int) row.getLong(COUNT); - - if (curValue > 0) - toReturn.put(row.getString(HASHTAG), curValue); - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public List getVREPostsByHashtag(String vreid, String hashtag) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException { - List toReturn = new ArrayList<>(); - CqlSession session = conn.getKeyspaceSession(); - - ResultSet resultPost = null; - PreparedStatement stmtFind1 = session.prepare(QueryBuilder - .selectFrom(HASHTAGGED_POSTS).all() - .whereColumn(HASHTAG) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - resultPost = session.execute(stmtFind1.bind(hashtag)); - } catch (Exception e){ - e.printStackTrace(); - - } - - PreparedStatement stmtFind2 = session.prepare(QueryBuilder - .selectFrom(HASHTAGGED_COMMENTS).all() - .whereColumn(HASHTAG) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - ResultSet resultComment = null; - try { - resultComment = session.execute(stmtFind2.bind(hashtag)); - } catch (Exception e){ - e.printStackTrace(); - - } - - Set postIds = new HashSet<>(); - // Iterate rows and their columns (post) - ListrowsPost=resultPost.all(); - for (Row row : rowsPost) { - if (row.getString(VRE_ID).compareTo(vreid)==0) - postIds.add(row.getUuid(POST_ID).toString()); - } - // Iterate rows and their columns (comments) - ListrowsComment=resultComment.all(); - for (Row row : rowsComment) { - if (row.getString(VRE_ID).compareTo(vreid)==0){ - try { - Comment c = readCommentById(row.getUuid(COMMENT_ID).toString()); - postIds.add(c.getPostid()); - } catch (CommentIDNotFoundException e) { - _log.warn("Failed to fetch comment with id " + row.getString(COMMENT_ID)); - } - } - } - toReturn = getPostsByIds(new ArrayList<>(postIds)); - return toReturn; - } - /* - * - ********************** Invites *********************** - * - */ - private List insertIntoInvites(CqlSession session, Invite invite){ - - PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(SENDER_USER_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(VRE_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(EMAIL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(CONTROL_CODE, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(STATUS, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(SENDER_FULL_NAME, QueryBuilder.bindMarker()).build()); - - List boundStatements = new ArrayList<>(); - - if(invite.getSenderUserId()!=null){ - boundStatements.add(prepStmt1.bind(UUID.fromString(invite.getKey()),invite.getSenderUserId())); - } - - if(invite.getVreid()!=null){ - boundStatements.add(prepStmt2.bind(UUID.fromString(invite.getKey()), invite.getVreid())); - } - - if(invite.getInvitedEmail()!=null){ - boundStatements.add(prepStmt3.bind(UUID.fromString(invite.getKey()), invite.getInvitedEmail())); - } - - if(invite.getControlCode()!=null){ - boundStatements.add(prepStmt4.bind(UUID.fromString(invite.getKey()),invite.getControlCode())); - } - if(invite.getStatus()!=null){ - boundStatements.add(prepStmt5.bind(UUID.fromString(invite.getKey()),invite.getStatus().toString())); - } - if(invite.getTime()!=null){ - boundStatements.add(prepStmt6.bind(UUID.fromString(invite.getKey()),invite.getTime().toInstant())); - } - - if(invite.getSenderFullName()!=null){ - boundStatements.add(prepStmt7.bind(UUID.fromString(invite.getKey()),invite.getSenderFullName())); - } - - return boundStatements; - } - - /** - * common part to save a invite - * @param invite - * @return the partial mutation batch instance - */ - private List initSaveInvite(Invite invite, CqlSession session) { - List boundStatements = insertIntoInvites(session, invite); - if (invite == null) - throw new NullArgumentException("Invite instance is null"); - - return boundStatements; - } - - /** - * @inheritDoc - */ - @Override - public String isExistingInvite(String vreid, String email) { - CqlSession session = conn.getKeyspaceSession(); - - ResultSet result = null; - PreparedStatement stmtFind1 = session.prepare(QueryBuilder - .selectFrom(EMAIL_INVITES).all() - .whereColumn(EMAIL) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind1.bind(email)); - } catch (Exception e){ - e.printStackTrace(); - - } - - // Iterate rows and their columns - Listrows=result.all(); - for (Row row : rows) { - if (row.getString(VRE_ID).compareTo(vreid)==0) - return row.getUuid(INVITE_ID).toString(); - - } - return null; - } - /** - * @inheritDoc - */ - @Override - public InviteOperationResult saveInvite(Invite invite) throws AddressException { - if (invite == null) - throw new NullArgumentException("Invite instance is null"); - String email = invite.getInvitedEmail(); - if (! verifyEmail(email)) - throw new AddressException("Email is not valid ->" + email); - if (invite.getVreid() == null || invite.getVreid().equals("")) - throw new NullArgumentException("VREId is null or empty"); - _log.debug("isExistingInvite? " + invite.getInvitedEmail() + " in " + invite.getVreid()); - if (isExistingInvite(invite.getVreid(), invite.getInvitedEmail()) != null) - return InviteOperationResult.ALREADY_INVITED; - _log.debug("Invite not found, proceed to save it ..."); - CqlSession session = conn.getKeyspaceSession(); - List boundStatements = initSaveInvite(invite, session); - //an entry in the VRE Invites - boundStatements.add(createNewVreInviteEntry(session).bind(invite.getVreid(), UUID.fromString(invite.getKey()), InviteStatus.PENDING.toString())); - //an entry in the EMAIL Invites - boundStatements.add(createNewEmailInviteEntry(session).bind(email, invite.getVreid(), UUID.fromString(invite.getKey()))); - BatchStatement writeBatch = getBatch().addAll(boundStatements); - boolean result = session.execute(writeBatch).wasApplied(); - - return result ? InviteOperationResult.SUCCESS : InviteOperationResult.FAILED; - } - /** - * @inheritDoc - */ - @Override - public Invite readInvite(String inviteid) throws InviteIDNotFoundException, InviteStatusNotFoundException { - Invite toReturn = null; - CqlSession session = conn.getKeyspaceSession(); - ResultSet result = null; - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(INVITES).all() - .whereColumn(INVITE_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(UUID.fromString(inviteid))); - toReturn = readAInviteFromRow(result.one()); - if (toReturn == null) { - throw new InviteStatusNotFoundException("The requested inviteid: " + inviteid + " is not existing"); - } - //toReturn = readAInviteFromRow(result.all().get(0)); - - } catch (Exception e){ - e.printStackTrace(); - - } - return toReturn; - } /** * helper method that retrieve all the Invites belonging to a list of Ids @@ -2454,176 +2180,17 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { return toReturn; } /** - * @inheritDoc - * @throws InviteStatusNotFoundException + * common part to save a invite + * @param invite + * @return the partial mutation batch instance */ - @Override - public boolean setInviteStatus(String vreid, String email, InviteStatus status) throws InviteIDNotFoundException, InviteStatusNotFoundException { - String inviteid = isExistingInvite(vreid, email); - Invite toSet = readInvite(inviteid); - if (toSet == null) - throw new InviteIDNotFoundException("The specified invite to set with id: " + inviteid + " does not exist"); - - CqlSession session = conn.getKeyspaceSession(); - BatchStatement writeBatch = getBatch().add(updateInviteEntry(session, STATUS).bind(status.toString(), UUID.fromString(inviteid))) - .add(updateVreInviteEntry(session, STATUS).bind(status.toString(), vreid, UUID.fromString(inviteid))); - try { - session.execute(writeBatch); - - } catch (Exception e) { - _log.error("ERROR while setting Invite " + inviteid + " to " + status.toString()); - - return false; - } - _log.trace("Invite Status Set to " + status.toString() + " OK"); - return true; - } - /** - * @inheritDoc - */ - @Override - public List getInvitedEmailsByVRE(String vreid, InviteStatus... status) throws InviteIDNotFoundException, InviteStatusNotFoundException{ - CqlSession session = conn.getKeyspaceSession(); - ResultSet result = null; - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(VRE_INVITES).all() - .whereColumn(VRE_ID) - .isEqualTo(QueryBuilder.bindMarker()) - .build()); - try { - result = session.execute(stmtFind.bind(vreid)); - - } catch (Exception e){ - e.printStackTrace(); - - } - - ArrayList invitesIds = new ArrayList(); - // Iterate rows and their columns - Listrows=result.all(); - for (Row row : rows) { - if (status != null) { - for (int i = 0; i < status.length; i++) { - if (row.getString(STATUS).compareTo(status[i].toString())==0) - invitesIds.add(row.getUuid(INVITE_ID).toString()); - } - } - else { - invitesIds.add(row.getUuid(INVITE_ID).toString()); - } - } - return getInvitesById(invitesIds); - } - /** - * @inheritDoc - */ - @Override - public List getAttachmentsByPostId(String postId) throws PostIDNotFoundException { - //index error - Post toCheck = null; - try { - toCheck = readPost(postId); - if (toCheck == null) - throw new PostIDNotFoundException("Could not find post with id " + postId, postId); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - List toReturn = new ArrayList(); - CqlSession session = conn.getKeyspaceSession(); - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(ATTACHMENTS).all() - .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) - .build()); - ResultSet result = null; - try { - result = session.execute(stmtFind.bind(UUID.fromString(postId))); - // Iterate rows and their columns - Listrows=result.all(); - for (Row row : rows) { - _log.trace("Reading attachment if post=" + row.getUuid(POST_ID).toString()); - Attachment toAdd = readAttachmentFromRow(row); - toReturn.add(toAdd); - } - - } catch (Exception e) { - e.printStackTrace(); - - return null; - } - return toReturn; - } - /** - * @inheritDoc - */ - @Override - public void closeConnection() { - conn.closeConnection(); - } - /* - * - ********************** Helper methods *********************** - * - */ - private List insertIntoAttachments(CqlSession session, Attachment attachment, String postId){ - - - PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(NAME, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(URI_THUMBNAIL, QueryBuilder.bindMarker()).build()); - PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(MIME_TYPE, QueryBuilder.bindMarker()).build()); - - List boundStatements = new ArrayList<>(); - - boundStatements.add(prepStmt1.bind(UUID.fromString(attachment.getId()),UUID.fromString(postId))); - - - if(attachment.getUri()!=null){ - boundStatements.add(prepStmt2.bind(UUID.fromString(attachment.getId()), attachment.getUri())); - } - - if(attachment.getName()!=null){ - boundStatements.add(prepStmt3.bind(UUID.fromString(attachment.getId()), attachment.getName())); - } - - if(attachment.getDescription()!=null){ - boundStatements.add(prepStmt4.bind(UUID.fromString(attachment.getId()),attachment.getDescription())); - } - if(attachment.getThumbnailURL()!=null){ - boundStatements.add(prepStmt5.bind(UUID.fromString(attachment.getId()),attachment.getThumbnailURL())); - } - if(attachment.getMimeType()!=null){ - boundStatements.add(prepStmt6.bind(UUID.fromString(attachment.getId()),attachment.getMimeType())); - } - + private List initSaveInvite(Invite invite, CqlSession session) { + List boundStatements = insertIntoInvites(session, invite); + if (invite == null) + throw new NullArgumentException("Invite instance is null"); return boundStatements; } - /** - * @inheritDoc - */ - @Override - public boolean saveAttachmentEntry(String postId, Attachment toSave) { - // Inserting data - CqlSession session = conn.getKeyspaceSession(); - //an entry in the Attachment CF - try { - List boundStatements = insertIntoAttachments(session, toSave, postId); - BatchStatement writeBatch = getBatch().addAll(boundStatements); - ResultSet res = session.execute(writeBatch); - _log.info(res.getExecutionInfos().toString()); - _log.info(""+res.wasApplied()); - - } catch (Exception e) { - - e.printStackTrace(); - return false; - } - return true; - } - /** * simply return an enum representing the privacy level @@ -2929,7 +2496,10 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { * @param increment set true if you want to add 1, false to subtract 1. */ private boolean updateVREHashtagCount(String vreid, String hashtag, boolean increment) { - Map vreHashtags = getVREHashtagsWithOccurrence(vreid); + List vreHashtagsList = getVREHashtagsWithOccurrence(vreid); + Map vreHashtags = new HashMap<>(); + vreHashtagsList.forEach(x-> vreHashtags.put(x.getId(), x.getOccurrence())); + //if the hashtag not yet exist int newCount = 0; @@ -2949,10 +2519,10 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { CqlSession session = conn.getKeyspaceSession(); BoundStatement stmt; - if (existRecordbyCompId(session, HASHTAG, VRE_ID, hashtag, vreid, HASHTAGS_COUNTER)){ + if (existRecordbyCompId(session, Schema.HASHTAG, VRE_ID, hashtag, vreid, HASHTAGS_COUNTER)){ stmt = session.prepare(QueryBuilder.update(HASHTAGS_COUNTER) .setColumn(COUNT, QueryBuilder.bindMarker()) - .whereColumn(HASHTAG).isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(Schema.HASHTAG).isEqualTo(QueryBuilder.bindMarker()) .whereColumn(VRE_ID).isEqualTo(QueryBuilder.bindMarker()) .build()).bind((long)newCount, hashtag, vreid); } @@ -2989,32 +2559,773 @@ public final class SocialDBDatastaxDriver implements SocialDBDriver { } - @Override - public List getAllVREIds(){ - Set ids = new HashSet<>(); - CqlSession session = conn.getKeyspaceSession(); - ResultSet result = null; - PreparedStatement stmtFind = session.prepare(QueryBuilder - .selectFrom(VRE_TIMELINE_POSTS).column(VRE_ID).all() + + + /* + * + ****** Helper Functions to return prepared statements to create entries in each CF ****** + * + */ + private static PreparedStatement createPostEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(POSTS) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(LINK_HOST, QueryBuilder.bindMarker()) + .value(DESCRIPTION, QueryBuilder.bindMarker()) + .value(EMAIL, QueryBuilder.bindMarker()) + .value(LIKES_NO, QueryBuilder.bindMarker()) + .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(LINK_DESCRIPTION, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(URI, QueryBuilder.bindMarker()) + .value(IS_APPLICATION_POST, QueryBuilder.bindMarker()) + .value(ENTITY_ID, QueryBuilder.bindMarker()) + .value(PRIVACY, QueryBuilder.bindMarker()) + .value(TYPE, QueryBuilder.bindMarker()) + .value(URI_THUMBNAIL, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(MULTI_FILE_UPLOAD, QueryBuilder.bindMarker()) + .value(FULL_NAME, QueryBuilder.bindMarker()) + .value(COMMENTS_NO, QueryBuilder.bindMarker()) + .value(LINK_TITLE, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createUserTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_TIMELINE_POSTS) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createVreTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(VRE_TIMELINE_POSTS) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createAppTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(APP_TIMELINE_POSTS) + .value(APP_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNotificationEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(NOTIFICATIONS) + .value(NOT_ID, QueryBuilder.bindMarker()) + .value(TYPE, QueryBuilder.bindMarker()) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(SUBJECT_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(DESCRIPTION, QueryBuilder.bindMarker()) + .value(URI, QueryBuilder.bindMarker()) + .value(SENDER_ID, QueryBuilder.bindMarker()) + .value(SENDER_FULL_NAME, QueryBuilder.bindMarker()) + .value(SENDER_THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(IS_READ, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createUserNotificationsEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_NOTIFICATIONS) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(NOT_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createUnreadNotificationEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_NOTIFICATIONS_UNREAD) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(NOT_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNotificationPreferenceEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_NOTIFICATIONS_PREFERENCES) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(TYPE, QueryBuilder.bindMarker()) + .value(PREFERENCE, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewCommentEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(COMMENTS) + .value(COMMENT_ID, QueryBuilder.bindMarker()) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(FULL_NAME, QueryBuilder.bindMarker()) + .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(Schema.COMMENT, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(IS_EDIT, QueryBuilder.bindMarker()) + .value(LAST_EDIT_TIME, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewLikeEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(LIKES) + .value(LIKE_ID, QueryBuilder.bindMarker()) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(FULL_NAME, QueryBuilder.bindMarker()) + .value(THUMBNAIL_URL, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewUserLikesEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(USER_LIKED_POSTS) + .value(USER_ID, QueryBuilder.bindMarker()) + .value(LIKE_ID, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewHashtagTimelineEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(HASHTAGGED_POSTS) + .value(Schema.HASHTAG, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewHashtagCommentEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(HASHTAGGED_COMMENTS) + .value(Schema.HASHTAG, QueryBuilder.bindMarker()) + .value(COMMENT_ID, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewEmailInviteEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(EMAIL_INVITES) + .value(EMAIL, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(INVITE_ID, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewInviteEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(INVITES) + .value(INVITE_ID, QueryBuilder.bindMarker()) + .value(SENDER_USER_ID, QueryBuilder.bindMarker()) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(EMAIL, QueryBuilder.bindMarker()) + .value(CONTROL_CODE, QueryBuilder.bindMarker()) + .value(STATUS, QueryBuilder.bindMarker()) + .value(TIMESTAMP, QueryBuilder.bindMarker()) + .value(SENDER_FULL_NAME, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewVreInviteEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(VRE_INVITES) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(INVITE_ID, QueryBuilder.bindMarker()) + .value(STATUS, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewaAttachEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(ATTACHMENTS) + .value(ATTACH_ID, QueryBuilder.bindMarker()) + .value(POST_ID, QueryBuilder.bindMarker()) + .value(URI, QueryBuilder.bindMarker()) + .value(NAME, QueryBuilder.bindMarker()) + .value(DESCRIPTION, QueryBuilder.bindMarker()) + .value(URI_THUMBNAIL, QueryBuilder.bindMarker()) + .value(MIME_TYPE, QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement createNewUHashtagCounterEntry(CqlSession session){ + return session.prepare( + QueryBuilder.insertInto(HASHTAGS_COUNTER) + .value(VRE_ID, QueryBuilder.bindMarker()) + .value(Schema.HASHTAG, QueryBuilder.bindMarker()) + .value(COUNT, QueryBuilder.bindMarker()) + .build()); + } + + /* + * + ****** Helper Functions to return prepared statements to update entries in some CF ****** + * + */ + private static PreparedStatement updatePostEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(POSTS) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) .build()); - try { - result = session.execute(stmtFind.bind()); + } + private static PreparedStatement updateInviteEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(INVITES) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(INVITE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement updateVreInviteEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(VRE_INVITES) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(VRE_ID).isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(INVITE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement updateCommentEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(COMMENTS) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(COMMENT_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement updateNotificationEntry(CqlSession session, String colName){ + return session.prepare(QueryBuilder.update(NOTIFICATIONS) + .setColumn(colName, QueryBuilder.bindMarker()) + .whereColumn(NOT_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } - } catch (Exception e){ - e.printStackTrace(); + /* + * + ****** Helper Functions to return prepared statements to delete entries in some CF ****** + * + */ + private static PreparedStatement deleteHashtagEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(HASHTAGGED_POSTS) + .whereColumn(Schema.HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(POST_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteHashtagCommentEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(HASHTAGGED_COMMENTS) + .whereColumn(Schema.HASHTAG) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(COMMENT_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteLikeEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(LIKES) + .whereColumn(LIKE_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteAttachmentEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(ATTACHMENTS) + .whereColumn(ATTACH_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deletePostEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(POSTS) + .whereColumn(POST_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteUserLikeEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(USER_LIKED_POSTS) + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(LIKE_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteCommentEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(COMMENTS) + .whereColumn(COMMENT_ID).isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + private static PreparedStatement deleteUnreadNotEntry(CqlSession session){ + return session.prepare(QueryBuilder.deleteFrom(USER_NOTIFICATIONS_UNREAD) + .whereColumn(USER_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(TIMESTAMP) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + } + /* + * + ****** Helper Functions to insert objects into the DB ****** + * + */ + private List insertIntoNotifications(CqlSession session, Notification notification){ + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(TYPE, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SUBJECT_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_FULL_NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt9 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(SENDER_THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt10 = session.prepare(QueryBuilder.insertInto(NOTIFICATIONS).value(NOT_ID, QueryBuilder.bindMarker()).value(IS_READ, QueryBuilder.bindMarker()).build()); + + List boundStatements = new ArrayList<>(); + + if(notification.getType()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(notification.getKey()),notification.getType().toString())); } - Listrows=result.all(); - for (Row row : rows) { - ids.add(row.getString(VRE_ID)); + if(notification.getUserid()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(notification.getKey()), notification.getUserid())); } - List toReturn = new ArrayList<>(); - toReturn.addAll(ids); - _log.debug("VRE ids are " + ids); - return toReturn; + if(notification.getSubjectid()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(notification.getKey()), notification.getSubjectid())); + } + if(notification.getTime()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(notification.getKey()),notification.getTime().toInstant())); + } + if(notification.getDescription()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(notification.getKey()),notification.getDescription())); + }if(notification.getUri()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(notification.getKey()),notification.getUri())); + }if(notification.getSenderid()!=null){ + boundStatements.add(prepStmt7.bind(UUID.fromString(notification.getKey()),notification.getSenderid())); + }if(notification.getSenderFullName()!=null){ + boundStatements.add(prepStmt8.bind(UUID.fromString(notification.getKey()),notification.getSenderFullName())); + }if(notification.getSenderThumbnail()!=null){ + boundStatements.add(prepStmt9.bind(UUID.fromString(notification.getKey()),notification.getSenderThumbnail())); + } + + boundStatements.add(prepStmt10.bind(UUID.fromString(notification.getKey()),notification.isRead())); + + return boundStatements; + } + private List insertIntoComments(CqlSession session, Comment comment){ + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(Schema.COMMENT, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(IS_EDIT, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(COMMENTS).value(COMMENT_ID, QueryBuilder.bindMarker()).value(LAST_EDIT_TIME, QueryBuilder.bindMarker()).build()); + + List boundStatements = new ArrayList<>(); + + if(comment.getUserid()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(comment.getKey()),comment.getUserid())); + } + + if(comment.getFullName()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(comment.getKey()), comment.getFullName())); + } + + if(comment.getThumbnailURL()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(comment.getKey()), comment.getThumbnailURL())); + } + if(comment.getText()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(comment.getKey()),comment.getText())); + } + if(comment.getPostid()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(comment.getKey()),UUID.fromString(comment.getPostid()))); + }if(comment.getTime()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(comment.getKey()),comment.getTime().toInstant())); + } + boundStatements.add(prepStmt7.bind(UUID.fromString(comment.getKey()),comment.isEdit())); + + if(comment.getLastEditTime()!=null){ + boundStatements.add(prepStmt8.bind(UUID.fromString(comment.getKey()),comment.getLastEditTime().toInstant())); + } + + return boundStatements; + } + private List insertIntoLikes(CqlSession session, Like like){ + + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(USER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(LIKES).value(LIKE_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + + List boundStatements = new ArrayList<>(); + + if(like.getUserid()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(like.getKey()),like.getUserid())); + } + + if(like.getFullName()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(like.getKey()), like.getFullName())); + } + + if(like.getThumbnailURL()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(like.getKey()), like.getThumbnailURL())); + } + + if(like.getPostid()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(like.getKey()),UUID.fromString(like.getPostid()))); + }if(like.getTime()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(like.getKey()),like.getTime().toInstant())); + } + + return boundStatements; + } + private List insertIntoInvites(CqlSession session, Invite invite){ + + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(SENDER_USER_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(VRE_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(EMAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(CONTROL_CODE, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(STATUS, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(INVITES).value(INVITE_ID, QueryBuilder.bindMarker()).value(SENDER_FULL_NAME, QueryBuilder.bindMarker()).build()); + + List boundStatements = new ArrayList<>(); + + if(invite.getSenderUserId()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(invite.getKey()),invite.getSenderUserId())); + } + + if(invite.getVreid()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(invite.getKey()), invite.getVreid())); + } + + if(invite.getInvitedEmail()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(invite.getKey()), invite.getInvitedEmail())); + } + + if(invite.getControlCode()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(invite.getKey()),invite.getControlCode())); + } + if(invite.getStatus()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(invite.getKey()),invite.getStatus().toString())); + } + if(invite.getTime()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(invite.getKey()),invite.getTime().toInstant())); + } + + if(invite.getSenderFullName()!=null){ + boundStatements.add(prepStmt7.bind(UUID.fromString(invite.getKey()),invite.getSenderFullName())); + } + + return boundStatements; + } + private List insertIntoAttachments(CqlSession session, Attachment attachment, String postId){ + + + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(POST_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(URI_THUMBNAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(ATTACHMENTS).value(ATTACH_ID, QueryBuilder.bindMarker()).value(MIME_TYPE, QueryBuilder.bindMarker()).build()); + + List boundStatements = new ArrayList<>(); + + boundStatements.add(prepStmt1.bind(UUID.fromString(attachment.getId()),UUID.fromString(postId))); + + + if(attachment.getUri()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(attachment.getId()), attachment.getUri())); + } + + if(attachment.getName()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(attachment.getId()), attachment.getName())); + } + + if(attachment.getDescription()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(attachment.getId()),attachment.getDescription())); + } + if(attachment.getThumbnailURL()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(attachment.getId()),attachment.getThumbnailURL())); + } + if(attachment.getMimeType()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(attachment.getId()),attachment.getMimeType())); + } + + + return boundStatements; + } + private List insertIntoPosts(CqlSession session, Post post){ + PreparedStatement prepStmt1 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_HOST, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt2 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt3 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(EMAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt4 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LIKES_NO, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt5 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(THUMBNAIL_URL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt6 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_DESCRIPTION, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt7 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(TIMESTAMP, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt8 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(URI, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt9 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(IS_APPLICATION_POST, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt10 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(ENTITY_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt11 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(PRIVACY, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt12 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(TYPE, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt13 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(URI_THUMBNAIL, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt14 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(VRE_ID, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt15 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(MULTI_FILE_UPLOAD, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt16 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(FULL_NAME, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt17 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(COMMENTS_NO, QueryBuilder.bindMarker()).build()); + PreparedStatement prepStmt18 = session.prepare(QueryBuilder.insertInto(POSTS).value(POST_ID, QueryBuilder.bindMarker()).value(LINK_TITLE, QueryBuilder.bindMarker()).build()); + List boundStatements = new ArrayList<>(); + + if(post.getLinkHost()!=null){ + boundStatements.add(prepStmt1.bind(UUID.fromString(post.getKey()), post.getLinkHost())); + }if(post.getDescription()!=null){ + boundStatements.add(prepStmt2.bind(UUID.fromString(post.getKey()), post.getDescription())); + }if(post.getEmail()!=null){ + boundStatements.add(prepStmt3.bind(UUID.fromString(post.getKey()), post.getEmail())); + }if(post.getLikesNo()!=null){ + boundStatements.add(prepStmt4.bind(UUID.fromString(post.getKey()), Long.parseLong(post.getLikesNo()))); + }if(post.getThumbnailURL()!=null){ + boundStatements.add(prepStmt5.bind(UUID.fromString(post.getKey()), post.getThumbnailURL())); + }if(post.getLinkDescription()!=null){ + boundStatements.add(prepStmt6.bind(UUID.fromString(post.getKey()), post.getLinkDescription())); + }if(post.getTime()!=null){ + boundStatements.add(prepStmt7.bind(UUID.fromString(post.getKey()), post.getTime().toInstant())); + }if(post.getUri()!=null){ + boundStatements.add(prepStmt8.bind(UUID.fromString(post.getKey()), post.getUri())); + } + boundStatements.add(prepStmt9.bind(UUID.fromString(post.getKey()), post.isApplicationPost())); + if(post.getEntityId()!=null){ + boundStatements.add(prepStmt10.bind(UUID.fromString(post.getKey()), post.getEntityId())); + }if(post.getPrivacy()!=null){ + boundStatements.add(prepStmt11.bind(UUID.fromString(post.getKey()), post.getPrivacy().toString())); + }if(post.getType()!=null){ + boundStatements.add(prepStmt12.bind(UUID.fromString(post.getKey()), post.getType().toString())); + }if(post.getUriThumbnail()!=null){ + boundStatements.add(prepStmt13.bind(UUID.fromString(post.getKey()), post.getUriThumbnail())); + }if(post.getVreid()!=null){ + boundStatements.add(prepStmt14.bind(UUID.fromString(post.getKey()), post.getVreid())); + } + boundStatements.add(prepStmt15.bind(UUID.fromString(post.getKey()), post.isMultiFileUpload())); + if(post.getFullName()!=null){ + boundStatements.add(prepStmt16.bind(UUID.fromString(post.getKey()), post.getFullName())); + }if(post.getCommentsNo()!=null){ + boundStatements.add(prepStmt17.bind(UUID.fromString(post.getKey()), Long.parseLong(post.getCommentsNo()))); + }if(post.getLinkTitle()!=null){ + boundStatements.add(prepStmt18.bind(UUID.fromString(post.getKey()), post.getLinkTitle())); + } + return boundStatements; + } + + /* + * + ****** Helper Functions to fetch rows by ID from some CF ****** + * + */ + private static Optional < Post > findPostById(String postid, CqlSession session) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException { + PreparedStatement stmtFindPost = session.prepare(QueryBuilder + .selectFrom(POSTS).all() + .whereColumn(POST_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet rs = session.execute(stmtFindPost.bind(UUID.fromString(postid))); + // We query by the primary key ensuring unicity + Row record = rs.one(); + return (null != record) ? Optional.of(readPostFromRow(record)) :Optional.empty(); + } + private static Optional < Notification > findNotById(String notid, CqlSession session) throws NotificationTypeNotFoundException { + PreparedStatement stmtFind = session.prepare(QueryBuilder + .selectFrom(NOTIFICATIONS).all() + .whereColumn(NOT_ID) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + ResultSet rs = session.execute(stmtFind.bind(UUID.fromString(notid))); + // We query by the primary key ensuring unicity + Row record = rs.one(); + return (null != record) ? Optional.of(readNotificationFromRow(record)) :Optional.empty(); + } + + /* + * + ****** Helper Functions to transform DB rows into objects ****** + * + */ + private static Attachment readAttachmentFromRow(Row record) { + Attachment a = new Attachment(); + a.setId(Objects.requireNonNull(record.getUuid(ATTACH_ID)).toString()); + a.setUri(record.getString(URI)); + a.setName(record.getString(NAME)); + a.setDescription(record.getString(DESCRIPTION)); + a.setThumbnailURL(record.getString(URI_THUMBNAIL)); + a.setMimeType(record.getString(MIME_TYPE)); + return a; + } + private static Notification readNotificationFromRow(Row record) throws NotificationTypeNotFoundException { + Notification a = new Notification(); + a.setKey(Objects.requireNonNull(record.getUuid(NOT_ID)).toString()); + a.setType(getNotificationType(Objects.requireNonNull(record.getString(TYPE)))); + a.setUserid(record.getString(USER_ID)); + a.setSubjectid(record.getString(SUBJECT_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setUri(record.getString(URI)); + a.setDescription(record.getString(DESCRIPTION)); + a.setRead(record.getBoolean(IS_READ)); + a.setSenderid(record.getString(SENDER_ID)); + a.setSenderFullName(record.getString(SENDER_FULL_NAME)); + a.setSenderThumbnail(record.getString(SENDER_THUMBNAIL_URL)); + return a; + } + private static Post readPostFromRow(Row record) throws PostTypeNotFoundException, PrivacyLevelTypeNotFoundException { + Post a = new Post(); + + a.setKey(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setType(getPostType(Objects.requireNonNull(record.getString(TYPE)))); + a.setEntityId(record.getString(ENTITY_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setVreid(record.getString(VRE_ID)); + a.setUri(record.getString(URI)); + a.setUriThumbnail(record.getString(URI_THUMBNAIL)); + a.setDescription(record.getString(DESCRIPTION)); + a.setPrivacy(getPrivacyLevel(Objects.requireNonNull(record.getString(PRIVACY)))); + a.setFullName(record.getString(FULL_NAME)); + a.setEmail(record.getString(EMAIL)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + a.setCommentsNo(String.valueOf(record.getLong(COMMENTS_NO))); + a.setLikesNo(String.valueOf(record.getLong(LIKES_NO))); + a.setLinkDescription(record.getString(LINK_DESCRIPTION)); + a.setLinkTitle(record.getString(LINK_TITLE)); + a.setLinkHost(record.getString(LINK_HOST)); + a.setApplicationPost(record.getBoolean(IS_APPLICATION_POST)); + a.setMultiFileUpload(record.getBoolean(MULTI_FILE_UPLOAD)); + + return a; + } + private static Like readLikeFromRow(Row record) { + Like a = new Like(); + a.setKey(Objects.requireNonNull(record.getUuid(LIKE_ID)).toString()); + a.setUserid(record.getString(USER_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setPostid(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setFullName(record.getString(FULL_NAME)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + return a; + } + private static Comment readCommentFromRow(Row record) { + Comment a = new Comment(); + a.setKey(Objects.requireNonNull(record.getUuid(COMMENT_ID)).toString()); + a.setUserid(record.getString(USER_ID)); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setPostid(Objects.requireNonNull(record.getUuid(POST_ID)).toString()); + a.setFullName(record.getString(FULL_NAME)); + a.setThumbnailURL(record.getString(THUMBNAIL_URL)); + a.setText(record.getString(Schema.COMMENT)); + a.setEdit(!record.isNull(IS_EDIT) && record.getBoolean(IS_EDIT)); + a.setLastEditTime(record.isNull(LAST_EDIT_TIME)? null : Date.from(Objects.requireNonNull(record.getInstant(LAST_EDIT_TIME)))); + return a; + } + private static Invite readAInviteFromRow(Row record) throws InviteStatusNotFoundException { + Invite a = new Invite(); + a.setKey(Objects.requireNonNull(record.getUuid(INVITE_ID)).toString()); + a.setSenderUserId(record.getString(SENDER_USER_ID)); + a.setVreid(record.getString(VRE_ID)); + a.setInvitedEmail(record.getString(EMAIL)); + a.setControlCode(record.getString(CONTROL_CODE)); + a.setStatus(getInviteStatusType(Objects.requireNonNull(record.getString(STATUS)))); + a.setTime(Date.from(Objects.requireNonNull(record.getInstant(TIMESTAMP)))); + a.setSenderFullName(record.getString(SENDER_FULL_NAME)); + return a; + } + + /* + * + ****** Helper Functions to check record existence by id ****** + * + */ + private static boolean existRecordbyId(CqlSession session, String id, String tableName, String colName) { + PreparedStatement stmt = session.prepare(QueryBuilder + .selectFrom(tableName).column(colName) + .whereColumn(colName) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + return session.execute(stmt.bind(id)).getAvailableWithoutFetching() > 0; + } + + private static boolean existRecordbyCompId(CqlSession session, String col1, String col2, String id1, String id2, String tableName) { + PreparedStatement stmt = session.prepare(QueryBuilder + .selectFrom(tableName).all() + .whereColumn(col1) + .isEqualTo(QueryBuilder.bindMarker()) + .whereColumn(col2) + .isEqualTo(QueryBuilder.bindMarker()) + .build()); + return session.execute(stmt.bind(id1, id2)).getAvailableWithoutFetching() > 0; + } + + /* + * + ********************** Helper function to get batch statement *********************** + * + */ + private static BatchStatement getBatch(){ + return BatchStatement.builder(BatchType.LOGGED).build(); } } + + /*private RangePosts getRecentPostsByVREAndRange(String vreid, int from, int quantity) throws IllegalArgumentException, PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException { + if (from < 1) { + throw new IllegalArgumentException("From must be greather than 0"); + } + ArrayList postsToReturn = new ArrayList(); + ArrayList postIDs = getVREPostIds(vreid); + + //if from is greater than posts size return empty + if (from >= postIDs.size()) { + _log.warn("The starting point of the range is greather than the total number of posts for this timeline: " + from + " >= " + postIDs.size()); + return new RangePosts(); + } + + int rangeStart = postIDs.size()-from; + int rangeEnd = rangeStart-quantity; + + //check that you reached the end + if (rangeEnd<1) + rangeEnd = 0; + + _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); + //need them in reverse order + int howMany = from; + for (int i = rangeStart; i > rangeEnd; i--) { + Post toAdd = readPost(postIDs.get(i)); + if (toAdd.getType() == PostType.TWEET || toAdd.getType() == PostType.SHARE || toAdd.getType() == PostType.PUBLISH) { + postsToReturn.add(toAdd); + _log.trace("Read recent post, i=" + i + " id= " + postIDs.get(i)); + } else { + _log.trace("Read and skipped post, i=" + i + " id=: " + postIDs.get(i) + " (Removed post) ."); + rangeEnd -= 1; //increase the upTo in case of removed post + //check if quantity is greater than user posts + rangeEnd = (rangeEnd > 0) ? rangeEnd : 0; + } + howMany++; + } + _log.debug("AFTER: starting Point==" + rangeStart + " rangeEnd= " + rangeEnd); + return new RangePosts(howMany+1, postsToReturn); + } + + private List getRangeNotificationsByUser(String userid,int from, int quantity) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException { + if (from < 1) { + throw new IllegalArgumentException("From must be greather than 0"); + } + ArrayList toReturn = new ArrayList(); + ArrayList notificationsIDs = getUserNotificationsIds(userid); + + //if from is greater than posts size return empty + if (from >= notificationsIDs.size()) { + _log.warn("The starting point of the range is greather than the total number of posts for this timeline: " + from + " >= " + notificationsIDs.size()); + return new ArrayList(); + } + + int rangeStart = notificationsIDs.size()-from; + int rangeEnd = rangeStart-quantity; + + //check that you reached the end + if (rangeEnd<1) + rangeEnd = 0; + + _log.debug("BEFORE starting Point=" + rangeStart + " rangeEnd= " + rangeEnd); + //need them in reverse order + for (int i = rangeStart; i > rangeEnd; i--) { + Notification toAdd = readNotification(notificationsIDs.get(i)); + toReturn.add(toAdd); + } + return toReturn; + } + */ + diff --git a/src/main/java/org/gcube/social_networking/server/SocialDBDriver.java b/src/main/java/org/gcube/social_networking/server/SocialDBDriver.java index f094306..1f77d9f 100644 --- a/src/main/java/org/gcube/social_networking/server/SocialDBDriver.java +++ b/src/main/java/org/gcube/social_networking/server/SocialDBDriver.java @@ -5,28 +5,10 @@ import java.util.Map; import javax.mail.internet.AddressException; -import org.gcube.social_networking.socialnetworking.model.shared.Attachment; -import org.gcube.social_networking.socialnetworking.model.shared.Comment; +import org.gcube.social_networking.socialnetworking.model.shared.Resource; import org.gcube.social_networking.socialnetworking.model.shared.Invite; import org.gcube.social_networking.socialnetworking.model.shared.InviteOperationResult; -import org.gcube.social_networking.socialnetworking.model.shared.InviteStatus; -import org.gcube.social_networking.socialnetworking.model.shared.Like; -import org.gcube.social_networking.socialnetworking.model.shared.Notification; -import org.gcube.social_networking.socialnetworking.model.shared.NotificationChannelType; -import org.gcube.social_networking.socialnetworking.model.shared.NotificationType; -import org.gcube.social_networking.socialnetworking.model.shared.Post; -import org.gcube.social_networking.socialnetworking.model.shared.RangePosts; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.ColumnNameNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.CommentIDNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.PostIDNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.PostTypeNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.InviteIDNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.InviteStatusNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.LikeIDNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.NotificationChannelTypeNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.NotificationIDNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.NotificationTypeNotFoundException; -import org.gcube.social_networking.socialnetworking.model.shared.exceptions.PrivacyLevelTypeNotFoundException; + /** * @author Massimiliano Assante ISTI-CNR @@ -35,415 +17,104 @@ import org.gcube.social_networking.socialnetworking.model.shared.exceptions.Priv */ public interface SocialDBDriver { /** - * save a Post instance in the store - * @return true if everything went fine + * create a resource in the DB */ - boolean saveUserPost(Post post); + Boolean create(Resource resource); /** - * Save a Post instance in the store having more than one attachment - * Use this if you need to attach more than one file to the post - * - * @param attachments a list of attachments starting from the second - * @return true if everything went fine + * create a child resource given its parent id in the DB */ - boolean saveUserPost(Post post, List attachments); + Boolean createChildOf(String parentid, Resource childResource, String parentResourceName); /** - * delete a post from the store - * @throws PostIDNotFoundException - * @return true if everything went fine + * batch create a child resource given its parent id in the DB */ - boolean deletePost(String postid) throws PostIDNotFoundException, PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException; - /** - * save a post in the VRES TimeLine in the store - * @param postKey the post id - * @param vreid vre identifier - * @throws PostIDNotFoundException - */ - boolean savePostToVRETimeline(String postKey, String vreid) throws PostIDNotFoundException; - /** - * save a Post instance in the store - * @return true if everything went fine - */ - boolean saveAppPost(Post post); - /** - * Save a Post instance in the store - * Use this if your app needs to attach more than one file to the post - * - * @param attachments a list of attachments starting from the second - * @return true if everything went fine - */ - boolean saveAppPost(Post post, List attachments); - /** - * read a post from a given id - * @throws PrivacyLevelTypeNotFoundException - * @throws PostTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - Post readPost(String postid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException; - /** - * @param userid user identifier - * return all the posts belonging to the userid - * @throws PostTypeNotFoundException - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - List getAllPostsByUser(String userid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException; - /** - * @param appid application identifier - * return all the posts belonging to the appid - * @throws PostTypeNotFoundException - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - List getAllPostsByApp(String appid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException; - /** - * @param userid the user identifier like andrea.rossi - * @param timeInMillis the initial time in millis to be considered - * @return a list of posts commented by userid starting from timeInMillis - * @throws Exception - */ - List getRecentCommentedPostsByUserAndDate(String userid, long timeInMillis) throws Exception; - /** - * return all the posts whose Level is PORTAL - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - * @throws PrivacyLevelTypeNotFoundException - */ - List getAllPortalPrivacyLevelPosts() throws PostTypeNotFoundException, ColumnNameNotFoundException, PrivacyLevelTypeNotFoundException; - /** - * return the most recent posts for this user up to quantity param - * @param userid user identifier - * @param quantity the number of most recent posts for this user - * @return a List of most recent posts for this user - * @throws PostTypeNotFoundException - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - List getRecentPostsByUser(String userid, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException; - /** - * @param vreid vre identifier - * return all the posts belonging to the userid - * @throws PostTypeNotFoundException - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - List getAllPostsByVRE(String vreid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException; - /** - * return the most recent posts for this vre up to quantity param - * @param vreid VRES identifier - * @param quantity the number of most recent posts for this vre - * @return a List of most recent posts for this vre - * @throws PostTypeNotFoundException - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - List getRecentPostsByVRE(String vreid, int quantity) throws IllegalArgumentException, PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException; - /** - * return the most recent posts for this vre up to quantity param and the last index of the posts in the timeline - * lastReturnedPostTimelineIndex is useful to know from where to start the range the next time you ask, because there are deletions - * - * @param vreid VRES identifier - * @param from the range start (most recent posts for this vre) has to be greater than 0 - * @param quantity the number of most recent posts for this vre starting from "from" param - * @return a RangePosts containing of most recent posts for this vre - * @throws PostTypeNotFoundException - * @throws PrivacyLevelTypeNotFoundException - * @throws ColumnNameNotFoundException - */ - RangePosts getRecentPostsByVREAndRange(String vreid, int from, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException; - /** - * @param userid user identifier - * @param timeInMillis time in milliseconds from which you want to start retrieve the posts - * @return the number of posts in the range from: today to: timeInMillis - */ - List getRecentPostsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException; - /** - * save a Notification instance in the store - * @return true if everything went fine - */ - boolean saveNotification(Notification notification); - /** - * set an existing Notification instance in the to read - * @return true if everything went fine - */ - boolean setNotificationRead(String notificationidToSet) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException; - /** - * read a notification from a given id - * @throws {@link ColumnNameNotFoundException} - * @throws {@link NotificationIDNotFoundException} - * @throws {@link NotificationTypeNotFoundException} - */ - Notification readNotification(String notificationid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException; + Boolean BatchCreateChildOfWithParameter(String parentid, String parameterName, String parameterValue, List childResource, String parentResourceName, String childResourceName); /** - * @param userid user identifier - * @param limit set 0 to get everything, an int to get the most recent -limit- notifications - * return all the notifications belonging to the userid up to limit, set 0 to get everything - * @throws NotificationTypeNotFoundException - * @throws ColumnNameNotFoundException + * read a resource given its id from the DB */ - List getAllNotificationByUser(String userid, int limit) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException; + Resource read(String id, String resourceName); /** - * - * @param userid user identifier - * @param from the range start has to be greater than 0 - * @param quantity the number of most recent notifications for this user starting from "from" param - * @return all the notifications for the userid in the range requested - * @throws NotificationTypeNotFoundException - * @throws ColumnNameNotFoundException - * @throws NotificationIDNotFoundException + * check attribute value of a resource given its id from the DB */ - List getRangeNotificationsByUser(String userid, int from, int quantity) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException; + Boolean check(String id, String parameterName, String parameterValue, String resourceName); /** - * This is a fast way to set all notification to read quickly - * @param userid - * @return true if everything went fine - * @throws {@link ColumnNameNotFoundException} - * @throws {@link NotificationIDNotFoundException} - * @throws {@link NotificationTypeNotFoundException} + * check attribute value of a child resource given its parent id from the DB */ - boolean setAllNotificationReadByUser(String userid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException; + Boolean checkChildOf(String parentid, String parameterName, String parameterValue, String parentResourceName, String childResourceName); /** - * return the not yet read notifications (not including messages) - * @param userid user identifier - * @return a List of not yet read notifications for this user - * @throws NotificationTypeNotFoundException - * @throws ColumnNameNotFoundException + * list all instances of a resource in the DB */ - List getUnreadNotificationsByUser(String userid) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException; + List readAll(String resourceName); /** - * - * @param userid user identifier - * @throws ColumnNameNotFoundException - * @throws NotificationTypeNotFoundException - * @throws NotificationIDNotFoundException - * @return true if there are unread notifications (not including messages), false if they are all read + * read a list of the children of a resource given its id from the DB */ - boolean checkUnreadNotifications(String userid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException; + ListreadChildOf(String parentid, String parentResourceName, String childResourceName); /** - * - * @param userid user identifier - * @throws ColumnNameNotFoundException - * @throws NotificationTypeNotFoundException self explaining - * @throws NotificationChannelTypeNotFoundException self explaining - * @throws NotificationIDNotFoundException - * @return true if there are unread messages notifications (including messages), false if they are all read + * read a list of resources with a specific attribute value */ - boolean checkUnreadMessagesNotifications(String userid) throws NotificationIDNotFoundException, NotificationTypeNotFoundException, ColumnNameNotFoundException; + List readWithParameter(String parameterName, String parameterValue, String resourceName); + /** + * read a list of the children of a resource with a specific attribute value + */ + List readChildOfWithParameter(String parentid, String parameterName, String parameterValue, String parentResourceName, String childResourceName); + /** + * update a resource given its id in the DB + */ + Boolean update(Resource resource); + /** + * update a child resource given its id and its parent id in the DB + */ + Boolean updateChildOf(String parentid, String childid, Resource childResource, String parentResourceName); + /** + * Batch update a child resource given its id and its parent id in the DB + */ + Boolean BatchUpdateChildOf(String parentid, List childResource, String parentResourceName); + /** + * update a resource with a certain attribute value + */ + Boolean updateWithParameter(String parameterName, String parameterValue, Resource resource); + /** + * update a child resource with a certain attribute value given its parent id + */ + Boolean updateChildOfWithParameter(String parentid, String parameterName, String parameterValue, Resource childResource,String parentResourceName); /** - * return the channels a user chose for being notified for a given notification type - * @param userid user identifier - * @param notificationType the type of the notification - * @return a list of NotificationChannelType that represents the channels this user wants to be notified + * delete a resource given its id in the DB */ - List getUserNotificationChannels(String userid, NotificationType notificationType) throws NotificationChannelTypeNotFoundException, NotificationTypeNotFoundException; + Boolean delete(String id, String resourceName); /** - * set the notification preferences map (enable or disable the channels to be used for notifying the user) - * @param userid user identifier - * @param enabledChannels a map of the channels to which reach the user per notification, empty array or null values to set the key notification type off - * @return true if everything was fine + * delete a child resource given its id and its parent id in the DB */ - boolean setUserNotificationPreferences(String userid, Map enabledChannels); + Boolean deleteChildOf(String parentid, String childid, String childResourceName); /** - * get the notification preferences map (enableor disable the channels to be used for notifying the user) - * @param userid user identifier - * @return the map - * @throws NotificationTypeNotFoundException self explaining - * @throws NotificationChannelTypeNotFoundException self explaining + * delete resources with a certain attribute value */ - Map getUserNotificationPreferences(String userid) throws NotificationTypeNotFoundException, NotificationChannelTypeNotFoundException; + Boolean deleteWithParameter(String parameterName, String parameterValue, String resourceName); + /** + * delete a child resource with a certain attribute value given its parent id + */ + Boolean deleteChildOfWithParameter(String parentid, String childid, String parameterName, String parameterValue, String parentResourceName, String childResourceName); + /** + * batch delete a child resource with a certain attribute value given its parent id + */ + Boolean BatchDeleteChildOfWithParameter(String parentid, String parameterName, String parameterValue, List childResource, String parentResourceName, String childResourceName); + + + + + + + //RangePosts getRecentPostsByVREAndRange(String vreid, int from, int quantity) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, PostIDNotFoundException; + //List getRangeNotificationsByUser(String userid, int from, int quantity) throws NotificationTypeNotFoundException, ColumnNameNotFoundException, NotificationIDNotFoundException; - /** - * @param commentId comment unique identifier - * @return the comment belonging to the commentId - * @throws CommentIDNotFoundException - */ - Comment readCommentById(String commentId) throws CommentIDNotFoundException; - /** - * add a comment to a post - * @param comment the Comment instance to add - */ - boolean addComment(Comment comment) throws PostIDNotFoundException; - /** - * @param postid the post identifier - * return all the comments belonging to the postid - */ - List getAllCommentByPost(String postid); - /** - * @param userid user identifier - * @param timeInMillis time in milliseconds from which you want to start retrieve the posts - * @return a list of comments (sorted starting from the most recent one) made by the user since timeInMillis up to now - */ - List getRecentCommentsByUserAndDate(String userid, long timeInMillis) throws Exception; - /** - * edit a comment - * @param comment the comment to edit - * @return true if success, false otherwise - */ - boolean editComment(Comment comment) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, PostIDNotFoundException; - /** - * deletes a comment - * @param commentid the comment identifier to delete - * @param postid the postid to which the comment is associated - * @return true if success, false otherwise - */ - boolean deleteComment(String commentid, String postid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, CommentIDNotFoundException, PostIDNotFoundException; - /** - * add a like to a post - * @param like instance - * @throws PostIDNotFoundException - */ - boolean like(Like like) throws PostIDNotFoundException; - /** - * unlike a post - * @param userid user identifier - * @param likeid the like identifier to delete - * @param postid the postid to which the comment is associated - * @return true if success, false otherwise - */ - boolean unlike(String userid, String likeid, String postid) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, ColumnNameNotFoundException, LikeIDNotFoundException, PostIDNotFoundException; - /** - * @param userid user identifier - * return all the postids a user has liked - */ - List getAllLikedPostIdsByUser(String userid); - /** - * @param userid user identifier - * @param limit set 0 to get everything, an int to get the most recent -limit- liked posts - * @throws ColumnNameNotFoundException . - * @throws PostIDNotFoundException . - * @throws PostTypeNotFoundException . - * @throws PrivacyLevelTypeNotFoundException - * return all the posts a user has liked - */ - List getAllLikedPostsByUser(String userid, int limit) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException; - /** - * @param userid user identifier - * @param timeInMillis time in milliseconds from which you want to start retrieve the posts - * @return the likes made to posts in the range from: today to: timeInMillis - */ - List getRecentLikedPostsByUserAndDate(String userid, long timeInMillis) throws IllegalArgumentException; - /** - * @param postid postid identifier - * return all the likes belonging to the postid - */ - List getAllLikesByPost(String postid); - /** - * - * @param hashtags the hashtag including the '#' - * @param postid the postid to which the hashtag is associated - * @param vreid VRE identifier - * @return true if success, false otherwise - * @throws PostIDNotFoundException - */ - boolean saveHashTags(String postid, String vreid, List hashtags) throws PostIDNotFoundException; - /** - * - * @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 '#' - * @param postid the postid to which the hashtag is associated - * @param vreid VRE identifier - * @return true if success, false otherwise - * @throws PostIDNotFoundException - */ - boolean deleteHashTags(String postid, String vreid, List hashtags) throws PostIDNotFoundException; - /** - * - * @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) - * @return a HashMap of vre Hashtags associated with their occurrence - */ - Map getVREHashtagsWithOccurrence(String vreid); - /** - * 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) - * @param timestamp do not consider hashtags used before timestamp - * @return a HashMap of vre Hashtags associated with their occurrence - */ - Map getVREHashtagsWithOccurrenceFilteredByTime(String vreid, long timestamp); - /** - * - * @param vreid VRE identifier - * @param hashtag the hashtag to look for including the '#', it is case sensitive - * @throws ColumnNameNotFoundException . - * @throws PostIDNotFoundException . - * @throws PostTypeNotFoundException . - * @throws PrivacyLevelTypeNotFoundException - * @return all the posts having the hashtag passed as parameter - */ - List getVREPostsByHashtag(String vreid, String hashtag) throws PrivacyLevelTypeNotFoundException, PostTypeNotFoundException, PostIDNotFoundException, ColumnNameNotFoundException; - /** - * Save the invite for a given email into a given vre - * @param invite the invite object instanc to save - * @return {@link InviteOperationResult} SUCCESS, FAILED or ALREADY_INVITED (if an invite is sent to en existing email in the same environment more than once) - */ InviteOperationResult saveInvite(Invite invite) throws AddressException; - /** - * - * @param vreid the environment where you want to check the invite - * @param email the email of the invite to check in the environmnet - * @return the InviteId if present, null otherwise - */ - String isExistingInvite(String vreid, String email); - /** - * read an invite from a given id - * @throws InviteIDNotFoundException - * @throws InviteStatusNotFoundException - */ - Invite readInvite(String inviteid) throws InviteIDNotFoundException, InviteStatusNotFoundException; - /** - * set the status of an invite, see {@link InviteStatus} - * @throws InviteIDNotFoundException - */ - boolean setInviteStatus(String vreid, String email, InviteStatus status) throws InviteIDNotFoundException, InviteStatusNotFoundException; - /** - * Use to get the list of invites per VRE - * @param vreid the vre id - * @param status optional, if you want to restict on the status, e.g. all pending invites - * @return return the list of invites - * @throws InviteIDNotFoundException - * @throws InviteStatusNotFoundException - */ - List getInvitedEmailsByVRE(String vreid, InviteStatus... status) throws InviteIDNotFoundException, InviteStatusNotFoundException; - /** - * - * @param postId - * @return the list of attachments of the post postId, starting from the second one (first attachment is included in post instance already) - */ - List getAttachmentsByPostId(String postId) throws PostIDNotFoundException; - - /** - * save an attachment - */ - boolean saveAttachmentEntry(String postId, Attachment toSave); - - /** - * Retrieve all the ids of the vre - * @return the set of ids of the vre available or empty list in case of errors. - */ - public List getAllVREIds(); /** * close the connection to the underlying database */ void closeConnection(); + + } diff --git a/src/main/java/org/gcube/social_networking/utils/ParameterNames.java b/src/main/java/org/gcube/social_networking/utils/ParameterNames.java new file mode 100644 index 0000000..76d3857 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/utils/ParameterNames.java @@ -0,0 +1,15 @@ +package org.gcube.social_networking.utils; + +public class ParameterNames { + public static final String RECENT_LIMIT = "recent_limit"; + public static final String RECENT_COMMENT = "recent_comment"; + public static final String UNREAD = "unread"; + public static final String UNREAD_MESSAGE = "unread_message"; + public static final String RECENT_LIKE = "recent_like"; + public static final String ALL_LIKE = "all_like"; + public static final String TIME = "time"; + public static final String HASHTAG = "hashtag"; + public static final String STATUS = "status"; + public static final String EMAIL = "email"; + public static final String NOTIFICATION_TYPE = "notification_type"; +} diff --git a/src/main/java/org/gcube/social_networking/utils/ResourceNames.java b/src/main/java/org/gcube/social_networking/utils/ResourceNames.java new file mode 100644 index 0000000..116cfc3 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/utils/ResourceNames.java @@ -0,0 +1,19 @@ +package org.gcube.social_networking.utils; + +import org.gcube.social_networking.socialnetworking.model.shared.*; + +public class ResourceNames { + public static final String NOTIFICATION = Notification.class.getSimpleName(); + + public static final String POST = Post.class.getSimpleName(); + public static final String COMMENT = Comment.class.getSimpleName(); + public static final String LIKE = Like.class.getSimpleName(); + public static final String INVITE = Invite.class.getSimpleName(); + public static final String HASHTAG = Hashtag.class.getSimpleName(); + public static final String Attachment = Attachment.class.getSimpleName(); + public static final String VRE = Vre.class.getSimpleName(); + public static final String USER = "User"; + public static final String APP = "App"; + public static final String NOTIFICATION_PREFERENCES = NotificationPreference.class.getSimpleName(); + +} diff --git a/src/main/java/org/gcube/social_networking/utils/ResponseBean.java b/src/main/java/org/gcube/social_networking/utils/ResponseBean.java new file mode 100644 index 0000000..8a90d1b --- /dev/null +++ b/src/main/java/org/gcube/social_networking/utils/ResponseBean.java @@ -0,0 +1,77 @@ +package org.gcube.social_networking.utils; + +import java.io.Serializable; + +/** + * Response bean + * + */ +public class ResponseBean implements Serializable { + + private static final long serialVersionUID = -2725238162673879658L; + /** + * The result of the request: true if it succeeded, false otherwise + */ + private boolean success; + + /** + * An error message if something wrong happened, null/empty otherwise + */ + private String message; + /** + * The result object of the request + */ + private T result; + + public ResponseBean() { + super(); + } + + /** + * @param success + * @param message + * @param result + */ + public ResponseBean(boolean success, String message, T result) { + super(); + this.success = success; + this.message = message; + this.result = result; + } + + + public boolean isSuccess() { + return success; + } + + + public void setSuccess(boolean success) { + this.success = success; + } + + + public String getMessage() { + return message; + } + + + public void setMessage(String message) { + this.message = message; + } + + + public T getResult() { + return result; + } + + + public void setResult(T result) { + this.result = result; + } + + @Override + public String toString() { + return "ResponseBean [success=" + success + + ", message=" + message + ", result=" + result + "]"; + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/WelcomeService.java b/src/main/java/org/gcube/social_networking/ws/WelcomeService.java new file mode 100644 index 0000000..da01883 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/WelcomeService.java @@ -0,0 +1,19 @@ +package org.gcube.social_networking.ws; + +import javax.inject.Singleton; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("/") +@Singleton +public class WelcomeService { + + @GET + @Produces(MediaType.TEXT_HTML) + public Response sayHtmlHello() { + return Response.ok("

The social networking web service is up and running!

").build(); + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/docs/DocsGenerator.java b/src/main/java/org/gcube/social_networking/ws/docs/DocsGenerator.java new file mode 100644 index 0000000..900444b --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/docs/DocsGenerator.java @@ -0,0 +1,50 @@ +package org.gcube.social_networking.ws.docs; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("api-docs") +public class DocsGenerator { + + private static Logger logger = LoggerFactory.getLogger(DocsGenerator.class); + + @GET + @Path("/{any: .*}") + public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException { + logger.info(DocsGenerator.class.getSimpleName() + " toDoc called"); + + String pathInfo = req.getPathInfo(); + logger.debug("pathInfo {}", pathInfo); + try { + + if (pathInfo.endsWith("/api-docs")) { + pathInfo += "index.html"; + } + + if (pathInfo.endsWith("/api-docs/")) { + pathInfo += "index.html"; + } + + + logger.info("going to {}", pathInfo); + + String realPath = req.getServletContext().getRealPath(pathInfo); + return new FileInputStream(new File(realPath)); + + } catch (Exception e) { + e.printStackTrace(); + //MANAGE THE EXCEPTION + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/ws/ex/ApplicationException.java b/src/main/java/org/gcube/social_networking/ws/ex/ApplicationException.java new file mode 100644 index 0000000..4644fe0 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/ex/ApplicationException.java @@ -0,0 +1,28 @@ +package org.gcube.social_networking.ws.ex; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.slf4j.LoggerFactory; + + +/** + * Exception gets thrown when @Valid fail + */ +@Provider +public class ApplicationException implements ExceptionMapper { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ApplicationException.class); + + public Response toResponse(Exception e) { + logger.warn("ApplicationException invoked for exception ", e); + return Response + .status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .type(MediaType.APPLICATION_JSON) + .entity(new ResponseBean(false, e.getMessage(), null)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/ws/ex/AuthException.java b/src/main/java/org/gcube/social_networking/ws/ex/AuthException.java new file mode 100644 index 0000000..3c34870 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/ex/AuthException.java @@ -0,0 +1,16 @@ +package org.gcube.social_networking.ws.ex; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response.Status; + +public class AuthException extends WebApplicationException { + /** + * + */ + private static final long serialVersionUID = 1L; + + public AuthException(Throwable cause) { + super(cause, Status.FORBIDDEN); + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/ws/ex/ValidationException.java b/src/main/java/org/gcube/social_networking/ws/ex/ValidationException.java new file mode 100644 index 0000000..ddbfc3a --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/ex/ValidationException.java @@ -0,0 +1,36 @@ +package org.gcube.social_networking.ws.ex; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.slf4j.LoggerFactory; + +/** + * Exception thrown on fail + * @author Costantino Perciante at ISTI-CNR + */ +@Provider +public class ValidationException implements ExceptionMapper { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ValidationException.class); + @Override + public Response toResponse(javax.validation.ValidationException e) { + final StringBuilder strBuilder = new StringBuilder(); + for (ConstraintViolation cv : ((ConstraintViolationException) e).getConstraintViolations()) { + strBuilder.append(cv.getMessage()); + break; + } + + logger.warn("ValidationException invoked, returning " + strBuilder.toString()); + return Response + .status(Response.Status.BAD_REQUEST.getStatusCode()) + .type(MediaType.APPLICATION_JSON) + .entity(new ResponseBean(false, strBuilder.toString(), null)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/ws/inputs/ApplicationId.java b/src/main/java/org/gcube/social_networking/ws/inputs/ApplicationId.java new file mode 100644 index 0000000..5b22292 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/inputs/ApplicationId.java @@ -0,0 +1,42 @@ +package org.gcube.social_networking.ws.inputs; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Application id object + * @author Costantino Perciante at ISTI-CNR + */ +//@ApiModel(description="An object containing the app_id field", value="Application") +public class ApplicationId { + + @JsonProperty("app_id") + @NotNull(message="app_id cannot be null") + @Size(message="app_id cannot be empty", min=1) + private String appId; + + public ApplicationId() { + super(); + } + + public ApplicationId(String appId) { + super(); + this.appId = appId; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + @Override + public String toString() { + return "ApplicationId [appId=" + appId + "]"; + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/inputs/CommentInputBean.java b/src/main/java/org/gcube/social_networking/ws/inputs/CommentInputBean.java new file mode 100644 index 0000000..d637932 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/inputs/CommentInputBean.java @@ -0,0 +1,72 @@ +package org.gcube.social_networking.ws.inputs; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.webcohesion.enunciate.metadata.DocumentationExample; +/** + * Generic input bean for methods that allow to comment posts + */ +@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization +public class CommentInputBean implements Serializable{ + + private static final long serialVersionUID = 5274608088828232980L; + + @JsonProperty("text") + @NotNull(message="text cannot be null") + @Size(min=1, message="text cannot be empty") + @DocumentationExample("I would like to comment that ...") + /** + * text the text of the comment + */ + private String text; + + @NotNull(message="postid cannot be null") + @JsonProperty("postid") + /** + * postid the postid of the post where you attach the comment + */ + private String postid; + + public CommentInputBean() { + super(); + } + + /** + * @param text + * @param postid + */ + public CommentInputBean(String text, String postid) { + super(); + this.text = text; + this.postid = postid; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getPostid() { + return postid; + } + + public void setPostid(String postid) { + this.postid = postid; + } + + @Override + public String toString() { + return "CommentInputBean [text=" + text + ", postid=" + postid + "]"; + } + + + +} diff --git a/src/main/java/org/gcube/social_networking/ws/inputs/LikeInputBean.java b/src/main/java/org/gcube/social_networking/ws/inputs/LikeInputBean.java new file mode 100644 index 0000000..a439419 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/inputs/LikeInputBean.java @@ -0,0 +1,60 @@ +package org.gcube.social_networking.ws.inputs; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Like Bean object + */ +public class LikeInputBean { + + @JsonProperty("likeid") + @NotNull(message="likeid cannot be null") + @Size(message="likeid cannot be empty", min=1) + private String likeid; + + @JsonProperty("postid") + @NotNull(message="postid cannot be null") + @Size(message="postid cannot be empty", min=1) + private String postid; + + public LikeInputBean() { + super(); + } + + /** + * @param likeid + * @param postid + */ + public LikeInputBean(String likeid, String postid) { + super(); + this.likeid = likeid; + this.postid = postid; + } + + public String getLikeid() { + return likeid; + } + + public void setLikeid(String likeid) { + this.likeid = likeid; + } + + public String getPostid() { + return postid; + } + + public void setPostid(String postid) { + this.postid = postid; + } + + @Override + public String toString() { + return "LikeInputBean [likeid=" + likeid + ", postid=" + postid + "]"; + } + + +} diff --git a/src/main/java/org/gcube/social_networking/ws/inputs/PostId.java b/src/main/java/org/gcube/social_networking/ws/inputs/PostId.java new file mode 100644 index 0000000..cf7b610 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/inputs/PostId.java @@ -0,0 +1,43 @@ +package org.gcube.social_networking.ws.inputs; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Application id object + + */ +public class PostId { + + @JsonProperty("postid") + @NotNull(message="postid cannot be null") + @Size(message="postid cannot be empty", min=1) + private String postId; + + public PostId() { + super(); + } + + public PostId(String postId) { + super(); + this.postId = postId; + } + + public String getPostId() { + return postId; + } + + public void setPostId(String postId) { + this.postId = postId; + } + + @Override + public String toString() { + return "PostId [postid=" + postId + "]"; + } + + +} diff --git a/src/main/java/org/gcube/social_networking/ws/inputs/PostInputBean.java b/src/main/java/org/gcube/social_networking/ws/inputs/PostInputBean.java new file mode 100644 index 0000000..051f73d --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/inputs/PostInputBean.java @@ -0,0 +1,146 @@ +package org.gcube.social_networking.ws.inputs; + +import java.io.Serializable; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.webcohesion.enunciate.metadata.DocumentationExample; +/** + * Generic input bean for methods that allow to write posts + * @author Costantino Perciante at ISTI-CNR + */ +@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization +public class PostInputBean implements Serializable{ + + private static final long serialVersionUID = 5274608088828232980L; + + @JsonProperty("text") + @NotNull(message="text cannot be null") + @Size(min=1, message="text cannot be empty") + @DocumentationExample("Dear vre members, ...") + /** + * text the text of the post + */ + private String text; + + private String previewtitle; + + @JsonProperty("preview_description") + private String previewdescription; + + @JsonProperty("preview_host") + private String previewhost; + + @JsonProperty("preview_url") + private String previewurl; + + /** + * param httpimageurl An image url for the preview" + */ + @JsonProperty("image_url") + private String httpimageurl; + + /** + * enablenotification If true send a notification to the other vre members about this post + */ + @JsonProperty("enable_notification") + private boolean enablenotification; + + @JsonProperty("params") + private String params; + + public PostInputBean() { + super(); + } + + public PostInputBean(String text, String previewtitle, + String previewdescription, String previewhost, String previewurl, + String httpimageurl, boolean enablenotification, String params) { + super(); + this.text = text; + this.previewtitle = previewtitle; + this.previewdescription = previewdescription; + this.previewhost = previewhost; + this.previewurl = previewurl; + this.httpimageurl = httpimageurl; + this.enablenotification = enablenotification; + this.params = params; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getPreviewtitle() { + return previewtitle; + } + + public void setPreviewtitle(String previewtitle) { + this.previewtitle = previewtitle; + } + + public String getPreviewdescription() { + return previewdescription; + } + + public void setPreviewdescription(String previewdescription) { + this.previewdescription = previewdescription; + } + + public String getPreviewhost() { + return previewhost; + } + + public void setPreviewhost(String previewhost) { + this.previewhost = previewhost; + } + + public String getPreviewurl() { + return previewurl; + } + + public void setPreviewurl(String previewurl) { + this.previewurl = previewurl; + } + + public String getHttpimageurl() { + return httpimageurl; + } + + public void setHttpimageurl(String httpimageurl) { + this.httpimageurl = httpimageurl; + } + + public boolean isEnablenotification() { + return enablenotification; + } + + public void setEnablenotification(boolean enablenotification) { + this.enablenotification = enablenotification; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + @Override + public String toString() { + return "PostInputBean [text=" + text + ", previewtitle=" + previewtitle + + ", previewdescription=" + previewdescription + + ", previewhost=" + previewhost + ", previewurl=" + previewurl + + ", httpimageurl=" + httpimageurl + ", enablenotification=" + + enablenotification + ", params=" + params + "]"; + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/inputs/UserSetNotificationBean.java b/src/main/java/org/gcube/social_networking/ws/inputs/UserSetNotificationBean.java new file mode 100644 index 0000000..73995dc --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/inputs/UserSetNotificationBean.java @@ -0,0 +1,63 @@ +package org.gcube.social_networking.ws.inputs; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * + * + */ +public class UserSetNotificationBean { + + @JsonProperty("username") + @NotNull(message="username cannot be null") + @Size(message="username cannot be empty", min=1) + private String username; + + @JsonProperty("disableNotification") + @NotNull(message="disableNotification cannot be null") + private Boolean disableNotification; + + public UserSetNotificationBean() { + super(); + } + + + /** + * @param username + * @param disableNotification + */ + public UserSetNotificationBean(String username, boolean disableNotification) { + super(); + this.username = username; + this.disableNotification = disableNotification; + } + + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public boolean isDisableNotification() { + return disableNotification; + } + + public void setDisableNotification(boolean disableNotification) { + this.disableNotification = disableNotification; + } + + + @Override + public String toString() { + return "UserSetNotificationBean [username=" + username + ", disableNotification=" + disableNotification + "]"; + } + + +} diff --git a/src/main/java/org/gcube/social_networking/ws/mappers/CatalogueEventTypeMapper.java b/src/main/java/org/gcube/social_networking/ws/mappers/CatalogueEventTypeMapper.java new file mode 100644 index 0000000..df2bb03 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/mappers/CatalogueEventTypeMapper.java @@ -0,0 +1,28 @@ +package org.gcube.social_networking.ws.mappers; + +import org.gcube.portal.databook.shared.NotificationType; +import org.gcube.portal.databook.shared.ex.NotificationTypeNotFoundException; +import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEventType; + +public class CatalogueEventTypeMapper { + + public CatalogueEventTypeMapper() { + } + + public static NotificationType getType(CatalogueEventType type) throws NotificationTypeNotFoundException { + switch (type) { + case ITEM_PUBLISHED: + return NotificationType.CAT_ITEM_PUBLISHED; + case ITEM_REJECTED: + return NotificationType.CAT_ITEM_REJECTED; + case ITEM_REMOVED: + return NotificationType.CAT_ITEM_DELETE; + case ITEM_SUBMITTED: + return NotificationType.CAT_ITEM_SUBMITTED; + case ITEM_UPDATED: + return NotificationType.CAT_ITEM_UPDATED; + default: + throw new NotificationTypeNotFoundException("The Catalogue event could not be mapped"); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/mappers/JobMapper.java b/src/main/java/org/gcube/social_networking/ws/mappers/JobMapper.java new file mode 100644 index 0000000..d65d808 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/mappers/JobMapper.java @@ -0,0 +1,64 @@ +package org.gcube.social_networking.ws.mappers; + +import org.gcube.portal.databook.shared.JobStatusType; +import org.gcube.portal.databook.shared.RunningJob; +import org.gcube.social_networking.socialnetworking.model.beans.JobNotificationBean; +import org.gcube.social_networking.socialnetworking.model.beans.JobStatusModelType; + +public class JobMapper { + + public JobMapper() { + } + + public static RunningJob getJob(JobNotificationBean item) { + String jobId = null; + String jobName = null; + JobStatusType status = null; + String message = null; + String serviceName = null; // i.e., Dataminer, SmartExecutor.. + + try { + jobId = item.getJobId(); + jobName = item.getJobName(); + status = getType(item.getStatus()); + message = item.getStatusMessage(); + serviceName = item.getServiceName(); + } catch (Exception e) { + e.printStackTrace(); + } + return new RunningJob(jobId, jobName, status, message, serviceName); + } + + public static JobStatusType getType(JobStatusModelType type) { + JobStatusType toReturn = null; + switch (type) { + case CANCELLED: + return JobStatusType.CANCELLED; + case DELETED: + return JobStatusType.DELETED; + case FAILED: + return JobStatusType.FAILED; + case CANCELLING: + return JobStatusType.CANCELLING; + case DELETING: + return JobStatusType.DELETING; + case EXECUTING: + return JobStatusType.EXECUTING; + case NEW: + return JobStatusType.NEW; + case SUBMITTED: + return JobStatusType.SUBMITTED; + case SUCCEEDED: + return JobStatusType.SUCCEEDED; + case TIMED_OUT: + return JobStatusType.TIMED_OUT; + case WAITING: + return JobStatusType.WAITING; + default: + break; + } + return toReturn; + } + + +} diff --git a/src/main/java/org/gcube/social_networking/ws/mappers/WorkspaceItemMapper.java b/src/main/java/org/gcube/social_networking/ws/mappers/WorkspaceItemMapper.java new file mode 100644 index 0000000..0cd47b3 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/mappers/WorkspaceItemMapper.java @@ -0,0 +1,57 @@ +package org.gcube.social_networking.ws.mappers; + +import org.gcube.applicationsupportlayer.social.shared.SocialFileItem; +import org.gcube.applicationsupportlayer.social.shared.SocialSharedFolder; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.FileItemBean; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderBean; + +public class WorkspaceItemMapper { + + public WorkspaceItemMapper() { + // TODO Auto-generated constructor stub + } + + public static SocialFileItem getFileItem(FileItemBean item) { + String id = null; + String name= null; + String title= null; + String path= null; + SocialSharedFolder parent = null; + + try { + id = item.getId(); + name = item.getName(); + title = item.getTitle(); + path = item.getPath(); + parent = getSharedFolder(item.getParent()); + } catch (Exception e) { + e.printStackTrace(); + } + SocialFileItem toReturn = new SocialFileItem(id, name, title, path, parent); + return toReturn; + } + + public static SocialSharedFolder getSharedFolder(FolderBean item) { + + String id = null; + String name= null; + String title= null; + String displayName= null; + String path= null; + String parentId= null; + boolean vreFolder = false; + try { + id = item.getId(); + name = item.getName(); + title = item.getTitle(); + displayName = item.getDisplayName(); + path = item.getPath(); + parentId = item.getParentId(); + vreFolder = item.isVreFolder(); + } catch (Exception e) { + e.printStackTrace(); + } + SocialSharedFolder toReturn = new SocialSharedFolder(id, name, title, displayName, path, parentId, vreFolder); + return toReturn; + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Comments.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Comments.java new file mode 100644 index 0000000..28d0b68 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Comments.java @@ -0,0 +1,233 @@ +package org.gcube.social_networking.ws.methods.v2; + + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.databook.shared.Comment; +import org.gcube.portal.databook.shared.Feed; +import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.social_networking.ws.inputs.CommentInputBean; +import org.gcube.social_networking.ws.inputs.PostInputBean; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.Filters; +import org.gcube.social_networking.ws.utils.SocialUtils; +import org.gcube.socialnetworking.socialtoken.SocialMessageParser; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.LoggerFactory; + +import com.liferay.portlet.journal.FeedIdException; +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * REST interface for the social networking library (comments). + * @author Ahmed Ibrahim ISTI-CNR + */ +@Path("2/comments") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") +}) +public class Comments { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Comments.class); + + /* + * Retrieve the list of comments belonging to the post id (key) of the token in the related context + * @param key the key as in the POST JSON representation + * @pathExample /get-comments-by-post-id?key=9ea137e9-6606-45ff-a1a2-94d4e8760583 + * @return the list of comments belonging to the post identified by the key in the context identified by the token + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-comments-by-post-id") + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllCommentsByPostId( + @NotNull + @QueryParam("key") + String key) { + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + String username = caller.getClient().getId(); + List comments = null; + + try{ + logger.debug("Retrieving comments for user id " + username); + comments = CassandraConnection.getInstance().getDatabookStore().getAllCommentByPost(key); + Filters.filterCommentsPerContext(comments, context); + responseBean.setResult(comments); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + /* + * Retrieve the list of comments belonging to the owner of the token in the related context + * @return the list of comments belonging to the owner of the token in the related context. + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-comments-user") + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getCommentsUser() { + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + String username = caller.getClient().getId(); + List comments = null; + + try{ + logger.debug("Retrieving comments for user id " + username); + comments = CassandraConnection.getInstance().getDatabookStore().getRecentCommentsByUserAndDate(username, 0); + Filters.filterCommentsPerContext(comments, context); + responseBean.setResult(comments); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + /* + * Retrieve comments of the token owner in the context bound to the token itself and filter them by date + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-comments-user-by-time") + public Response getCommentsUserByTime( + @QueryParam("time") + @Min(value = 0, message="time cannot be negative") + long timeInMillis + ) throws ValidationException{ + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + String username = caller.getClient().getId(); + List comments = null; + + try{ + logger.debug("Retrieving comments for user id " + username); + comments = CassandraConnection.getInstance().getDatabookStore().getRecentCommentsByUserAndDate(username, timeInMillis); + Filters.filterCommentsPerContext(comments, context); + responseBean.setResult(comments); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + /** + * Create a new comment to a post having as owner the auth token's owner + * @param comment The CommentInputBean object + * @return + * @throws ValidationException + */ + @POST + @Path("comment-post") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Successfull created, the new comment is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response writeComment( + @NotNull(message="Comment to write is missing") + @Valid + CommentInputBean comment) throws ValidationException { + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + logger.debug("Request of writing a comment coming from user " + username); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + try { + String postId = comment.getPostid(); + String commentText = comment.getText(); + String userid = username; + Date time = new Date(); + + String postOwnerId = CassandraConnection.getInstance().getDatabookStore().readPost(postId).getEntityId(); + Comment theComment = SocialUtils.commentPost(userid, time, postId, commentText, postOwnerId, context); + if (theComment != null) + logger.debug("Added comment " + theComment.toString()); + else { + logger.error("Unable to write comment"); + responseBean.setMessage("Unable to write comment, something went wrong please see server log"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + responseBean.setResult(theComment); + responseBean.setSuccess(true); + return Response.status(status).entity(responseBean).build(); + } catch(FeedIDNotFoundException ex) { + logger.error("Unable to find a post comment", ex); + responseBean.setMessage("Could not reach the DB to write the comment, something went wrong"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + catch(Exception e) { + logger.error("Unable to write comment", e); + responseBean.setMessage("Could not reach the DB to write the comment, something went wrong"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/FullTextSearch.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/FullTextSearch.java new file mode 100644 index 0000000..7fc367d --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/FullTextSearch.java @@ -0,0 +1,167 @@ +package org.gcube.social_networking.ws.methods.v2; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ValidationException; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.databook.server.DatabookStore; +import org.gcube.portal.databook.shared.EnhancedFeed; +import org.gcube.portal.databook.shared.Feed; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ElasticSearchConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.Filters; +import org.gcube.social_networking.ws.utils.TokensUtils; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.model.GCubeGroup; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * REST interface for the social networking library (post and its comments). + */ +@Path("2/full-text-search") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") + }) +public class FullTextSearch { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(FullTextSearch.class); + + /** + * Retrieve posts/comments that match the given query + * @param httpServletRequest + * @param query A string to search for + * @param from the index of the base result to be returned, range[0, infinity], defaults from = 0 + * @param quantity defines how many results are most are to be returned, range[1, infinity], defaults from = 0, + * @return The posts/comments returned belong to the context bound to the AUTH Token + * @throws ValidationException + */ + @GET + @Path("search-by-query") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful retrieval of posts/comments that match the query, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response searchByQuery( + @Context HttpServletRequest httpServletRequest, + @QueryParam("query") @NotNull(message="query cannot be null") @Size(min=1, message="query cannot be empty") + String query, + @DefaultValue("0") @QueryParam("from") @Min(value=0, message="from cannot be negative") + int from, + @DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity cannot be negative") + int quantity + ) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.BAD_REQUEST; + responseBean.setMessage("This method can be only invoked by using a user token."); + + if(!TokensUtils.isUserToken(caller)) + return Response.status(status).entity(responseBean).build(); + + status = Status.OK; + responseBean.setMessage(null); + + GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager(); + + try{ + // Retrieve user's vres in which we must search + Set vres = new HashSet(); + + // get the group id from the current context + long currentGroupId = groupManager.getGroupIdFromInfrastructureScope(context); + GCubeUser currUser = userManager.getUserByUsername(username); + List userContexts = groupManager.listGroupsByUser(currUser.getUserId()); + + if (groupManager.isRootVO(currentGroupId)) { + for (GCubeGroup group : groupManager.listGroupsByUser(currUser.getUserId())) { + if (groupManager.isVRE(group.getGroupId()) && userContexts.contains(group)) { + vres.add(groupManager.getInfrastructureScope(group.getGroupId())); + } + } + } + else if(groupManager.isVO(currentGroupId)){ + for (GCubeGroup group : groupManager.listGroupsByUser(currUser.getUserId())) { + if (groupManager.isVRE(group.getGroupId()) && group.getParentGroupId() == currentGroupId && userContexts.contains(group)) { + vres.add(groupManager.getInfrastructureScope(group.getGroupId())); + } + } + } + else { + vres.add(context); + } + + // query elastic search + List enhancedFeeds = ElasticSearchConnection.getSingleton().getElasticSearchClient().search(query, vres, from, quantity); + Filters.hideSensitiveInformation(enhancedFeeds, caller.getClient().getId()); + DatabookStore store = CassandraConnection.getInstance().getDatabookStore(); + + // retrieve the ids of liked feeds by the user + List likedFeeds = store.getAllLikedFeedIdsByUser(username); + + // update fields "liked" and "isuser" + for (EnhancedFeed enhancedFeed : enhancedFeeds) { + if(isUsers(enhancedFeed.getFeed(), username)) + enhancedFeed.setUsers(true); + if(likedFeeds.contains(enhancedFeed.getFeed().getKey())) + enhancedFeed.setLiked(true); + } + responseBean.setResult((ArrayList) enhancedFeeds); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Something went wrong while searching", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + + } + return Response.status(status).entity(responseBean).build(); + } + + /** + * tell if a feed belongs to the current user or not + * @param tocheck + * @param username + * @return true if this feed is of the current user + */ + private static final boolean isUsers(Feed tocheck, String username) { + return (tocheck.getEntityId().equals(username)); + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/HashTags.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/HashTags.java new file mode 100644 index 0000000..be3e7b6 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/HashTags.java @@ -0,0 +1,84 @@ +package org.gcube.social_networking.ws.methods.v2; + +import java.util.List; +import java.util.Map; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.databook.server.DatabookStore; +import org.gcube.portal.databook.shared.Post; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * REST interface for the social networking library (hash tags). + * @author Ahmed Ibrahim ISTI-CNR + */ +@Path("2/hashtags") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") +}) +public class HashTags { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(HashTags.class); + + @GET + @Path("get-hashtags-and-occurrences/") + @Produces({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Hashtags and occurrences retrieved, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + /** + * @return hashtags in the context bound to the auth token + */ + public Response getHashTagsAndOccurrences(){ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + logger.debug("User " + username + " has requested hashtags of context " + context); + + try{ + DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore(); + // TODO handle the case of VO and ROOT + boolean isVRE = GroupManagerWSBuilder.getInstance().getGroupManager().isVRE(GroupManagerWSBuilder.getInstance().getGroupManager().getGroupIdFromInfrastructureScope(context)); + if(isVRE){ + Map map = datastore.getVREHashtagsWithOccurrence(context); + responseBean.setResult(map); + responseBean.setSuccess(true); + }else{ + responseBean.setMessage("Please provide a VRE token. VO and ROOT VO cases are not yet managed."); + responseBean.setResult(false); + } + }catch(Exception e){ + logger.error("Failed to retrieve hashtags", e); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Lib.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Lib.java new file mode 100644 index 0000000..cc0b55d --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Lib.java @@ -0,0 +1,1397 @@ +package org.gcube.social_networking.ws.methods.v2; + + +import com.webcohesion.enunciate.metadata.Ignore; +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; +import org.gcube.portal.databook.shared.*; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.slf4j.LoggerFactory; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import java.util.List; +import java.util.Map; + +/** + * REST interface for the social networking library. + * @author Ahmed Ibrahim ISTI-CNR + */ +@Ignore +@Path("2/lib") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") +}) +public class Lib { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Lib.class); + + //Comments + // + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("add-comment-lib/") + public Response addCommentLib(@NotNull(message="Comment to write is missing") + @Valid + Comment comment)throws ValidationException { + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try { + logger.debug("Writing comment with commentid " + comment.getKey()); + boolean result = CassandraConnection.getInstance().getDatabookStore().addComment(comment); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + } catch (Exception e) { + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("read-comment-by-id-lib/") + public Response readCommentByIdLib(@QueryParam("commentid") + String commentid)throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("Getting comment with commentid " + commentid); + Comment result = CassandraConnection.getInstance().getDatabookStore().readCommentById(commentid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to find comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-comments-by-post-id-lib/") + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllCommentsByPostIdLib( + @NotNull + @QueryParam("postid") + String postid) { + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List comments = null; + + try{ + logger.debug("Retrieving comments for postid " + postid); + comments = CassandraConnection.getInstance().getDatabookStore().getAllCommentByPost(postid); + responseBean.setResult(comments); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-recent-comments-by-user-and-date-lib/") + public Response getRecentCommentsByUserAndDateLib( + @QueryParam("time") + @Min(value = 0, message="time cannot be negative") + long timeInMillis, + @QueryParam("username") + String username + ) throws ValidationException{ + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List comments = null; + + try{ + logger.debug("Retrieving comments for user id " + username); + comments = CassandraConnection.getInstance().getDatabookStore().getRecentCommentsByUserAndDate(username, timeInMillis); + responseBean.setResult(comments); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("edit-comment-lib/") + public Response editCommentLib( + @NotNull(message="Comment to edit is missing") + @Valid + Comment comment + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("Writing comment with commentid " + comment.getKey()); + boolean result = CassandraConnection.getInstance().getDatabookStore().editComment(comment); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("delete-comment-lib/") + public Response deleteCommentLib( + @QueryParam("commentid") + String commentid, + @QueryParam("postid") + String postid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("deleting comment with commentid " + commentid); + boolean result = CassandraConnection.getInstance().getDatabookStore().deleteComment(commentid, postid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to delete comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + //Hashtags + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-hashtag-lib/") + public Response saveHashTagsLib( + @QueryParam("feedid") + String feedid, + @QueryParam("vreid") + String vreid, + @NotNull(message="hashtag to save is missing") + @Valid + List hashtags + ) throws ValidationException { + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("Saving hashtags " ); + boolean result = CassandraConnection.getInstance().getDatabookStore().saveHashTags(feedid,vreid,hashtags); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to save hashtags.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("delete-hashtag-lib/") + public Response deleteHashTagsLib( + @QueryParam("feedid") + String feedid, + @QueryParam("vreid") + String vreid, + @NotNull(message="hashtag to delete is missing") + @Valid + List hashtags + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("deleting hashtags " ); + boolean result = CassandraConnection.getInstance().getDatabookStore().deleteHashTags(feedid,vreid,hashtags); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to delete hashtags.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-hashtag-comment-lib/") + public Response saveHashTagsCommentLib( + @QueryParam("commentid") + String commentid, + @QueryParam("vreid") + String vreid, + @NotNull(message="hashtag to save is missing") + @Valid + List hashtags + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("Saving hashtags comments " ); + boolean result = CassandraConnection.getInstance().getDatabookStore().saveHashTagsComment(commentid,vreid,hashtags); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to save hashtags comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("delete-hashtag-comment-lib/") + public Response deleteHashTagsCommentLib( + @QueryParam("commentid") + String commentid, + @QueryParam("vreid") + String vreid, + @NotNull(message="hashtag to delete is missing") + @Valid + List hashtags + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("deleting hashtags " ); + boolean result = CassandraConnection.getInstance().getDatabookStore().deleteHashTagsComment(commentid,vreid,hashtags); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to delete hashtags.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-vre-hashtags-occurrences-lib/") + public Response getVREHashtagsWithOccurrenceLib( + @QueryParam("vreid") + String vreid + ) throws ValidationException { + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Map hashtags = null; + + try{ + logger.debug("getting vre hashtags occurrences " + vreid); + hashtags = CassandraConnection.getInstance().getDatabookStore().getVREHashtagsWithOccurrence(vreid); + responseBean.setResult(hashtags); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-vre-hashtags-occurrences-time-lib/") + public Response getVREHashtagsWithOccurrenceFilteredByTimeLib( + @QueryParam("vreid") + String vreid, + @QueryParam("time") + @Min(value = 0, message="time cannot be negative") + long timestamp + ) throws ValidationException { + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Map hashtags = null; + + try{ + logger.debug("getting vre hashtags occurrences " + vreid); + hashtags = CassandraConnection.getInstance().getDatabookStore().getVREHashtagsWithOccurrenceFilteredByTime(vreid, timestamp); + responseBean.setResult(hashtags); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-vre-post-by-hashtag-lib/") + public Response getVREPostsByHashtagLib( + @QueryParam("vreid") + String vreid, + @QueryParam("hashtag") + String hashtag + ) throws ValidationException { + hashtag = "#" + hashtag; + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List posts = null; + + try{ + logger.debug("getting vre hashtags occurrences " + vreid); + posts = CassandraConnection.getInstance().getDatabookStore().getVREPostsByHashtag(vreid, hashtag); + responseBean.setResult(posts); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such comments.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + //Invites + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("is-existing-invite-lib/") + public Response isExistingInviteLib( + @QueryParam("vreid") + String vreid, + @QueryParam("email") + String email + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + String inv = null; + + try{ + logger.debug("Retrieving invite for vre " + vreid); + inv = CassandraConnection.getInstance().getDatabookStore().isExistingInvite(vreid, email); + responseBean.setResult(inv); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-invite-lib/") + public Response saveInviteLib( + @NotNull(message="invite to save is missing") + @Valid + Invite invite + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + InviteOperationResult inv = null; + + try{ + inv = CassandraConnection.getInstance().getDatabookStore().saveInvite(invite); + responseBean.setResult(inv); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("read-invite-lib/") + public Response readInviteLib( + @QueryParam("inviteid") + String inviteid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Invite inv = null; + + try{ + logger.debug("Retrieving invite for id " + inviteid); + inv = CassandraConnection.getInstance().getDatabookStore().readInvite(inviteid); + responseBean.setResult(inv); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("set-invite-status-lib/") + public Response setInviteStatusLib( + @QueryParam("vreid") + String vreid, + @QueryParam("email") + String email, + @NotNull(message="invitestatus to save is missing") + @Valid + InviteStatus stat + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Boolean inv = null; + + try{ + inv = CassandraConnection.getInstance().getDatabookStore().setInviteStatus(vreid,email,stat); + responseBean.setResult(inv); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("get-invited-email-by-vre-lib/") + public Response getInvitedEmailsByVRELib( + @QueryParam("vreid") + String vreid, + @NotNull(message="invitestatus to save is missing") + @Valid + InviteStatus... stat + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List inv = null; + + try{ + inv = CassandraConnection.getInstance().getDatabookStore().getInvitedEmailsByVRE(vreid, stat); + responseBean.setResult(inv); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + //Likes + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("like-lib/") + public Response likeLib( + @NotNull(message="like to add is missing") + @Valid + Like like + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("Writing like with likeid " + like.getKey()); + boolean result = CassandraConnection.getInstance().getDatabookStore().like(like); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("unlike-lib/") + public Response unlikeLib( + @QueryParam("userid") + String userid, + @QueryParam("likeid") + String likeid, + @QueryParam("feedid") + String feedid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + logger.debug("Writing unlike with likeid " + likeid); + boolean result = CassandraConnection.getInstance().getDatabookStore().unlike(userid,likeid,feedid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-liked-posts-by-user-lib/") + public Response getAllLikedPostIdsByUserLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List likes = null; + + try{ + logger.debug("Retrieving likes for user id " + userid); + likes = CassandraConnection.getInstance().getDatabookStore().getAllLikedPostIdsByUser(userid); + responseBean.setResult(likes); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-likes-by-post-lib/") + public Response getAllLikesByPostLib( + @QueryParam("postid") + String postid + ) throws ValidationException{ + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List likes = null; + + try{ + logger.debug("Retrieving likes for post id " + postid); + likes = CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(postid); + responseBean.setResult(likes); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + //Notifications + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-notification-lib/") + public Response saveNotificationLib( + @NotNull(message="notification to add is missing") + @Valid + Notification not + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().saveNotification(not); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("read-notification-lib/") + public Response readNotificationLib( + @QueryParam("notid") + String notid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + Notification result = CassandraConnection.getInstance().getDatabookStore().readNotification(notid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("set-notification-read-lib/") + public Response setNotificationReadLib( + @QueryParam("notid") + String notid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().setNotificationRead(notid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-notifications-user/") + public Response getAllNotificationByUserLib( + @QueryParam("userid") + String userid, + @QueryParam("limit") + int limit + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAllNotificationByUser(userid,limit); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-unread-notifications-user/") + public Response getUnreadNotificationsByUserLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getUnreadNotificationsByUser(userid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-range-notifications-user/") + public Response getRangeNotificationsByUserLib( + @QueryParam("userid") + String userid, + @QueryParam("from") + int from, + @QueryParam("quantity") + int quantity + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getRangeNotificationsByUser(userid,from, quantity); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("set-all-notification-read-lib/") + public Response setAllNotificationReadByUserLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().setAllNotificationReadByUser(userid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("check-unread-notification-lib/") + public Response checkUnreadNotificationsLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().checkUnreadNotifications(userid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("check-unread-messages-notification-lib/") + public Response checkUnreadMessagesNotificationsLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().checkUnreadMessagesNotifications(userid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-user-notification-channels-lib/") + public Response getUserNotificationChannelsLib( + @QueryParam("userid") + String userid, + @QueryParam("type") + String type + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getUserNotificationChannels(userid,NotificationType.valueOf(type)); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("set-notification-preference-lib/") + public Response setUserNotificationPreferencesLib( + @QueryParam("userid") + String userid, + @NotNull(message="notification prefs to add is missing") + @Valid + Map enabledChannels + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + for(NotificationType notificationType: enabledChannels.keySet()){ + logger.debug("Type: " + notificationType.toString()); + for(NotificationChannelType channelType: enabledChannels.get(notificationType)){ + logger.debug(channelType.toString()); + } + } + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().setUserNotificationPreferences(userid,enabledChannels); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write settings.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-notification-preference-lib/") + public Response getUserNotificationPreferencesLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + Map result = CassandraConnection.getInstance().getDatabookStore().getUserNotificationPreferences(userid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + //Posts + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-user-post-lib/") + public Response saveUserPostLib( + @NotNull(message="post to add is missing") + @Valid + Post post + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(post); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-attachment-lib/") + public Response saveAttachmentEntryLib( + @QueryParam("postid") + String postkey, + @NotNull(message="attachment to add is missing") + @Valid + Attachment attachment + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().saveAttachmentEntry(postkey,attachment); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write attachment.", e); + logger.error(e.getMessage()); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-app-post-lib/") + public Response saveAppPostLib( + @NotNull(message="post to add is missing") + @Valid + Post post + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().saveAppPost(post); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-post-to-vretimeline-lib/") + public Response savePostToVRETimelineLib( + @QueryParam("postid") + String postid, + @QueryParam("vreid") + String vreid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().savePostToVRETimeline(postid, vreid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("read-post-lib/") + public Response readPostLib( + @QueryParam("postid") + String postid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + Post result = CassandraConnection.getInstance().getDatabookStore().readPost(postid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-recent-posts-by-user-date-lib/") + public Response getRecentPostsByUserAndDateLib( + @QueryParam("userid") + String userid, + @QueryParam("time") + long timeinmillis + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByUserAndDate(userid, timeinmillis); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("delete-post-lib/") + public Response deletePostLib( + @QueryParam("postid") + String postid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + boolean result = CassandraConnection.getInstance().getDatabookStore().deletePost(postid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-posts-by-user-lib/") + public Response getAllPostsByUserLib( + @QueryParam("userid") + String userid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAllPostsByUser(userid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-posts-by-app-lib/") + public Response getAllPostsByAppLib( + @QueryParam("appid") + String appid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAllPostsByApp(appid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-recent-commented-posts-by-user-lib/") + public Response getRecentCommentedPostsByUserAndDateLib( + @QueryParam("userid") + String userid, + @QueryParam("time") + long timeinmillis + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getRecentCommentedPostsByUserAndDate(userid, timeinmillis); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-portal-privacy-level-posts-lib/") + public Response getAllPortalPrivacyLevelPostsLib() throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAllPortalPrivacyLevelPosts(); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-recent-posts-by-user-lib/") + public Response getRecentPostsByUserLib( + @QueryParam("userid") + String userid, + @QueryParam("quantity") + int quantity + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByUser(userid, quantity); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-posts-by-vre-lib/") + public Response getAllPostsByVRELib( + @QueryParam("vreid") + String vreid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAllPostsByVRE(vreid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-recent-posts-by-vre-lib/") + public Response getRecentPostsByVRELib( + @QueryParam("vreid") + String vreid, + @QueryParam("quantity") + int quantity + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByVRE(vreid, quantity); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-recent-posts-by-vre-range-lib/") + public Response getRecentPostsByVREAndRangeLib( + @QueryParam("vreid") + String vreid, + @QueryParam("from") + int from, + @QueryParam("quantity") + int quantity + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + RangePosts result = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByVREAndRange(vreid, from, quantity); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-attachment-by-postid-lib/") + public Response getAttachmentsByFeedIdLib( + @QueryParam("postid") + String postid + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAttachmentsByFeedId(postid); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-all-vre-ids-lib/") + public Response getAllVREIdsLib() throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List result = CassandraConnection.getInstance().getDatabookStore().getAllVREIds(); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Likes.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Likes.java new file mode 100644 index 0000000..32e125f --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Likes.java @@ -0,0 +1,168 @@ +package org.gcube.social_networking.ws.methods.v2; + + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.databook.shared.Like; +import org.gcube.social_networking.ws.inputs.LikeInputBean; +import org.gcube.social_networking.ws.inputs.PostId; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.SocialUtils; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * REST interface for the social networking library (likes). + * @author Ahmed Ibrahim ISTI-CNR + */ +@Path("2/likes") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") +}) +public class Likes { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Likes.class); + + /* + * Retrieve the list of likes belonging to the post id (key) of the token in the related context + * @param key the key as in the POST JSON representation + * @pathExample /get-likes-by-post-id?key=9ea137e9-6606-45ff-a1a2-94d4e8760583 + * @return the list of likes belonging to the post identified by the key in the context identified by the token + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("get-likes-by-post-id") + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The list of likes is put into the 'result' field"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllLikesByPostId( + @NotNull + @QueryParam("key") + String key) { + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + String username = caller.getClient().getId(); + List likes = null; + + try{ + logger.debug("Retrieving likes for user id " + username); + likes = CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(key); + responseBean.setResult(likes); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such likes.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Create a new like to a post in the context of the token + * @param postid The post id to be liked + * @return true if everything is OK + * @throws ValidationException + */ + @POST + @Path("like-post") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Successful created, the like operation result is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response like( + @NotNull(message="Post to like is missing") + @Valid + PostId post) throws ValidationException { + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + logger.debug("Request of like coming from user " + username); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + boolean likeResultOperation = SocialUtils.like(username, post.getPostId(), context); + if (likeResultOperation) + logger.debug("Added like OK to postId " + post.getPostId()); + else { + logger.error("Unable to like this post"+ post.getPostId()); + responseBean.setMessage("Unable to like, something went wrong please see server log"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + responseBean.setResult(true); + responseBean.setSuccess(true); + return Response.status(status).entity(responseBean).build(); + } + + /** + * Unlike to a post in the context of the token + * @param postid The post id to be liked + * @return true if everything is OK + * @throws ValidationException + */ + @POST + @Path("unlike-post") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "The unlike operation result is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response unlike( + @NotNull(message="Post to unlike is missing") + @Valid + LikeInputBean likeInputBean) throws ValidationException { + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + logger.debug("Request of unlike coming from user " + username); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + boolean likeResultOperation = SocialUtils.unlike(username, likeInputBean.getLikeid(), likeInputBean.getPostid()); + if (likeResultOperation) + logger.debug("Unlike OK to postId " + likeInputBean.getPostid()); + else { + logger.error("Unable to unlike this post"+ likeInputBean.getPostid()); + responseBean.setMessage("Unable to unlike, something went wrong please see server log"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + responseBean.setResult(true); + responseBean.setSuccess(true); + return Response.status(status).entity(responseBean).build(); + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Messages.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Messages.java new file mode 100644 index 0000000..a853023 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Messages.java @@ -0,0 +1,295 @@ +package org.gcube.social_networking.ws.methods.v2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager; +import org.gcube.applicationsupportlayer.social.NotificationsManager; +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser; +import org.gcube.common.authorization.control.annotations.AuthorizationControl; +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.common.storagehub.client.plugins.AbstractPlugin; +import org.gcube.common.storagehub.client.proxies.MessageManagerClient; +import org.gcube.common.storagehub.model.messages.Message; +import org.gcube.portal.notifications.bean.GenericItemBean; +import org.gcube.portal.notifications.thread.MessageNotificationsThread; +import org.gcube.portal.social.networking.liferay.ws.LiferayJSONWsCredentials; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.social_networking.caches.SocialNetworkingSiteFinder; +import org.gcube.social_networking.socialnetworking.model.beans.MessageInputBean; +import org.gcube.social_networking.socialnetworking.model.beans.Recipient; +import org.gcube.social_networking.ws.ex.AuthException; +import org.gcube.social_networking.ws.inputs.UserSetNotificationBean; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.TokensUtils; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; +import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * Messages services REST interface + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + */ +@Path("2/messages") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") + }) +public class Messages { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Messages.class); + + /** + * Write a message to another user. The sender is the token's owner by default + * @responseExample application/json {"success": true, "message": null, "result": "556142e3-d6f5-4550-b2fa-abe5626625d3"} + * @param input The message to write" + * @param httpServletRequest + * @return see response example + * @throws ValidationException + * @throws UserManagementSystemException + * @throws UserRetrievalFault + */ + @POST + @Path("write-message/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful write a message. Its id is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response writeMessage( + @NotNull(message="Message to send is missing") + @Valid + MessageInputBean input, + @Context HttpServletRequest httpServletRequest) throws ValidationException, UserManagementSystemException, UserRetrievalFault{ + + logger.debug("Incoming message bean is " + input); + + Caller caller = AuthorizationProvider.instance.get(); + UserManager um = UserManagerWSBuilder.getInstance().getUserManager(); + GCubeUser senderUser = null; + SocialNetworkingUser user = null; + // check if the token belongs to an application token. In this case use J.A.R.V.I.S (the username used to communicate with Liferay) + String username = null; + String fullName = ""; + logger.debug("Catalogue Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller)); + if(!TokensUtils.isUserToken(caller)){ + GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser()); + SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken()); + username = jarvis.getUsername(); + fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client + senderUser = um.getUserByUsername(username); + user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL()); + }else{ + username = caller.getClient().getId(); + senderUser = um.getUserByUsername(username); + fullName = senderUser.getFullname(); + user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL()); + } + String scope = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.CREATED; + String body = input.getBody(); + String subject = input.getSubject(); + List recipientsIds = input.getRecipients(); // "recipients":[{"recipient":"id recipient"}, ......] + logger.debug("Sender is going to be [" + fullName + "]"); + + // get the recipients ids (simple check, trim) + List recipientsListFiltered = new ArrayList(); + List recipientsBeans = new ArrayList(); + for (Recipient recipientId : recipientsIds) { + try{ + String tempId = recipientId.getId().trim(); + if(tempId.isEmpty()) + continue; + GCubeUser userRecipient = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(tempId); + if(userRecipient == null) + userRecipient = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(tempId); + if(userRecipient != null){ + GenericItemBean beanUser = new GenericItemBean(userRecipient.getUsername(), userRecipient.getUsername(), userRecipient.getFullname(), userRecipient.getUserAvatarURL()); + recipientsBeans.add(beanUser); + recipientsListFiltered.add(userRecipient.getUsername()); + } + }catch(Exception e){ + logger.error("Unable to retrieve recipient information for recipient with id " + recipientId, e); + } + } + + if(recipientsListFiltered.isEmpty()){ + logger.error("Missing/wrong request parameters"); + status = Status.BAD_REQUEST; + responseBean.setMessage(ErrorMessages.MISSING_PARAMETERS); + return Response.status(status).entity(responseBean).build(); + } + + try{ + + logger.debug("Trying to send message with body " + body + " subject " + subject + " to users " + recipientsIds + " from " + username); + + // send message + MessageManagerClient client = AbstractPlugin.messages().build(); + logger.debug("Sending message to " + recipientsListFiltered); + String messageId = client.sendMessage(recipientsListFiltered, subject, body, input.getAttachmentIds()); + + // send notification + logger.debug("Message sent to " + recipientsIds + ". Sending message notification to: " + recipientsIds); + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(scope); + NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, ScopeProvider.instance.get(), user); + new Thread(new MessageNotificationsThread(recipientsBeans, messageId, subject, body, nm)).start(); + responseBean.setSuccess(true); + responseBean.setResult(messageId); + + }catch(Exception e){ + logger.error("Unable to send message.", e); + status = Status.INTERNAL_SERVER_ERROR; + responseBean.setMessage(e.toString()); + } + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Path("get-sent-messages") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful read of the sent messages, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + /** + * + * @return the list of sent messages of the user (the token's owner) + */ + public Response getSentMessages(){ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + logger.debug("Request for retrieving sent messages by " + username); + + try{ + MessageManagerClient client = AbstractPlugin.messages().build(); + List sentMessages = client.getSentMessages(); + Collections.reverse(sentMessages); + responseBean.setSuccess(true); + logger.debug("Result is " + sentMessages); + responseBean.setResult(sentMessages); + }catch(Exception e){ + logger.error("Unable to retrieve sent messages", e); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + @GET + @Path("get-received-messages") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful read of the received messages, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + /** + * + * @return the list of received messages of the user (the token's owner) + */ + public Response getReceivedMessages(){ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + logger.debug("Request for retrieving received messages by " + username); + try{ + MessageManagerClient client = AbstractPlugin.messages().build(); + List getMessages =client.getReceivedMessages(); + Collections.reverse(getMessages); + responseBean.setSuccess(true); + responseBean.setResult(getMessages); + + }catch(Exception e){ + logger.error("Unable to retrieve sent messages", e); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Set message read or unread + * @param messageId the message identifier + * @param read true to set read, false to set unread + * @return the result of the operation + * @throws ValidationException + */ + @POST + @Path("set-message-read/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Message set Read or Unread is correctly executed"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response setMessageRead( + @NotNull(message="input is missing") + @FormParam("messageId") String messageId, + @FormParam("read") Boolean read) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + String opExecutor = ""; + try{ + opExecutor = caller.getClient().getId(); + MessageManagerClient client = AbstractPlugin.messages().build(); + client.setRead(messageId, read); + String toReturn = "set Message id:" + messageId + (read ? " read" : " unread"); + logger.debug("set Message id:" + messageId + " read?" + read + " for " + opExecutor); + + responseBean.setSuccess(true); + responseBean.setResult(toReturn); + + } catch(Exception e){ + logger.error("Unable to set message read / unread property for user " + opExecutor, e); + responseBean.setSuccess(false); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + + + return Response.status(status).entity(responseBean).build(); + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Notifications.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Notifications.java new file mode 100644 index 0000000..e2c7911 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Notifications.java @@ -0,0 +1,684 @@ +package org.gcube.social_networking.ws.methods.v2; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager; +import org.gcube.applicationsupportlayer.social.NotificationsManager; +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser; +import org.gcube.common.authorization.control.annotations.AuthorizationControl; +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.portal.databook.shared.Notification; +import org.gcube.portal.databook.shared.NotificationChannelType; +import org.gcube.portal.databook.shared.NotificationType; +import org.gcube.portal.databook.shared.RunningJob; +import org.gcube.portal.notifications.bean.GenericItemBean; +import org.gcube.portal.notifications.thread.JobStatusNotificationThread; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.LiferayJSONWsCredentials; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.social_networking.caches.SocialNetworkingSiteFinder; +import org.gcube.social_networking.caches.UsersCache; +import org.gcube.social_networking.socialnetworking.model.beans.JobNotificationBean; +import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.AddedItemEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.DeletedItemEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAddedUserEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAdminDowngradeEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAdminUpgradeEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderRemovedUserEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.RenamedFolderEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.SharedFolderEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.UnsharedFolderEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.UpdatedItemEvent; +import org.gcube.social_networking.socialnetworking.model.beans.workspace.WorkspaceEvent; +import org.gcube.social_networking.ws.ex.AuthException; +import org.gcube.social_networking.ws.mappers.CatalogueEventTypeMapper; +import org.gcube.social_networking.ws.mappers.JobMapper; +import org.gcube.social_networking.ws.mappers.WorkspaceItemMapper; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.TokensUtils; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; +import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.mortbay.log.Log; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * REST interface for the social networking library (notifications). + * @author Ahmed Ibrahim ISTI-CNR + */ +@Path("2/notifications") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") +}) +public class Notifications { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Notifications.class); + private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager"; + + /** + * Retrieve notifications of the token's owner + * @param from must be greater or equal to 1, range[0, infinity] + * @param quantity quantity must be greater or equal to 0 + * @return notifications up to quantity + * @throws ValidationException + */ + @GET + @Path("get-range-notifications/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Notifications retrieved and reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getRangeNotifications( + @DefaultValue("1") @QueryParam("from") @Min(value=1, message="from must be greater or equal to 1") + int from, + @DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity must be greater or equal to 0") + int quantity + ) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + + logger.debug("Retrieving " + quantity + " notifications of user = " + username + " from " + from); + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + List notifications = null; + try{ + notifications = CassandraConnection.getInstance().getDatabookStore().getRangeNotificationsByUser(username, from, quantity); + responseBean.setResult(notifications); + responseBean.setSuccess(true); + logger.debug("List of notifications retrieved"); + }catch(Exception e){ + logger.error("Unable to retrieve such notifications.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + + /** + * Return whether the notifications for this user are enabled or not + * @pathExample /is-user-disabled?username=john.smith + * @responseExample application/json { "success": true, "message": null "result": true } + * @param username the username you want to check + * @return true if the notification for the user are disabled (Catalogue and Workspace ones) + * + */ + @GET + @Path("is-user-disabled/") + + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "true if the notification for the username given as query param are disabled (Catalogue and Workspace ones), false otherwise"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class) + public Response isUserDisabled( + @QueryParam("username") @NotNull(message="username cannot be null") + String username) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + Boolean userDisabled= !isNotificationEnabled(username); + responseBean.setResult(userDisabled); + responseBean.setSuccess(true); + logger.debug("are User " + username + " Notifications Disabled?"+userDisabled); + }catch(Exception e){ + logger.error("Unable to read whether the notifications for this user are enabled or not.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + +// /** +// * Set user notification enabled or disabled +// * @param disable true if you want to disable the notifications for this user, false if you want to enable them +// * @return the result of the operation +// * @throws ValidationException +// */ +// @POST +// @Path("set-user-notifications/") +// @Consumes(MediaType.APPLICATION_JSON) +// @Produces(MediaType.APPLICATION_JSON) +// @StatusCodes ({ +// @ResponseCode ( code = 200, condition = "Notification set Off or On correctly executed"), +// @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) +// }) +// @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class) +// public Response setUserNotifications( +// @NotNull(message="input is missing") +// @Valid +// UserSetNotificationBean setting) throws ValidationException{ +// +// Caller caller = AuthorizationProvider.instance.get(); +// String context = ScopeProvider.instance.get(); +// ResponseBean responseBean = new ResponseBean(); +// Status status = Status.OK; +// +// +// try{ +// String opExecutor = caller.getClient().getId(); +// Boolean result = setUserNotificationsOnOff(setting.getUsername(), setting.isDisableNotification(), opExecutor); +// String toReturn = "Could not set notifications"; +// if (result) { +// toReturn = "Notifications have been set"; +// toReturn += setting.isDisableNotification() ? " OFF (for 29 days unless re-enabled manually) ": " ON "; +// toReturn += "for username=" + setting.getUsername(); +// } +// responseBean.setSuccess(true); +// responseBean.setResult(toReturn); +// +// } catch(Exception e){ +// logger.error("Unable to set user notification", e); +// responseBean.setSuccess(false); +// responseBean.setMessage(e.getMessage()); +// status = Status.INTERNAL_SERVER_ERROR; +// } +// +// +// return Response.status(status).entity(responseBean).build(); +// } + + /** + * @deprecated + * @param usernameToCheck + * @return true if notification are enabled for this user + * @throws IOException + */ + private boolean isNotificationEnabled(String usernameToCheck) throws IOException { +// MemcachedClient entries = new DistributedCacheClient().getMemcachedClient(); +// String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+usernameToCheck; +// Boolean userEnabled = false; +// if(entries.get(key) == null) +// userEnabled = true; +// entries.getConnection().shutdown(); +// return userEnabled; + return true; + } +// /** +// * +// * @param username the user you want to disable or enable notifications (max 29 days) +// * @param callerId the username or clientid of the operation executor +// * @param disable true if you want to disable the notifications for this user +// * @return true if the operation was performed +// * @throws IOException +// */ +// private Boolean setUserNotificationsOnOff(String username, boolean disable, String callerId) throws IOException { +// MemcachedClient entries = new DistributedCacheClient().getMemcachedClient(); +// String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+username; +// OperationFuture result = null; +// if (disable) { +// result = entries.set(key, SocialUtils.CACHING_TIME_TO_EXPIRATION, "op.ex:" + callerId); //operator executor is who silenced the user +// } else { +// result = entries.delete(key); +// } +// try { +// boolean res = result.getStatus().isSuccess(); +// entries.getConnection().shutdown(); +// return res; +// } catch (Exception e) { +// entries.getConnection().shutdown(); +// e.printStackTrace(); +// } +// return null; +// } + + /** + * Send a JOB notification to a given recipient + * @param job The job bean + * @return + * @throws ValidationException + */ + @POST + @Path("notify-job-status/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Notification is sent correctly"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response notifyJobStatus( + @NotNull(message="input is missing") + @Valid + JobNotificationBean job) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + String appQualifier = caller.getClient().getId(); + logger.debug("Received request from app " + appQualifier + " to notify job status described by bean " + job); + + try{ + + String recipient = job.getRecipient(); + GCubeUser userRecipient = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(recipient); + GenericItemBean recipientBean = new GenericItemBean(userRecipient.getUsername(), userRecipient.getUsername(), userRecipient.getFullname(), userRecipient.getUserAvatarURL()); + + // notifications are sent by using the user allowed to use liferay's json apis + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context); + GCubeUser senderUser = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser()); + SocialNetworkingUser user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL()); + NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user); + + RunningJob theJob = JobMapper.getJob(job); + + new Thread(new JobStatusNotificationThread(theJob, Arrays.asList(recipientBean), nm)).start(); + responseBean.setSuccess(true); + responseBean.setResult("Notification thread started"); + + }catch(Exception e){ + logger.error("Unable to send job notification", e); + responseBean.setSuccess(false); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Send a Catalogue notification to a given user + * @param event + * @return + * @throws ValidationException + */ + @POST + @Path("catalogue/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Catalogue Notification is sent correctly"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response catalogue( + @NotNull(message="input is missing") + @Valid + CatalogueEvent event) throws ValidationException, UserManagementSystemException, UserRetrievalFault{ + + Caller caller = AuthorizationProvider.instance.get(); + UserManager um = UserManagerWSBuilder.getInstance().getUserManager(); + GCubeUser senderUser = null; + SocialNetworkingUser user = null; + // check if the token belongs to an application token. In this case use J.A.R.V.I.S (the username used to communicate with Liferay) + String username = null; + String fullName = ""; + logger.debug("Catalogue Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller)); + if(!TokensUtils.isUserToken(caller)){ + GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser()); + SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken()); + username = jarvis.getUsername(); + fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client + senderUser = um.getUserByUsername(username); + user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL()); + }else{ + username = caller.getClient().getId(); + senderUser = um.getUserByUsername(username); + user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL()); + } + + String context = ScopeProvider.instance.get(); + + logger.debug("catalogue notifications from user = " + username); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + boolean deliveryResult = false; + try { + //logger.debug("catalogue notifications type is " + event.getType()); + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context); + //logger.debug("social networking site is " + site.getName()); + //logger.debug("context is " + context); + //logger.debug("user is " + user.getUsername()); + + NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user); + + String[] idsToNotify = event.getIdsToNotify(); + if (! event.idsAsGroup()) { + for (int i = 0; i < idsToNotify.length; i++) { + String userIdToNotify = idsToNotify[i]; + if (isNotificationEnabled(userIdToNotify)) { + String username2Notify = null; + try { + username2Notify = um.getUserByUsername(userIdToNotify).getUsername(); + } + catch (Exception e) { + status = Status.BAD_REQUEST; + logger.error("Username not found", e); + responseBean.setSuccess(false); + responseBean.setMessage("Username not found, got: " + userIdToNotify); + return Response.status(status).entity(responseBean).build(); + } + //logger.debug("username2notify " + username2Notify); + //logger.debug("type is " + CatalogueEventTypeMapper.getType(event.getType())); + //logger.debug("item id is " + event.getItemId()); + //logger.debug("item text is " + event.getNotifyText()); + //logger.debug("item url is " + event.getItemURL()); + + deliveryResult = + nm.notifyCatalogueEvent( + CatalogueEventTypeMapper.getType(event.getType()), + username2Notify, + event.getItemId(), + event.getNotifyText(), + event.getItemURL()); + } + else { + Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify"); + } + + } + } else { //the ids are contexts + for (int i = 0; i < idsToNotify.length; i++) { + String contextId = idsToNotify[i]; + try { + ScopeBean scope = new ScopeBean(contextId); + if (scope.type() != ScopeBean.Type.VRE) { + logger.error("Context not a VRE"); + status = Status.BAD_REQUEST; + responseBean.setSuccess(false); + responseBean.setMessage("Not a VRE Context, only VREs are supported"); + return Response.status(status).entity(responseBean).build(); + } else { // it is a context and it is a valid VRE + String[] userIdsToNotify = getUsernamesByContext(scope).toArray(new String[0]); //resolve the members + for (int j = 0; j < userIdsToNotify.length; j++) { + String userIdToNotify = userIdsToNotify[j]; + if (isNotificationEnabled(userIdToNotify)) { + deliveryResult = + nm.notifyCatalogueEvent( + CatalogueEventTypeMapper.getType(event.getType()), + userIdToNotify, + event.getItemId(), + event.getNotifyText(), + event.getItemURL()); + } else { + Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify"); + } + } + } + } + catch(IllegalArgumentException e) { + status = Status.BAD_REQUEST; + logger.error("Context not valid", e); + responseBean.setSuccess(false); + responseBean.setMessage("Context not valid, must start with / " + e.getMessage()); + return Response.status(status).entity(responseBean).build(); + } + } + } + } catch(Exception e){ + logger.error("Unable to send job notification", e); + responseBean.setSuccess(false); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + logger.debug("catalogue notifications should have been sent"); + if (deliveryResult) { + responseBean.setSuccess(true); + responseBean.setMessage("catalogue notification delivered correctly"); + responseBean.setResult(new Boolean(true)); + } else { + responseBean.setSuccess(false); + responseBean.setMessage("An error occurred between this service and Cassandra DB, notification not delivered correctly"); + responseBean.setResult(new Boolean(false)); + } + return Response.status(status).entity(responseBean).build(); + } + + /** + * Send a Workspace notification to a given user + * @param event + * @return + * @throws ValidationException + */ + @POST + @Path("workspace/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Workspace Notification is sent correctly"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response workspace( + @NotNull(message="input is missing") + @Valid + WorkspaceEvent event) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + String username = caller.getClient().getId(); + + logger.debug("workspace notifications from = " + username); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + boolean deliveryResult = false; + try { + GCubeUser senderUser = null; + SocialNetworkingUser user = null; + String fullName = ""; + logger.debug("workspace notifications type is " + event.getType()); + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context); + UserManager um = UserManagerWSBuilder.getInstance().getUserManager(); + logger.debug("Workspace Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller)); + if(!TokensUtils.isUserToken(caller)){ + GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser()); + SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken()); + username = jarvis.getUsername(); + fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client + senderUser = um.getUserByUsername(username); + user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL()); + }else{ + username = caller.getClient().getId(); + senderUser = um.getUserByUsername(username); + user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL()); + } + NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user); + + String[] idsToNotify = event.getIdsToNotify(); + if (! event.idsAsGroup()) { + for (int i = 0; i < idsToNotify.length; i++) { + String userIdToNotify = idsToNotify[i]; + if (isNotificationEnabled(userIdToNotify)) { + String username2Notify = ""; + try { + username2Notify = um.getUserByUsername(userIdToNotify).getUsername(); + } + catch (Exception e) { + status = Status.NOT_ACCEPTABLE; + logger.error("Username not found", e); + responseBean.setSuccess(false); + responseBean.setMessage("Username not found, received: " + userIdToNotify); + return Response.status(status).entity(responseBean).build(); + } + deliveryResult = notifyWorkspaceEvent(event, nm, username2Notify); + } + else { + Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify"); + } + } + } else { //the ids are contexts + for (int i = 0; i < idsToNotify.length; i++) { + String contextId = idsToNotify[i]; + try { + ScopeBean scope = new ScopeBean(contextId); + if (scope.type() != ScopeBean.Type.VRE) { + logger.error("Context not a VRE"); + status = Status.BAD_REQUEST; + responseBean.setSuccess(false); + responseBean.setMessage("Not a VRE Context, only VREs are supported"); + return Response.status(status).entity(responseBean).build(); + } else { // it is a context and it is a valid VRE + String[] userIdsToNotify = getUsernamesByContext(scope).toArray(new String[0]); //resolve the members + for (int j = 0; j < userIdsToNotify.length; j++) { + String userIdToNotify = userIdsToNotify[j]; + if (isNotificationEnabled(userIdToNotify)) + deliveryResult = notifyWorkspaceEvent(event, nm, userIdToNotify); + else { + Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify"); + } + } + } + } + catch(IllegalArgumentException e) { + status = Status.BAD_REQUEST; + logger.error("Context not valid", e); + responseBean.setSuccess(false); + responseBean.setMessage("Context not valid, must start with / " + e.getMessage()); + return Response.status(status).entity(responseBean).build(); + } + } + } + } catch(Exception e){ + logger.error("Unable to send job notification", e); + responseBean.setSuccess(false); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + logger.debug("workspace notifications should have been sent"); + if (deliveryResult) { + responseBean.setSuccess(true); + responseBean.setMessage("Workspace notification delivered correctly"); + responseBean.setResult(new Boolean(true)); + } else { + responseBean.setSuccess(false); + responseBean.setMessage("An error occurred between this service and Cassandra DB, notification not delivered correctly"); + responseBean.setResult(new Boolean(false)); + } + return Response.status(status).entity(responseBean).build(); + } + /** + * + * @param event + * @param nm + * @param idToNotify + * @return + */ + private boolean notifyWorkspaceEvent(WorkspaceEvent event, NotificationsManager nm, String idToNotify) { + try { + switch (event.getType()) { + case ITEM_NEW: { + AddedItemEvent itemBean = (AddedItemEvent) event; + return nm.notifyAddedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent())); + } + case ITEM_UPDATE: { + UpdatedItemEvent itemBean = (UpdatedItemEvent) event; + return nm.notifyUpdatedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent())); + } + case ITEM_DELETE: { + DeletedItemEvent itemBean = (DeletedItemEvent) event; + return nm.notifyRemovedItem(idToNotify, itemBean.getItemName(), WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); + } + case FOLDER_SHARE: { + SharedFolderEvent itemBean = (SharedFolderEvent) event; + return nm.notifyFolderSharing(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); + } + case FOLDER_UNSHARE: { + UnsharedFolderEvent itemBean = (UnsharedFolderEvent) event; + return nm.notifyFolderUnsharing(idToNotify, itemBean.getUnsharedFolderId(), itemBean.getUnsharedFolderName()); + } + case FOLDER_RENAME: { + RenamedFolderEvent itemBean = (RenamedFolderEvent) event; + return nm.notifyFolderRenaming(idToNotify, itemBean.getPreviousName(), itemBean.getNewName(), itemBean.getRenamedFolderId()); + } + case FOLDER_ADMIN_UPGRADE: { + FolderAdminUpgradeEvent itemBean = (FolderAdminUpgradeEvent) event; + return nm.notifyAdministratorUpgrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); + } + case FOLDER_ADMIN_DOWNGRADE: { + FolderAdminDowngradeEvent itemBean = (FolderAdminDowngradeEvent) event; + return nm.notifyAdministratorDowngrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); + } + case FOLDER_ADDEDUSER: { + FolderAddedUserEvent itemBean = (FolderAddedUserEvent) event; + UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager(); + return nm.notifyFolderAddedUsers(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()), itemBean.getNewAddedUserIds(), userManager); + } + case FOLDER_REMOVEDUSER: { + FolderRemovedUserEvent itemBean = (FolderRemovedUserEvent) event; + return nm.notifyFolderRemovedUser(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); + } + default: + break; + } + } catch(Exception e){ + logger.error("Unable to send job notification", e); + return false; + } + return false; + } + /** + * + * @param context + * @return + * @throws Exception + */ + private List getUsernamesByContext(ScopeBean context) throws Exception { + List usernames = new ArrayList(); + GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager(); + long groupId = groupManager.getGroupIdFromInfrastructureScope(context.toString()); + + // first retrieve ids + List userIds = userManager.getUserIdsByGroup(groupId); + + // check info in cache when available + UsersCache cache = UsersCache.getSingleton(); + + for (Long userId : userIds) { + if(cache.getUser(userId) == null){ + GCubeUser theUser = userManager.getUserById(userId); + if(theUser != null){ + usernames.add(theUser.getUsername()); + cache.pushEntry(userId, theUser); + } + }else + usernames.add(cache.getUser(userId).getUsername()); + } + return usernames; + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/People.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/People.java new file mode 100644 index 0000000..0d99a02 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/People.java @@ -0,0 +1,105 @@ +package org.gcube.social_networking.ws.methods.v2; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.RoleManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.TokensUtils; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.RoleManager; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.model.GCubeRole; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + + +/** + * REST interface for the social service (people). Used by OAUTH 2.0 apps/users. + */ +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") + }) +@Path("2/people") +public class People { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(People.class); + + /** + * @responseExample application/json { "success" : true, "message" : null, "result" : { "roles" : [ ], "context" : "***", "avatar" : "https://*****3D", "fullname" : "John Smith", "username" : "john.smith" } } + * @return the user's profile. The user in this case is the one bound to the token + */ + @Produces(MediaType.APPLICATION_JSON) + @GET + @Path("profile") + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful retrieval of user's profile, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getProfile(){ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + GCubeUser user = null; + String scope = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + if(!TokensUtils.isUserToken(caller)){ + status = Status.FORBIDDEN; + responseBean.setMessage("User's information can only be retrieved through a user token"); + logger.warn("Trying to access users method via a token different than 'user-token' is not allowed"); + }else{ + + try{ + UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager(); + RoleManager roleManager = RoleManagerWSBuilder.getInstance().getRoleManager(); + GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + user = userManager.getUserByUsername(username); + + Map toReturn = new HashMap(); + toReturn.put("username", user.getUsername()); + toReturn.put("avatar", user.getUserAvatarURL()); + toReturn.put("fullname", user.getFullname()); + toReturn.put("context", scope); + List roles = roleManager.listRolesByUserAndGroup(user.getUserId(), groupManager.getGroupIdFromInfrastructureScope(scope)); + List rolesNames = new ArrayList(); + for (GCubeRole gCubeRole : roles) { + rolesNames.add(gCubeRole.getRoleName()); + } + toReturn.put("roles", rolesNames); + + responseBean.setResult(toReturn); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve user's profile", e); + responseBean.setMessage(e.getMessage()); + status = Status.INTERNAL_SERVER_ERROR; + } + } + + return Response.status(status).entity(responseBean).build(); + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Posts.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Posts.java new file mode 100644 index 0000000..daea140 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Posts.java @@ -0,0 +1,702 @@ +package org.gcube.social_networking.ws.methods.v2; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.gcube.portal.databook.shared.PostWithAttachment; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.databook.server.DatabookStore; +import org.gcube.portal.databook.shared.*; +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.gcube.social_networking.ws.inputs.PostInputBean; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.CassandraConnection; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.Filters; +import org.gcube.social_networking.ws.utils.SocialUtils; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + +/** + * REST interface for the social networking library (posts). + * @author Ahmed Ibrahim ISTI-CNR + */ +@Path("2/posts") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") +}) +public class Posts { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Posts.class); + + /** + * Retrieve posts of the auth token's owner, and allow to filter them by time" + * @param timeInMillis The reference time since when retrieving posts + * @return the posts + * @throws ValidationException + */ + @GET + @Path("get-posts-user-since/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getRecentPostsByUserAndDate( + @QueryParam("time") @Min(value = 0, message="time cannot be negative") + long timeInMillis + ) throws ValidationException{ + + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + Caller caller = AuthorizationProvider.instance.get(); + String context = ScopeProvider.instance.get(); + String username = caller.getClient().getId(); + List posts = null; + + try{ + logger.debug("Retrieving post for user id " + username + " and reference time " + timeInMillis); + posts = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByUserAndDate(username, timeInMillis); + Filters.filterPostsPerContext(posts, context); + Filters.hideSensitiveInformation(posts, caller.getClient().getId()); + responseBean.setResult(posts); + responseBean.setMessage(""); + responseBean.setSuccess(true); + + }catch(Exception e){ + logger.error("Unable to retrieve such posts.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + + /** + * Retrieve all user's posts + * @return all posts of the auth token's owner in the context identified by the token + */ + @GET + @Path("get-posts-user/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllPostsByUser() { + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List posts = null; + try{ + logger.debug("Retrieving posts for user with id " + username); + posts = CassandraConnection.getInstance().getDatabookStore().getAllPostsByUser(username); + Filters.filterPostsPerContext(posts, context); + Filters.hideSensitiveInformation(posts, caller.getClient().getId()); + responseBean.setResult(posts); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such feeds.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Retrieve a post by id + * @return the post if the post id belongs to a post in the context identified by the token + */ + @GET + @Path("get-post/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getPost(@QueryParam("id") String id) { + String context = ScopeProvider.instance.get(); + Caller caller = AuthorizationProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + List posts = new ArrayList<>(); + try{ + logger.debug("Retrieving post with id " + id); + try { + posts.add(CassandraConnection.getInstance().getDatabookStore().readPost(id)); + } catch(FeedIDNotFoundException e){ + responseBean.setMessage("The post with id " + id + " does not exist in context " + context); + responseBean.setSuccess(false); + return Response.status(status).entity(responseBean).build(); + } + Filters.filterPostsPerContext(posts, context); + Filters.hideSensitiveInformation(posts, caller.getClient().getId()); + if (posts.isEmpty()) { + responseBean.setMessage("The post with id " + id + " does not belong to this context " + context); + responseBean.setSuccess(false); + status = Status.FORBIDDEN; + return Response.status(status).entity(responseBean).build(); + } + responseBean.setResult(posts.get(0)); + responseBean.setMessage(""); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such post.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Retrieve a given quantity of latest user's posts + * @param quantity the number of latest post to get + * @pathExample /get-posts-user-quantity?quantity=10 + * @return all posts of the auth token's owner in the context identified by the token, in reverse chronological order up to quantity (at most) + * @throws ValidationException + */ + @GET + @Path("get-posts-user-quantity/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getQuantityPostsByUser( + @DefaultValue("10") + @QueryParam("quantity") + @Min(value=0, message="quantity cannot be negative") + int quantity) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + List posts = new ArrayList<>(); + + // if quantity is zero, just return an empty list + if(quantity == 0){ + responseBean.setSuccess(true); + return Response.status(status).entity(responseBean).build(); + } + try{ + logger.debug("getRecentPostsByUser first, posts made by user " + username); + posts = CassandraConnection.getInstance().getDatabookStore().getAllPostsByUser(username); + if (posts != null) + logger.debug("got " + posts.size() + " posts"); + logger.debug("Retrieving last " + quantity + " posts made by user " + username + " in context = "+context); + Filters.filterPostsPerContext(posts, context); + quantity = (quantity > posts.size()) ? posts.size() : quantity; + posts = posts.subList(0, quantity); + Filters.hideSensitiveInformation(posts, caller.getClient().getId()); + responseBean.setResult(posts); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve such posts.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + /** + * Create a new user post having as owner the auth token's owner + * @param post The post to be written + * @return + * @throws ValidationException + */ + @POST + @Path("write-post-user") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response writePostUser( + @NotNull(message="Post to write is missing") + @Valid + PostInputBean post) throws ValidationException{ + + logger.debug("Request of writing a feed coming from user " + post); + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.CREATED; + + // parse + String postText = post.getText(); + String previewTitle = post.getPreviewtitle(); + String previewDescription = post.getPreviewdescription(); + String previewHost = post.getPreviewhost(); + String previewUrl = post.getPreviewurl(); + String httpImageUrl = post.getHttpimageurl(); + boolean enableNotification = post.isEnablenotification(); + + // convert enablenotification parameter + if(enableNotification) + logger.debug("Enable notification for this user post."); + else + logger.debug("Disable notification for this user post."); + + + // try to share + logger.debug("Trying to share user post..."); + Post res = SocialUtils.shareUserUpdate( + username, + postText, + context, + previewTitle, + previewDescription, + previewHost, + previewUrl, + httpImageUrl, + enableNotification + ); + + if(res != null){ + logger.debug("Post correctly written by user " + username); + responseBean.setResult(res); + responseBean.setSuccess(true); + return Response.status(status).entity(responseBean).build(); + + } + + logger.error("Unable to write post."); + responseBean.setMessage("Unable to write post"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + + } + + /** + * Retrieve the application's posts + * @return the application (IAM Client) posts belonging to the token's owner (i.e., an application)" + */ + @GET + @Path("get-posts-app/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 403, condition = "\"There is no application profile with such token"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllPostsByApp() { + + Caller caller = AuthorizationProvider.instance.get(); + String appId = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + // check if the token actually matches an application + ApplicationProfile appProfile = SocialUtils.getProfileFromInfrastrucure(appId, context); + if(appProfile == null){ + + logger.error("The given token is not belonging to an application!!!"); + status = Status.FORBIDDEN; + responseBean.setSuccess(false); + responseBean.setMessage(ErrorMessages.NOT_APP_TOKEN); + return Response.status(status).entity(responseBean).build(); + + } + try{ + + logger.debug("Retrieving posts for app with id " + appId); + List feeds = CassandraConnection.getInstance().getDatabookStore().getAllPostsByApp(appId); + Filters.filterPostsPerContext(feeds, context); + responseBean.setSuccess(true); + responseBean.setResult(feeds); + + }catch(Exception e){ + + logger.error("Unable to retrieve such feeds.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Create a new application post having as owner-application the token's owner (the IAM Client), note that the application must be registered on the Information System + * @param post The post to be written + * @return + */ + @POST + @Path("write-post-app") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"), + @ResponseCode ( code = 403, condition = "\"There is no application profile with such token"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response writePostApp( + @NotNull(message="Post to write is null") + @Valid + PostInputBean post){ + + Caller caller = AuthorizationProvider.instance.get(); + String appId = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.CREATED; + + logger.debug("Request of writing a feed coming from an application."); + + // check if the token actually matches an application profile + ApplicationProfile appProfile = SocialUtils.getProfileFromInfrastrucure(appId, context); + + if(appProfile == null){ + logger.error("The given token doesn't belong to an application!!!"); + responseBean.setSuccess(false); + responseBean.setMessage(ErrorMessages.NOT_APP_TOKEN); + status = Status.FORBIDDEN; + return Response.status(status).entity(responseBean).build(); + } + + // parse + String postText = post.getText(); + String previewTitle = post.getPreviewtitle(); + String previewDescription = post.getPreviewdescription(); + String httpImageUrl = post.getHttpimageurl(); + boolean enableNotification = post.isEnablenotification(); + String params = post.getParams(); + + // convert enablenotification parameter + if(enableNotification) + logger.debug("Enable notification for this application post."); + else + logger.debug("Disable notification for this application post."); + + // write post + notification if it is the case + Post written = SocialUtils.shareApplicationUpdate( + postText, + params, + previewTitle, + previewDescription, + httpImageUrl, + appProfile, + caller, + enableNotification + ); + + if(written != null){ + responseBean.setResult(written); + responseBean.setSuccess(true); + return Response.status(status).entity(responseBean).build(); + } + + logger.error("Unable to write post."); + responseBean.setMessage("Unable to write post"); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + return Response.status(status).entity(responseBean).build(); + } + + /** + * + * @return all the posts in the context bound to the auth token + */ + @GET + @Path("get-posts-vre/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllPostsByVRE() { + + String context = ScopeProvider.instance.get(); + Caller caller = AuthorizationProvider.instance.get(); + logger.debug("Retrieving all posts coming from vre = " + context); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + List posts = CassandraConnection.getInstance().getDatabookStore().getAllPostsByVRE(context); + Filters.hideSensitiveInformation(posts, caller.getClient().getId()); + responseBean.setResult(posts); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve posts for vre = " + context, e); + status = Status.INTERNAL_SERVER_ERROR; + responseBean.setMessage(e.toString()); + responseBean.setSuccess(false); + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * return the most recent posts for this vre up to quantity param and the last index of the posts in the timeline + * lastReturnedPostTimelineIndex is useful to know from where to start the range the next time you ask, because there are deletions + * + * @param from the range start (most recent feeds for this vre) has to be greater than 0 + * @param quantity the number of most recent feeds for this vre starting from "from" param + * @pathExample /get-recent-posts-vre-by-range?from=1&quantity=10 + * @return a RangePosts containing of most recent feeds for this vre + * @throws FeedTypeNotFoundException + * @throws PrivacyLevelTypeNotFoundException + * @throws ColumnNameNotFoundException + */ + @GET + @Path("get-recent-posts-vre-by-range/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getRecentPostsByVREAndRange( + @QueryParam("from") + @Min(value=1, message="from cannot be negative") + int from, + @QueryParam("quantity") + @Min(value=1, message="quantity cannot be negative") + int quantity) throws ValidationException { + + String context = ScopeProvider.instance.get(); + Caller caller = AuthorizationProvider.instance.get(); + logger.debug("Retrieving all posts coming from vre = " + context); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + RangePosts rangePosts = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByVREAndRange(context, from, quantity); + Filters.hideSensitiveInformation(rangePosts.getPosts(), caller.getClient().getId()); + responseBean.setResult(rangePosts); + responseBean.setSuccess(true); + }catch(Exception e){ + logger.error("Unable to retrieve posts for vre = " + context, e); + status = Status.INTERNAL_SERVER_ERROR; + responseBean.setMessage(e.toString()); + responseBean.setSuccess(false); + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Retrieve posts containing the hashtag in the context bound to the auth token + * @param hashtag he hashtag to be contained within the posts + * @pathExample /get-posts-by-hashtag?hashtag=#thehashtag + * @return the posts in the context bound to the auth token matching the hashtag + * @throws ValidationException + */ + @GET + @Path("get-posts-by-hashtag/") + @Produces({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getPostsByHashTags( + @QueryParam("hashtag") + @NotNull(message="hashtag cannot be missing") + String hashtag) throws ValidationException { + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + logger.debug("User " + username + " has requested posts containing hashtag " + hashtag + " in context " + context); + try{ + DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore(); + List posts = datastore.getVREPostsByHashtag(context, hashtag); + Filters.hideSensitiveInformation(posts, caller.getClient().getId()); + responseBean.setResult(posts); + responseBean.setSuccess(true); + + }catch(Exception e){ + logger.error("Failed to retrieve hashtags", e); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + /** + * Retrieve ids (UUID) of the liked posts by the user + * @return ids (UUID) of the liked posts by the user in the context bound to the auth token + */ + @GET + @Path("get-id-liked-posts/") + @Produces({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Sccessfull retrieved ids, they are reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllLikedPostIdsByUser() { + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + logger.debug("Retrieving all liked posts for user with id " + username + " in context " + context); + + List retrievedLikedPostsIds = null; + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + + DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore(); + retrievedLikedPostsIds = datastore.getAllLikedPostIdsByUser(username); + Filters.filterFeedsPerContextById(retrievedLikedPostsIds, context); + responseBean.setResult(retrievedLikedPostsIds); + responseBean.setSuccess(true); + logger.debug("Ids of liked posts by " + username + " retrieved"); + }catch(Exception e){ + logger.error("Unable to read such ids of liked Posts.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + + return Response.status(status).entity(responseBean).build(); + } + + /** + * Retrieve posts liked by the user + * @param limit The maximum number of posts to be retrieved + * @return posts liked by the user (up to a given quantity) in the context bound to the auth token + * @throws ValidationException + */ + @GET + @Path("get-liked-posts/") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "Successfull retrieved posts, they are reported in the 'result' field of the returned object"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getAllLikedPostsByUser( + @DefaultValue("10") + @QueryParam("limit") + @Min(message="limit cannot be negative", value = 0) + int limit) throws ValidationException{ + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + String context = ScopeProvider.instance.get(); + List retrievedLikedPosts = null; + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + try{ + logger.debug("Retrieving " + limit + " liked posts for user with id " + username + " in context " + context); + retrievedLikedPosts = CassandraConnection.getInstance().getDatabookStore().getAllLikedPostsByUser(username, limit); + Filters.filterPostsPerContext(retrievedLikedPosts, context); + Filters.hideSensitiveInformation(retrievedLikedPosts, caller.getClient().getId()); + responseBean.setResult(retrievedLikedPosts); + responseBean.setSuccess(true); + logger.debug("Liked posts by " + username + " retrieved"); + }catch(Exception e){ + logger.error("Unable to read such liked posts.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + //libapi + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-user-post-attachments-lib") + public Response saveUserPostLib( + @NotNull(message="post to add is missing") + @Valid + PostWithAttachment postWithAttachment + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + Post post = postWithAttachment.getPost(); + logger.debug("Post is " + post); + List attachments = postWithAttachment.getAttachments(); + logger.debug("Attachments are " + attachments); + boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(post,attachments); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("save-app-post-attachments-lib") + public Response saveAppPostLib( + @NotNull(message="post to add is missing") + @Valid + PostWithAttachment postWithAttachment + ) throws ValidationException{ + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + try{ + Post post = postWithAttachment.getPost(); + List attachments = postWithAttachment.getAttachments(); + boolean result = CassandraConnection.getInstance().getDatabookStore().saveAppPost(post,attachments); + responseBean.setResult(result); + responseBean.setMessage(""); + responseBean.setSuccess(result); + }catch(Exception e){ + logger.error("Unable to write comment.", e); + responseBean.setMessage(e.getMessage()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + } + return Response.status(status).entity(responseBean).build(); + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/Tokens.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/Tokens.java new file mode 100644 index 0000000..a909423 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/Tokens.java @@ -0,0 +1,89 @@ +package org.gcube.social_networking.ws.methods.v2; + +import static org.gcube.common.authorization.client.Constants.authorizationService; + +import javax.validation.Valid; +import javax.validation.ValidationException; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.databook.shared.ApplicationProfile; +import org.gcube.social_networking.ws.inputs.ApplicationId; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.ErrorMessages; +import org.gcube.social_networking.ws.utils.SocialUtils; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; + + +/** + * REST interface for the social networking library (tokens). + */ +@Path("2/tokens") +@Deprecated +public class Tokens { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Tokens.class); + + @POST + @Path("generate-application-token/") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "Successful creation of the token, reported in the 'result' field of the returned object"), + @ResponseCode ( code = 403, condition = "There is no application profile with such id"), + @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + /** + * Generate a legacy application auth token for the application with id app_id + * @param input The bean containing the app_id field + * @return the legacy application token + * @throws ValidationException + */ + public Response generateApplicationToken( + @NotNull(message="Missing input parameter") + @Valid + ApplicationId input) throws ValidationException{ + + logger.debug("Incoming request for app token generation."); + String context = ScopeProvider.instance.get(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.CREATED; + String appId = input.getAppId(); + try { + // check if the token actually matches an application profile + ApplicationProfile appProfile = SocialUtils.getProfileFromInfrastrucure(appId, context); + if(appProfile == null){ + logger.error("The given id doesn't belong to an application!!!"); + responseBean.setSuccess(false); + responseBean.setMessage(ErrorMessages.NOT_APP_ID); + status = Status.FORBIDDEN; + return Response.status(status).entity(responseBean).build(); + } + logger.debug("Generating token for the application with id " + appId); + // each token is related to an identifier and the context + String appToken = authorizationService().generateExternalServiceToken(appId); + responseBean.setSuccess(true); + responseBean.setResult(appToken); + } catch (Exception e) { + logger.error("Unable to generate token for app " + appId + " and scope " + context); + status = Status.INTERNAL_SERVER_ERROR; + responseBean.setSuccess(false); + responseBean.setMessage(ErrorMessages.TOKEN_GENERATION_APP_FAILED); + return Response.status(status).entity(responseBean).build(); + } + + return Response.status(status).entity(responseBean).build(); + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/methods/v2/VREs.java b/src/main/java/org/gcube/social_networking/ws/methods/v2/VREs.java new file mode 100644 index 0000000..377fceb --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/methods/v2/VREs.java @@ -0,0 +1,135 @@ +package org.gcube.social_networking.ws.methods.v2; + +import java.util.List; + +import javax.validation.ValidationException; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.common.authorization.library.provider.AuthorizationProvider; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.RoleManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.social_networking.ws.outputs.ResponseBean; +import org.gcube.social_networking.ws.utils.TokensUtils; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.RoleManager; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.model.GCubeGroup; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.gcube.vomanagement.usermanagement.model.GatewayRolesNames; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.slf4j.LoggerFactory; + +import com.webcohesion.enunciate.metadata.rs.RequestHeader; +import com.webcohesion.enunciate.metadata.rs.RequestHeaders; + + +/** + * REST interface for the social networking library (vres). + */ +@Path("2/vres") +@RequestHeaders ({ + @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), + @RequestHeader( name = "Content-Type", description = "application/json") + }) +public class VREs { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Users.class); + + /** + * @responseExample application/json { + "success" : true, + "message" : null, + "result" : [ { + "name" : "NextNext", + "context" : "/gcube/devNext/NextNext", + "description" : "NextNext description AAA" + }, { + "name" : "devVRE", + "context" : "/gcube/devsec/devVRE", + "description" : "devVRE description BBB" + } ] +} + * @pathExample /get-my-vres?getManagers=false + * @param getManagers set true if you also want to know the VRE-Managers + * @return the list of vres along with some metadata + * @throws ValidationException + */ + @SuppressWarnings("unchecked") + @GET + @Path("get-my-vres/") + @Produces(MediaType.APPLICATION_JSON) + public Response getMyVres( + @DefaultValue("false") @QueryParam("getManagers") boolean getManagers + ) throws ValidationException { + + Caller caller = AuthorizationProvider.instance.get(); + String username = caller.getClient().getId(); + ResponseBean responseBean = new ResponseBean(); + Status status = Status.OK; + + if(!TokensUtils.isUserToken(caller)){ + status = Status.FORBIDDEN; + responseBean.setMessage("This method can only be invoked with a user token!"); + logger.warn("Trying to access get-my-vres method via a token different than USER is not allowed"); + }else{ + GroupManager gmManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager(); + RoleManager roleManager = RoleManagerWSBuilder.getInstance().getRoleManager(); + try{ + + GCubeUser user = userManager.getUserByUsername(username); + List vres = gmManager.listVresByUser(user.getUserId()); + JSONArray toReturn = new JSONArray(); + + for (GCubeGroup group : vres) { + + // # ticket 9333 + JSONObject obj = new JSONObject(); + obj.put("name", group.getGroupName()); + obj.put("context", gmManager.getInfrastructureScope(group.getGroupId())); + obj.put("description", group.getDescription()); + //obj.put("thumbnail_url", ...); // TODO + JSONArray managers = new JSONArray(); + + if(getManagers){ + List vreManagers = userManager.listUsersByGroupAndRole(group.getGroupId(), + roleManager.getRoleIdByName(GatewayRolesNames.VRE_MANAGER.getRoleName())); + + for (GCubeUser vreManager : vreManagers) { + JSONObject manager = new JSONObject(); + manager.put("username", vreManager.getUsername()); + manager.put("fullname", vreManager.getFullname()); + managers.add(manager); + } + + obj.put("managers", managers); + } + toReturn.add(obj); + } + + responseBean.setSuccess(true); + responseBean.setResult(toReturn); + + }catch(Exception e){ + + logger.error("Unable to retrieve vres for user.", e); + responseBean.setMessage(e.toString()); + responseBean.setSuccess(false); + status = Status.INTERNAL_SERVER_ERROR; + + } + } + return Response.status(status).entity(responseBean).build(); + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/outputs/ResponseBean.java b/src/main/java/org/gcube/social_networking/ws/outputs/ResponseBean.java new file mode 100644 index 0000000..b7dc1f9 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/outputs/ResponseBean.java @@ -0,0 +1,77 @@ +package org.gcube.social_networking.ws.outputs; + +import java.io.Serializable; + +/** + * Response bean + * + */ +public class ResponseBean implements Serializable { + + private static final long serialVersionUID = -2725238162673879658L; + /** + * The result of the request: true if it succeeded, false otherwise + */ + private boolean success; + + /** + * An error message if something wrong happened, null/empty otherwise + */ + private String message; + /** + * The result object of the request + */ + private Object result; + + public ResponseBean() { + super(); + } + + /** + * @param success + * @param message + * @param result + */ + public ResponseBean(boolean success, String message, Object result) { + super(); + this.success = success; + this.message = message; + this.result = result; + } + + + public boolean isSuccess() { + return success; + } + + + public void setSuccess(boolean success) { + this.success = success; + } + + + public String getMessage() { + return message; + } + + + public void setMessage(String message) { + this.message = message; + } + + + public Object getResult() { + return result; + } + + + public void setResult(Object result) { + this.result = result; + } + + @Override + public String toString() { + return "ResponseBean [success=" + success + + ", message=" + message + ", result=" + result + "]"; + } +} diff --git a/src/main/java/org/gcube/social_networking/ws/providers/CustomObjectMapper.java b/src/main/java/org/gcube/social_networking/ws/providers/CustomObjectMapper.java new file mode 100644 index 0000000..3ef0379 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/providers/CustomObjectMapper.java @@ -0,0 +1,37 @@ +package org.gcube.social_networking.ws.providers; + +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; + +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.SerializationFeature; + +@Provider +/** + * Custom mapper with property CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES to perform serialization/deserialization + * with snake case over camel case for json beans. + * TODO check https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations for applying such transformation + * only to some classes. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class CustomObjectMapper implements ContextResolver { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CustomObjectMapper.class); + private final ObjectMapper mapper; + + public CustomObjectMapper() { + logger.debug("new ObjectMapperResolver()"); + mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); + } + + @Override + public ObjectMapper getContext(Class type) { + logger.debug("ObjectMapperResolver.getContext(...) invoked"); + return mapper; + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/social_networking/ws/utils/CassandraConnection.java b/src/main/java/org/gcube/social_networking/ws/utils/CassandraConnection.java new file mode 100644 index 0000000..b051246 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/CassandraConnection.java @@ -0,0 +1,50 @@ +package org.gcube.social_networking.ws.utils; + +import org.gcube.portal.databook.server.DBCassandraAstyanaxImpl; +import org.gcube.portal.databook.server.DatabookStore; +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.slf4j.LoggerFactory; + +/** + * Cassandra connection class. + * @author Costantino Perciante at ISTI-CNR + */ +public class CassandraConnection { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CassandraConnection.class); + + // databook store (singleton) + private static DatabookStore store; + + private static CassandraConnection singleton = new CassandraConnection(); + + private CassandraConnection(){ + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + logger.debug("Getting connection to cassandra"); + store = new DBCassandraAstyanaxImpl(ctx.container().configuration().infrastructure()); + logger.debug("Connection to cassandra created"); + } + + /** + * Returns the object to query the cassandra cluster. + * @return connection pool to cassandra cluster + */ + public DatabookStore getDatabookStore(){ + + return store; + + } + + /** + * Get the instance + * @return + */ + public static CassandraConnection getInstance(){ + + return singleton; + + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/utils/ElasticSearchConnection.java b/src/main/java/org/gcube/social_networking/ws/utils/ElasticSearchConnection.java new file mode 100644 index 0000000..ba75e47 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/ElasticSearchConnection.java @@ -0,0 +1,52 @@ +package org.gcube.social_networking.ws.utils; + +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.socialnetworking.social_data_search_client.ElasticSearchClient; +import org.gcube.socialnetworking.social_data_search_client.ElasticSearchClientImpl; +import org.slf4j.LoggerFactory; + +/** + * The class discovers and offer connections to the elastic search cluster. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ElasticSearchConnection { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ElasticSearchConnection.class); + + // databook store (singleton) + private ElasticSearchClient es; + + // singleton + private static ElasticSearchConnection singleton = new ElasticSearchConnection(); + + private ElasticSearchConnection(){ + try { + ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears + logger.debug("Creating connection to Elasticsearch"); + es = new ElasticSearchClientImpl(ctx.container().configuration().infrastructure()); + logger.debug("Elasticsearch connection created"); + } catch (Exception e) { + logger.error("Failed to connect to elasticsearch", e); + } + } + + public static ElasticSearchConnection getSingleton(){ + + return singleton; + + } + + /** + * Returns the object to connect to cassandra cluster. + * @return connection pool to cassandra cluster + * @throws Exception + */ + public ElasticSearchClient getElasticSearchClient(){ + + return es; + + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/utils/ErrorMessages.java b/src/main/java/org/gcube/social_networking/ws/utils/ErrorMessages.java new file mode 100644 index 0000000..7a4de11 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/ErrorMessages.java @@ -0,0 +1,21 @@ +package org.gcube.social_networking.ws.utils; + + +/** + * Class that contains error messages to be returned in the HTTP responses. + * @author Costantino Perciante at ISTI-CNR + */ +public class ErrorMessages { + + public static final String MISSING_TOKEN = "Missing token."; + public static final String MISSING_PARAMETERS = "Missing request parameters."; + public static final String INVALID_TOKEN = "Invalid token."; + public static final String TOKEN_GENERATION_APP_FAILED = "Token generation failed."; + public static final String NOT_APP_TOKEN = "Invalid token: not belonging to an application."; + public static final String NOT_APP_ID = "Invalid application id: it doesn't belong to an application."; + public static final String NO_APP_PROFILE_FOUND = "There is no application profile for this app id/scope."; + public static final String BAD_REQUEST = "Please check the parameter you passed, it seems a bad request"; + public static final String ERROR_IN_API_RESULT = "The error is reported into the 'message' field of the returned object"; + public static final String POST_OUTSIDE_VRE = "A post cannot be written into a context that is not a VRE"; + public static final String DEPRECATED_METHOD = "This method is deprecated, must use version 2"; +} diff --git a/src/main/java/org/gcube/social_networking/ws/utils/Filters.java b/src/main/java/org/gcube/social_networking/ws/utils/Filters.java new file mode 100644 index 0000000..51eddd3 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/Filters.java @@ -0,0 +1,193 @@ +package org.gcube.social_networking.ws.utils; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.gcube.portal.databook.server.DatabookStore; +import org.gcube.portal.databook.shared.Comment; +import org.gcube.portal.databook.shared.EnhancedFeed; +import org.gcube.portal.databook.shared.Feed; +import org.gcube.portal.databook.shared.Post; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault; +import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; +import org.gcube.vomanagement.usermanagement.model.GCubeGroup; +import org.slf4j.LoggerFactory; + +/** + * Filters to apply to feeds/comments etc + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class Filters { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Filters.class); + + private static List getContexts(String context) throws IllegalArgumentException, UserManagementSystemException, GroupRetrievalFault{ + + // retrieve group information + GroupManager gm = GroupManagerWSBuilder.getInstance().getGroupManager(); + GCubeGroup group = gm.getGroup(gm.getGroupIdFromInfrastructureScope(context)); + + List contexts = new ArrayList(); + + if(gm.isRootVO(group.getGroupId())){ + + } + else if(gm.isVO(group.getGroupId())){ + + List vres = group.getChildren(); + for (GCubeGroup gCubeGroup : vres) { + contexts.add(gm.getInfrastructureScope(gCubeGroup.getGroupId())); + } + + }else{ + contexts.add(gm.getInfrastructureScope(group.getGroupId())); + } + + return contexts; + } + + /** + * Given a list of not filtered feeds, the methods remove feeds unaccessible in this scope. + * If the initial context is the root: all feeds are returned; + * If the initial context is a VO: feeds for vres within the vo are returned; + * If the initial context is a vre: feeds of the vre are returned; + * @param feedsIds + * @param context + * @throws Exception + */ + public static void filterFeedsPerContextById( + List feedsIds, String context) throws Exception { + + DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore(); + List feeds = new ArrayList(); + + for (String feedId : feedsIds) { + try{ + feeds.add(datastore.readFeed(feedId)); + }catch(Exception e){ + logger.error("Unable to read feed with id " + feedId, e); + } + } + + // filter + filterFeedsPerContext(feeds, context); + + // clear and convert + feedsIds.clear(); + for (Feed feed : feeds) { + feedsIds.add(feed.getKey()); + } + + } + + /** + * Given a list of not filtered feeds, the methods remove feeds unaccessible in this scope. + * If the initial context is the root: all feeds are returned; + * If the initial context is a VO: feeds for vres within the vo are returned; + * If the initial context is a vre: feeds of the vre are returned; + * @param feeds + * @param context + * @throws Exception + */ + @Deprecated + public static void filterFeedsPerContext(List feeds, String context) throws Exception { + + List contexts = getContexts(context); + + // filter + Iterator iterator = feeds.iterator(); + while (iterator.hasNext()) { + Feed feed = (Feed) iterator.next(); + if(!contexts.contains(feed.getVreid())) + iterator.remove(); + } + + } + /** + * Given a list of not filtered posts, the methods remove posts unaccessible in this scope. + * If the initial context is the root: all posts are returned; + * If the initial context is a VO: posts for vres within the vo are returned; + * If the initial context is a vre: posts of the vre are returned; + * @param context + * @throws Exception + */ + public static void filterPostsPerContext(List posts, String context) throws Exception { + + List contexts = getContexts(context); + + // filter + Iterator iterator = posts.iterator(); + while (iterator.hasNext()) { + Post post = (Post) iterator.next(); + if(!contexts.contains(post.getVreid())) + iterator.remove(); + } + + } + + /** + * Filter comments per context + * @param comments + * @param context + * @throws Exception + */ + public static void filterCommentsPerContext(List comments, String context) throws Exception { + + List contexts = getContexts(context); + + // get cassandra store + DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore(); + + // filter + Iterator iterator = comments.iterator(); + while (iterator.hasNext()) { + try{ + Comment comment = (Comment) iterator.next(); + Feed parent = datastore.readFeed(comment.getFeedid()); + if(!contexts.contains(parent.getVreid())) + iterator.remove(); + }catch(Exception e){ + logger.warn("Failed to analyze this comment", e); + iterator.remove(); // remove it anyway + } + } + + } + + /** + * Depending on the type of object provided (e.g. Feed, Comment etc), some information are removed + * @param toClear + * @throws Exception + */ + public static void hideSensitiveInformation(List toClear, String usernameCaller){ + + if(toClear == null || toClear.isEmpty() || usernameCaller == null || usernameCaller.isEmpty()) + return; + else{ + + // for feeds + if(toClear.get(0).getClass().equals(Feed.class)){ + + for (T feed : toClear) { + Feed feeded = ((Feed)feed); + if(!usernameCaller.equals(feeded.getEntityId())) + feeded.setEmail(""); // remove the email field + } + + }else if(toClear.get(0).getClass().equals(EnhancedFeed.class)){ + for (T enhancedFeed : toClear) { + Feed feeded = ((EnhancedFeed)enhancedFeed).getFeed(); + if(!usernameCaller.equals(feeded.getEntityId())) + feeded.setEmail(""); // remove the email field + } + } + + } + + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/utils/SocialUtils.java b/src/main/java/org/gcube/social_networking/ws/utils/SocialUtils.java new file mode 100644 index 0000000..d4dd3a9 --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/SocialUtils.java @@ -0,0 +1,725 @@ +package org.gcube.social_networking.ws.utils; + +import static org.gcube.resources.discovery.icclient.ICFactory.client; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager; +import org.gcube.applicationsupportlayer.social.NotificationsManager; +import org.gcube.applicationsupportlayer.social.ex.ApplicationProfileNotFoundException; +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; +import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser; +import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.resources.gcore.utils.XPathHelper; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.portal.databook.shared.ApplicationProfile; +import org.gcube.portal.databook.shared.Comment; +import org.gcube.portal.databook.shared.Like; +import org.gcube.portal.databook.shared.Post; +import org.gcube.portal.databook.shared.PostType; +import org.gcube.portal.databook.shared.PrivacyLevel; +import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException; +import org.gcube.portal.notifications.bean.GenericItemBean; +import org.gcube.portal.notifications.thread.CommentNotificationsThread; +import org.gcube.portal.notifications.thread.LikeNotificationsThread; +import org.gcube.portal.notifications.thread.MentionNotificationsThread; +import org.gcube.portal.notifications.thread.PostNotificationsThread; +import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder; +import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; +import org.gcube.portlets.widgets.pickitem.shared.ItemBean; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.Query; +import org.gcube.resources.discovery.client.queries.impl.QueryBox; +import org.gcube.social_networking.caches.SocialNetworkingSiteFinder; +import org.gcube.social_networking.socialutillibrary.Utils; +import org.gcube.socialnetworking.socialtoken.SocialMessageParser; +import org.gcube.vomanagement.usermanagement.GroupManager; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.exception.TeamRetrievalFault; +import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; +import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; +import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Utility class. + */ +@SuppressWarnings("deprecation") +public class SocialUtils { + + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SocialUtils.class); + + public final static String NO_TEXT_FILE_SHARE = "_N0_73X7_SH4R3_"; + public final static int CACHING_TIME_TO_EXPIRATION = 2506000;//29 days 6 minutes 40 seconds + public final static String DISABLED_USERS_NOTIFICATIONS_NAMESPACE = "dun:"; + + // name of the portlet for vre notification + public static final String NEWS_FEED_PORTLET_CLASSNAME = "org.gcube.portlets.user.newsfeed.server.NewsServiceImpl"; + + /** + * + * @param mentions the set of string containing the usernames + * @return a list of existing usernames associated with their fullnames + */ + private static ArrayList getUsersFromUsernames(Set mentions) { + if (mentions.isEmpty()) + return new ArrayList<>(); + ArrayList toReturn = new ArrayList<>(); + UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager(); + for (String username : mentions) { + try{ + GCubeUser user = uManager.getUserByUsername(username); + String fullName = user.getFirstName() + " " + user.getLastName(); + toReturn.add(new GenericItemBean(""+user.getUserId(), username, fullName, "")); + }catch(Exception e){ + logger.error("Unable to get user informations for username=" + username); + } + } + return toReturn; + } + + // utility method + private static ArrayList convertToItemBean(Collection items) { + ArrayList toReturn = new ArrayList<>(items.size()); + for (GenericItemBean item : items) { + toReturn.add(new ItemBean(item.getId(), item.getName(), item.getAlternativeName(), item.getThumbnailURL())); + } + return toReturn; + } + + /** + * Method used when an application needs to publish something. + * @param postText + * @param uriParams + * @param previewTitle + * @param previewDescription + * @param httpImageUrl + * @return true upon success, false on failure + */ + public static Post shareApplicationUpdate( + String postText, + String uriParams, + String previewTitle, + String previewDescription, + String httpImageUrl, + ApplicationProfile applicationProfile, + Caller caller, + boolean notifyGroup + ){ + + SocialMessageParser messageParser = new SocialMessageParser(postText); + String escapedPostText = messageParser.getParsedMessage(); + List hashtags = messageParser.getHashtags(); + ArrayList mentionedUsers = getUsersFromUsernames(Utils.getMentionedUsernames(postText)); + ArrayList mentionedUsersToConvertInHTML = convertToItemBean(mentionedUsers); + + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get()); + + escapedPostText = Utils.convertMentionUsernamesAnchorHTML(escapedPostText, mentionedUsersToConvertInHTML, site.getSiteURL(), site.getSiteLandingPagePath()); + logger.debug("*** Escaped post text is " + escapedPostText); + + String scope = ScopeProvider.instance.get(); + String appId = caller.getClient().getId(); + + Post toWrite = + buildPost( + escapedPostText, + uriParams == null ? "" : uriParams, + previewTitle == null ? "" : previewTitle, + previewDescription == null ? "" : previewDescription, + httpImageUrl == null ? "" : httpImageUrl, + applicationProfile, + scope); + + // try to save it + boolean res = CassandraConnection.getInstance().getDatabookStore().saveAppPost(toWrite); + + if(res){ + logger.debug("Feed correctly written by application " + appId); + + // wait a bit before saving hashtags + if(hashtags != null && !hashtags.isEmpty()) + new Thread(()->{ + try { + Thread.sleep(1000); + CassandraConnection.getInstance().getDatabookStore().saveHashTags(toWrite.getKey(), scope, hashtags); + } catch (Exception e1) { + logger.error("Failed to save hashtags in Cassandra", e1); + } + }).start(); + + + // build the notification manager + + SocialNetworkingUser user = new SocialNetworkingUser(appId, "", applicationProfile.getName(), applicationProfile.getImageUrl()); + NotificationsManager nm = new ApplicationNotificationsManager( + UserManagerWSBuilder.getInstance().getUserManager(), + site, + scope, + user, + NEWS_FEED_PORTLET_CLASSNAME); + + if (!mentionedUsers.isEmpty()) + new Thread(new MentionNotificationsThread(toWrite.getKey(), toWrite.getDescription(), nm, null, mentionedUsers)).start(); + + if(notifyGroup){ + + logger.debug("Sending notifications for " + appId + " " + scope); + + try{ + + String name = new ScopeBean(scope).name(); // scope such as devVRE + + // retrieve group information + GroupManager gManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + + long groupId = gManager.getGroupId(name); + String groupName = gManager.getGroup(groupId).getGroupName(); + + logger.debug("Company id and name " + groupId + " " + groupName); + + // start notification thread + new Thread(new PostNotificationsThread( + UserManagerWSBuilder.getInstance().getUserManager(), + toWrite.getKey(), + toWrite.getDescription(), + ""+groupId, + nm, + new HashSet(hashtags), + new HashSet()) + ).start(); + }catch (Exception e) { + logger.debug("Feed succesfully created but unable to send notifications."); + } + + } + return toWrite; + } + else + return null; + + } + + /** + * Build an ApplicationProfile Feed. + * + * @param description add a description for the update you are sharing + * @param uriParams the additional parameters your applicationProfile needs to open the subject of this update e.g. id=12345&type=foo + * @param previewTitle the title to show in the preview + * @param previewDescription the description to show in the preview + * @param previewThumbnailUrl the image url to show in the preview + * @return a feed instance ready to be written + */ + private static Post buildPost( + String description, + String uriParams, + String previewTitle, + String previewDescription, + String previewThumbnailUrl, + ApplicationProfile applicationProfile, + String scopeApp) { + + String uri = applicationProfile.getUrl(); + + //add the GET params if necessary + if (uriParams != null && uriParams.compareTo("") != 0) + uri += "?"+uriParams; + + Post toReturn = new Post( + UUID.randomUUID().toString(), + PostType.PUBLISH, + applicationProfile.getKey(), + new Date(), + scopeApp, + uri, + previewThumbnailUrl, + description, + PrivacyLevel.SINGLE_VRE, + applicationProfile.getName(), + "no-email", + applicationProfile.getImageUrl(), + previewTitle, + previewDescription, + "", + true); + + return toReturn; + } + + /** + * This method looks up the applicationProfile profile among the ones available in the infrastructure + * @param idApp as identifier of your application (as reported in the ApplicationProfile) + * @param scopeApp the scope of the application + */ + public static ApplicationProfile getProfileFromInfrastrucure(String idApp, String scopeApp) { + ScopeBean scope = new ScopeBean(scopeApp); + + logger.debug("Trying to fetch applicationProfile profile from the infrastructure for " + idApp + " scope: " + scope); + + // set the scope of the root infrastructure + String rootInfrastructure = scopeApp.split("/")[1]; + ScopeProvider.instance.set("/"+rootInfrastructure); + + try { + + ApplicationProfile toReturn = new ApplicationProfile(); + Query q = new QueryBox("for $profile in collection('/db/Profiles/GenericResource')//Resource " + + "where $profile/Profile/SecondaryType/string() eq 'ApplicationProfile' and $profile/Profile/Body/AppId/string() " + + " eq '" + idApp + "'" + + "return $profile"); + + + DiscoveryClient client = client(); + List appProfile = client.submit(q); + + if (appProfile == null || appProfile.size() == 0) + throw new Exception("Your applicationProfile is not registered in the infrastructure"); + + else { + + String elem = appProfile.get(0); + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Node node = docBuilder.parse(new InputSource(new StringReader(elem))).getDocumentElement(); + XPathHelper helper = new XPathHelper(node); + + List currValue = null; + currValue = helper.evaluate("/Resource/Profile/Name/text()"); + if (currValue != null && currValue.size() > 0) { + + toReturn.setName(currValue.get(0)); + + } + else throw new ApplicationProfileNotFoundException("Your applicationProfile NAME was not found in the profile"); + + currValue = helper.evaluate("/Resource/Profile/Description/text()"); + if (currValue != null && currValue.size() > 0) { + + toReturn.setDescription(currValue.get(0)); + + } + else logger.warn("No Description exists for " + toReturn.getName()); + + currValue = helper.evaluate("/Resource/Profile/Body/AppId/text()"); + + if (currValue != null && currValue.size() > 0) { + + toReturn.setKey(currValue.get(0)); + + } + else throw new ApplicationProfileNotFoundException("Your applicationProfile ID n was not found in the profile, consider adding element in "); + + currValue = helper.evaluate("/Resource/Profile/Body/ThumbnailURL/text()"); + if (currValue != null && currValue.size() > 0) { + + toReturn.setImageUrl(currValue.get(0)); + + } + else throw new Exception("Your applicationProfile Image Url was not found in the profile, consider adding element in "); + currValue = helper.evaluate("/Resource/Profile/Body/EndPoint/Scope/text()"); + if (currValue != null && currValue.size() > 0) { + + List scopes = currValue; + boolean foundUrl = false; + for (int i = 0; i < scopes.size(); i++) { + if (currValue.get(i).trim().compareTo(scope.toString()) == 0) { + toReturn.setUrl(helper.evaluate("/Resource/Profile/Body/EndPoint/URL/text()").get(i)); + toReturn.setScope(scope.toString()); + foundUrl = true; + break; + } + } + + if (! foundUrl) + throw new ApplicationProfileNotFoundException("Your applicationProfile URL was not found in the profile for Scope: " + scope.toString()); + } + + else throw new ApplicationProfileNotFoundException("Your applicationProfile EndPoint was not found in the profile, consider adding element in "); + logger.debug("Returning " + toReturn); + return toReturn; + } + + } catch (Exception e) { + + logger.error("Error while trying to fetch applicationProfile profile from the infrastructure", e); + + } finally{ + + // set the scope back + ScopeProvider.instance.set(scopeApp); + + } + + return null; + + } + + /** + * Allows user to post a feed in a certain vre. + * @param userId + * @param postText + * @param vreId + * @param previewTitle + * @param previewDescription + * @param previewHost + * @param previewUrl + * @param urlThumbnail + * @param notifyGroup + * @return The written Feed + */ + public static Post shareUserUpdate( + String userId, + String postText, + String vreId, + String previewTitle, + String previewDescription, + String previewHost, + String previewUrl, + String urlThumbnail, + boolean notifyGroup) { + + SocialMessageParser messageParser = new SocialMessageParser(postText); + String escapedPostText = messageParser.getParsedMessage(); + List hashtags = messageParser.getHashtags(); + //check if any mention exists + ArrayList mentionedUsers = getUsersFromUsernames(Utils.getMentionedUsernames(postText)); + ArrayList mentionedUsersToConvertInHTML = convertToItemBean(mentionedUsers); + + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get()); + + escapedPostText = Utils.convertMentionUsernamesAnchorHTML(escapedPostText, mentionedUsersToConvertInHTML, site.getSiteURL(), site.getSiteLandingPagePath()); + + GCubeUser user; + + // retrieve group information + UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager(); + try { + user = uManager.getUserByUsername(userId); + } catch(Exception e){ + logger.error("Unable to get user informations, post write fails.", e); + return null; + } + + String email = user.getEmail(); + String fullName = user.getFirstName() + " " + user.getLastName(); + String thumbnailURL = user.getUserAvatarURL(); + String linkTitle = previewTitle == null ? "" : previewTitle; + String linkDesc = previewDescription == null ? "" : previewDescription; + String host = previewHost == null ? "" : previewHost; + String url = previewUrl == null ? "" : previewUrl; + if (urlThumbnail == null) + urlThumbnail = "null"; + + //this means the user has shared a file without text in it. + String textToPost = ""; + if (escapedPostText.trim().compareTo(NO_TEXT_FILE_SHARE) == 0) { + textToPost = org.gcube.social_networking.socialutillibrary.Utils.convertFileNameAnchorHTML(url); + } else { + textToPost = escapedPostText; + } + + Post toShare = new Post(UUID.randomUUID().toString(), PostType.PUBLISH, userId, new Date(), + vreId, url, urlThumbnail, textToPost, PrivacyLevel.SINGLE_VRE, fullName, email, thumbnailURL, linkTitle, linkDesc, host); + + logger.debug("Attempting to save Post with text: " + textToPost + " Level = " + PrivacyLevel.SINGLE_VRE + " Timeline = " + vreId); + + boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(toShare); + + if(vreId != null && vreId.compareTo("") != 0 && result) { + + logger.trace("Attempting to write onto " + vreId); + + try { + + try{ + logger.debug("Sleeping waiting for cassandra's update"); + Thread.sleep(1000); + + }catch(Exception e){ + + logger.error(e.toString()); + + } + CassandraConnection.getInstance().getDatabookStore().saveFeedToVRETimeline(toShare.getKey(), vreId); + + if (hashtags != null && !hashtags.isEmpty()) + CassandraConnection.getInstance().getDatabookStore().saveHashTags(toShare.getKey(), vreId, hashtags); + + } catch (FeedIDNotFoundException e) { + logger.error("Error writing onto VRES Time Line" + vreId); + } + logger.trace("Success writing onto " + vreId); + } + + if (!result) + return null; + + SocialNetworkingUser socialUser = + new SocialNetworkingUser(userId, email, fullName, thumbnailURL); + NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, vreId, socialUser, NEWS_FEED_PORTLET_CLASSNAME); + if (!mentionedUsers.isEmpty()) + new Thread(new MentionNotificationsThread(toShare.getKey(), toShare.getDescription(), nm, null, mentionedUsers)).start(); + + //send the notification about this posts to everyone in the group if notifyGroup is true + if (vreId != null && vreId.compareTo("") != 0 && notifyGroup) { + + try{ + // retrieve group information + GroupManager gManager = GroupManagerWSBuilder.getInstance().getGroupManager(); + // handle the scope + String name = new ScopeBean(vreId).name(); // scope such as devVR + long groupId = gManager.getGroupId(name); + String groupName = gManager.getGroup(groupId).getGroupName(); + + logger.debug("Company id and name " + groupId + " " + groupName); + new Thread( + new PostNotificationsThread( + UserManagerWSBuilder.getInstance().getUserManager(), + toShare.getKey(), + toShare.getDescription(), + ""+groupId, + nm, + new HashSet(), + new HashSet(hashtags)) + ).start(); + + logger.debug("Start sending notifications for post written by " + userId); + }catch(Exception e){ + logger.error("Unable to notify users", e); + } + } + return toShare; + } + /** + * Allows to comment post in a certain vre. + + * @param userid the username + * @param time the date and time of the comment + * @param postId the key of the post that was commented + * @param commentText the text as it is, it will be parsed + * @param postOwnerId the username of the user who created the post that was commented + * @param context the VRE context + * + * @return the Comment instance if ok, null if somwthign went KO + * @throws FeedIDNotFoundException + */ + public static Comment commentPost(String userid, Date time, String postId, String commentText, String postOwnerId, String context) throws FeedIDNotFoundException { + + SocialMessageParser messageParser = new SocialMessageParser(commentText); + String escapedCommentText = messageParser.getParsedMessage(); + //check if any mention exists + ArrayList mentionedUsers = getUsersFromUsernames(Utils.getMentionedUsernames(commentText)); + ArrayList mentionedUsersToConvertInHTML = convertToItemBean(mentionedUsers); + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get()); + + escapedCommentText = Utils.convertMentionUsernamesAnchorHTML(escapedCommentText, mentionedUsersToConvertInHTML, site.getSiteURL(), site.getSiteLandingPagePath()); + + // retrieve user information + GCubeUser user; + UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager(); + try { + user = uManager.getUserByUsername(userid); + } catch(Exception e){ + logger.error("Unable to get user informations, comment write fails.", e); + return null; + } + String commentKey = UUID.randomUUID().toString(); // a unique id that goes in the DB + String email = user.getEmail(); + String fullName = user.getFirstName() + " " + user.getLastName(); + String thumbnailURL = user.getUserAvatarURL(); + + Comment theComment = new Comment(commentKey, userid, time, postId, escapedCommentText, fullName, thumbnailURL); + logger.debug("Attempting to save Comment with text: " + commentText + " postid="+postId); + + boolean result = CassandraConnection.getInstance().getDatabookStore().addComment(theComment); + logger.debug("Added comment? " + theComment.toString() + " Result is " +result); + + if (!result) + return null; + + //if the comment was correctly delivered notify users involved + SocialNetworkingUser socialUser = new SocialNetworkingUser(userid, email, fullName, thumbnailURL); + + NotificationsManager nm = new ApplicationNotificationsManager(uManager, site, context, socialUser, NEWS_FEED_PORTLET_CLASSNAME); + + //if the user who commented this post is not the user who posted it notify the poster user (Post owner) + logger.debug("The post creator is " + postOwnerId); + if (! user.getUsername().equals(postOwnerId)) { + boolean resultNotifyOwnComment = nm.notifyOwnCommentReply(postOwnerId, postId, escapedCommentText, theComment.getKey()); + logger.debug("Comment Notification to post creator added? " + resultNotifyOwnComment); + } + //if there are users who liked this post they get notified, asynchronously with this thread + ArrayList likes = getAllLikesByPost(postId); + Thread likesThread = new Thread(new LikeNotificationsThread(escapedCommentText, nm, likes, postOwnerId, theComment.getKey())); + likesThread.start(); + + //notify the other users who commented this post (excluding the ones above) + Thread commentsNotificationthread = new Thread(new CommentNotificationsThread( + CassandraConnection.getInstance().getDatabookStore(), + uManager, user.getUsername(), theComment.getFeedid(), escapedCommentText, nm, postOwnerId, theComment.getKey(), likes)); + commentsNotificationthread.start(); + + //send the notification to the mentioned users, if any + if (mentionedUsers != null && mentionedUsers.size() > 0) { + ArrayList toPass = new ArrayList(); + + + // among the mentionedUsers there could be groups of people + Map uniqueUsersToNotify = new HashMap<>(); + UserManager um = new LiferayUserManager(); + + for (ItemBean bean : mentionedUsersToConvertInHTML) { + + if(bean.isItemGroup()){ + + // retrieve the users of this group + try { + List teamUsers = um.listUsersByTeam(Long.parseLong(bean.getId())); + + for (GCubeUser userTeam : teamUsers) { + if(!uniqueUsersToNotify.containsKey(userTeam.getUsername())) + uniqueUsersToNotify.put(userTeam.getUsername(), new ItemBean(userTeam.getUserId()+"", + userTeam.getUsername(), userTeam.getFullname(), userTeam.getUserAvatarURL())); + } + + } catch (NumberFormatException + | UserManagementSystemException + | TeamRetrievalFault | UserRetrievalFault e) { + logger.error("Unable to retrieve team information", e); + } + + }else{ + // it is a user, just add to the hashmap + if(!uniqueUsersToNotify.containsKey(bean.getName())) + uniqueUsersToNotify.put(bean.getName(), bean); + + } + } + + // iterate over the hashmap + Iterator> userMapIterator = uniqueUsersToNotify.entrySet().iterator(); + while (userMapIterator.hasNext()) { + Map.Entry userEntry = (Map.Entry) userMapIterator + .next(); + ItemBean userBean = userEntry.getValue(); + toPass.add(new GenericItemBean(userBean.getId(), userBean.getName(), userBean.getAlternativeName(), userBean.getThumbnailURL())); + } + + Thread thread = new Thread(new MentionNotificationsThread(theComment.getFeedid(), escapedCommentText, nm, null, toPass)); + thread.start(); + } + return theComment; + } + + private static ArrayList getAllLikesByPost(String postid) { + ArrayList toReturn = (ArrayList) CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(postid); + logger.debug("Asking likes for " + postid); + for (Like like : toReturn) { + // retrieve user information + GCubeUser user; + UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager(); + try { + user = uManager.getUserByUsername(like.getUserid()); + } catch(Exception e){ + logger.error("Unable to get user informations, comment write fails.", e); + return null; + } + String thumbnailURL = user.getUserAvatarURL(); + + like.setThumbnailURL(thumbnailURL == null ? "" : thumbnailURL); + } + return toReturn; + } + + public static boolean like(String username, String postid, String context) { + boolean likeCommitResult = false; + // retrieve user information + GCubeUser user; + UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager(); + try { + user = uManager.getUserByUsername(username); + } catch(Exception e){ + logger.error("Unable to get user informations, like write fails.", e); + return false; + } + String email = user.getEmail(); + String fullName = user.getFirstName() + " " + user.getLastName(); + String thumbnailURL = user.getUserAvatarURL(); + SocialNetworkingUser socialUser = new SocialNetworkingUser(user.getUsername(), email, fullName, thumbnailURL); + + Like toLike = new Like(UUID.randomUUID().toString(), user.getUsername(), + new Date(), postid, user.getFullname(), user.getUserAvatarURL()); + Post thePost = null; + try { + logger.debug("Attempting to read post with id: " +postid); + thePost = CassandraConnection.getInstance().getDatabookStore().readPost(postid); + likeCommitResult = CassandraConnection.getInstance().getDatabookStore().like(toLike); + } catch (Exception e) { + logger.error("Post not found for this like ot could not like the post " + e.getMessage()); + return false; + } + //if the like was correctly delivered notify the user who made the post + + boolean resultNotifyLike =false; + if (likeCommitResult) { + SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get()); + NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, socialUser, NEWS_FEED_PORTLET_CLASSNAME); + + String postText = thePost.getDescription(); + String postOwnerId = thePost.getEntityId(); + SocialMessageParser messageParser = new SocialMessageParser(postText); + String escapedPostText = messageParser.getParsedMessage(); + + //if the user who liked this post is not the user who posted it notify the poster user (Post owner) + logger.debug("The post creator is " + postOwnerId); + if (! user.getUsername().equals(postOwnerId)) { + resultNotifyLike = nm.notifyLikedPost(postOwnerId, postid, escapedPostText); + logger.debug("Like Notification to post creator added? " + resultNotifyLike); + } + } + return likeCommitResult && resultNotifyLike; + } + + public static boolean unlike(String username, String likeid, String postid) { + boolean unlikeCommitResult = false; + // retrieve user information + GCubeUser user; + UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager(); + try { + user = uManager.getUserByUsername(username); + } catch(Exception e){ + logger.error("Unable to get user informations, unlike write fails.", e); + return false; + } + String fullName = user.getFirstName() + " " + user.getLastName(); + String thumbnailURL = user.getUserAvatarURL(); + try { + + unlikeCommitResult = CassandraConnection.getInstance().getDatabookStore().unlike(username, likeid, postid); + } catch (Exception e) { + logger.error("Post not Found for this like ot could not unlike the post " + e.getMessage()); + return false; + } + + return unlikeCommitResult; + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/utils/TokensUtils.java b/src/main/java/org/gcube/social_networking/ws/utils/TokensUtils.java new file mode 100644 index 0000000..36cb61e --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/TokensUtils.java @@ -0,0 +1,82 @@ +package org.gcube.social_networking.ws.utils; + +import org.gcube.common.authorization.library.ClientType; +import org.gcube.common.authorization.library.utils.Caller; +import org.slf4j.LoggerFactory; + + +/** + * Tokens utils methods + */ +public class TokensUtils { + + // a user context token (not qualified) has as qualifier the word "TOKEN" + private static final String DEFAULT_QUALIFIER_USER_TOKEN = "TOKEN"; + // Logger + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TokensUtils.class); + /** + * Check if it is a service token + * @return a boolean value + */ + public static boolean isServiceToken(Caller caller){ + + return caller.getClient().getType().equals(ClientType.SERVICE); + + } + + /** + * Check if it is an application token + * @return a boolean value + */ + public static boolean isApplicationToken(Caller caller){ + String username = caller.getClient().getId(); + if (username.startsWith("service-account-")) { + return true; + } + return caller.getClient().getType().equals(ClientType.EXTERNALSERVICE); + + } + + /** + * Check if it is a container token + * @return a boolean value + */ + public static boolean isContainerToken(Caller caller){ + + return caller.getClient().getType().equals(ClientType.CONTAINER); + + } + + /** + * Check if it is a user token + * @return a boolean value + */ + public static boolean isUserToken(Caller caller) { + logger.debug("\n ****** \n isUserToken: caller.getClient().getType().equals(ClientType.USER) => " + caller.getClient().getType().equals(ClientType.USER)); + String username = caller.getClient().getId(); + if (username.startsWith("service-account-")) { + return false; + } + return caller.getClient().getType().equals(ClientType.USER); + + } + + /** + * Check if it is a user token (not qualified) + * @return a boolean value + */ + public static boolean isUserTokenDefault(Caller caller){ + return isUserToken(caller); + } + + /** + * Check if it is a user token (qualified) + * @return a boolean value + */ + public static boolean isUserTokenQualified(Caller caller){ + + return caller.getClient().getType().equals(ClientType.USER) && !caller.getTokenQualifier().equals(DEFAULT_QUALIFIER_USER_TOKEN); + + } + +} diff --git a/src/main/java/org/gcube/social_networking/ws/utils/UserProfileExtendedWithVerifiedEmail.java b/src/main/java/org/gcube/social_networking/ws/utils/UserProfileExtendedWithVerifiedEmail.java new file mode 100644 index 0000000..0f061ed --- /dev/null +++ b/src/main/java/org/gcube/social_networking/ws/utils/UserProfileExtendedWithVerifiedEmail.java @@ -0,0 +1,194 @@ +package org.gcube.social_networking.ws.utils; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserProfileExtendedWithVerifiedEmail { + + @JsonProperty("id") + private String username; + + @JsonProperty("roles") + private List roles; + + @JsonProperty("picture") + private String avatar; + + @JsonProperty("name") + private String fullname; + + @JsonProperty("middle_name") + private String middleName; + + @JsonProperty("male") + private boolean male; + + @JsonProperty("location_industry") + private String locationIndustry; + + @JsonProperty("given_name") + private String firstName; + + @JsonProperty("email") + private String email; + + @JsonProperty("job_title") + private String jobTitle; + + @JsonProperty("family_name") + private String lastName; + + @JsonProperty("verified_email") + private boolean verifiedEmail = true; + + public UserProfileExtendedWithVerifiedEmail() { + super(); + } + + /** + * @param username + * @param roles + * @param avatar + * @param fullname + */ + public UserProfileExtendedWithVerifiedEmail(String username, List roles, String avatar, String fullname) { + this.username = username; + this.roles = roles; + this.avatar = avatar; + this.fullname = fullname; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getFullname() { + return fullname; + } + + public void setFullname(String fullname) { + this.fullname = fullname; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public boolean isMale() { + return male; + } + + public void setMale(boolean male) { + this.male = male; + } + + public String getLocationIndustry() { + return locationIndustry; + } + + public void setLocationIndustry(String locationIndustry) { + this.locationIndustry = locationIndustry; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getJobTitle() { + return jobTitle; + } + + public void setJobTitle(String jobTitle) { + this.jobTitle = jobTitle; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public boolean isVerifiedEmail() { + return verifiedEmail; + } + + public void setVerifiedEmail(boolean verifiedEmail) { + this.verifiedEmail = verifiedEmail; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("UserProfileExtendedWithVerifiedEmail [username="); + builder.append(username); + builder.append(", roles="); + builder.append(roles); + builder.append(", avatar="); + builder.append(avatar); + builder.append(", fullname="); + builder.append(fullname); + builder.append(", middleName="); + builder.append(middleName); + builder.append(", male="); + builder.append(male); + builder.append(", locationIndustry="); + builder.append(locationIndustry); + builder.append(", firstName="); + builder.append(firstName); + builder.append(", email="); + builder.append(email); + builder.append(", jobTitle="); + builder.append(jobTitle); + builder.append(", lastName="); + builder.append(lastName); + builder.append(", verifiedEmail="); + builder.append(verifiedEmail); + builder.append("]"); + return builder.toString(); + } + + + + +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index ef9a39b..9f610e6 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,19 +1,19 @@ + + admin-username + {{adminId}} + + + admin-pwd + {{adminPwd}} + - org.gcube.acme.ResourceInitializer + org.gcube.social_networking.SocialService - default - /docs/* - - - default - /api-docs/* - - - org.gcube.acme.ResourceInitializer - /* + org.gcube.social_networking.SocialService + /social-service/* \ No newline at end of file diff --git a/src/test/java/org/gcube/portal/test/GcoreEndpointReader.java b/src/test/java/org/gcube/portal/test/GcoreEndpointReader.java new file mode 100644 index 0000000..6185e66 --- /dev/null +++ b/src/test/java/org/gcube/portal/test/GcoreEndpointReader.java @@ -0,0 +1,78 @@ +/** + * + */ +package org.gcube.portal.test; + +import static org.gcube.resources.discovery.icclient.ICFactory.client; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.List; + +import org.gcube.common.resources.gcore.GCoreEndpoint; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GcoreEndpointReader { + + private static final String resource = "jersey-servlet"; + private static final String serviceName = "SocialNetworking"; + private static final String serviceClass = "Portal"; + + private static Logger logger = LoggerFactory.getLogger(GcoreEndpointReader.class); + private String resourceEntyName; + + /** + * Instantiates a new gcore endpoint reader. + * + * @param scope the scope + * @throws Exception the exception + */ + public GcoreEndpointReader(String scope) throws Exception { + + String currentScope = ScopeProvider.instance.get(); + + try{ + + logger.info("set scope "+scope); + ScopeProvider.instance.set(scope); + + SimpleQuery query = queryFor(GCoreEndpoint.class); + query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'",serviceClass)); + query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'"); + query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'",serviceName)); + query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+resource+"\"]/text()"); + + logger.debug("submitting quey "+query.toString()); + + DiscoveryClient client = client(); + List endpoints = client.submit(query); + if (endpoints == null || endpoints.isEmpty()) throw new Exception("Cannot retrieve the GCoreEndpoint serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+scope); + + + this.resourceEntyName = endpoints.get(0); + if(resourceEntyName==null) + throw new Exception("Endpoint:"+resource+", is null for serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+scope); + + logger.info("found entyname "+resourceEntyName+" for ckanResource: "+resource); + + }catch(Exception e){ + String error = "An error occurred during GCoreEndpoint discovery, serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+scope +"."; + logger.error(error, e); + throw new Exception(error); + }finally{ + if(currentScope != null) + ScopeProvider.instance.set(currentScope); + } + } + + /** + * @return the ResourceEntyName + */ + public String getResourceEntyName() { + + return resourceEntyName; + } +} diff --git a/src/test/java/org/gcube/portal/test/ServiceEndPointReaderSocial.java b/src/test/java/org/gcube/portal/test/ServiceEndPointReaderSocial.java new file mode 100644 index 0000000..a98a765 --- /dev/null +++ b/src/test/java/org/gcube/portal/test/ServiceEndPointReaderSocial.java @@ -0,0 +1,103 @@ +package org.gcube.portal.test; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.Iterator; +import java.util.List; + +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Retrieves the base url of the social-networking service in the scope provided + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ServiceEndPointReaderSocial { + + private String basePath = null; + + private static Logger logger = LoggerFactory.getLogger(ServiceEndPointReaderSocial.class); + private final static String RUNTIME_RESOURCE_NAME = "SocialNetworking"; + private final static String CATEGORY = "Portal"; + + public ServiceEndPointReaderSocial(String context){ + + if(context == null || context.isEmpty()) + throw new IllegalArgumentException("A valid context is needed to discover the service"); + + + String oldContext = ScopeProvider.instance.get(); + ScopeProvider.instance.set(context); + + try{ + + List resources = getConfigurationFromIS(); + if (resources.size() == 0){ + logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope."); + throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope."); + } + else { + + for (ServiceEndpoint res : resources) { + + Iterator accessPointIterator = res.profile().accessPoints().iterator(); + + while (accessPointIterator.hasNext()) { + ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator + .next(); + + // get base path + basePath = accessPoint.address(); + + // break + break; + } + } + + } + + }catch(Exception e){ + + logger.error("Unable to retrieve such service endpoint information!", e); + + }finally{ + + if(oldContext != null && !oldContext.equals(context)) + ScopeProvider.instance.set(oldContext); + + } + + logger.info("Found base path " + basePath + " for the service"); + + } + + /** + * Retrieve endpoints information from IS for DB + * @return list of endpoints for ckan database + * @throws Exception + */ + private List getConfigurationFromIS() throws Exception{ + + SimpleQuery query = queryFor(ServiceEndpoint.class); + query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'"); + query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'"); + DiscoveryClient client = clientFor(ServiceEndpoint.class); + List toReturn = client.submit(query); + return toReturn; + + } + + /** + * Get the base path of the social networking service + * @return + */ + public String getBasePath() { + return basePath; + } +}