From 519276d9a927c0eb47ab9bb8a3b3a29a8cae6729 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20K=C3=A4stle?= <sven.kaestle@gmx.de>
Date: Wed, 18 Jul 2018 16:56:48 +0200
Subject: [PATCH] feat: Implement first simple WebSocket, so far no connection

---
 gemeinsamforschen/pom.xml                     | 14 ++++
 .../annotation/model/AnnotationMessage.java   | 47 ++++++++++++++
 .../websocket/AnnotationMessageDecoder.java   | 34 ++++++++++
 .../websocket/AnnotationMessageEncoder.java   | 29 +++++++++
 .../AnnotationWebSocketEndpoint.java          | 64 +++++++++++++++++++
 .../main/webapp/assets/js/annotationScript.js |  2 +
 .../webapp/assets/js/annotationWebsocket.js   | 22 +++++++
 .../main/webapp/pages/annotation-document.jsp |  2 +
 8 files changed, 214 insertions(+)
 create mode 100644 gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java
 create mode 100644 gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java
 create mode 100644 gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java
 create mode 100644 gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java
 create mode 100644 gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js

diff --git a/gemeinsamforschen/pom.xml b/gemeinsamforschen/pom.xml
index 52c20b79..28935787 100644
--- a/gemeinsamforschen/pom.xml
+++ b/gemeinsamforschen/pom.xml
@@ -165,6 +165,20 @@
             <version>1.3.4</version>
         </dependency>
 
+        <!-- websocket api -->
+        <dependency>
+            <groupId>javax.websocket</groupId>
+            <artifactId>javax.websocket-api</artifactId>
+            <version>1.1</version>
+        </dependency>
+
+        <!-- gson -->
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.5</version>
+        </dependency>
+
         <dependency>
             <groupId>com.atlassian.commonmark</groupId>
             <artifactId>commonmark</artifactId>
diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java
new file mode 100644
index 00000000..318aceb2
--- /dev/null
+++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/model/AnnotationMessage.java
@@ -0,0 +1,47 @@
+package unipotsdam.gf.modules.annotation.model;
+
+public class AnnotationMessage {
+    // variables
+    private String from;
+    private AnnotationMessageType type;
+    private String annotationId;
+
+    public enum AnnotationMessageType {
+        GET,
+        DELETE
+    }
+
+    // methods
+    public String getFrom() {
+        return from;
+    }
+
+    public void setFrom(String from) {
+        this.from = from;
+    }
+
+    public AnnotationMessageType getType() {
+        return type;
+    }
+
+    public void setType(AnnotationMessageType type) {
+        this.type = type;
+    }
+
+    public String getAnnotationId() {
+        return annotationId;
+    }
+
+    public void setAnnotationId(String annotationId) {
+        this.annotationId = annotationId;
+    }
+
+    @Override
+    public String toString() {
+        return "AnnotationMessage{" +
+                "from='" + from + '\'' +
+                ", type=" + type +
+                ", annotationId='" + annotationId + '\'' +
+                '}';
+    }
+}
diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java
new file mode 100644
index 00000000..e4b2d832
--- /dev/null
+++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageDecoder.java
@@ -0,0 +1,34 @@
+package unipotsdam.gf.modules.annotation.websocket;
+
+import com.google.gson.Gson;
+import unipotsdam.gf.modules.annotation.model.AnnotationMessage;
+
+import javax.websocket.DecodeException;
+import javax.websocket.Decoder;
+import javax.websocket.EndpointConfig;
+
+public class AnnotationMessageDecoder implements Decoder.Text<AnnotationMessage> {
+
+    public static Gson gson = new Gson();
+
+    @Override
+    public AnnotationMessage decode(String s) throws DecodeException {
+        AnnotationMessage annotationMessage = gson.fromJson(s, AnnotationMessage.class);
+        return annotationMessage;
+    }
+
+    @Override
+    public boolean willDecode(String s) {
+        return (null != s);
+    }
+
+    @Override
+    public void init(EndpointConfig endpointConfig) {
+        // todo
+    }
+
+    @Override
+    public void destroy() {
+        // todo
+    }
+}
diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java
new file mode 100644
index 00000000..16105582
--- /dev/null
+++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationMessageEncoder.java
@@ -0,0 +1,29 @@
+package unipotsdam.gf.modules.annotation.websocket;
+
+import com.google.gson.Gson;
+import unipotsdam.gf.modules.annotation.model.AnnotationMessage;
+
+import javax.websocket.EncodeException;
+import javax.websocket.Encoder;
+import javax.websocket.EndpointConfig;
+
+public class AnnotationMessageEncoder implements Encoder.Text<AnnotationMessage> {
+
+    private static Gson gson = new Gson();
+
+    @Override
+    public String encode(AnnotationMessage annotationMessage) throws EncodeException {
+        String json = gson.toJson(annotationMessage);
+        return json;
+    }
+
+    @Override
+    public void init(EndpointConfig endpointConfig) {
+        // todo
+    }
+
+    @Override
+    public void destroy() {
+        // todo
+    }
+}
diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java
new file mode 100644
index 00000000..c3633979
--- /dev/null
+++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/annotation/websocket/AnnotationWebSocketEndpoint.java
@@ -0,0 +1,64 @@
+package unipotsdam.gf.modules.annotation.websocket;
+
+import unipotsdam.gf.modules.annotation.model.AnnotationMessage;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+@ServerEndpoint(value = "/ws/annotation/{targetId}", decoders = AnnotationMessageDecoder.class, encoders = AnnotationMessageEncoder.class)
+public class AnnotationWebSocketEndpoint {
+
+    private Session session;
+    private static final Set<AnnotationWebSocketEndpoint> endpoints = new CopyOnWriteArraySet<>();
+    private static HashMap<String, String> targets = new HashMap<>();
+
+    @OnOpen
+    public void onOpen(Session session, @PathParam("targetId") String targetId) throws IOException {
+        // initialize session
+        this.session = session;
+        // save endpoint in set of endpoints
+        endpoints.add(this);
+        // save mapping of session and target id
+        targets.put(session.getId(), targetId);
+
+        System.out.println(endpoints.toString());
+    }
+
+    @OnMessage
+    public void onMessage(Session session, AnnotationMessage annotationMessage) throws IOException, EncodeException {
+        annotationMessage.setFrom(targets.get(session.getId()));
+        broadcast(annotationMessage);
+
+    }
+
+    @OnClose
+    public void onClose(Session session) throws IOException {
+        endpoints.remove(this);
+    }
+
+    @OnError
+    public void onError(Session session, Throwable throwable) {
+        // todo
+    }
+
+    private void broadcast(AnnotationMessage annotationMessage) throws IOException, EncodeException {
+        endpoints.forEach(endpoint -> {
+            synchronized (endpoint) {
+                try {
+                    if (targets.get(endpoint.session.getId()).equals(annotationMessage.getFrom())) {
+                        endpoint.session.getBasicRemote().sendObject(annotationMessage);
+                    }
+                }
+                catch (IOException | EncodeException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
+}
diff --git a/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js b/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js
index 5a18f3fd..0a4f4214 100644
--- a/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js
+++ b/gemeinsamforschen/src/main/webapp/assets/js/annotationScript.js
@@ -12,6 +12,8 @@ var documentText, startCharacter, endCharacter;
  */
 $(document).ready(function() {
 
+    connect("200");
+
     /**
      * Context menu handler
      */
diff --git a/gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js b/gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js
new file mode 100644
index 00000000..6b7410de
--- /dev/null
+++ b/gemeinsamforschen/src/main/webapp/assets/js/annotationWebsocket.js
@@ -0,0 +1,22 @@
+var ws;
+
+function connect(targetId) {
+    var host = document.location.host;
+    var pathname = document.location.pathname;
+
+    ws = new WebSocket("ws://" + host  + "/ws/annotation/" + targetId);
+
+    ws.onmessage = function (e) {
+        var message = JSON.parse(e.data);
+        console.log(message.from)
+    };
+}
+
+function send(type, annotationId) {
+    var json = JSON.stringify({
+        "type":type,
+        "annotationId":annotationId
+    })
+
+    ws.send(json);
+}
\ No newline at end of file
diff --git a/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp b/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp
index 36738f2a..4d8fc1a2 100644
--- a/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp
+++ b/gemeinsamforschen/src/main/webapp/pages/annotation-document.jsp
@@ -34,6 +34,8 @@
     <script src="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.js" type="text/javascript"></script>
     <!-- js - utility script -->
     <script src="../assets/js/utility.js"></script>
+    <!-- js - annotation websocket script -->
+    <script src="../assets/js/annotationWebsocket.js"></script>
     <!-- js - annotationScript -->
     <script src="../assets/js/annotationScript.js"></script>
 
-- 
GitLab