Java tutorial
/* * Copyright Rgion Nord Pas de Calais-Picardie, Dpartement 91, Rgion Aquitaine-Limousin-Poitou-Charentes, 2016. * * This file is part of OPEN ENT NG. OPEN ENT NG is a versatile ENT Project based on the JVM and ENT Core Project. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation (version 3 of the License). * * For the sake of explanation, any module that communicate over native * Web protocols, such as HTTP, with OPEN ENT NG is outside the scope of this * license and could be license under its own terms. This is merely considered * normal use of OPEN ENT NG, and does not fall under the heading of "covered work". * * 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 net.atos.entng.forum.services.impl; import static org.entcore.common.mongodb.MongoDbResult.validActionResultHandler; import static org.entcore.common.mongodb.MongoDbResult.validResultHandler; import java.util.ArrayList; import java.util.List; import net.atos.entng.forum.services.MessageService; import org.bson.types.ObjectId; import org.entcore.common.service.VisibilityFilter; import org.entcore.common.user.UserInfos; import org.entcore.common.utils.StringUtils; import org.vertx.java.core.Handler; import org.vertx.java.core.eventbus.Message; import org.vertx.java.core.json.JsonArray; import org.vertx.java.core.json.JsonObject; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.QueryBuilder; import fr.wseduc.mongodb.MongoDb; import fr.wseduc.mongodb.MongoQueryBuilder; import fr.wseduc.mongodb.MongoUpdateBuilder; import fr.wseduc.webutils.Either; public class MongoDbMessageService extends AbstractService implements MessageService { public MongoDbMessageService(final String categories_collection, final String subjects_collection) { super(categories_collection, subjects_collection); } @Override public void list(final String categoryId, final String subjectId, final UserInfos user, final Handler<Either<String, JsonArray>> handler) { // Prepare Query QueryBuilder query = QueryBuilder.start("_id").is(subjectId).put("category").is(categoryId); // Projection JsonObject projection = new JsonObject(); projection.putNumber("messages", 1); mongo.findOne(subjects_collection, MongoQueryBuilder.build(query), projection, validResultHandler(new Handler<Either<String, JsonObject>>() { @Override public void handle(Either<String, JsonObject> event) { if (event.isRight()) { try { // Extract messages JsonObject subject = event.right().getValue(); if (subject.containsField("messages")) { handler.handle( new Either.Right<String, JsonArray>(subject.getArray("messages"))); } else { handler.handle(new Either.Right<String, JsonArray>(new JsonArray())); } } catch (Exception e) { handler.handle(new Either.Left<String, JsonArray>( "Malformed response : " + e.getClass().getName() + " : " + e.getMessage())); } } else { handler.handle(new Either.Left<String, JsonArray>(event.left().getValue())); } } })); } @Override public void create(final String categoryId, final String subjectId, final JsonObject body, final UserInfos user, final Handler<Either<String, JsonObject>> handler) { // Prepare Message object final ObjectId newId = new ObjectId(); JsonObject now = MongoDb.now(); body.putString("_id", newId.toStringMongod()) .putObject("owner", new JsonObject().putString("userId", user.getUserId()).putString("displayName", user.getUsername())) .putString("contentPlain", StringUtils.stripHtmlTag(body.getString("content", ""))) .putObject("created", now).putObject("modified", now); // Prepare Query QueryBuilder query = QueryBuilder.start("_id").is(subjectId); query.put("category").is(categoryId); MongoUpdateBuilder modifier = new MongoUpdateBuilder(); modifier.push("messages", body); modifier.inc("nbMessages", 1); modifier.set("modified", MongoDb.now()); // Execute query mongo.update(subjects_collection, MongoQueryBuilder.build(query), modifier.build(), validActionResultHandler(new Handler<Either<String, JsonObject>>() { @Override public void handle(Either<String, JsonObject> event) { if (event.isRight()) { try { if (event.right().getValue().getNumber("number").intValue() == 1) { // Respond with created message Id JsonObject created = new JsonObject(); created.putString("_id", newId.toStringMongod()); handler.handle(new Either.Right<String, JsonObject>(created)); } else { handler.handle(new Either.Left<String, JsonObject>("Subject not found")); } } catch (Exception e) { handler.handle(new Either.Left<String, JsonObject>( "Malformed response : " + e.getClass().getName() + " : " + e.getMessage())); } } else { handler.handle(event); } } })); } @Override public void retrieve(final String categoryId, final String subjectId, final String messageId, final UserInfos user, final Handler<Either<String, JsonObject>> handler) { // Prepare Query QueryBuilder query = QueryBuilder.start("_id").is(subjectId).put("category").is(categoryId).put("messages") .elemMatch(new BasicDBObject("_id", messageId)); // Projection JsonObject idMatch = new JsonObject(); idMatch.putString("_id", messageId); JsonObject elemMatch = new JsonObject(); elemMatch.putObject("$elemMatch", idMatch); JsonObject projection = new JsonObject(); projection.putObject("messages", elemMatch); mongo.findOne(subjects_collection, MongoQueryBuilder.build(query), projection, validResultHandler(new Handler<Either<String, JsonObject>>() { @Override public void handle(Either<String, JsonObject> event) { if (event.isRight()) { try { // Extract message JsonObject subject = event.right().getValue(); if (subject.containsField("messages")) { JsonArray messages = subject.getArray("messages"); JsonObject extractedMessage = messages.get(0); handler.handle(new Either.Right<String, JsonObject>(extractedMessage)); } else { handler.handle(new Either.Right<String, JsonObject>(null)); } } catch (Exception e) { handler.handle(new Either.Left<String, JsonObject>( "Malformed response : " + e.getClass().getName() + " : " + e.getMessage())); } } else { handler.handle(event); } } })); } @Override public void update(final String categoryId, final String subjectId, final String messageId, final JsonObject body, final UserInfos user, final Handler<Either<String, JsonObject>> handler) { // Prepare Query QueryBuilder query = QueryBuilder.start("_id").is(subjectId).put("category").is(categoryId).put("messages") .elemMatch(new BasicDBObject("_id", messageId)); MongoUpdateBuilder modifier = new MongoUpdateBuilder(); // Prepare Message object update body.removeField("_id"); body.removeField("owner"); for (String attr : body.getFieldNames()) { modifier.set("messages.$." + attr, body.getValue(attr)); } modifier.set("messages.$.modified", MongoDb.now()); modifier.set("messages.$.contentPlain", StringUtils.stripHtmlTag(body.getString("content", ""))); // Prepare Subject update modifier.set("modified", MongoDb.now()); // Execute query mongo.update(subjects_collection, MongoQueryBuilder.build(query), modifier.build(), validActionResultHandler(handler)); } @Override public void delete(final String categoryId, final String subjectId, final String messageId, final UserInfos user, final Handler<Either<String, JsonObject>> handler) { // Prepare Query QueryBuilder query = QueryBuilder.start("_id").is(subjectId).put("category").is(categoryId).put("messages") .elemMatch(new BasicDBObject("_id", messageId)); MongoUpdateBuilder modifier = new MongoUpdateBuilder(); // Prepare Message delete JsonObject messageMatcher = new JsonObject(); modifier.pull("messages", messageMatcher.putString("_id", messageId)); modifier.inc("nbMessages", -1); modifier.set("modified", MongoDb.now()); // Execute query mongo.update(subjects_collection, MongoQueryBuilder.build(query), modifier.build(), validActionResultHandler(handler)); } @Override public void checkIsSharedOrMine(final String categoryId, final String subjectId, final String messageId, final UserInfos user, final String sharedMethod, final Handler<Boolean> handler) { // Prepare Category Query final QueryBuilder methodSharedQuery = QueryBuilder.start(); prepareIsSharedMethodQuery(methodSharedQuery, user, categoryId, sharedMethod); // Check Category Sharing with method executeCountQuery(categories_collection, MongoQueryBuilder.build(methodSharedQuery), 1, new Handler<Boolean>() { @Override public void handle(Boolean event) { if (event) { handler.handle(true); } else { // Prepare Category Query final QueryBuilder anySharedQuery = QueryBuilder.start(); prepareIsSharedAnyQuery(anySharedQuery, user, categoryId); // Check Category Sharing with any method executeCountQuery(categories_collection, MongoQueryBuilder.build(anySharedQuery), 1, new Handler<Boolean>() { @Override public void handle(Boolean event) { if (event) { // Prepare Subject and Message query QueryBuilder query = QueryBuilder.start("_id").is(subjectId) .put("category").is(categoryId); DBObject messageMatch = new BasicDBObject(); messageMatch.put("_id", messageId); messageMatch.put("owner.userId", user.getUserId()); query.put("messages").elemMatch(messageMatch); // Check Message is mine executeCountQuery(subjects_collection, MongoQueryBuilder.build(query), 1, handler); } else { handler.handle(false); } } }); } } }); } protected void prepareIsSharedMethodQuery(final QueryBuilder query, final UserInfos user, final String threadId, final String sharedMethod) { // ThreadId query.put("_id").is(threadId); // Permissions List<DBObject> groups = new ArrayList<>(); groups.add(QueryBuilder.start("userId").is(user.getUserId()).put(sharedMethod).is(true).get()); for (String gpId : user.getProfilGroupsIds()) { groups.add(QueryBuilder.start("groupId").is(gpId).put(sharedMethod).is(true).get()); } query.or(QueryBuilder.start("owner.userId").is(user.getUserId()).get(), QueryBuilder.start("visibility").is(VisibilityFilter.PUBLIC.name()).get(), QueryBuilder.start("visibility").is(VisibilityFilter.PROTECTED.name()).get(), QueryBuilder.start("shared") .elemMatch(new QueryBuilder().or(groups.toArray(new DBObject[groups.size()])).get()).get()); } protected void prepareIsSharedAnyQuery(final QueryBuilder query, final UserInfos user, final String threadId) { // ThreadId query.put("_id").is(threadId); // Permissions List<DBObject> groups = new ArrayList<>(); groups.add(QueryBuilder.start("userId").is(user.getUserId()).get()); for (String gpId : user.getProfilGroupsIds()) { groups.add(QueryBuilder.start("groupId").is(gpId).get()); } query.or(QueryBuilder.start("owner.userId").is(user.getUserId()).get(), QueryBuilder.start("visibility").is(VisibilityFilter.PUBLIC.name()).get(), QueryBuilder.start("visibility").is(VisibilityFilter.PROTECTED.name()).get(), QueryBuilder.start("shared") .elemMatch(new QueryBuilder().or(groups.toArray(new DBObject[groups.size()])).get()).get()); } protected void executeCountQuery(final String collection, final JsonObject query, final int expectedCountResult, final Handler<Boolean> handler) { mongo.count(collection, query, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> event) { JsonObject res = event.body(); handler.handle(res != null && "ok".equals(res.getString("status")) && expectedCountResult == res.getInteger("count")); } }); } @Override public void getContributors(String categoryId, String subjectId, UserInfos user, final Handler<Either<String, JsonArray>> handler) { this.list(categoryId, subjectId, user, new Handler<Either<String, JsonArray>>() { @Override public void handle(Either<String, JsonArray> event) { JsonArray contibutorsIds = new JsonArray(); if (event.isRight()) { try { // get all messages JsonArray messages = event.right().getValue(); // at least one message posted before this one just created if (messages.size() > 1) { JsonObject message = null; // Extract owners for (int i = 0; i < messages.size(); i++) { message = messages.get(i); contibutorsIds.add(message.getObject("owner")); } handler.handle(new Either.Right<String, JsonArray>(contibutorsIds)); } else { handler.handle(new Either.Right<String, JsonArray>(new JsonArray())); } } catch (Exception e) { handler.handle(new Either.Left<String, JsonArray>( "Malformed response : " + e.getClass().getName() + " : " + e.getMessage())); } } else { handler.handle(new Either.Left<String, JsonArray>(event.left().getValue())); } } }); } }