Another playground for you Guys. This time it is to evaluate a "calc field" expressions. The official name of the syntax is Siebel Query Language and it is used widely through Siebel apps, for example:
A playground is very handy when it comes to prototyping or debugging expressions or simply if you need to get a value of an active field or profile attribute.
Less words more code, let's get down to the implementation.
This time we will be invoking a built-in BusComp method EvalExpr. So let's create another method in runtime business service:
function EvalExpr (Inputs, Outputs) {
var bc:BusComp;
try {
bc = TheApplication().ActiveBusObject().GetBusComp(Inputs.GetProperty("BC"));
Outputs.SetProperty("Result", bc.InvokeMethod("EvalExpr", Inputs.GetProperty("Expr")));
} catch(e) {
Outputs.SetProperty("Result", e.toString());
} finally {
bc = null;
}
}
Here is a full version of my client-side Business Service.
For UI we will be using a bookmarklet with a dialog which contains a drop-down with active BusComps, two text areas for input expression and a result, and a button to run the service.
/*
@desc UI allowing to evaluate expressions (EvalExpr) on active BCs
@author VB(xapuk.com)
@version 1.2 2018/07/23
@requires BS "FWK Runtime" to be published
*/
if ("undefined" == typeof SiebelApp){
alert("It works only in Siebel OUI session!");
}else{
var func = "SiebelEvalExpr";
$("#" + func).parent().remove();
var a = LoadBCs();
if (a.length === 0){
alert("No BusComps/Records available!");
}else{
var s = '<div title="Runtime calculations">' +
'<label for="' + func + 'List">Business Component:</label>' +
'<select id = "' + func + 'List" style="display:block"></select>' +
'<label for="' + func + '">Expression:</label>' +
'<textarea id = "' + func + '" rows="3"></textarea>' +
'<label for="' + func + 'Out">Results:</label>' +
'<textarea id = "' + func + 'Out" disabled rows="2"></textarea>' +
'<style>select,textarea{width:100%!Important}</style>' +
'</div>';
var d = $(s).dialog({
modal: true,
width: 1024,
heigth: 640,
open: function(){
$('#'+func).focus();
// key bindings
$("#"+func+"Out").parent().keydown(function(event) {
if (event.ctrlKey && event.keyCode === 13) { // ctrl + Enter
EvalExpr();
}
});
// list of BCs
$("#" + func + "List").append("<option>" + a.join("</option><option>") + "</option>");
$("#" + func + "List").val(SiebelApp.S_App.GetActiveView().GetActiveApplet().GetBusComp().GetName());
// recent expression
$("#" + func).val(JSON.parse(window.localStorage[func]));
//style
$(this).append('<style type="text/css">textarea, select { height:auto; width:100% }</style>');
},
close: function(){
$(this).dialog('destroy').remove();
},
buttons: [
{
text:'Run (Ctrl+Enter)',
click: EvalExpr
},
{
text:'Close (Esc)',
click: function() {
$(this).dialog('destroy').remove();
}
}
]
});
// bind and trigger auto-adjust
$(d).find("#" + func).keyup(function(){
TextAdjust(this, 3);
}).keyup();
}
}
function EvalExpr(){
var sExpr = $('#'+func).val();
var sRes = "";
// save last query
window.localStorage[func] = JSON.stringify(sExpr);
// if there is a selection
var ele = document.getElementById(func);
if(ele.selectionStart !== undefined && ele.selectionStart != ele.selectionEnd){// Normal browsers
sExpr = ele.value.substring(ele.selectionStart, ele.selectionEnd);
}else if(document.selection !== undefined){// IE
ele.focus();
var sel = document.selection.createRange();
sExpr = sel.text;
}
// invoke BS
var service = SiebelApp.S_App.GetService("FWK Runtime");
var ps = SiebelApp.S_App.NewPropertySet();
ps.SetProperty("Expr", sExpr);
ps.SetProperty("BC", $("#" + func + "List").val());
var outputSet = service.InvokeMethod("EvalExpr", ps);
if (outputSet.GetProperty("Status") == "Error"){
sRes = outputSet.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg");
}else{
sRes = outputSet.GetChildByType("ResultSet").GetProperty("Result");
console.log(outputSet);
}
TextAdjust($('#'+func + "Out").show().text(sRes)[0]);
}
// auto-ajust textarea height
function TextAdjust(scope, minrows, maxrows) {
maxrows = maxrows>0?maxrows:10;
minrows = minrows>0?minrows:2;
var txt = scope.value;
var cols = scope.cols;
var arraytxt = txt.split('\n');
var rows = arraytxt.length;
if (rows > maxrows) {
scope.rows = maxrows;
} else if (rows < minrows) {
scope.rows = minrows;
} else {
scope.rows = rows;
}
}
// gather the list of active BCs
function LoadBCs(){
var a = [];
for(var i in SiebelApp.S_App.GetActiveBusObj().GetBCMap()){
var bc = SiebelApp.S_App.GetActiveBusObj().GetBCMap()[i];
if (a.indexOf(bc.GetName()) == -1 && bc.GetNumRows() > 0){
a.push(bc.GetName());
}
}
return a;
}
javascript:void function(){function e(){var e=$("#"+i).val(),o="";window.localStorage[i]=JSON.stringify(e);var l=document.getElementById(i);if(void 0!==l.selectionStart&&l.selectionStart!=l.selectionEnd)e=l.value.substring(l.selectionStart,l.selectionEnd);else if(void 0!==document.selection){l.focus();var r=document.selection.createRange();e=r.text}var s=SiebelApp.S_App.GetService("FWK Runtime"),a=SiebelApp.S_App.NewPropertySet();a.SetProperty("Expr",e),a.SetProperty("BC",$("#"+i+"List").val());var n=s.InvokeMethod("EvalExpr",a);"Error"==n.GetProperty("Status")?o=n.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg"):(o=n.GetChildByType("ResultSet").GetProperty("Result"),console.log(n)),t($("#"+i+"Out").show().text(o)[0])}function t(e,t,o){o=o>0?o:10,t=t>0?t:2;var i=e.value,l=(e.cols,i.split("\n")),r=l.length;r>o?e.rows=o:t>r?e.rows=t:e.rows=r}function o(){var e=[];for(var t in SiebelApp.S_App.GetActiveBusObj().GetBCMap()){var o=SiebelApp.S_App.GetActiveBusObj().GetBCMap()[t];-1==e.indexOf(o.GetName())&&o.GetNumRows()>0&&e.push(o.GetName())}return e}if("undefined"==typeof SiebelApp)alert("It works only in Siebel OUI session!");else{var i="SiebelEvalExpr";$("#"+i).parent().remove();var l=o();if(0===l.length)alert("No BusComps/Records available!");else{var r='<div title="Runtime calculations"><label for="'+i+'List">Business Component:</label><select id = "'+i+'List" style="display:block"></select><label for="'+i+'">Expression:</label><textarea id = "'+i+'" rows="3"></textarea><label for="'+i+'Out">Results:</label><textarea id = "'+i+'Out" disabled rows="2"></textarea><style>select,textarea{width:100%!Important}</style></div>',s=$(r).dialog({modal:!0,width:1024,heigth:640,open:function(){$("#"+i).focus(),$("#"+i+"Out").parent().keydown(function(t){t.ctrlKey&&13===t.keyCode&&e()}),$("#"+i+"List").append("<option>"+l.join("</option><option>")+"</option>"),$("#"+i+"List").val(SiebelApp.S_App.GetActiveView().GetActiveApplet().GetBusComp().GetName()),$("#"+i).val(JSON.parse(window.localStorage[i])),$(this).append('<style type="text/css">textarea, select { height:auto; width:100% }</style>')},close:function(){$(this).dialog("destroy").remove()},buttons:[{text:"Run (Ctrl+Enter)",click:e},{text:"Close (Esc)",click:function(){$(this).dialog("destroy").remove()}}]});$(s).find("#"+i).keyup(function(){t(this,3)}).keyup()}}}();
Here is a new version with a built-in beautifier from another topic:
/*
@desc UI allowing to evaluate expressions (EvalExpr) on active BCs
@author VB(xapuk.com)
@version 1.3 2019/03/10
@requires BS "FWK Runtime" to be compiled and published
*/
if ("undefined" == typeof SiebelApp){
alert("It works only in Siebel OUI session!");
} else {
var func = "SiebelEvalExpr";
$("#" + func).parent().remove();
var bBeauty = false;
var a = LoadBCs();
if (a.length === 0){
alert("No BusComps/Records available!");
}else{
var s = '<div title="Runtime calculations">' +
'<label for="' + func + 'List">Business Component:</label>' +
'<select id = "' + func + 'List" style="display:block"></select>' +
'<label for="' + func + '">Expression:</label>' +
'<textarea id = "' + func + '" rows="5" nowrap></textarea>' +
'<label for="' + func + 'Out">Results:</label>' +
'<textarea id = "' + func + 'Out" disabled rows="2"></textarea>' +
'<style type="text/css">.ui-dialog textarea, .ui-dialog select {height:auto; width:100%; margin-bottom:10px} .ui-dialog label{margin-top:20px!}</style>'
'</div>';
var d = $(s).dialog({
modal: true,
width: 1024,
heigth: 640,
open: function(){
$('#'+func).focus();
// key bindings
$("#"+func+"Out").parent().keydown(function(event) {
if (event.ctrlKey && event.keyCode === 13) { // ctrl + Enter
EvalExpr();
}
});
// list of BCs
$("#" + func + "List").append("<option>" + a.join("</option><option>") + "</option>");
$("#" + func + "List").val(SiebelApp.S_App.GetActiveView().GetActiveApplet().GetBusComp().GetName());
// recent expression
$("#" + func).val(JSON.parse(window.localStorage[func]));
},
close: function(){
$(this).dialog('destroy').remove();
},
buttons: [
{
text:'Format/Linarise',
click: Beauty,
id: 'BeautyBtn'
},{
text:'Run (Ctrl+Enter)',
click: EvalExpr
},{
text:'Close (Esc)',
click: function() {
$(this).dialog('destroy').remove();
}
}
]
});
// bind and trigger auto-adjust
$(d).find("#" + func).keyup(function(){
TextAdjust(this, 5);
}).keyup();
// bind a beautifier
$(".ui-dialog #BeautyBtn").hide();
require(["3rdParty/SiebelQueryLang"], function(e){
console.log("Beautifier loaded!");
$(".ui-dialog #BeautyBtn").show();
});
}
}
function Beauty(){
var s = $('#'+func).val();
if (s){
if (bBeauty){
// linarise
s = s.replace(/\n(\t|\s)*/gm,"");
$('#'+func).val(s).attr("wrap", "on");
bBeauty = false;
} else {
// beautify
try {
var o = SiebelQueryLang.parse(s);
s = trav(o.expression, "");
$('#'+func).val(s).attr("wrap", "off");
bBeauty = true;
} catch(e) {
// silence the error
console.log(e);
}
}
TextAdjust($('#'+func)[0]);
}
}
function trav(o, t, f) {
var r = "";
if ("object" === typeof o) {
var p = o.par;
var n = o.not;
if (o.type === "bin") {
r = trav(o.left, t) + " " + o.operator + " " + trav(o.right, t);
} else if (o.type === "log") {
if(p) { // format logical operators eclosed in brackets
tt = t + "\t";
r = "(\n";
r += tt + trav(o.left, tt, true);
r += "\n" + tt + o.operator + " " + trav(o.right, tt, true);
r += "\n" + t + ")";
p = false;
} else {
if(f) {
r = trav(o.left, t, true);
r += "\n" + t + o.operator + " " + trav(o.right, t, true);
} else {
r = trav(o.left, t) + " " + o.operator + " " + trav(o.right, t);
}
}
} else if (o.type === "func") {
var l = o.arguments.length;
var f = l > 2; // split params when more then 2
var s = (f ? "\n" + t : "");
var st = (f ? s + "\t" : "");
r = o.name + "(";
o.arguments.forEach(function(a, i) {
r += st + trav(a, t + "\t") + (i < l - 1 ? ", " : "");
});
r += s + ")";
} else if (o.type === "field") {
r = "[" + o.field + "]";
} else if (o.type === "param") {
r = "[&" + o.param + "]";
} else if (o.type === "num") {
r = o.value;
} else if (o.type === "str") {
r = '"' + o.value +'"';
}
if (p) {
r = "(" + r + ")";
}
if (n) {
r = "NOT " + r;
}
} else {
r = o;
}
return r;
}
function EvalExpr(){
var sExpr = $('#'+func).val();
var sRes = "";
// save last query
window.localStorage[func] = JSON.stringify(sExpr);
// if there is a selection
var ele = document.getElementById(func);
if(ele.selectionStart !== undefined && ele.selectionStart != ele.selectionEnd){// Normal browsers
sExpr = ele.value.substring(ele.selectionStart, ele.selectionEnd);
}else if(document.selection !== undefined){// IE
ele.focus();
var sel = document.selection.createRange();
sExpr = sel.text;
}
// invoke BS
var service = SiebelApp.S_App.GetService("FWK Runtime");
var ps = SiebelApp.S_App.NewPropertySet();
ps.SetProperty("Expr", sExpr);
ps.SetProperty("BC", $("#" + func + "List").val());
var outputSet = service.InvokeMethod("EvalExpr", ps);
if (outputSet.GetProperty("Status") == "Error"){
sRes = outputSet.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg");
}else{
sRes = outputSet.GetChildByType("ResultSet").GetProperty("Result");
console.log(outputSet);
}
TextAdjust($('#'+func + "Out").show().text(sRes)[0]);
}
// auto-ajust textarea height
function TextAdjust(scope, minrows, maxrows) {
maxrows = maxrows>0?maxrows:30;
minrows = minrows>0?minrows:5;
var txt = scope.value;
var cols = scope.cols;
var arraytxt = txt.split('\n');
var rows = arraytxt.length;
if (rows > maxrows) {
scope.rows = maxrows;
} else if (rows < minrows) {
scope.rows = minrows;
} else {
scope.rows = rows;
}
}
// put active BC in the list with active applet's bc as selected
function LoadBCs(){
var a = [];
for(var i in SiebelApp.S_App.GetActiveBusObj().GetBCMap()){
var bc = SiebelApp.S_App.GetActiveBusObj().GetBCMap()[i];
if (a.indexOf(bc.GetName()) == -1 && bc.GetNumRows() > 0){
a.push(bc.GetName());
}
}
return a;
}
javascript:void function(){function e(){var e=$("#"+a).val();if(e){if(l)e=e.replace(/\n(\t|\s)*/gm,""),$("#"+a).val(e).attr("wrap","on"),l=!1;else try{var o=SiebelQueryLang.parse(e);e=t(o.expression,""),$("#"+a).val(e).attr("wrap","off"),l=!0}catch(r){console.log(r)}i($("#"+a)[0])}}function t(e,o,i){var r="";if("object"==typeof e){var a=e.par,l=e.not;if("bin"===e.type)r=t(e.left,o)+" "+e.operator+" "+t(e.right,o);else if("log"===e.type)a?(tt=o+" ",r="(\n",r+=tt+t(e.left,tt,!0),r+="\n"+tt+e.operator+" "+t(e.right,tt,!0),r+="\n"+o+")",a=!1):i?(r=t(e.left,o,!0),r+="\n"+o+e.operator+" "+t(e.right,o,!0)):r=t(e.left,o)+" "+e.operator+" "+t(e.right,o);else if("func"===e.type){var n=e.arguments.length,i=n>2,s=i?"\n"+o:"",p=i?s+" ":"";r=e.name+"(",e.arguments.forEach(function(e,i){r+=p+t(e,o+" ")+(n-1>i?", ":"")}),r+=s+")"}else"field"===e.type?r="["+e.field+"]":"param"===e.type?r="[&"+e.param+"]":"num"===e.type?r=e.value:"str"===e.type&&(r='"'+e.value+'"');a&&(r="("+r+")"),l&&(r="NOT "+r)}else r=e;return r}function o(){var e=$("#"+a).val(),t="";window.localStorage[a]=JSON.stringify(e);var o=document.getElementById(a);if(void 0!==o.selectionStart&&o.selectionStart!=o.selectionEnd)e=o.value.substring(o.selectionStart,o.selectionEnd);else if(void 0!==document.selection){o.focus();var r=document.selection.createRange();e=r.text}var l=SiebelApp.S_App.GetService("FWK Runtime"),n=SiebelApp.S_App.NewPropertySet();n.SetProperty("Expr",e),n.SetProperty("BC",$("#"+a+"List").val());var s=l.InvokeMethod("EvalExpr",n);"Error"==s.GetProperty("Status")?t=s.GetChildByType("Errors").GetChild(0).GetProperty("ErrMsg"):(t=s.GetChildByType("ResultSet").GetProperty("Result"),console.log(s)),i($("#"+a+"Out").show().text(t)[0])}function i(e,t,o){o=o>0?o:30,t=t>0?t:5;var i=e.value,r=(e.cols,i.split("\n")),a=r.length;a>o?e.rows=o:t>a?e.rows=t:e.rows=a}function r(){var e=[];for(var t in SiebelApp.S_App.GetActiveBusObj().GetBCMap()){var o=SiebelApp.S_App.GetActiveBusObj().GetBCMap()[t];-1==e.indexOf(o.GetName())&&o.GetNumRows()>0&&e.push(o.GetName())}return e}if("undefined"==typeof SiebelApp)alert("It works only in Siebel OUI session!");else{var a="SiebelEvalExpr";$("#"+a).parent().remove();var l=!1,n=r();if(0===n.length)alert("No BusComps/Records available!");else{var s='<div title="Runtime calculations"><label for="'+a+'List">Business Component:</label><select id = "'+a+'List" style="display:block"></select><label for="'+a+'">Expression:</label><textarea id = "'+a+'" rows="5" nowrap></textarea><label for="'+a+'Out">Results:</label><textarea id = "'+a+'Out" disabled rows="2"></textarea><style type="text/css">.ui-dialog textarea, .ui-dialog select {height:auto; width:100%; margin-bottom:10px} .ui-dialog label{margin-top:20px!}</style>',p=$(s).dialog({modal:!0,width:1024,heigth:640,open:function(){$("#"+a).focus(),$("#"+a+"Out").parent().keydown(function(e){e.ctrlKey&&13===e.keyCode&&o()}),$("#"+a+"List").append("<option>"+n.join("</option><option>")+"</option>"),$("#"+a+"List").val(SiebelApp.S_App.GetActiveView().GetActiveApplet().GetBusComp().GetName()),$("#"+a).val(JSON.parse(window.localStorage[a]))},close:function(){$(this).dialog("destroy").remove()},buttons:[{text:"Format/Linarise",click:e,id:"BeautyBtn"},{text:"Run (Ctrl+Enter)",click:o},{text:"Close (Esc)",click:function(){$(this).dialog("destroy").remove()}}]});$(p).find("#"+a).keyup(function(){i(this,5)}).keyup(),$(".ui-dialog #BeautyBtn").hide(),require(["3rdParty/SiebelQueryLang"],function(e){console.log("Beautifier loaded!"),$(".ui-dialog #BeautyBtn").show()})}}}();