Modify rootObject from within a Spring expression - javascript

Is it possible to use SpEL to modify the provided rootObject from within the expression?
Consider the following code to see what I mean:
Pojo:
public class Person {
private int age;
private boolean mature;
// getters and setters omitted for brevity
}
Expression:
Person person = new Person();
person.setAge(18);
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, this.getClass().getClassLoader());
ExpressionParser parser = new SpelExpressionParser(config);
Expression ex = parser.parseExpression("age >= 18");
boolean result = ex.getValue(person, Boolean.class);
See below what I want to do. Is that possible?
ex = parser.parseExpression("if (age >= 18) {mature = true}");
// person now has mature == true
Edit:
Instead of SpEL it is possible to use javax.script, which supports JavaScript and is included in the JVM. Here an example:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine jsEngine = manager.getEngineByName("JavaScript");
Person person = new Person();
person.setAge(18);
jsEngine.put("person", person);
jsEngine.eval("if (person.getAge() >= 18) { person.setMature(true); }");
// Calling person.isMature() in Java will now return `true`.

No you would get next an exception SpelParseException with the next message error After parsing a valid expression, there is still more data in the expression.
You may do it as two next options:
With a ternary Operator:
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, this.getClass().getClassLoader());
ExpressionParser parser = new SpelExpressionParser(config);
Boolean parsedValue = parser.parseExpression("age >= 18 ? Mature=true : Mature=false").getValue(person, Boolean.class);
System.out.println(person.getMature()); // Output = true
System.out.println(parsedValue); //Output = true
With two spEL expressions:
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, this.getClass().getClassLoader());
ExpressionParser parser = new SpelExpressionParser(config);
Expression ex = parser.parseExpression("age >= 18");
boolean result = ex.getValue(person, Boolean.class);
if(result)
parser.parseExpression("mature").setValue(person, "true");
System.out.println(person.getMature()); //Output = true

Related

Formulation Formatting

I want to save my formulas to SQL and use it in both the controller side and javascript side on my .net core project.
{H}+({FA}*2)+{VW}
Formulas are like this format. I want to change values of H, FA and VW with numbers.
string str2 = "{H}+({FA}*2)+{VW}";
string str3 = string.Format(str2, 60, 10, 20);
string value = new DataTable().Compute(str, null).ToString();
I can calculate like this on the controller side. (If there is a better way for it i can get advice too.)
I need to do on JavaScript side too. What should I do?
EDIT;
Btw C# code doesn't work, here is the working one i need a modular thing but i don't know how to do it.
var H = "150";
var VW = "200";
var FA = "20";
string str = $"{H}+{VW}*2";
string value = new DataTable().Compute(str, null).ToString();
I can use string.replace but I've 26 variable and will be complex. I'm adding more examples to formulas.
string formula1 = {H}+({FA}*2)+{VW};
string formula2 = {W}+({FA}*2)+{HW};
string formula3 = {FA}*2+{GFH}-{MTF};
string formula4 = {VSP}/{FA}+{GFV}*(A+B+C);
string formula5 = {TH}+{W}*2+{FT}*2;
***EDIT2:
I'm thinking about to use this on C# side.
public void CalculateTest()
{
List<varKeyDto> varKeys = new List<varKeyDto>(){
new varKeyDto(){
Variable = "H",
Value ="150"
},
new varKeyDto(){
Variable = "VW",
Value ="200"
},
new varKeyDto(){
Variable = "FA",
Value ="20"
},
};
string formula = "{H}+({FA}*2)+{VW}";
string cmptd = ReturnFormula(formula, varKeys);
}
public string ReturnFormula(string formula, List<varKeyDto> varKeys)
{
string formulaString = formula;
foreach (var varKey in varKeys)
{
formulaString = formulaString.Replace("{" + varKey.Variable + "}", varKey.Value);
}
string value = new DataTable().Compute(formulaString, null).ToString();
return value;
}
You could process the string to extract the variable names and make it valid JavaScript code and use all that to create a Function, here is an example:
const str = '{H}+({FA}*2)+{VW}';
const vars = str.match(/{[A-Z]+}/g).map(v => v.replace(/[{}]/g, ''));
const fnBody = str.replace(/[{}]/g, '');
const fn = new Function(...vars, `return ${fnBody}`);
const result = fn(60, 10, 20);
console.log(result);
The generated function looks something like this:
function (H, FA, VW) {
return H+(FA*2)+VW
}
You cannot format string with such custom literals, they have to be like - {0} {1} {2} and so on.
You can use .Replace instead -
var formulaString = formula.Replace("{H}", "1").Replace("{FA}", "2").Replace("{VW}", "3");
string value = new DataTable().Compute(formulaString, null).ToString();
In javascript you can use .replaceAll-
var formula = "{H}+({FA}*2)+{VW}";
var formulaString = formula.replaceAll("{H}", 1).replaceAll("{FA}", 2).replaceAll("{VW}", 3)
console.log(eval(formulaString));

Operator replacement "with" in strict mode

I have string value which entered user, for example the variable f.
f = "1/log(x)";
In vanilla JavaScript, i used operator with:
f = "with (Math) {" + f + "}";
The code work excellent in vanilla javascript, but i use Vue js and have problems in strict mode. I don't know how replace this operator. Who faced with this problem please answer me.
I try this:
let math = Math
math.f = f
console.log(f)
But nothing working.
Basically with is not recommended to be used because it can cause issues in programs. So what are your options?
define a bunch of globals
const sqrt = Math.sqrt
const log = Math.log
const test1 = new Function("a","return sqrt(a)")
const test2 = new Function("b","return log(b)")
console.log(test1(4))
console.log(test2(100))
Other option is to do the replacements with a reg exp
const fixMath = eq => eq.replace(/(sqrt|log|pow)/g,'Math.$1')
const test1 = new Function("a", fixMath("return sqrt(a)"))
const test2 = new Function("b", fixMath("return log(b)"))
const test3 = new Function("a", "b", fixMath("return pow(a, b)"))
const test4 = new Function("a", "b", fixMath("return sqrt(pow(a, 2) + pow(b, 2))"))
console.log(test1(4))
console.log(test2(100))
console.log(test3(10, 3))
console.log(test4(3, 3))

How to get the real value in a mathematic function

hello everyone i have this code that makes functions in mathematics but with this function the result is wrong o.O
x=0
"-3*X^2-16*X+2"
Code:
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.put("X", 0);
Object operation = engine.eval("-3*X^2-16*X+2");
//Object operation2 = engine.eval("(X+3)");
System.out.println("Evaluado operacion 1: " + operation);
//System.out.println("Evaluado operacion 2: " + operation2);
}
the result is 2 but i get 4
Evaluado operacion 1: 4
i have other code that i made
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package gustavo_santa;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.JOptionPane;
/**
*
* #author osmarvirux
*/
public class SerieB {
//xi and x4
int xi;
int x4;
//f(x) function variables
String positive_negative;
int num_one;
int elevation_one;
String add_subtract_one;
int num_two;
int elevation_two;
String add_subtract_two;
int num_three;
//results
String xi_result;
String x4_result;
public SerieB(int xi, int x4, String positive_negative, int num_one, int elevation_one, String add_subtract_one, int num_two, int elevation_two, String add_subtract_two, int num_three) {
this.xi = xi;
this.x4 = x4;
this.positive_negative = positive_negative;
this.num_one = num_one;
this.elevation_one = elevation_one;
this.add_subtract_one = add_subtract_one;
this.num_two = num_two;
this.elevation_two = elevation_two;
this.add_subtract_two = add_subtract_two;
this.num_three = num_three;
}
public void Procedure_xi(){
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
if (positive_negative == "-"){
try {
xi_result=(num_one*(Math.pow(xi, elevation_one)))+add_subtract_one+(num_two*(Math.pow(xi, elevation_two)))
+add_subtract_two+num_three;
Object result = engine.eval(xi_result);
System.out.println(xi_result+" = "+result);
} catch(ScriptException se) {
se.printStackTrace();
}
}else{
try {
xi_result=((-num_one*(Math.pow(xi, elevation_one)))+add_subtract_one+(num_two*(Math.pow(xi, elevation_two)))
+add_subtract_two+num_three);
Object result = engine.eval(xi_result);
System.out.println(xi_result+" = "+result);
} catch(ScriptException se) {
se.printStackTrace();
}
}
}
public void Procedure_x4(){
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
if (positive_negative == "-"){
try {
x4_result=(num_one*(Math.pow(x4, elevation_one)))+add_subtract_one+(num_two*(Math.pow(x4, elevation_two)))
+add_subtract_two+num_three;
Object result = engine.eval(x4_result);
System.out.println(x4_result+" = "+result);
} catch(ScriptException se) {
se.printStackTrace();
}
}else{
try {
x4_result=((-num_one*(Math.pow(x4, elevation_one)))+add_subtract_one+(num_two*(Math.pow(x4, elevation_two)))
+add_subtract_two+num_three);
Object result = engine.eval(x4_result);
System.out.println(x4_result+" = "+result);
} catch(ScriptException se) {
se.printStackTrace();
}
}
}
public static void main(String[] args){
//-3x^2-16x+2
SerieB obj = new SerieB(0, 1, "+", -3, 2, "-", 16, 1, "+", 2);
obj.Procedure_xi();
obj.Procedure_x4();
}
}
the result with this code is 2 but i wanna use
ScriptEngineManager manager = new ScriptEngineManager();ScriptEngineManager manager = new ScriptEngineManager();
because is a library and i think is more precise and i dont wanna use my code because there are many lines and i dont know if is 100% efficient. someone can help me? or give me a recomendation to resolve this mathematic functions? thanks a lot
The result you're getting is correct.
The confusion arises from the fact that what you're assuming to be the power operator (^) is actually the bitwise XOR operator in JavaScript (you're using a JavaScript script engine).
So, evaluating 0 ^ 2 yields 2, while evaluating Math.pow(0, 2) yields 0, hence the difference.
To get the result you expect, the expression would have to read:
-3*Math.pow(X,2)-16*X+2
You could pre-process the expression to replace the exponential operations with invocations of Math.pow():
let X = 0;
let expression = "-3*X^2-16*X+2"
let processed = expression.replace(/(\w+)\^(\w+)/g, 'Math.pow($1,$2)');
console.log(processed); // prints "-3*Math.pow(X,2)-16*X+2"
console.log(eval(processed)); // prints "2"
Using the script engine, that could look like:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.put("X", 0);
engine.put("expression", "-3*X^2-16*X+2");
engine.put("processed", engine.eval("expression.replace(/(\\w+)\\^(\\w+)/g, 'Math.pow($1,$2)')"));
System.out.println(engine.eval("eval(processed)")); // 2.0
Or, if you prefer to do the regular expression replacement in Java:
String expression = "-3*X^2-16*X+2";
String processed = expression.replaceAll("(\\w+)\\^(\\w+)", "Math.pow($1,$2)");
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.put("X", 0);
System.out.println(engine.eval(processed)); // 2.0
You have incorrect syntax for power. Replace -3*X^2-16*X+2 with -3*Math.pow(X,2)-16*X+2. See Javascript, What does the ^ (caret) operator do?
I think what's happening is your program is evaluating
(-3*0)^2 - 16*0 + 2 = 0^2 +2 = 2+2 =4
because the operator ^ in computer science mean bitwise exclusive or,
which basically means if the bits are both 1 or 0 then change them to 0, else 1. And 2 is represented by 10 while 0 is 0 so 2^0 = 2
Try replacing ^2 with *X
alternatively you can use Math.pow(X,n) , if you need exponentiation to some power n, but for squaring it's better to just write it out as X*X
The Below is Outdated Due to Edits to Question, but is still functional:
In the second part of your question you wrote
Object operation = engine.eval("-3*(X^2)-16*X +2");
String processed = operation.replace(/(\w+)\^(\w+)/g, 'Math.pow($1,$2)');
based on an answer by another user. You should have written
String expr = "-3*(X^2)-16*X +2";
String processed = expr.replaceAll("(\\w+)(\\^)(\\w+)", 'Math.pow($1,$2'));
Object operation = engine.eval(processed);

Passing and returning an object to / from a function in Javascript.

I've done some digging on the above topic but am now more confused than when I started.
I have a unit converter that I'm working on.
It's working fine as a base model but I'm now trying to make it more modular.
There are many units and many conversions.
My plan is to have a function that determines what type of conversion is required, temperature, area etc etc, that can then call the appropriate function to carry out the math.
I'm very new to JS which isn't helping matters as it could be a simple mistake that I'm making but it's just as likely that I'm getting huge errors.
I think the problem is passing the object to the next function and then using it.
I've played with the code a great deal and tried many different suggestions online but still no success.
here is my code:
<script type="text/javascript">
function Convert(from, to, units, res){
this.from = from;
this.to = to;
this.units = units;
this.res = res;
}
Convert.convertUnits = function(){
var measurementType = $(".from option:selected").attr("class");
var result = "invalid input";
var input = parseInt(this.units.val());
if(measurementType == "temp"){
var test = new Convert($("#from"), $("#to"), $("#units"), $("#result"));
test.convertTemp();
console.log('Did we get this far?!?! ::', measurementType);
}
console.log('or not???? ::', measurementType);
}
Convert.prototype.convertTemp = function(){
var result = "invalid input";
var input = parseInt(this.units.val());
var f = this.from.val();
var t = this.to.val()
if(!isNaN(input)) {
if(f == "degC"){
if(t == "degF"){
result = input * 1.8 + 32;
}
if(t == "kelvin"){
result = input + 273.15;
}
}
}
console.log('Parsed input is', input, "and result is", result);
this.res.val(result);
return result;
}
//var calcTempTest = new Convert($("#from"), $("#to"), $("#units"), $("#result"));
//var test = new Convert($("#from"), $("#to"), $("#units"), $("#result"));
$("#btnConvert").click.convertUnits();
</script>
The first obvious problem is this line:
$("#btnConvert").click.convertUnits();
This tries to call a convertUnits() method defined on the click method of the jQuery object returned by $("#btnConvert"). There is no such method, so you get'll get an error about how click has no method 'convertUnits'.
What you want to be doing there is binding the convertUnits() function as a click handler, which you do by passing it to the .click() method as an argument:
$("#btnConvert").click(Convert.convertUnits)
It doesn't make sense to have declared convertUnits() as a property of Convert(), though, so (although it will work as is) I'd change it to just be:
function convertUnits() {
// your code here
}
$("#btnConvert").click(convertUnits);
The only other thing stopping the code working is that on this line:
var input = parseInt(this.units.val());
...you use this assuming it will be a Convert object with a units property but you haven't yet created a Convert object - you do that inside the if(measurementType == "temp") block with this line:
var test = new Convert($("#from"), $("#to"), $("#units"), $("#result"));
So move that line to the beginning of the function and then use test instead of this:
function convertUnits(){
var test = new Convert($("#from"), $("#to"), $("#units"), $("#result"));
var measurementType = $(".from option:selected").attr("class");
var result = "invalid input";
var input = parseInt(test.units.val());
if(measurementType == "temp"){
test.convertTemp();
console.log('Did we get this far?!?! ::', measurementType);
}
console.log('or not???? ::', measurementType);
}
Working demo: http://jsfiddle.net/jT2ke/
Some unrelated advice: parseInt() doesn't really make sense for a number to feed into your converter, because the user might want to enter decimal values. You can use parseFloat() instead, or the unary plus operator:
var input = +test.units.val();
But if you want parseInt() it is generally recommended to pass it a second argument to specify the radix:
var input = parseInt(test.units.val(), 10);
...because otherwise if the input text has a leading zero some browsers will assume the value is octal rather than base ten. (parseFloat() and the unary plus don't have that issue.)
I think you should not implement the method convertUnits inside Convert object. And the new code will look like the following:
convertUnits = function(){
var measurementType = $(".from option:selected").attr("class");
var result = "invalid input";
if(measurementType == "temp"){
var test = new Convert($("#from"), $("#to"), $("#units"), $("#result"));
test.convertTemp();
console.log('Did we get this far?!?! ::', measurementType);
}
console.log('or not???? ::', measurementType);
}
Now you can initiate the convertUnits on the button click:
$("#btnConvert").click(function(){new convertUnits()});

Javascript indexOf not working

The following code looks for the name of a person in a message that they have entered using the indexOf method.
However it is returning the not present result even when the name is present. If I only Darren as the cardMessage it works.
Can anyone point out what is wrong.
<%
firstName = "Darren"
cardMessage = "Is Darren in the message?"
cardMessage = CleanX(cardMessage)
firstName = UCase(firstName)
cardMessage = UCase(cardMessage)
Function CleanX(strString)
Set regEx = New RegExp
regEx.Pattern = "[^a-z0-9 ]+"
regEx.IgnoreCase = True
regEx.Global = True
CleanX = regEx.Replace(strString, "")
End Function
%>
<p><%=cardMessage%></p>
<p><%=firstName%></p>
Click Here
<script type="text/javascript">
s1 = new String("<%=firstName%>")
s2 = new String("<%=cardMessage%>")
function check_message()
{
var purchaser=s1;
var purchaser_ok=purchaser.indexOf(s2);
if (purchaser_ok==-1)
{
confirm('Name is NOT in message');
}
else
alert('Name is in message');
}
</script>
You're doing it backwards. It should be
var purchaser_ok = s2.indexOf(purchaser);
The ".indexOf()" function checks to see whether the argument you pass into it is in the string that's used as the receiver (the context object; that is, the string before the "." when you call it).
You have it backwards.
s2.indexOf(purchaser)

Categories