-
Notifications
You must be signed in to change notification settings - Fork 0
Computing Functions AddOwnFunction ru
Для создания своей собственной функции вы должны:
- Создать класс функции.
- Реализовать метод функции.
- Определить входящие параметры функции.
- Зарегистрировать новую функцию в
ObjCalcEngine
.
Теперь более подробно.
Класс для функции должен быть унаследован от a2u.tn.utils.computer.calculator.Function
.
Это может быть любой класс внутренний или внешний.
В созданном классе необходимо реализовать метод run
, который будет выполнять задуманное действие функции.
/**
* Invoke function to execution
*
* @param calculator Calculator for executing or type conversion
* @param params Incoming params
* @param paramValues Prepared values of parameters
* @param ctx Data for calculating
* @return Result of execution function
*/
@Override
public Object run(Calculator calculator, List<FormulaPart> params, Map<String, Object> paramValues, CalcContext ctx) {
...
В параметре calculator
придёт текущий калькулятор, который выполняет запрос.
В параметре paramValues
придут значения настроенных входящие параметров, приведённые к запрашиваемому типу.
В параметре params
придут все входящие значения переданные в функцию. В сыром виде как есть. Для получения значений из этих параметров необходимо произвести расчёт.
Про настройку параметров смотрите в п.3
В параметре ctx
придёт контекст выполнения.
Если на вход калькулятора поступает объект содержащий список значений,
то он начинает применять формулы для каждой строки отдельно.
Узнать весь список значений входящего объекта можно методом ctx.getAllRows()
,
текущее обрабатываемо значение из списка можно получить методом ctx.getRowData()
,
а позицию текущего обрабатываемого значения методом ctx.getRowIndex()
.
Определение входящих параметров позволяет калькулятору проверять какие парамеры поступили на вход,
конвертировать их в запрашиваемый тип, и выдавать понятные сообщения об ошибках в параметрах.
Если функция принимает параметры, то нужно переопределить метод initParameters
.
protected List<Parameter> initParameters() {
...
В этом методе вы можете настроить каждый параметр, задать следующие характеристики:
type
Тип значения параметра. Калькулятор автоматически сконвертирует входящее значение в этот тип.
name
Имя параметра. Параметр можно будет получить из мапы params
.
required
Если параметр обязательный, то true.
defaultValue
Значение параметра по умолчанию. Используйте если параметр не обязательный, но должен иметь значение.
@Override
protected List<Parameter> initParameters() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(new Parameter(String.class, "stringA", false, null));
parameters.add(new Parameter(String.class, "stringB", false, null));
return parameters;
}
Если у вас параметр обязательный, то можно применить сокращённую версию конструктора
@Override
protected List<Parameter> initParameters() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(new Parameter(String.class, "stringA"));
parameters.add(new Parameter(String.class, "stringB"));
return parameters;
}
Если функция не принимает параметры, то этот метод можно не переопределять.
Если функция принимает параметры, но вы не хотите чтобы калькулятор о них заботился, то переопределите этот метод и верните пустой массив.
@Override
protected List<Parameter> initParameters() {
return new ArrayList<>();
}
Для того, чтобы функция работала, необходимо сказать калькулятору о наличии новой функции
ObjCalcEngine engine = new ObjCalcEngine();
engine.addFunction(new Concat(), "cnct");
Здесь Concat
- это новая функция, а cnct
имя новой функции.
Имя функции не чувствительно к регистру, поэтому внутри калькулятора они хранятся приведёнными к нижнему регистру.
Если не задать имя новой функции, то будет взято имя класса реализующего эту функцию.
Вы можете создавать синонимы функций, просто указывая разные имена.
package a2u.tn.utils.computer.calcobj.functions;
import a2u.tn.utils.computer.calcobj.ObjCalcEngine;
import a2u.tn.utils.computer.calculator.CalcContext;
import a2u.tn.utils.computer.calculator.Calculator;
import a2u.tn.utils.computer.calculator.Function;
import a2u.tn.utils.computer.formula.FormulaPart;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class OwnFunctionTest {
private static class Concat extends Function {
/**
* Return descriptors for incoming parameters
*
* @return descriptors for incoming parameters
*/
@Override
protected List<Parameter> initParameters() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(new Parameter(String.class, "stringA"));
parameters.add(new Parameter(String.class, "stringB"));
return parameters;
}
/**
* Invoke function to execution
*
* @param calculator Calculator for executing or type conversion
* @param params Other params
* @param paramValues Prepared values of parameters
* @param ctx Data for calculating
* @return Result of execution function
*/
@Override
public Object run(Calculator calculator, List<FormulaPart> params, Map<String, Object> paramValues, CalcContext ctx) {
String stringA = (String) paramValues.get("stringA");
String stringB = (String) paramValues.get("stringB");
return stringA+stringB;
}
}
@Test
public void countTest() {
ObjCalcEngine engine = new ObjCalcEngine();
Function fn = new Concat();
engine.addFunction(fn);
engine.addFunction(fn, "cnct");
Function fn1 = engine.getFunction(Concat.class.getSimpleName().toLowerCase());
Function fn2 = engine.getFunction("cnct");
assertEquals(fn, fn1);
assertEquals(fn, fn2);
assertEquals("AB", engine.calc("cnct('A', 'B')"));
}
}
Здесь внутри тестового класса определяется новая функция Concat
, которая в методе countTest()
регистрируется в калькуляторе.
- Home
- Extendable Query Language
- Computing
- Simple Usage
- Own Value Extraction
- Functions
- What is Type
- Known Types
- Add Own Type
- Data conversion
- Generate SQL Query
- Find files