Add common functions #302

This commit is contained in:
Francis Dong
2021-09-06 23:32:19 +08:00
committed by dxfeng10
parent f086029b51
commit d2e689f58c
7 changed files with 645 additions and 14 deletions

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package we.fizz.function;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Common Functions
*
* @author Francis Dong
*
*/
public class CommonFunc implements IFunc {
private static final Logger LOGGER = LoggerFactory.getLogger(CommonFunc.class);
private static CommonFunc singleton;
public static CommonFunc getInstance() {
if (singleton == null) {
synchronized (CommonFunc.class) {
if (singleton == null) {
CommonFunc instance = new CommonFunc();
instance.init();
singleton = instance;
}
}
}
return singleton;
}
private CommonFunc() {
}
public void init() {
FuncExecutor.register(NAME_SPACE_PREFIX + "common.iif", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.equals", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.isNull", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.isNotNull", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.isBlank", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.isNotBlank", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.isEmpty", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "common.isNotEmpty", this);
}
/**
* Immediate if function (iif)
*
* @param exprResult the result of expression that is to be evaluated.
* @param truepart defines what the iif function returns if the exprResult is
* true.
* @param falsepart defines what the iif function returns if the exprResult is
* false.
* @return returns the truepart or falsepart based on the value of the
* exprResult
*/
public Object iif(boolean exprResult, Object truepart, Object falsepart) {
return exprResult ? truepart : falsepart;
}
/**
*
* @param obj1
* @param obj2
* @return
*/
public boolean equals(Object obj1, Object obj2) {
if (obj1 == null) {
if (obj2 == null) {
return true;
}
return false;
}
return obj1.equals(obj2);
}
public boolean isNull(Object obj) {
return null == obj;
}
public boolean isNotNull(Object obj) {
return null != obj;
}
public boolean isBlank(String obj) {
return StringUtils.isBlank(obj);
}
public boolean isNotBlank(String obj) {
return StringUtils.isNotBlank(obj);
}
@SuppressWarnings("rawtypes")
public boolean isEmpty(Object obj) {
if (obj == null) {
return true;
}
if (obj instanceof Collection) {
return ((Collection) obj).isEmpty();
} else if (obj instanceof Map) {
return ((Map) obj).isEmpty();
} else if (obj.getClass().isArray()) {
return Array.getLength(obj) == 0;
} else if (obj instanceof CharSequence) {
return ((CharSequence) obj).length() == 0;
}
return false;
}
public boolean isNotEmpty(Object obj) {
return !isEmpty(obj);
}
}

View File

@@ -55,6 +55,8 @@ public class FuncExecutor {
private static Pattern NUMBER_PATTERN = Pattern
.compile("^[-\\+]?[\\d]+\\s*[,\\)]{1}|^[-\\+]?[\\d]+\\.[\\d]+\\s*[,\\)]{1}");
private static Pattern FLOAT_PATTERN = Pattern.compile("^[-\\+]?[\\d]+\\.[\\d]+\\s*[,\\)]{1}");
private static FuncExecutor singleton;
@@ -251,7 +253,7 @@ public class FuncExecutor {
throw new FizzRuntimeException(
String.format("invalid argument: %s, Function Expression: %s", argsStr, funcExpression));
}
} else if (argsStr.matches("^null\\s*,") || argsStr.matches("^null\\s*\\)")) { // null
} else if (argsStr.matches("^null\s*,.*") || argsStr.matches("^null\s*\\).*")) { // null
if (isVarArgs && i == paramTypes.length - 1) {
varArgs.add(null);
Object arr = Array.newInstance(clazz.getComponentType(), varArgs.size());
@@ -265,7 +267,7 @@ public class FuncExecutor {
argsStrContainer = this.trimArgStr(argsStrContainer, 4, isVarArgs, paramTypes.length, funcExpression);
argsStr = argsStrContainer.getArgsStr();
i = argsStrContainer.getIndex();
} else if (argsStr.matches("^true\\s*,") || argsStr.matches("^true\\s*\\)")) { // boolean
} else if (argsStr.matches("^true\s*,.*") || argsStr.matches("^true\s*\\).*")) { // boolean
if (isVarArgs && i == paramTypes.length - 1) {
varArgs.add(true);
args[i] = varArgs.toArray(new Boolean[varArgs.size()]);
@@ -275,7 +277,7 @@ public class FuncExecutor {
argsStrContainer = this.trimArgStr(argsStrContainer, 4, isVarArgs, paramTypes.length, funcExpression);
argsStr = argsStrContainer.getArgsStr();
i = argsStrContainer.getIndex();
} else if (argsStr.matches("^false\\s*,") || argsStr.matches("^false\\s*\\)")) { // boolean
} else if (argsStr.matches("^false\s*,.*") || argsStr.matches("^false\s*\\).*")) { // boolean
if (isVarArgs && i == paramTypes.length - 1) {
varArgs.add(false);
args[i] = varArgs.toArray(new Boolean[varArgs.size()]);
@@ -321,7 +323,16 @@ public class FuncExecutor {
// Number
String strNum = StringUtils.trim(matchedStr.substring(0, pos - 1));
if (isVarArgs && i == paramTypes.length - 1) {
Object arg = ConvertUtils.convert(strNum, clazz.getComponentType());
Object arg = null;
if (clazz.getComponentType().equals(Object.class)) {
if (FLOAT_PATTERN.matcher(argsStr).find()) {
arg = ConvertUtils.convert(strNum, Double.class);
} else {
arg = ConvertUtils.convert(strNum, Long.class);
}
} else {
arg = ConvertUtils.convert(strNum, clazz.getComponentType());
}
varArgs.add(arg);
Object arr = Array.newInstance(clazz.getComponentType(), varArgs.size());
for (int j = 0; j < varArgs.size(); j++) {
@@ -329,7 +340,16 @@ public class FuncExecutor {
}
args[i] = arr;
} else {
Object arg = ConvertUtils.convert(strNum, clazz);
Object arg = null;
if (clazz.equals(Object.class)) {
if (FLOAT_PATTERN.matcher(argsStr).find()) {
arg = ConvertUtils.convert(strNum, Double.class);
} else {
arg = ConvertUtils.convert(strNum, Long.class);
}
} else {
arg = ConvertUtils.convert(strNum, clazz);
}
args[i] = arg;
}
argsStrContainer = this.trimArgStr(argsStrContainer, pos - 1, isVarArgs, paramTypes.length,
@@ -467,7 +487,7 @@ public class FuncExecutor {
if (!"\\".equals(prevChar)) {
return pos;
}
pos = ep.indexOf("\"", pos);
pos = ep.indexOf("\"", pos + 1);
}
return -1;
}

View File

@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
* @author Francis Dong
*
*/
@SuppressWarnings("unused")
public class MathFunc implements IFunc {
private static final Logger LOGGER = LoggerFactory.getLogger(MathFunc.class);
@@ -70,6 +71,12 @@ public class MathFunc implements IFunc {
FuncExecutor.register(NAME_SPACE_PREFIX + "math.maxDecimal", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.minDecimal", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.scaleDecimal", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.compare", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.equals", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.lt", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.le", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.gt", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "math.ge", this);
}
public long absExact(long a) {
@@ -159,4 +166,60 @@ public class MathFunc implements IFunc {
return BigDecimal.valueOf(a).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* Compares number x with the specified number y.
*
* @param x number
* @param y number
* @return -1, 0, or 1 as x is numerically less than, equal to, or greater than
* y.
*/
public int compare(double x, double y) {
return BigDecimal.valueOf(x).compareTo(BigDecimal.valueOf(y));
}
public boolean equals(double x, double y) {
return BigDecimal.valueOf(x).equals(BigDecimal.valueOf(y));
}
/**
* Checks if x is less than y
* @param x
* @param y
* @return
*/
public boolean lt(double x, double y) {
return BigDecimal.valueOf(x).compareTo(BigDecimal.valueOf(y)) == -1;
}
/**
* Checks if x is less than or equals y
* @param x
* @param y
* @return
*/
public boolean le(double x, double y) {
return BigDecimal.valueOf(x).compareTo(BigDecimal.valueOf(y)) <= 0;
}
/**
* Checks if x is greater than y
* @param x
* @param y
* @return
*/
public boolean gt(double x, double y) {
return BigDecimal.valueOf(x).compareTo(BigDecimal.valueOf(y)) == 1;
}
/**
* Checks if x is greater than or equals y
* @param x
* @param y
* @return
*/
public boolean ge(double x, double y) {
return BigDecimal.valueOf(x).compareTo(BigDecimal.valueOf(y)) >= 0;
}
}

View File

@@ -53,6 +53,9 @@ public class StringFunc implements IFunc {
}
public void init() {
FuncExecutor.register(NAME_SPACE_PREFIX + "string.equals", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.equalsIgnoreCase", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.compare", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.concat", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.concatws", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.substring", this);
@@ -62,6 +65,76 @@ public class StringFunc implements IFunc {
FuncExecutor.register(NAME_SPACE_PREFIX + "string.toUpperCase", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.toLowerCase", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.uuid", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "string.toString", this);
}
/**
* <p>
* Compares two Strings, returning {@code true} if they represent equal
* sequences of Strings.
* </p>
*
* <p>
* {@code null}s are handled without exceptions. Two {@code null} references are
* considered to be equal. The comparison is <strong>case sensitive</strong>.
* </p>
*
* <pre>
* equals(null, null) = true
* equals(null, "abc") = false
* equals("abc", null) = false
* equals("abc", "abc") = true
* equals("abc", "ABC") = false
* </pre>
*
* @param str1 the first String, may be {@code null}
* @param str2 the second String, may be {@code null}
* @return {@code true} if the Strings are equal (case-sensitive), or both
* {@code null}
*/
public boolean equals(String str1, String str2) {
return StringUtils.equals(str1, str2);
}
/**
* <p>
* Compares two Strings, returning {@code true} if they represent equal
* sequences of Strings, ignoring case.
* </p>
*
* <p>
* {@code null}s are handled without exceptions. Two {@code null} references are
* considered equal. The comparison is <strong>case insensitive</strong>.
* </p>
*
* <pre>
* equalsIgnoreCase(null, null) = true
* equalsIgnoreCase(null, "abc") = false
* equalsIgnoreCase("abc", null) = false
* equalsIgnoreCase("abc", "abc") = true
* equalsIgnoreCase("abc", "ABC") = true
* </pre>
*
* @param str1 the first String, may be {@code null}
* @param str2 the second String, may be {@code null}
* @return {@code true} if the Strings are equal (case-insensitive), or both
* {@code null}
*/
public boolean equalsIgnoreCase(String str1, String str2) {
return StringUtils.equalsIgnoreCase(str1, str2);
}
/**
* Compare two Strings lexicographically
*
* @param str1
* @param str2
* @return -1, 0, 1, if {@code str1} is respectively less, equal or greater than
* {@code str2}
*/
public int compare(String str1, String str2) {
int n = StringUtils.compare(str1, str2);
return n == 0 ? 0 : (n > 0 ? 1 : -1);
}
/**
@@ -172,9 +245,17 @@ public class StringFunc implements IFunc {
}
return str.toLowerCase();
}
/**
*
* @return UUID
*/
public String uuid() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
public String toString(Object obj) {
return obj == null ? null : obj.toString();
}
}

View File

@@ -0,0 +1,241 @@
/*
* Copyright (C) 2021 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package we.fizz.function;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.noear.snack.ONode;
import we.fizz.input.PathMapping;
/**
*
* @author Francis Dong
*
*/
class CommonFuncTests {
@Test
void contextLoads() {
}
private Map<String, Object> createRecord(String key, Object value) {
Map<String, Object> m = new HashMap<>();
m.put(key, value);
return m;
}
private ONode getCtxNode() {
ONode ctxNode = ONode.load(new HashMap());
Map<String, Object> m = new HashMap<>();
m.put("a", "1");
m.put("b", "1");
m.put("d", "");
List<Object> list = new ArrayList<>();
list.add(createRecord("a", "a1"));
list.add(createRecord("a", "a2"));
list.add(createRecord("a", "a3"));
List<Object> list2 = new ArrayList<>();
PathMapping.setByPath(ctxNode, "data.m", m, true);
PathMapping.setByPath(ctxNode, "data.m2", new HashMap<>(), true);
PathMapping.setByPath(ctxNode, "data.list", list, true);
PathMapping.setByPath(ctxNode, "data.list2", list2, true);
return ctxNode;
}
@Test
void testIif() {
String funcExpression = "fn.common.iif(true, \"abc\", \"xyz\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals("abc", result.toString());
}
@Test
void testIif2() {
String funcExpression = "fn.common.iif(false, \"abc\", \"xyz\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals("xyz", result.toString());
}
@Test
void testIif3() {
String funcExpression = "fn.common.iif(false, \"abc\", 123)";
Long result = (Long)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(123, result.intValue());
}
@Test
void testIif4() {
String funcExpression = "fn.common.iif(false, \"abc\", 123.4)";
Double result = (Double)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(123.4, result);
}
@Test
void testIif5() {
String funcExpression = "fn.common.iif(false, \"abc\", true)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals() {
String funcExpression = "fn.common.equals(\"abc\", true)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(false, result);
}
@Test
void testEquals2() {
String funcExpression = "fn.common.equals(\"abc\", \"abc\")";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals3() {
String funcExpression = "fn.common.equals(123, 123)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals4() {
String funcExpression = "fn.common.equals(123, 123.0)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(false, result);
}
@Test
void testEquals5() {
String funcExpression = "fn.common.equals(true, true)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals6() {
String funcExpression = "fn.common.equals(123.2, 123.2)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals7() {
String funcExpression = "fn.common.equals(null, 123.2)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(false, result);
}
@Test
void testEquals8() {
String funcExpression = "fn.common.equals(null, null)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals9() {
String funcExpression = "fn.common.equals(123, null)";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(false, result);
}
@Test
void testIsNull() {
ONode ctx = getCtxNode();
String funcExpression = "fn.common.isNull({data.m.c})";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
}
@Test
void testIsNotNull() {
ONode ctx = getCtxNode();
String funcExpression = "fn.common.isNotNull({data.m.a})";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
}
@Test
void testIsBlank() {
ONode ctx = getCtxNode();
String funcExpression = "fn.common.isBlank({data.m.c})";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
}
@Test
void testIsNotBlank() {
ONode ctx = getCtxNode();
String funcExpression = "fn.common.isNotBlank({data.m.a})";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
}
@Test
void testIsEmpty() {
ONode ctx = getCtxNode();
String funcExpression = "fn.common.isEmpty({data.list2})";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
funcExpression = "fn.common.isEmpty({data.m2})";
result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
funcExpression = "fn.common.isEmpty({data.m.x})";
result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
funcExpression = "fn.common.isEmpty({data.m.d})";
result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
}
@Test
void testIsNotEmpty() {
ONode ctx = getCtxNode();
String funcExpression = "fn.common.isNotEmpty({data.list})";
Boolean result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
funcExpression = "fn.common.isNotEmpty({data.m})";
result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
funcExpression = "fn.common.isNotEmpty({data.m.a})";
result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(true, result);
funcExpression = "fn.common.isNotEmpty({data.m.y})";
result = (Boolean)FuncExecutor.getInstance().exec(ctx, funcExpression);
assertEquals(false, result);
}
}

View File

@@ -18,13 +18,7 @@ package we.fizz.function;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.noear.snack.ONode;
import we.fizz.input.PathMapping;
/**
*
@@ -175,5 +169,47 @@ class MathFuncTests {
double result = (double) FuncExecutor.getInstance().exec(null, funcExpression);
// System.out.println(result);
}
@Test
void testcompare() {
String funcExpression = "fn.math.compare(4.8456,2)";
int result = (int) FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(1, result);
}
@Test
void testequals() {
String funcExpression = "fn.math.equals(3,3)";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testLt() {
String funcExpression = "fn.math.lt(3,23)";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testle() {
String funcExpression = "fn.math.le(3,3)";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testgt() {
String funcExpression = "fn.math.gt(3,1)";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testge() {
String funcExpression = "fn.math.ge(3,3)";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
}

View File

@@ -32,10 +32,46 @@ import we.fizz.input.PathMapping;
*
*/
class StringFuncTests {
@Test
void contextLoads() {
}
@Test
void testEquals() {
String funcExpression = "fn.string.equals(\"abc\", \"abc\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testEquals2() {
String funcExpression = "fn.string.equals(null, \"abc\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(false, result);
}
@Test
void testEquals3() {
String funcExpression = "fn.string.equals(\"ab\\\"c\", \"abc\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(false, result);
}
@Test
void testEqualsIgnoreCase() {
String funcExpression = "fn.string.equalsIgnoreCase(\"abc\", \"Abc\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(true, result);
}
@Test
void testcompare() {
String funcExpression = "fn.string.compare(\"abc\", \"cde\")";
Object result = FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals(-1, result);
}
@Test
void testConcat() {
@@ -126,6 +162,25 @@ class StringFuncTests {
assertEquals("aBc".toLowerCase(), result);
}
@Test
void testToString() {
String funcExpression = "fn.string.toString(\"aBc\")";
String result = (String)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals("aBc", result);
}
@Test
void testToString2() {
String funcExpression = "fn.string.toString(true)";
String result = (String)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals("true", result);
}
@Test
void testToString3() {
String funcExpression = "fn.string.toString(234)";
String result = (String)FuncExecutor.getInstance().exec(null, funcExpression);
assertEquals("234", result);
}
}