summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/core/domain.js
diff options
context:
space:
mode:
authorChristophe Matthieu <chm@odoo.com>2018-07-11 13:27:30 +0200
committerChristophe Matthieu <chm@odoo.com>2018-08-13 17:09:28 +0200
commit6ca026119e918e5de19316c71ab50b4034dd6f99 (patch)
tree9f659b95b2d24f13d4a2208171fb7967d4d2cd49 /addons/web/static/src/js/core/domain.js
parentcad272d5b62a0769703f825a569dd360b2bf074a (diff)
[IMP] web: add method to convert JS domain into python condition
Diffstat (limited to 'addons/web/static/src/js/core/domain.js')
-rw-r--r--addons/web/static/src/js/core/domain.js112
1 files changed, 112 insertions, 0 deletions
diff --git a/addons/web/static/src/js/core/domain.js b/addons/web/static/src/js/core/domain.js
index e8f089dca76..c4011b049b9 100644
--- a/addons/web/static/src/js/core/domain.js
+++ b/addons/web/static/src/js/core/domain.js
@@ -3,6 +3,7 @@ odoo.define("web.Domain", function (require) {
var collections = require("web.collections");
var pyUtils = require("web.py_utils");
+var py = window.py; // look py.js
/**
* The Domain Class allows to work with a domain as a tree and provides tools
@@ -346,6 +347,117 @@ var Domain = collections.Tree.extend({
}
return domain;
},
+ /**
+ * Converts JS prefix-array representation of a domain to a python condition
+ *
+ * @static
+ * @param {Array} domain
+ * @returns {string}
+ */
+ domainToCondition: function (domain) {
+ if (!domain.length) {
+ return 'True';
+ }
+ var self = this;
+ function consume(stack) {
+ var len = stack.length;
+ if (len <= 1) {
+ return stack;
+ } else if (stack[len-1] === '|' || stack[len-1] === '&' || stack[len-2] === '|' || stack[len-2] === '&') {
+ return stack;
+ } else if (len == 2) {
+ stack.splice(-2, 2, stack[len-2] + ' and ' + stack[len-1]);
+ } else if (stack[len-3] == '|') {
+ if (len === 3) {
+ stack.splice(-3, 3, stack[len-2] + ' or ' + stack[len-1]);
+ } else {
+ stack.splice(-3, 3, '(' + stack[len-2] + ' or ' + stack[len-1] + ')');
+ }
+ } else {
+ stack.splice(-3, 3, stack[len-2] + ' and ' + stack[len-1]);
+ }
+ consume(stack);
+ }
+
+ var stack = [];
+ _.each(domain, function (dom) {
+ if (dom === '|' || dom === '&') {
+ stack.push(dom);
+ } else {
+ var operator = dom[1] === '=' ? '==' : dom[1];
+ if (!operator) {
+ throw new Error('Wrong operator for this domain');
+ }
+ if (operator === '!=' && dom[2] === false) { // the field is set
+ stack.push(dom[0]);
+ } else if (dom[2] === null || dom[2] === true || dom[2] === false) {
+ stack.push(dom[0] + ' ' + (operator === '!=' ? 'is not ' : 'is ') + (dom[2] === null ? 'None' : (dom[2] ? 'True' : 'False')));
+ } else {
+ stack.push(dom[0] + ' ' + operator + ' ' + JSON.stringify(dom[2]));
+ }
+ consume(stack);
+ }
+ });
+
+ if (stack.length !== 1) {
+ throw new Error('Wrong domain');
+ }
+
+ return stack[0];
+ },
+ /**
+ * Converts python condition to a JS prefix-array representation of a domain
+ *
+ * @static
+ * @param {string} domain
+ * @returns {Array}
+ */
+ conditionToDomain: function (condition) {
+ if (!condition || condition.match(/^\s*(True)?\s*$/)) {
+ return [];
+ }
+
+ var ast = py.parse(py.tokenize(condition));
+
+
+ function astToStackValue (node) {
+ switch (node.id) {
+ case '(name)': return node.value;
+ case '.': return astToStackValue(node.first) + '.' + astToStackValue(node.second);
+ case '(string)': return node.value;
+ case '(number)': return node.value;
+ case '(constant)': return node.value === 'None' ? null : node.value === 'True' ? true : false;
+ case '[': return _.map(node.first, function (node) {return astToStackValue(node);});
+ }
+ }
+ function astToStack (node) {
+ switch (node.id) {
+ case '(name)': return [[astToStackValue(node), '!=', false]];
+ case '.': return [[astToStackValue(node.first) + '.' + astToStackValue(node.second), '!=', false]];
+ case 'not': return [[astToStackValue(node.first), '=', false]];
+
+ case 'or': return ['|'].concat(astToStack(node.first)).concat(astToStack(node.second));
+ case 'and': return ['&'].concat(astToStack(node.first)).concat(astToStack(node.second));
+ case '(comparator)':
+ if (node.operators.length !== 1) {
+ throw new Error('Wrong condition to convert in domain');
+ }
+ var right = astToStackValue(node.expressions[0]);
+ var left = astToStackValue(node.expressions[1]);
+ var operator = node.operators[0];
+ switch (operator) {
+ case 'is': operator = '='; break;
+ case 'is not': operator = '!='; break;
+ case '==': operator = '='; break;
+ }
+ return [[right, operator, left]];
+ default:
+ throw "Condition cannot be transformed into domain";
+ }
+ }
+
+ return astToStack(ast);
+ },
});
return Domain;