summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alon@pobox.com>2014-12-23 21:53:46 +0200
committerAlon Levy <alon@pobox.com>2014-12-23 22:03:17 +0200
commitf7ff8bc38410c2666665c4c70cc71c17f6eb7835 (patch)
tree458bd97cf23a2672102d85babe1deaa2ec581233
parent3e3944c42517a2745d9dd2312e8c3a571de41863 (diff)
use topo_diff for user input changes
pretty large commit, but it mainly boils to - reusing the same format clone returns to the client for topo_diff bad bad code introduced mainly in client side, but server wasn't spared: - graph/commit_topo__diff massages the links too much - this should not be there at all, it should be in the correct format to begin with. server code duplication between clone & topo_diff post processing, should be factored out on the good side: single transaction whenever user presses enter, and the correct place to send back any accumulated diffs (other user changes).
-rw-r--r--src/client/model/graph.js115
-rw-r--r--src/client/textanalysis.js36
-rw-r--r--src/client/textanalysis.ui.js7
-rw-r--r--src/server/db_controller.py42
-rw-r--r--src/server/neo4j_util.py4
5 files changed, 147 insertions, 57 deletions
diff --git a/src/client/model/graph.js b/src/client/model/graph.js
index 26bf96b2..b7f3e67e 100644
--- a/src/client/model/graph.js
+++ b/src/client/model/graph.js
@@ -27,6 +27,58 @@ function Graph() {
}
/**
+ *
+ * @param a topo_diff but that might be missing a few things, sanitize it first.
+ * all sanitation should be idempotent, but probably isn't.
+ */
+ this.commit_diff__topo = function (topo_diff, on_success, on_error) {
+ var name_to_node = {};
+ topo_diff.node_set_add = topo_diff.node_set_add.map(function(n) {
+ if (n.id === undefined) {
+ n.id = model_core.random_node_name();
+ }
+ name_to_node[n.name] = n;
+ return model_util.adapt_format_write_node(n);
+ });
+
+ topo_diff.link_set_add = topo_diff.link_set_add.map(function(l) {
+ if (l.id === undefined) {
+ l.id = model_core.random_node_name();
+ }
+ if (typeof l.__src === 'string') {
+ l.__src = name_to_node[l.__src];
+ }
+ if (typeof l.__dst === 'string') {
+ l.__dst = name_to_node[l.__dst];
+ }
+ if (l.source === undefined) {
+ l.source = l.__src;
+ }
+ if (l.target === undefined) {
+ l.target = l.__dst;
+ }
+ if (l.__type === undefined) {
+ l.__type = l.name;
+ }
+ return model_util.adapt_format_write_link(l);
+ });
+ var graph_on_success = function(diff) {
+ on_backend__diff(diff);
+ if (on_success) {
+ on_success(nodes);
+ }
+ }
+ var graph_on_error = function(error) {
+ if (on_error) {
+ on_error(error);
+ }
+ }
+ console.log("COMMIT DIFF TOPO");
+ console.dir(topo_diff);
+ rz_api_backend.commit_diff__topo(topo_diff, graph_on_success, graph_on_error);
+ }
+
+ /**
* Inner implementation
*
* @param notify whether or not a presenter notification will be sent, default = true
@@ -729,46 +781,47 @@ function Graph() {
rz_api_mesh.broadcast_possible_next_diff_block(diff_set);
}
- /**
- * perform initial DB load from backend
- *
- * @param on_success: should be used by MVP presentors to trigger UI update
- */
- // @ajax-trans
- function load_from_backend(on_success) {
+ function on_backend__node_add(n_spec) {
+ n_spec = model_util.adapt_format_read_node(n_spec);
- function on_success__ajax(data) {
- var n_set = []; // added node set
- var l_set = []; // added link set
- var len;
+ util.assert(undefined != n_spec.id, 'load_from_backend: n_spec missing id');
- data['node_set'].map(function(n_spec) {
- n_spec = model_util.adapt_format_read_node(n_spec);
+ var n = __addNode(n_spec, false, false);
+ }
- util.assert(undefined != n_spec.id, 'load_from_backend: n_spec missing id');
+ function on_backend__link_add(l_spec) {
+ var l_ptr = model_util.adapt_format_read_link_ptr(l_spec);
- var n = __addNode(n_spec, false, false);
- n_set.push(n);
- });
+ util.assert(undefined != l_ptr.id, 'load_from_backend: l_ptr missing id');
- data['link_set'].map(function(l_spec){
- var l_ptr = model_util.adapt_format_read_link_ptr(l_spec);
+ // resolve link ptr
+ var src = find_node__by_id(l_ptr.__src_id),
+ dst = find_node__by_id(l_ptr.__dst_id);
- util.assert(undefined != l_ptr.id, 'load_from_backend: l_ptr missing id');
+ // cleanup & reuse as link_spec
+ delete l_ptr.__src_id;
+ delete l_ptr.__dst_id;
+ var link_spec = l_ptr;
+ var link = model_core.create_link_from_spec(src, dst, link_spec);
+ var l = addLink(link, false);
+ }
- // resolve link ptr
- var src = find_node__by_id(l_ptr.__src_id),
- dst = find_node__by_id(l_ptr.__dst_id);
+ function on_backend__diff(data) {
+ data['node_set'].map(on_backend__node_add);
- // cleanup & reuse as link_spec
- delete l_ptr.__src_id;
- delete l_ptr.__dst_id;
- var link_spec = l_ptr;
- var link = model_core.create_link_from_spec(src, dst, link_spec);
- var l = addLink(link, false);
- l_set.push(l);
- });
+ data['link_set'].map(on_backend__link_add);
+ }
+
+ /**
+ * perform initial DB load from backend
+ *
+ * @param on_success: should be used by MVP presentors to trigger UI update
+ */
+ // @ajax-trans
+ function load_from_backend(on_success) {
+ function on_success__ajax(data) {
+ on_backend__diff(data);
undefined != on_success && on_success()
}
diff --git a/src/client/textanalysis.js b/src/client/textanalysis.js
index 7881a767..63287913 100644
--- a/src/client/textanalysis.js
+++ b/src/client/textanalysis.js
@@ -467,17 +467,19 @@ var textAnalyser = function (newtext, finalize) {
graph.removeNodes(function(n){ return "temp" == n.state; });
graph.removeLinks("temp");
- ret.for_each_node_add(function (node) {
- if (true == finalize && node.state == 'temp') {
- console.log('bug: temp node creation on finalize');
- } else {
- if (!finalize) {
- lastnode = graph.addNode(node);
+ if (!finalize) { // finalize done via topo diff below
+ ret.for_each_node_add(function (node) {
+ if (true == finalize && node.state == 'temp') {
+ console.log('bug: temp node creation on finalize');
} else {
- graph.addNode(node);
+ if (!finalize) {
+ lastnode = graph.addNode(node);
+ } else {
+ graph.addNode(node);
+ }
}
- }
- });
+ });
+ }
}
ret.for_each_link_add(function (link) {
if (false == finalize || link.name !== 'and') {
@@ -499,13 +501,19 @@ var textAnalyser = function (newtext, finalize) {
// broadcast diff:
// - finalize?
// - broadcast_diff requested by caller
- var topo_diff = model_util.adapt_format_write_topo_diff(ret.nodes, ret.links);
- var diff_set = model_diff.new_diff_set();
- diff_set.add_diff_obj(topo_diff);
- graph.commit_diff_set(diff_set);
+ var on_success = function (ret) {
+ console.dir(ret);
+ rz_core.update_view__graph();
+ }
+ var on_error = function () {
+ console.log('askeeeeeeeeeeeeew');
+ }
+ // drop bubble node
+ ret.node_set_add = ret.node_set_add.filter(function(n) { return n.type != 'bubble'; });
+ graph.commit_diff__topo(ret, on_success, on_error);
}
- // UPDATE GRAPH ONCE
+ // update graph if not going through backend
rz_core.update_view__graph(!finalize && comp.graph_same);
};
diff --git a/src/client/textanalysis.ui.js b/src/client/textanalysis.ui.js
index 5f5718bd..52b886be 100644
--- a/src/client/textanalysis.ui.js
+++ b/src/client/textanalysis.ui.js
@@ -1,7 +1,7 @@
"use strict"
-define(['jquery', 'Bacon', 'consts', 'rz_bus', 'rz_core', 'textanalysis', 'view/completer'],
-function($, Bacon, consts, rz_bus, rz_core, textanalysis, completer) {
+define(['jquery', 'Bacon', 'consts', 'rz_bus', 'rz_core', 'rz_config', 'textanalysis', 'view/completer'],
+function($, Bacon, consts, rz_bus, rz_core, rz_config, textanalysis, completer) {
var text = "", // Last text of sentence
element_name = '#textanalyser',
@@ -65,8 +65,7 @@ function analyzeSentence(sentence, finalize)
break;
}
- var backend_commit = false;
- ret.applyToGraph(rz_core.graph, backend_commit);
+ ret.applyToGraph(rz_core.graph, rz_config.backend_enabled);
if (finalize || sentence.length == 0) {
typeselection.hide();
diff --git a/src/server/db_controller.py b/src/server/db_controller.py
index fac4146a..b9e1ef8d 100644
--- a/src/server/db_controller.py
+++ b/src/server/db_controller.py
@@ -133,6 +133,8 @@ class DBO_topo_diff_commit(DB_composed_op):
l_rm_set = topo_diff.link_set_rm
n_rm_set = topo_diff.node_set_rm
+ self.n_add_map = len(n_add_map) > 0
+ self.l_add_map = len(l_add_map) > 0
#
# [!] order critical
#
@@ -152,6 +154,34 @@ class DBO_topo_diff_commit(DB_composed_op):
op = DBO_rm_node_set(n_rm_set)
self.add_sub_op(op)
+ def process_result_set(self):
+ ret_n_set = []
+ ret_l_set = []
+ it = iter(self)
+
+ if self.n_add_map:
+ for _, _, row_set in it.next():
+ for row in row_set:
+ n, n_lbl_set = row.items() # see query return statement
+
+ assert None != n.get('id'), "db contains nodes with no id"
+
+ n['__label_set'] = n_lbl_set
+ ret_n_set.append(n)
+
+ if self.l_add_map:
+ for _, _, l_set in it.next():
+ for l, l_src, l_dst, l_type in l_set:
+ l['__src_id'] = l_src
+ l['__dst_id'] = l_dst
+ l['__label_set'] = [l_type] # box single value returned by type()
+
+ ret_l_set.append(l)
+
+ return {'node_set': ret_n_set,
+ 'link_set': ret_l_set }
+
+
class DBO_attr_diff_commit(DB_op):
"""
commit a Attr_Diff
@@ -257,13 +287,13 @@ class DBO_add_node_set(DB_op):
self.add_statement(q, q_param_set)
def process_result_set(self):
- id_set = []
+ n_set = []
for _, _, row_set in self:
for row in row_set:
for clo in row:
- id_set.append(clo)
+ n_set.append(clo)
- return id_set
+ return n_set
class DBO_add_link_set(DB_op):
def __init__(self, link_map):
@@ -276,13 +306,13 @@ class DBO_add_link_set(DB_op):
self.add_statement(q, q_params)
def process_result_set(self):
- id_set = []
+ l_set = []
for _, _, r_set in self:
for row in r_set:
for col_val in row:
- id_set.append(col_val)
+ l_set.append(col_val)
- return id_set
+ return l_set
class DBO_load_node_set_by_DB_id(DB_op):
def __init__(self, id_set):
diff --git a/src/server/neo4j_util.py b/src/server/neo4j_util.py
index 5bc65032..5cd920a1 100644
--- a/src/server/neo4j_util.py
+++ b/src/server/neo4j_util.py
@@ -185,7 +185,7 @@ def gen_query_create_from_node_map(node_map, input_to_DB_property_map=lambda _:
assert len(label) > 2 and label[0].isupper() and label[1:].islower(), 'malformed label: ' + label
q_arr = ['create (n:%s {node_attr})' % (quote__backtick(label)),
- 'return n.id'
+ 'return n, labels(n)'
]
q = ' '.join(q_arr)
@@ -211,7 +211,7 @@ def gen_query_create_from_link_map(link_map, input_to_DB_property_map=lambda _:
for l_type, l_set in link_map.items():
q = "match (src {id: {src}.id}),(dst {id: {dst}.id}) " + \
"create (src)-[r:%(__type)s {link_attr}]->(dst) " + \
- "return id(r)"
+ "return r, src.id, dst.id, type(r)"
q = q % {'__type': quote__backtick(l_type)}
for link in l_set: