From a17b772dc06aed72ee2ae4edcfa63af4f2fc8992 Mon Sep 17 00:00:00 2001
From: feger <marc.feger@hhu.de>
Date: Mon, 4 Mar 2019 19:45:00 +0100
Subject: [PATCH] Refactor code by abstracting specific tasks

---
 .../adoc/browser_guide.adoc                   |   0
 api/{ => browser_guide}/create_html.sh        |   0
 api/browser_guide/examplegraph.py             | 110 ++++++++++++++++++
 .../html/browser_guide.html                   |   0
 .../templates/block_admonition.html.erb       |   0
 .../templates/block_audio.html.erb            |   0
 .../templates/block_colist.html.erb           |   0
 .../templates/block_dlist.html.erb            |   0
 .../templates/block_example.html.erb          |   0
 .../templates/block_floating_title.html.erb   |   0
 .../templates/block_image.html.erb            |   0
 .../templates/block_listing.html.erb          |   0
 .../templates/block_literal.html.erb          |   0
 .../templates/block_math.html.erb             |   0
 .../templates/block_olist.html.erb            |   0
 .../templates/block_open.html.erb             |   0
 .../templates/block_page_break.html.erb       |   0
 .../templates/block_paragraph.html.erb        |   0
 .../templates/block_pass.html.erb             |   0
 .../templates/block_preamble.html.erb         |   0
 .../templates/block_quote.html.erb            |   0
 .../templates/block_ruler.html.erb            |   0
 .../templates/block_sidebar.html.erb          |   0
 .../templates/block_table.html.erb            |   0
 .../templates/block_toc.html.erb              |   0
 .../templates/block_ulist.html.erb            |   0
 .../templates/block_verse.html.erb            |   0
 .../templates/block_video.html.erb            |   0
 .../templates/document.html.erb               |   0
 .../templates/embedded.html.erb               |   0
 .../templates/inline_anchor.html.erb          |   0
 .../templates/inline_break.html.erb           |   0
 .../templates/inline_button.html.erb          |   0
 .../templates/inline_callout.html.erb         |   0
 .../templates/inline_footnote.html.erb        |   0
 .../templates/inline_image.html.erb           |   0
 .../templates/inline_indexterm.html.erb       |   0
 .../templates/inline_kbd.html.erb             |   0
 .../templates/inline_menu.html.erb            |   0
 .../templates/inline_quoted.html.erb          |   0
 .../templates/section.html.erb                |   0
 api/interface/graphql.py                      |  78 -------------
 api/server.py                                 |  48 ++++----
 api/{interface => src}/__init__.py            |   0
 44 files changed, 135 insertions(+), 101 deletions(-)
 rename api/{ => browser_guide}/adoc/browser_guide.adoc (100%)
 rename api/{ => browser_guide}/create_html.sh (100%)
 create mode 100644 api/browser_guide/examplegraph.py
 rename api/{ => browser_guide}/html/browser_guide.html (100%)
 rename api/{ => browser_guide}/templates/block_admonition.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_audio.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_colist.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_dlist.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_example.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_floating_title.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_image.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_listing.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_literal.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_math.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_olist.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_open.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_page_break.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_paragraph.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_pass.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_preamble.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_quote.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_ruler.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_sidebar.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_table.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_toc.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_ulist.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_verse.html.erb (100%)
 rename api/{ => browser_guide}/templates/block_video.html.erb (100%)
 rename api/{ => browser_guide}/templates/document.html.erb (100%)
 rename api/{ => browser_guide}/templates/embedded.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_anchor.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_break.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_button.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_callout.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_footnote.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_image.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_indexterm.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_kbd.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_menu.html.erb (100%)
 rename api/{ => browser_guide}/templates/inline_quoted.html.erb (100%)
 rename api/{ => browser_guide}/templates/section.html.erb (100%)
 delete mode 100644 api/interface/graphql.py
 rename api/{interface => src}/__init__.py (100%)

diff --git a/api/adoc/browser_guide.adoc b/api/browser_guide/adoc/browser_guide.adoc
similarity index 100%
rename from api/adoc/browser_guide.adoc
rename to api/browser_guide/adoc/browser_guide.adoc
diff --git a/api/create_html.sh b/api/browser_guide/create_html.sh
similarity index 100%
rename from api/create_html.sh
rename to api/browser_guide/create_html.sh
diff --git a/api/browser_guide/examplegraph.py b/api/browser_guide/examplegraph.py
new file mode 100644
index 0000000..480eb3a
--- /dev/null
+++ b/api/browser_guide/examplegraph.py
@@ -0,0 +1,110 @@
+import os
+from api.src.traffic.injector import Injector
+
+URL = 'jdbc:postgresql://db/discussion?user=postgres&password=FooBar'
+
+
+class ExampleGraph(Injector):
+    def __init__(self):
+        Injector.__init__(self)
+        self.url = "jdbc:postgresql://{host}/{name}?user={user}&password={pwd}".format(
+            host=os.getenv("DB_HOST"),
+            name=os.getenv("DB_NAME"),
+            user=os.getenv("DB_USER"),
+            pwd=os.getenv("DB_PW")
+        )
+
+    def inject_to_neo(self):
+        t0 = self.run(self._delete_everything())
+        t1 = self.run(self._create_index_on_statement_uid())
+        t2 = self.run(self._create_statement_nodes())
+        t3 = self.run(self._fill_statements_with_content())
+        t4 = self.run(self._create_user_nodes())
+        t5 = self.run(self._create_relations_between_users_and_statements())
+        t6 = self.run(self._create_issue_nodes())
+        t7 = self.run(self._connect_issues_with_statements())
+        t8 = self.run(self._every_user_likes_his_position())
+        t9 = self.run(self._create_random_ratings())
+        t10 = self.run(self._delete_zero_ratings())
+
+        res = {
+            "delete_time": t0.get("total_time"),
+            "index_time": t1.get("total_time"),
+            "statement_node_time": t2.get("total_time"),
+            "statement_content_time": t3.get("total_time"),
+            "user_node_time": t4.get("total_time"),
+            "statement_user_relation_time": t5.get("total_time"),
+            "issue_node_time": t6.get("total_time"),
+            "statement_to_issue_time": t7.get("total_time"),
+            "user_rates_own_positions_time": t8.get("total_time"),
+            "random_ratings_time": t9.get("total_time"),
+            "delete_zero_ratings_time": t10.get("total_time")
+        }
+        res["total"] = round(sum(res.values()), 4)
+        return res
+
+    def _create_statement_nodes(self):
+        return "CALL apoc.load.jdbc('" + self.url + "', 'statements') " + \
+               "YIELD row " + \
+               "MERGE (statement:Statement{uid:row.uid, is_position:row.is_position, is_disabled:row.is_disabled})"
+
+    def _fill_statements_with_content(self):
+        return "CALL apoc.load.jdbc('" + self.url + "', 'textversions') " + \
+               "YIELD row " + \
+               "MATCH (statement:Statement{uid:row.statement_uid}) " + \
+               "WHERE NOT EXISTS(statement.content) " + \
+               "SET statement += {content:row.content}"
+
+    def _create_user_nodes(self):
+        return "CALL apoc.load.jdbc('" + self.url + "', 'users') " + \
+               "YIELD row " + \
+               "MERGE (user:User{uid:row.uid, public_nickname:row.public_nickname})"
+
+    def _create_relations_between_users_and_statements(self):
+        return "CALL apoc.load.jdbc('" + self.url + "', 'textversions') " + \
+               "YIELD row " + \
+               "MATCH (user:User), (statement:Statement) " + \
+               "WHERE user.uid = row.author_uid AND statement.uid = row.statement_uid " + \
+               "MERGE (user)-[:HAS_WRITTEN]->(statement)"
+
+    def _create_issue_nodes(self):
+        return "CALL apoc.load.jdbc('" + self.url + "', 'issues') " + \
+               "YIELD row " + \
+               "MERGE (issue:Issue{uid:row.uid, title:row.title})"
+
+    def _connect_issues_with_statements(self):
+        return "CALL apoc.load.jdbc('" + self.url + "', 'statement_to_issue') " + \
+               "YIELD row " + \
+               "MATCH (statement:Statement{uid:row.statement_uid}), (issue:Issue{uid:row.issue_uid}) " + \
+               "MERGE (statement)-[:WRITTEN_IN]->(issue)"
+
+    @staticmethod
+    def _every_user_likes_his_position():
+        return "MATCH(user:User)-[:HAS_WRITTEN]->(statement:Statement{is_position:True}) " + \
+               "MERGE(user)-[:LIKES{rating: 5}]->(statement)"
+
+    @staticmethod
+    def _create_random_ratings():
+        return "MATCH (user:User) " + \
+               "WHERE NOT EXISTS((user)-[:LIKES]->()) " + \
+               "MATCH (statement:Statement) " + \
+               "WHERE statement.is_position " + \
+               "MERGE (user)-[:LIKES{rating:round(rand()*5)}]->(statement)"
+
+    @staticmethod
+    def _delete_zero_ratings():
+        return "MATCH ()-[r:LIKES{rating:0.0}]->() " + \
+               "DETACH DELETE r"
+
+    @staticmethod
+    def _delete_everything():
+        return "MATCH (a) " + \
+               "DETACH DELETE a"
+
+    @staticmethod
+    def _create_index_on_statement_uid():
+        return "CREATE INDEX ON :Statement(uid) "
+
+    @staticmethod
+    def _create_index_on_user_uid():
+        return "CREATE INDEX ON :User(uid) "
diff --git a/api/html/browser_guide.html b/api/browser_guide/html/browser_guide.html
similarity index 100%
rename from api/html/browser_guide.html
rename to api/browser_guide/html/browser_guide.html
diff --git a/api/templates/block_admonition.html.erb b/api/browser_guide/templates/block_admonition.html.erb
similarity index 100%
rename from api/templates/block_admonition.html.erb
rename to api/browser_guide/templates/block_admonition.html.erb
diff --git a/api/templates/block_audio.html.erb b/api/browser_guide/templates/block_audio.html.erb
similarity index 100%
rename from api/templates/block_audio.html.erb
rename to api/browser_guide/templates/block_audio.html.erb
diff --git a/api/templates/block_colist.html.erb b/api/browser_guide/templates/block_colist.html.erb
similarity index 100%
rename from api/templates/block_colist.html.erb
rename to api/browser_guide/templates/block_colist.html.erb
diff --git a/api/templates/block_dlist.html.erb b/api/browser_guide/templates/block_dlist.html.erb
similarity index 100%
rename from api/templates/block_dlist.html.erb
rename to api/browser_guide/templates/block_dlist.html.erb
diff --git a/api/templates/block_example.html.erb b/api/browser_guide/templates/block_example.html.erb
similarity index 100%
rename from api/templates/block_example.html.erb
rename to api/browser_guide/templates/block_example.html.erb
diff --git a/api/templates/block_floating_title.html.erb b/api/browser_guide/templates/block_floating_title.html.erb
similarity index 100%
rename from api/templates/block_floating_title.html.erb
rename to api/browser_guide/templates/block_floating_title.html.erb
diff --git a/api/templates/block_image.html.erb b/api/browser_guide/templates/block_image.html.erb
similarity index 100%
rename from api/templates/block_image.html.erb
rename to api/browser_guide/templates/block_image.html.erb
diff --git a/api/templates/block_listing.html.erb b/api/browser_guide/templates/block_listing.html.erb
similarity index 100%
rename from api/templates/block_listing.html.erb
rename to api/browser_guide/templates/block_listing.html.erb
diff --git a/api/templates/block_literal.html.erb b/api/browser_guide/templates/block_literal.html.erb
similarity index 100%
rename from api/templates/block_literal.html.erb
rename to api/browser_guide/templates/block_literal.html.erb
diff --git a/api/templates/block_math.html.erb b/api/browser_guide/templates/block_math.html.erb
similarity index 100%
rename from api/templates/block_math.html.erb
rename to api/browser_guide/templates/block_math.html.erb
diff --git a/api/templates/block_olist.html.erb b/api/browser_guide/templates/block_olist.html.erb
similarity index 100%
rename from api/templates/block_olist.html.erb
rename to api/browser_guide/templates/block_olist.html.erb
diff --git a/api/templates/block_open.html.erb b/api/browser_guide/templates/block_open.html.erb
similarity index 100%
rename from api/templates/block_open.html.erb
rename to api/browser_guide/templates/block_open.html.erb
diff --git a/api/templates/block_page_break.html.erb b/api/browser_guide/templates/block_page_break.html.erb
similarity index 100%
rename from api/templates/block_page_break.html.erb
rename to api/browser_guide/templates/block_page_break.html.erb
diff --git a/api/templates/block_paragraph.html.erb b/api/browser_guide/templates/block_paragraph.html.erb
similarity index 100%
rename from api/templates/block_paragraph.html.erb
rename to api/browser_guide/templates/block_paragraph.html.erb
diff --git a/api/templates/block_pass.html.erb b/api/browser_guide/templates/block_pass.html.erb
similarity index 100%
rename from api/templates/block_pass.html.erb
rename to api/browser_guide/templates/block_pass.html.erb
diff --git a/api/templates/block_preamble.html.erb b/api/browser_guide/templates/block_preamble.html.erb
similarity index 100%
rename from api/templates/block_preamble.html.erb
rename to api/browser_guide/templates/block_preamble.html.erb
diff --git a/api/templates/block_quote.html.erb b/api/browser_guide/templates/block_quote.html.erb
similarity index 100%
rename from api/templates/block_quote.html.erb
rename to api/browser_guide/templates/block_quote.html.erb
diff --git a/api/templates/block_ruler.html.erb b/api/browser_guide/templates/block_ruler.html.erb
similarity index 100%
rename from api/templates/block_ruler.html.erb
rename to api/browser_guide/templates/block_ruler.html.erb
diff --git a/api/templates/block_sidebar.html.erb b/api/browser_guide/templates/block_sidebar.html.erb
similarity index 100%
rename from api/templates/block_sidebar.html.erb
rename to api/browser_guide/templates/block_sidebar.html.erb
diff --git a/api/templates/block_table.html.erb b/api/browser_guide/templates/block_table.html.erb
similarity index 100%
rename from api/templates/block_table.html.erb
rename to api/browser_guide/templates/block_table.html.erb
diff --git a/api/templates/block_toc.html.erb b/api/browser_guide/templates/block_toc.html.erb
similarity index 100%
rename from api/templates/block_toc.html.erb
rename to api/browser_guide/templates/block_toc.html.erb
diff --git a/api/templates/block_ulist.html.erb b/api/browser_guide/templates/block_ulist.html.erb
similarity index 100%
rename from api/templates/block_ulist.html.erb
rename to api/browser_guide/templates/block_ulist.html.erb
diff --git a/api/templates/block_verse.html.erb b/api/browser_guide/templates/block_verse.html.erb
similarity index 100%
rename from api/templates/block_verse.html.erb
rename to api/browser_guide/templates/block_verse.html.erb
diff --git a/api/templates/block_video.html.erb b/api/browser_guide/templates/block_video.html.erb
similarity index 100%
rename from api/templates/block_video.html.erb
rename to api/browser_guide/templates/block_video.html.erb
diff --git a/api/templates/document.html.erb b/api/browser_guide/templates/document.html.erb
similarity index 100%
rename from api/templates/document.html.erb
rename to api/browser_guide/templates/document.html.erb
diff --git a/api/templates/embedded.html.erb b/api/browser_guide/templates/embedded.html.erb
similarity index 100%
rename from api/templates/embedded.html.erb
rename to api/browser_guide/templates/embedded.html.erb
diff --git a/api/templates/inline_anchor.html.erb b/api/browser_guide/templates/inline_anchor.html.erb
similarity index 100%
rename from api/templates/inline_anchor.html.erb
rename to api/browser_guide/templates/inline_anchor.html.erb
diff --git a/api/templates/inline_break.html.erb b/api/browser_guide/templates/inline_break.html.erb
similarity index 100%
rename from api/templates/inline_break.html.erb
rename to api/browser_guide/templates/inline_break.html.erb
diff --git a/api/templates/inline_button.html.erb b/api/browser_guide/templates/inline_button.html.erb
similarity index 100%
rename from api/templates/inline_button.html.erb
rename to api/browser_guide/templates/inline_button.html.erb
diff --git a/api/templates/inline_callout.html.erb b/api/browser_guide/templates/inline_callout.html.erb
similarity index 100%
rename from api/templates/inline_callout.html.erb
rename to api/browser_guide/templates/inline_callout.html.erb
diff --git a/api/templates/inline_footnote.html.erb b/api/browser_guide/templates/inline_footnote.html.erb
similarity index 100%
rename from api/templates/inline_footnote.html.erb
rename to api/browser_guide/templates/inline_footnote.html.erb
diff --git a/api/templates/inline_image.html.erb b/api/browser_guide/templates/inline_image.html.erb
similarity index 100%
rename from api/templates/inline_image.html.erb
rename to api/browser_guide/templates/inline_image.html.erb
diff --git a/api/templates/inline_indexterm.html.erb b/api/browser_guide/templates/inline_indexterm.html.erb
similarity index 100%
rename from api/templates/inline_indexterm.html.erb
rename to api/browser_guide/templates/inline_indexterm.html.erb
diff --git a/api/templates/inline_kbd.html.erb b/api/browser_guide/templates/inline_kbd.html.erb
similarity index 100%
rename from api/templates/inline_kbd.html.erb
rename to api/browser_guide/templates/inline_kbd.html.erb
diff --git a/api/templates/inline_menu.html.erb b/api/browser_guide/templates/inline_menu.html.erb
similarity index 100%
rename from api/templates/inline_menu.html.erb
rename to api/browser_guide/templates/inline_menu.html.erb
diff --git a/api/templates/inline_quoted.html.erb b/api/browser_guide/templates/inline_quoted.html.erb
similarity index 100%
rename from api/templates/inline_quoted.html.erb
rename to api/browser_guide/templates/inline_quoted.html.erb
diff --git a/api/templates/section.html.erb b/api/browser_guide/templates/section.html.erb
similarity index 100%
rename from api/templates/section.html.erb
rename to api/browser_guide/templates/section.html.erb
diff --git a/api/interface/graphql.py b/api/interface/graphql.py
deleted file mode 100644
index 1b854f7..0000000
--- a/api/interface/graphql.py
+++ /dev/null
@@ -1,78 +0,0 @@
-import json
-import logging
-import time
-
-import requests
-from neo4j import GraphDatabase
-
-
-class Adapter(object):
-    def __init__(self, url):
-        self.url = url
-
-    @staticmethod
-    def _json_to_dict(col):
-        if isinstance(col, dict):
-            return col
-        elif isinstance(col, bytes):
-            col = col.decode("utf-8")
-        return json.loads(col)
-
-    def request(self):
-        try:
-            response = requests.get(self.url)
-        except requests.exceptions.ConnectionError:
-            logging.error("Connection Error")
-            return {}
-
-        ret = self._json_to_dict(response.content)
-        return ret
-
-
-class GraphQl(Adapter):
-
-    def __init__(self, protocol, host, port, query):
-        self.protocol = protocol
-        self.host = host
-        self.port = port
-        self.query = query
-        super().__init__("{}://{}:{}/api/v2/query?q={}".format(self.protocol, self.host, self.port, query))
-
-
-class Discussion(GraphQl):
-
-    def __init__(self, protocol, host, port, uri, user, password, slug):
-        super().__init__(protocol, host, port, query=self._cypher_query(slug))
-        self._driver = GraphDatabase.driver(uri, auth=(user, password))
-
-    def close(self):
-        self._driver.close()
-
-    @staticmethod
-    def _cypher_query(slug):
-        return """
-            query{{
-                issue(slug: "{0}"){{
-                    completeGraphCypher
-                }}
-            }}
-        """.format(slug)
-
-    def to_cypher(self):
-        result = super().request()
-        return result['issue']['completeGraphCypher']
-
-    @staticmethod
-    def _create_discussion(tx, query):
-        result = tx.run(
-            query
-        )
-        return result
-
-    def inject_to_neo(self):
-        t1 = time.time()
-        query = self.to_cypher()
-
-        with self._driver.session() as session:
-            session.write_transaction(self._create_discussion, query)
-        return {"total": time.time() - t1}
diff --git a/api/server.py b/api/server.py
index 3920c23..410d5fe 100644
--- a/api/server.py
+++ b/api/server.py
@@ -1,33 +1,35 @@
-from flask import Flask, render_template, jsonify
+from flask import Flask, render_template, jsonify, request, Response
 from flask_cors import CORS
 
-from api.graph import Graph
-from api.interface.graphql import Discussion
+from api.browser_guide.examplegraph import ExampleGraph
+from api.src.models.discussion_skeleton import DiscussionSkeleton
+from api.src.models.discussion import Discussion
 
 app = Flask(__name__, template_folder='.')
 CORS(app)
 
 
-@app.route('/<file>')
-def load_html(file):
-    return render_template('html/' + file)
-
-
-@app.route('/load')
-def load_graph():
-    return jsonify(Graph(uri='bolt://neo:7687', user='neo4j', password='neo4j').load())
-
-
-@app.route('/load/<slug>')
-def load_discussion(slug):
-    result = Discussion(protocol='https',
-                        host='dbas.cs.uni-duesseldorf.de',
-                        port='443',
-                        uri='bolt://neo:7687',
-                        user='neo4j',
-                        password='neo4j',
-                        slug=slug).inject_to_neo()
-    return jsonify(result)
+@app.route('/load/<q>')
+def load(q):
+    if q == 'example_graph':
+        return jsonify(ExampleGraph().inject_to_neo())
+    elif q == 'dbas_live':
+        slug = request.args.get('slug')
+        if not slug:
+            return jsonify({"error": "Parameter slug is missing"}), 404
+        return jsonify(Discussion(protocol='https',
+                                  host='dbas.cs.uni-duesseldorf.de',
+                                  port='443',
+                                  slug=slug).inject_to_neo())
+    elif q == 'skeleton':
+        return jsonify(DiscussionSkeleton(protocol='http',
+                                          host='web',
+                                          port='4284').inject_to_neo())
+    elif q == 'guide':
+        guide = request.args.get('guide')
+        if not guide:
+            return jsonify({"error": "Parameter guide is missing"}), 404
+        return render_template('browser_guide/html/' + guide)
 
 
 if __name__ == '__main__':
diff --git a/api/interface/__init__.py b/api/src/__init__.py
similarity index 100%
rename from api/interface/__init__.py
rename to api/src/__init__.py
-- 
GitLab