Java tutorial
/* * Copyright "Open Digital Education", 2016 * * This program is published by "Open Digital Education". * 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. */ package org.entcore.timeline.events; import fr.wseduc.mongodb.MongoDb; import fr.wseduc.webutils.Either; import org.entcore.common.mongodb.MongoDbResult; import org.entcore.common.user.UserInfos; import io.vertx.core.Handler; import io.vertx.core.eventbus.Message; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; import java.util.Locale; public class DefaultTimelineEventStore implements TimelineEventStore { private static final String TIMELINE_COLLECTION = "timeline"; private MongoDb mongo = MongoDb.getInstance(); private final DateFormat mongoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmX", Locale.getDefault()); @Override public void add(JsonObject event, final Handler<JsonObject> result) { JsonObject doc = validAndGet(event); if (doc != null) { if (!doc.containsKey("date")) { doc.put("date", MongoDb.now()); } doc.put("created", doc.getJsonObject("date")); mongo.save(TIMELINE_COLLECTION, doc, resultHandler(result)); } else { result.handle(invalidArguments()); } } @Override public void delete(String resource, Handler<JsonObject> result) { if (resource != null && !resource.trim().isEmpty()) { JsonObject query = new JsonObject().put("resource", resource); mongo.delete(TIMELINE_COLLECTION, query, resultHandler(result)); } else { result.handle(invalidArguments()); } } @Override public void get(final UserInfos user, List<String> types, int offset, int limit, JsonObject restrictionFilter, boolean mine, final Handler<JsonObject> result) { final String recipient = user.getUserId(); final String externalId = user.getExternalId(); if (recipient != null && !recipient.trim().isEmpty()) { final JsonObject query = new JsonObject().put("deleted", new JsonObject().put("$exists", false)) .put("date", new JsonObject().put("$lt", MongoDb.now())); if (externalId == null || externalId.trim().isEmpty()) { query.put(mine ? "sender" : "recipients.userId", recipient); } else { query.put(mine ? "sender" : "recipients.userId", new JsonObject().put("$in", new fr.wseduc.webutils.collections.JsonArray().add(recipient).add(externalId))); } query.put("reportAction.action", new JsonObject().put("$ne", "DELETE")); if (types != null && !types.isEmpty()) { if (types.size() == 1) { query.put("type", types.get(0)); } else { JsonArray typesFilter = new fr.wseduc.webutils.collections.JsonArray(); for (String t : types) { typesFilter.add(new JsonObject().put("type", t)); } query.put("$or", typesFilter); } } if (restrictionFilter != null && restrictionFilter.size() > 0) { JsonArray nor = new fr.wseduc.webutils.collections.JsonArray(); for (String type : restrictionFilter.getMap().keySet()) { for (Object eventType : restrictionFilter.getJsonArray(type, new fr.wseduc.webutils.collections.JsonArray())) { nor.add(new JsonObject().put("type", type).put("event-type", eventType.toString())); } query.put("$nor", nor); } } JsonObject sort = new JsonObject().put("created", -1); JsonObject keys = new JsonObject().put("message", 1).put("params", 1).put("date", 1).put("sender", 1) .put("comments", 1).put("type", 1).put("event-type", 1).put("resource", 1) .put("sub-resource", 1).put("add-comment", 1); if (!mine) { keys.put("recipients", new JsonObject().put("$elemMatch", new JsonObject().put("userId", user.getUserId()))); keys.put("reporters", new JsonObject().put("$elemMatch", new JsonObject().put("userId", user.getUserId()))); } mongo.find(TIMELINE_COLLECTION, query, sort, keys, offset, limit, 100, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { result.handle(message.body()); } }); } else { result.handle(invalidArguments()); } } @Override public void deleteSubResource(String resource, Handler<JsonObject> result) { if (resource != null && !resource.trim().isEmpty()) { JsonObject query = new JsonObject().put("sub-resource", resource); mongo.delete(TIMELINE_COLLECTION, query, resultHandler(result)); } else { result.handle(invalidArguments()); } } @Override public void listTypes(final Handler<JsonArray> result) { mongo.distinct(TIMELINE_COLLECTION, "type", new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> event) { if ("ok".equals(event.body().getString("status"))) { result.handle( event.body().getJsonArray("values", new fr.wseduc.webutils.collections.JsonArray())); } else { result.handle(new fr.wseduc.webutils.collections.JsonArray()); } } }); } private JsonObject validAndGet(JsonObject json) { if (json != null) { JsonObject e = json.copy(); for (String attr : json.fieldNames()) { if (!FIELDS.contains(attr) || e.getValue(attr) == null) { e.remove(attr); } } if (e.getMap().keySet().containsAll(REQUIRED_FIELDS)) { return e; } } return null; } private JsonObject invalidArguments() { return new JsonObject().put("status", "error").put("message", "Invalid arguments."); } private Handler<Message<JsonObject>> resultHandler(final Handler<JsonObject> result) { return new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { result.handle(message.body()); } }; } private void markEventsAsRead(Message<JsonObject> message, String recipient) { JsonArray events = message.body().getJsonArray("results"); if (events != null && "ok".equals(message.body().getString("status"))) { JsonArray ids = new fr.wseduc.webutils.collections.JsonArray(); for (Object o : events) { if (!(o instanceof JsonObject)) continue; JsonObject json = (JsonObject) o; ids.add(json.getString("_id")); } JsonObject q = new JsonObject().put("_id", new JsonObject().put("$in", ids)).put("recipients", new JsonObject().put("$elemMatch", new JsonObject().put("userId", recipient).put("unread", 1))); mongo.update(TIMELINE_COLLECTION, q, new JsonObject().put("$set", new JsonObject().put("recipients.$.unread", 0)), false, true); } } @Override public void delete(String id, String sender, Handler<Either<String, JsonObject>> result) { JsonObject matcher = new JsonObject().put("_id", id).put("sender", sender); JsonObject objNew = new JsonObject().put("$set", new JsonObject() .put("recipients", new fr.wseduc.webutils.collections.JsonArray()).put("deleted", 1)); mongo.update(TIMELINE_COLLECTION, matcher, objNew, MongoDbResult.validActionResultHandler(result)); } @Override public void discard(String id, String recipient, Handler<Either<String, JsonObject>> result) { JsonObject criteria = new JsonObject().put("_id", id); JsonObject objNew = new JsonObject().put("$pull", new JsonObject().put("recipients", new JsonObject().put("userId", recipient))); mongo.update(TIMELINE_COLLECTION, criteria, objNew, MongoDbResult.validActionResultHandler(result)); } @Override public void report(String id, UserInfos user, Handler<Either<String, JsonObject>> result) { String now = mongoFormat.format(Calendar.getInstance().getTime()); JsonObject criteria = new JsonObject().put("_id", id).put("reporters.userId", new JsonObject().put("$ne", user.getUserId())); JsonObject objNew = new JsonObject().put("$addToSet", new JsonObject() .put("reportedStructures", new JsonObject().put("$each", new fr.wseduc.webutils.collections.JsonArray(user.getStructures()))) .put("reporters", new JsonObject().put("userId", user.getUserId()) .put("firstName", user.getFirstName()).put("lastName", user.getLastName()) .put("date", now))); mongo.update(TIMELINE_COLLECTION, criteria, objNew, MongoDbResult.validActionResultHandler(result)); } @Override public void listReported(String structure, boolean pending, int offset, int limit, Handler<Either<String, JsonArray>> result) { JsonObject matcher = new JsonObject().put("reportedStructures", structure); JsonObject sort = new JsonObject(); JsonObject keys = new JsonObject().put("recipients", 0); if (pending) { matcher.put("reportAction", new JsonObject().put("$exists", false)); sort.put("reporters.date", -1); } else { matcher.put("reportAction", new JsonObject().put("$exists", true)); sort.put("reportAction.date", -1); } mongo.find(TIMELINE_COLLECTION, matcher, sort, keys, offset, limit, 100, MongoDbResult.validResultsHandler(result)); } @Override public void performAdminAction(String id, String structureId, UserInfos user, AdminAction action, Handler<Either<String, JsonObject>> result) { String now = mongoFormat.format(Calendar.getInstance().getTime()); JsonObject criteria = new JsonObject().put("_id", id).put("reportedStructures", structureId) .put("reportAction", new JsonObject().put("$ne", AdminAction.DELETE.name())); JsonObject objSet = new JsonObject().put("reportAction", new JsonObject().put("action", action.name()).put("userId", user.getUserId()) .put("firstName", user.getFirstName()).put("lastName", user.getLastName()) .put("date", now)); JsonObject objNew = new JsonObject().put("$set", objSet); if (action == AdminAction.DELETE) { objSet.put("recipients", new fr.wseduc.webutils.collections.JsonArray()); } mongo.update(TIMELINE_COLLECTION, criteria, objNew, MongoDbResult.validActionResultHandler(result)); } @Override public void deleteReportNotification(String resourceId, Handler<Either<String, JsonObject>> result) { JsonObject matcher = new JsonObject().put("type", "TIMELINE").put("event-type", "NOTIFY-REPORT") .put("resource", resourceId); mongo.delete(TIMELINE_COLLECTION, matcher, MongoDbResult.validActionResultHandler(result)); } }