Skip to content

Commit

Permalink
Support arithmetic expressions in the JSON generator
Browse files Browse the repository at this point in the history
  • Loading branch information
x4base committed May 5, 2016
1 parent 48d78c5 commit 95a2c1e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 23 deletions.
25 changes: 19 additions & 6 deletions caravel/assets/javascripts/datasource.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
var $ = window.$ || require('jquery');
var jsonGenerator = require("./modules/json_generator");

$(document).ready(function () {
var $modal = $('#json_gen_modal');
$('#convertButton').click(function () {
var expression = $('#expression').val().trim();
var parse_tree = jsonGenerator.parse(expression);
console.log(parse_tree);
$('#json').val(JSON.stringify(parse_tree));
$(this).closest('.modal').modal('hide');
var $alert = $modal.find('#errorMsg');
$alert
.removeClass('hidden')
.hide()
.html("");
try {
var parse_tree = jsonGenerator.parse(expression);
$('#json').val(JSON.stringify(parse_tree));

$(this).closest('.modal').modal('hide');
} catch (e) {
$alert
.show()
.html(e.message);
}
});
$('#json_gen_modal').on('shown.bs.modal', function () {
$modal.on('shown.bs.modal', function () {
$('#expression').focus();
});

var showJsonGenModal = function () {
$('#json_gen_modal').modal('show');
$modal.modal('show');
};

$.extend(window, {
Expand Down
78 changes: 63 additions & 15 deletions caravel/assets/javascripts/modules/json_generator.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
var jsep = require("jsep");

var typeMap = {
sum: 'doubleSum',
doubleSum: 'doubleSum',
longSum: 'longSum',
};

var capitalize = function (string) {
return string.charAt(0).toUpperCase() + string.slice(1);
var capitalize = function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};

var convertFuncCall = function (node) {
var funcName = node.callee.name;
var fieldName = node.arguments[0].name;
if (!funcName) return;
var fieldName = node.arguments[0].name || "";
var m = funcName.toLowerCase().match(/^(double|long)?(sum|min|max)$/);
if (!m) return;
if (!m) {
throw new Error("Unsupported function call: " + funcName);
}

var varType = m[1] || 'double'; // default to double
var funcType = m[2];
Expand All @@ -25,15 +20,68 @@ var convertFuncCall = function (node) {
return {
type: type,
name: fieldName,
fieldName: fieldName,
fieldName: fieldName
};
};

var convertField = function (node) {
var fieldName = node.name;
return {
type: "fieldAccess",
name: fieldName,
fieldName: fieldName
};
};

var convertBinary = function (node) {
var op = node.operator;
// TODO: Support the "quotient" type
if (!/[+\-*\/]/.test(op)) {
throw new Error("Unsupported operation: " + op);
}
return {
type: "arithmetic",
fn: op,
fields: [node.left, node.right].map(function (child) {
return convertArithmetic(child);
})
};
};

var convertLiteral = function (node) {
return {
type: "constant",
value: node.value
};
};

var arithmeticTokenHandler = {
Identifier: convertField,
BinaryExpression: convertBinary,
Literal: convertLiteral
};

var convertArithmetic = function (node) {
var converter = arithmeticTokenHandler[node.type];
if (!converter) {
throw new Error("Invalid Expression (" + node.type + ")");
}
return converter(node);
};

var parse = function (expression) {
expression = expression.trim();
expression = expression.trim().replace('\n', '');
var parse_tree = jsep(expression);
parse_tree = convertFuncCall(parse_tree);
return parse_tree;
var converterMap = {
CallExpression: convertFuncCall,
BinaryExpression: convertArithmetic,
Literal: convertArithmetic
};
var converter = converterMap[parse_tree.type];
if (!converter) {
throw new Error("Invalid Expression (" + parse_tree.type + ")");
}
return converter(parse_tree);
};

module.exports = {
Expand Down
6 changes: 5 additions & 1 deletion caravel/templates/caravel/models/datasource/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">JSON Generator</h4>
<h6><strong>Enter the algebraic expression to convert. E.g. longSum(price), doubleMin(price)</strong></h6>
<p>Enter the algebraic expression to convert. For example: <br>
<strong>Normal metrics</strong>: longSum(price), doubleMin(price)<br>
<strong>Post Aggregation</strong>: (price/count)*100<br>
</p>
</div>
<div class="modal-body">
<textarea id="expression" rows="5" cols="60"></textarea>
<div class="alert alert-danger hidden" id="errorMsg"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
Expand Down
1 change: 0 additions & 1 deletion caravel/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ class DruidMetricInlineView(CompactCRUDMixin, CaravelModelView): # noqa
"[Druid Post Aggregation]"
"(http://druid.io/docs/latest/querying/post-aggregations.html)",
True),
# 'json': Markup("<a href='javascript:showJsonGenModal()'>Json Generator</a>")
'json': utils.markdown(
"You can also use the [generator](javascript:showJsonGenModal()) to generate json",
True),
Expand Down

0 comments on commit 95a2c1e

Please sign in to comment.