Java tutorial
/* * Copyright "Open Digital Education" (SAS WebServices pour lEducation?), 2014 * * This program is published by "Open Digital Education" (SAS WebServices pour lEducation?). * You must indicate the name of the software and the company in any production /contribution * using the software and indicate on the home page of the software industry in question, * "powered by Open Digital Education" with a reference to the website: https: //opendigitaleducation.com/. * * This program is free software, licensed under the terms of the GNU Affero General Public License * as published by the Free Software Foundation, version 3 of the License. * * You can redistribute this application and/or modify it since you respect the terms of the GNU Affero General Public License. * If you modify the source code and then use this modified source code in your creation, you must make available the source code of your modifications. * * You should have received a copy of the GNU Affero General Public License along with the software. * If not, please see : <http://www.gnu.org/licenses/>. Full compliance requires reading the terms of this license and following its directives. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ package org.entcore.blog.services.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.entcore.blog.services.BlogTimelineService; import org.entcore.common.mongodb.MongoDbResult; import org.entcore.common.neo4j.Neo; import org.entcore.common.notification.NotificationUtils; import org.entcore.common.notification.TimelineHelper; import org.entcore.common.user.UserInfos; import org.entcore.common.utils.Config; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.eventbus.EventBus; import io.vertx.core.eventbus.Message; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import com.mongodb.QueryBuilder; import fr.wseduc.mongodb.MongoDb; import fr.wseduc.mongodb.MongoQueryBuilder; import fr.wseduc.webutils.Either; import fr.wseduc.webutils.collections.Joiner; import fr.wseduc.webutils.http.Renders; public class DefaultBlogTimelineService implements BlogTimelineService { private final Neo neo; private final MongoDb mongo; private final TimelineHelper notification; public DefaultBlogTimelineService(Vertx vertx, EventBus eb, JsonObject config, Neo neo, MongoDb mongo) { this.neo = neo; this.mongo = mongo; this.notification = new TimelineHelper(vertx, eb, config); } @Override public void notifyShare(final HttpServerRequest request, final String blogId, final UserInfos user, final JsonArray sharedArray, final String resourceUri) { if (sharedArray != null && user != null && blogId != null && request != null && resourceUri != null) { QueryBuilder query = QueryBuilder.start("_id").is(blogId); JsonObject keys = new JsonObject().put("title", 1); mongo.findOne("blogs", MongoQueryBuilder.build(query), keys, new Handler<Message<JsonObject>>() { @Override public void handle(final Message<JsonObject> event) { if ("ok".equals(event.body().getString("status"))) { List<String> shareIds = getSharedIds(sharedArray); if (!shareIds.isEmpty()) { Map<String, Object> params = new HashMap<>(); params.put("userId", user.getUserId()); neo.send(neoQuery(shareIds), params, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> res) { if ("ok".equals(res.body().getString("status"))) { JsonObject r = res.body().getJsonObject("result"); List<String> recipients = new ArrayList<>(); for (String attr : r.fieldNames()) { String id = r.getJsonObject(attr).getString("id"); if (id != null) { recipients.add(id); } } String blogTitle = event.body().getJsonObject("result", new JsonObject()) .getString("title"); JsonObject p = new JsonObject() .put("uri", "/userbook/annuaire#" + user.getUserId() + "#" + user.getType()) .put("username", user.getUsername()).put("blogTitle", blogTitle) .put("resourceUri", resourceUri).put("disableAntiFlood", true); notification.notifyTimeline(request, "blog.share", user, recipients, blogId, p); } } }); } } } }); } } @Override public void notifySubmitPost(final HttpServerRequest request, final String blogId, final String postId, final UserInfos user, final String resourceUri) { if (resourceUri != null && user != null && blogId != null && request != null) { QueryBuilder blogQuery = QueryBuilder.start("_id").is(blogId); JsonObject blogKeys = new JsonObject().put("author", 1); mongo.findOne("blogs", MongoQueryBuilder.build(blogQuery), blogKeys, new Handler<Message<JsonObject>>() { @Override public void handle(final Message<JsonObject> event) { if ("ok".equals(event.body().getString("status"))) { final String authorId = event.body().getJsonObject("result", new JsonObject()) .getJsonObject("author", new JsonObject()).getString("userId"); final QueryBuilder query = QueryBuilder.start("_id").is(postId); final JsonObject keys = new JsonObject().put("title", 1).put("blog", 1); final JsonArray fetch = new JsonArray().add("blog"); mongo.findOne("posts", MongoQueryBuilder.build(query), keys, fetch, MongoDbResult.validResultHandler(new Handler<Either<String, JsonObject>>() { public void handle(Either<String, JsonObject> event) { if (event.isLeft()) return; final JsonObject post = event.right().getValue(); findRecipiants("posts", query, keys, fetch, "org-entcore-blog-controllers-PostController|publish", user, new Handler<Map<String, Object>>() { @Override public void handle(Map<String, Object> event) { List<String> recipients = new ArrayList<>(); if (event != null) recipients = (List<String>) event .get("recipients"); recipients.add(authorId); JsonObject p = new JsonObject() .put("uri", "/userbook/annuaire#" + user.getUserId() + "#" + user.getType()) .put("username", user.getUsername()) .put("blogTitle", post.getJsonObject("blog", new JsonObject()) .getString("title")) .put("blogUri", resourceUri) .put("postTitle", post.getString("title")) .put("postUri", resourceUri + "/" + postId) .put("resourceUri", resourceUri + "/" + postId) .put("disableAntiFlood", true); notification.notifyTimeline(request, "blog.submit-post", user, recipients, blogId, postId, p); } }); } })); } } }); } } @Override public void notifyPublishPost(final HttpServerRequest request, final String blogId, final String postId, final UserInfos user, final String resourceUri) { if (resourceUri != null && user != null && blogId != null && request != null) { QueryBuilder query = QueryBuilder.start("_id").is(postId); JsonObject keys = new JsonObject().put("title", 1).put("blog", 1).put("content", 1); JsonArray fetch = new JsonArray().add("blog"); findRecipiants("posts", query, keys, fetch, user, new Handler<Map<String, Object>>() { @Override public void handle(Map<String, Object> event) { if (event != null) { List<String> recipients = (List<String>) event.get("recipients"); JsonObject blog = (JsonObject) event.get("blog"); if (recipients != null) { JsonObject p = new JsonObject() .put("uri", "/userbook/annuaire#" + user.getUserId() + "#" + user.getType()) .put("username", user.getUsername()) .put("blogTitle", blog.getJsonObject("blog", new JsonObject()).getString("title")) .put("blogUri", resourceUri).put("postTitle", blog.getString("title")) .put("postUri", resourceUri + "/" + postId) .put("resourceUri", resourceUri + "/" + postId).put("pushNotif", new JsonObject().put("title", "push.notif.blog.published.post").put( "body", user.getUsername() + " : " + blog.getJsonObject("blog", new JsonObject()) .getString("title"))); notification.notifyTimeline(request, "blog.publish-post", user, recipients, blogId, postId, p, true, NotificationUtils.htmlContentToPreview(blog.getString("content"))); } } } }); } } @Override public void notifyPublishComment(final HttpServerRequest request, final String blogId, final String postId, final UserInfos user, final String resourceUri) { if (resourceUri != null && user != null && blogId != null && request != null) { QueryBuilder query = QueryBuilder.start("_id").is(postId); JsonObject keys = new JsonObject().put("title", 1).put("blog", 1); JsonArray fetch = new JsonArray().add("blog"); findRecipiants("posts", query, keys, fetch, user, new Handler<Map<String, Object>>() { @Override public void handle(Map<String, Object> event) { if (event != null) { List<String> recipients = (List<String>) event.get("recipients"); JsonObject blog = (JsonObject) event.get("blog"); String ownerId = blog.getJsonObject("blog", new JsonObject()) .getJsonObject("author", new JsonObject()).getString("userId"); if (ownerId != null && !ownerId.equals(user.getUserId())) { if (recipients == null) { recipients = new ArrayList<String>(); } recipients.add(ownerId); } if (recipients != null) { JsonObject p = new JsonObject() .put("uri", "/userbook/annuaire#" + user.getUserId() + "#" + user.getType()) .put("username", user.getUsername()) .put("blogTitle", blog.getJsonObject("blog", new JsonObject()).getString("title")) .put("blogUri", resourceUri).put("postTitle", blog.getString("title")) .put("postUri", resourceUri + "/" + postId) .put("resourceUri", resourceUri + "/" + postId).put("disableAntiFlood", true); notification.notifyTimeline(request, "blog.publish-comment", user, recipients, blogId, postId, p); } } } }); } } private void findRecipiants(String collection, QueryBuilder query, JsonObject keys, final JsonArray fetch, final UserInfos user, final Handler<Map<String, Object>> handler) { findRecipiants(collection, query, keys, fetch, null, user, handler); } private void findRecipiants(String collection, QueryBuilder query, JsonObject keys, final JsonArray fetch, final String filterRights, final UserInfos user, final Handler<Map<String, Object>> handler) { mongo.findOne(collection, MongoQueryBuilder.build(query), keys, fetch, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> event) { if ("ok".equals(event.body().getString("status"))) { final JsonObject blog = event.body().getJsonObject("result", new JsonObject()); JsonArray shared; if (fetch == null) { shared = blog.getJsonArray("shared"); } else { shared = blog.getJsonObject("blog", new JsonObject()).getJsonArray("shared"); } if (shared != null) { shared.add(blog.getJsonObject("blog", new JsonObject()).getJsonObject("author")); //Allows owner to get notified for contributors posts List<String> shareIds = getSharedIds(shared, filterRights); if (!shareIds.isEmpty()) { Map<String, Object> params = new HashMap<>(); params.put("userId", user.getUserId()); neo.send(neoQuery(shareIds), params, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> res) { if ("ok".equals(res.body().getString("status"))) { JsonObject r = res.body().getJsonObject("result"); List<String> recipients = new ArrayList<>(); for (String attr : r.fieldNames()) { String id = r.getJsonObject(attr).getString("id"); if (id != null) { recipients.add(id); } } Map<String, Object> t = new HashMap<>(); t.put("recipients", recipients); t.put("blog", blog); handler.handle(t); } else { handler.handle(null); } } }); } else { handler.handle(null); } } else { handler.handle(null); } } else { handler.handle(null); } } }); } private List<String> getSharedIds(JsonArray shared) { return getSharedIds(shared, null); } private List<String> getSharedIds(JsonArray shared, String filterRights) { List<String> shareIds = new ArrayList<>(); for (Object o : shared) { if (!(o instanceof JsonObject)) continue; JsonObject userShared = (JsonObject) o; if (filterRights != null && !userShared.getBoolean(filterRights, false)) continue; String userOrGroupId = userShared.getString("groupId", userShared.getString("userId")); if (userOrGroupId != null && !userOrGroupId.trim().isEmpty()) { shareIds.add(userOrGroupId); } } return shareIds; } private String neoQuery(List<String> shareIds) { return "MATCH (u:User) " + "WHERE u.id IN ['" + Joiner.on("','").join(shareIds) + "'] AND u.id <> {userId} " + "RETURN distinct u.id as id " + "UNION " + "MATCH (n:Group)<-[:IN]-(u:User) " + "WHERE n.id IN ['" + Joiner.on("','").join(shareIds) + "'] AND u.id <> {userId} " + "RETURN distinct u.id as id "; } }