From caa6bdaf7f913b5c5bc8bcd99bd892097bec3dc8 Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Fri, 6 Jan 2017 18:17:33 +0100
Subject: [PATCH] - Market/Registry: Add notification when replying to a
 comment

---
 .../src/test/es-home/config/elasticsearch.yml |   4 +-
 .../service/AbstractService.java              |   4 +
 .../model/event/GchangeEventCodes.java        |   4 +-
 .../service/CommentUserEventService.java      | 129 +++++++++++-------
 4 files changed, 90 insertions(+), 51 deletions(-)

diff --git a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
index 57a0be9d..8e0079e2 100644
--- a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
+++ b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
@@ -53,7 +53,7 @@ cluster.name: duniter4j-elasticsearch-TEST
 #
 # Set the bind address to a specific IP (IPv4 or IPv6):
 #
-#network.host: 192.168.233.118
+#network.host: 192.168.0.28
 #
 # Set a custom port for HTTP:
 #
@@ -140,8 +140,8 @@ duniter.keyring.password: def
 
 # Enable security, to disable HTTP access to the default ES admin API
 #
-duniter.security.enable: true
 #duniter.security.enable: false
+duniter.security.enable: false
 #
 # Security token prefix (default: 'duniter-')
 #
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
index fc0fdef1..487f18ca 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
@@ -369,6 +369,10 @@ public abstract class AbstractService implements Bean {
         return result.get(fieldName);
     }
 
+    protected <T> T getTypedFieldById(String index, String type, String docId, String fieldName) {
+        return (T)getFieldById(index, type, docId, fieldName);
+    }
+
     /**
      * Retrieve a document by id (safe mode)
      * @param docId
diff --git a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/model/event/GchangeEventCodes.java b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/model/event/GchangeEventCodes.java
index 2cdf6e3a..445cdae0 100644
--- a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/model/event/GchangeEventCodes.java
+++ b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/model/event/GchangeEventCodes.java
@@ -6,5 +6,7 @@ package org.duniter.elasticsearch.gchange.model.event;
 public enum GchangeEventCodes {
 
     NEW_COMMENT,
-    UPDATE_COMMENT
+    UPDATE_COMMENT,
+    NEW_REPLY_COMMENT,
+    UPDATE_REPLY_COMMENT,
 }
diff --git a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/CommentUserEventService.java b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/CommentUserEventService.java
index 3798b991..72059722 100644
--- a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/CommentUserEventService.java
+++ b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/CommentUserEventService.java
@@ -31,6 +31,7 @@ import org.duniter.core.client.model.bma.jackson.JacksonUtils;
 import org.duniter.core.client.model.elasticsearch.RecordComment;
 import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
+import org.duniter.core.util.StringUtils;
 import org.duniter.core.util.websocket.WebsocketClientEndpoint;
 import org.duniter.elasticsearch.PluginSettings;
 import org.duniter.elasticsearch.gchange.model.market.MarketRecord;
@@ -60,10 +61,14 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
         I18n.n("duniter.market.error.comment.recordNotFound");
         I18n.n("duniter.market.event.newComment");
         I18n.n("duniter.market.event.updateComment");
+        I18n.n("duniter.market.event.newReplyComment");
+        I18n.n("duniter.market.event.updateReplyComment");
 
         I18n.n("duniter.registry.error.comment.recordNotFound");
         I18n.n("duniter.registry.event.newComment");
         I18n.n("duniter.registry.event.updateComment");
+        I18n.n("duniter.registry.event.newReplyComment");
+        I18n.n("duniter.registry.event.updateReplyComment");
     }
 
     public final UserService userService;
@@ -76,6 +81,8 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
 
     public final boolean enable;
 
+    public final String recordType;
+
     @Inject
     public CommentUserEventService(Client client, PluginSettings settings, CryptoService cryptoService,
                                    BlockchainService blockchainService,
@@ -87,11 +94,13 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
         this.objectMapper = JacksonUtils.newObjectMapper();
         this.changeListenSources = ImmutableList.of(
                 new ChangeSource(MarketService.INDEX, MarketService.RECORD_COMMENT_TYPE),
-                new ChangeSource(RegistryService.INDEX, MarketService.RECORD_COMMENT_TYPE));
+                new ChangeSource(RegistryService.INDEX, RegistryService.RECORD_COMMENT_TYPE));
         ChangeService.registerListener(this);
 
         this.enable = pluginSettings.enableBlockchainSync();
 
+        this.recordType = MarketService.RECORD_TYPE; // same as RegistryService.RECORD_TYPE
+
         if (this.enable) {
             blockchainService.registerConnectionListener(createConnectionListeners());
         }
@@ -107,19 +116,17 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
 
 
         try {
-
-
             switch (change.getOperation()) {
                 case CREATE:
                     if (change.getSource() != null) {
                         RecordComment comment = objectMapper.readValue(change.getSource().streamInput(), RecordComment.class);
-                        processCreateComment(change.getIndex(), MarketService.RECORD_TYPE, change.getId(), comment);
+                        processCreateComment(change.getIndex(), change.getType(), change.getId(), comment);
                     }
                     break;
                 case INDEX:
                     if (change.getSource() != null) {
                         RecordComment comment = objectMapper.readValue(change.getSource().streamInput(), RecordComment.class);
-                        processUpdateComment(change.getIndex(), MarketService.RECORD_TYPE, change.getId(), comment);
+                        processUpdateComment(change.getIndex(), change.getType(), change.getId(), comment);
                     }
                     break;
 
@@ -185,71 +192,73 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
         };
     }
 
-    private void processCreateComment(String index, String recordType, String commentId, RecordComment comment) {
-
-        String issuer = comment.getIssuer();
-        String recordId = comment.getRecord();
+    /**
+     * Send notification from a new comment
+     *
+     * @param index
+     * @param type
+     * @param commentId
+     * @param comment
+     */
+    private void processCreateComment(String index, String type, String commentId, RecordComment comment) {
 
-        // Notify issuer of record (is not same as comment writer)
-        Map<String, Object> recordFields = getFieldsById(index, recordType, recordId,
-                MarketRecord.PROPERTY_TITLE, MarketRecord.PROPERTY_ISSUER);
-        if (MapUtils.isEmpty(recordFields)) { // record not found
-            logger.warn(I18n.t(String.format("duniter.%s.error.comment.recordNotFound", index.toLowerCase()), recordId));
-        }
-        String recordIssuer = recordFields.get(MarketRecord.PROPERTY_ISSUER).toString();
+        processUpdateOrCreateComment(index, type, commentId, comment,
+                GchangeEventCodes.NEW_COMMENT,  String.format("duniter.%s.event.newComment", index.toLowerCase()),
+                GchangeEventCodes.NEW_REPLY_COMMENT,  String.format("duniter.%s.event.newReplyComment", index.toLowerCase()));
+    }
 
-        // Get user title
-        String issuerTitle = userService.getProfileTitle(issuer);
+    /**
+     * Same as processCreateComment(), but with other code and message.
+     *
+     * @param index
+     * @param type
+     * @param commentId
+     * @param comment
+     */
+    private void processUpdateComment(String index, String type, String commentId, RecordComment comment) {
 
-        String recordTitle = recordFields.get(MarketRecord.PROPERTY_TITLE).toString();
-        if (!issuer.equals(recordIssuer)) {
-            userEventService.notifyUser(
-                    UserEvent.newBuilder(UserEvent.EventType.INFO, GchangeEventCodes.NEW_COMMENT.name())
-                            .setMessage(
-                                    String.format("duniter.%s.event.newComment", index.toLowerCase()),
-                                    issuer,
-                                    issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer),
-                                    recordTitle
-                            )
-                            .setRecipient(recordIssuer)
-                            .setReference(index, recordType, recordId)
-                            .setReferenceAnchor(commentId)
-                            .setTime(comment.getTime())
-                            .build());
-        }
+        processUpdateOrCreateComment(index, type, commentId, comment,
+                GchangeEventCodes.UPDATE_COMMENT,  String.format("duniter.%s.event.updateComment", index.toLowerCase()),
+                GchangeEventCodes.UPDATE_REPLY_COMMENT,  String.format("duniter.%s.event.updateReplyComment", index.toLowerCase()));
     }
 
+
     /**
      * Same as processCreateComment(), but with other code and message.
      *
      * @param index
-     * @param recordType
+     * @param type
      * @param commentId
      * @param comment
      */
-    private void processUpdateComment(String index, String recordType, String commentId, RecordComment comment) {
-
-        String issuer = comment.getIssuer();
+    private void processUpdateOrCreateComment(String index, String type, String commentId, RecordComment comment,
+                                              GchangeEventCodes eventCodeForRecordIssuer, String messageKeyForRecordIssuer,
+                                              GchangeEventCodes eventCodeForParentCommentIssuer, String messageKeyForParentCommentIssuer) {
+        // Get record issuer
         String recordId = comment.getRecord();
-
-        // Notify issuer of record (is not same as comment writer)
-        Map<String, Object> recordFields = getFieldsById(index, recordType, recordId,
+        Map<String, Object> record = getFieldsById(index, this.recordType, recordId,
                 MarketRecord.PROPERTY_TITLE, MarketRecord.PROPERTY_ISSUER);
-        if (MapUtils.isEmpty(recordFields)) { // record not found
+
+        // Record not found : nothing to emit
+        if (MapUtils.isEmpty(record)) {
             logger.warn(I18n.t(String.format("duniter.%s.error.comment.recordNotFound", index.toLowerCase()), recordId));
-            return; // no event to emit
+            return;
         }
-        String recordIssuer = recordFields.get(MarketRecord.PROPERTY_ISSUER).toString();
 
-        // Get user title
+        // Fetch record info
+        String recordIssuer = record.get(MarketRecord.PROPERTY_ISSUER).toString();
+        String recordTitle = record.get(MarketRecord.PROPERTY_TITLE).toString();
+
+        // Get comment issuer title
+        String issuer = comment.getIssuer();
         String issuerTitle = userService.getProfileTitle(issuer);
 
-        String recordTitle = recordFields.get(MarketRecord.PROPERTY_TITLE).toString();
+        // Notify issuer of record (is not same as comment writer)
         if (!issuer.equals(recordIssuer)) {
             userEventService.notifyUser(
-                    UserEvent.newBuilder(UserEvent.EventType.INFO, GchangeEventCodes.UPDATE_COMMENT.name())
+                    UserEvent.newBuilder(UserEvent.EventType.INFO, eventCodeForRecordIssuer.name())
                             .setMessage(
-                                    String.format("duniter.%s.event.updateComment", index.toLowerCase()),
+                                    messageKeyForRecordIssuer,
                                     issuer,
                                     issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer),
                                     recordTitle
@@ -261,6 +270,30 @@ public class CommentUserEventService extends AbstractService implements ChangeSe
                             .build());
         }
 
+        // Notify comment is a reply to another comment
+        if (StringUtils.isNotBlank(comment.getReplyTo())) {
+
+            String parentCommentIssuer = getTypedFieldById(index, type, commentId, RecordComment.PROPERTY_ISSUER);
+
+            if (StringUtils.isNotBlank(parentCommentIssuer) &&
+                    !issuer.equals(parentCommentIssuer) &&
+                    !recordIssuer.equals(parentCommentIssuer)) {
+
+                userEventService.notifyUser(
+                        UserEvent.newBuilder(UserEvent.EventType.INFO, eventCodeForParentCommentIssuer.name())
+                                .setMessage(
+                                        messageKeyForParentCommentIssuer,
+                                        issuer,
+                                        issuerTitle != null ? issuerTitle : ModelUtils.minifyPubkey(issuer),
+                                        recordTitle
+                                )
+                                .setRecipient(parentCommentIssuer)
+                                .setReference(index, recordType, recordId)
+                                .setReferenceAnchor(commentId)
+                                .setTime(comment.getTime())
+                                .build());
+            }
+        }
 
     }
 
-- 
GitLab