com.anysoft.formula.Function Maven / Gradle / Ivy
package com.anysoft.formula;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
import java.util.Vector;
import java.util.regex.Pattern;
/**
* Function
* @author duanyy
* @version 1.0.0
* @version 1.6.12.4 [20171029 duanyy]
* - 增加floor,round,ceil等函数;
*/
abstract public class Function extends Expression{
/**
* constructor
* @param _prototype the prototype of the function
*/
public Function(String _prototype) {
super(Operator.OP_Extend);
prototype = _prototype;
}
/**
* arguments
*/
protected Vector args = new Vector();
/**
* prototype
*/
protected String prototype = "Function";
/**
* to get argument list
* @return argument list
*/
public Expression [] arguments(){
return args.toArray(new Expression[0]);
}
/**
* to get count of argument
* @return count
*/
public int getArgumentCount(){
return args.size();
}
/**
* to get argument by index
* @param index index of argument
* @return argument
*/
public Expression getArgument(int index){
return args.elementAt(index);
}
public String getOperatorPrototype() {
return prototype;
}
public String toString(){
StringBuffer buffer = new StringBuffer();
buffer.append(getOperatorPrototype());
buffer.append("(");
for (int i = 0 ; i < getArgumentCount() ; i ++){
if (i != 0){
buffer.append(",");
}
buffer.append(getArgument(i).toString());
}
buffer.append(")");
return buffer.toString();
}
/**
* to add a argument to argument list
* @param arg the argument added
* @return this
*/
public Function addArgument(Expression arg){
if (arg == null){
throw new FormulaException("argument can not be null.");
}
checkArgument(arg);
args.add(arg);
return this;
}
/**
* to check argument before added
* @param arg the argument to be checked
* @throws FormulaException an exception when error occurs
*/
abstract public void checkArgument(Expression arg) throws FormulaException;
/**
* Choice function
*
* Make choice between 2 expressions with a condition expression.
* Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* choice(bool_expr,expr1,expr2)
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:if bool_expr is true ,expr1 otherwise expr2.
*
* @author duanyy
* @version 1.0.0
*/
public static class Choice extends Function{
/**
* constructor
*/
public Choice() {
super("choice");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 3){
throw new FormulaException("choice function only supports 3 arguments.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 3){
throw new FormulaException("choice function need 3 arguments.we have " + getArgumentCount());
}
Expression boolExpr = getArgument(0);
ExprValue boolValue = boolExpr.getValue(provider);
if (boolValue.getBoolean()){
return getArgument(1).getValue(provider);
}else{
return getArgument(2).getValue(provider);
}
}
}
/**
* Nvl
*
*
* if a expr is null,give a default value.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~
* nvl(expr,default_expr)
* ~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:expr if expr is not null,or default_expr
* @author duanyy
* @version 1.0.0
*/
public static class Nvl extends Function{
public Nvl() {
super("nvl");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 2){
throw new FormulaException("nvl function only supports 2 arguments.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 2){
throw new FormulaException("nvl function need 2 arguments.we have " + getArgumentCount());
}
ExprValue value = getArgument(0).getValue(provider);
if (value == null){
value = getArgument(1).getValue(provider);
}
return value;
}
}
/**
* Parse string value into date value
*
*
* Parse string value into date value with a date pattern.The default pattern is 'yyyyMMddHHmmss'
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~
* to_date(str_expr[,pattern])
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:date_expr
* @author duanyy
* @version 1.0.0
*/
public static class Char2Date extends Function{
public Char2Date() {
super("to_date");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 2){
throw new FormulaException("to_date function only supports 1 or 2 arguments.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() < 1){
throw new FormulaException("to_date function need at least 1 argument.we have " + getArgumentCount());
}
String pattern = "yyyyMMddHHmmss";
if (getArgument(1) != null){
pattern = getArgument(1).getValue(provider).getString();
}
String value = getArgument(0).getValue(provider).getString();
return new ExprValue(DateUtil.parseDate(value, pattern));
}
}
/**
* Format date value to string value
*
*
Format date value to string value with a date pattern.The default pattern is 'yyyyMMddHHmmss'
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* to_char(date_expr[,pattern])
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:string_expr
* @author duanyy
* @version 1.0.0
*/
public static class Date2Char extends Function{
public Date2Char() {
super("to_char");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 2){
throw new FormulaException("to_char function only supports 1 or 2 arguments.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() < 1){
throw new FormulaException("to_char function need at least 1 argument.we have " + getArgumentCount());
}
String pattern = "yyyyMMddHHmmss";
if (getArgument(1) != null){
pattern = getArgument(1).getValue(provider).getString();
}
Date value = getArgument(0).getValue(provider).getDate();
return new ExprValue(DateUtil.formatDate(value, pattern));
}
}
/**
* Convert string value to long value
*
*
Convert string value to long value.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~
* to_long(string_expr)
* ~~~~~~~~~~~~~~~~~~~~~
*
* return:long_expr
* @author duanyy
* @version 1.0.0
*/
public static class ToLong extends Function{
public ToLong() {
super("to_long");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_long function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_long function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
return new ExprValue(Long.valueOf(value));
}
}
/**
* Convert string value to double value
*
* Convert string value to double value.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~
* to_double(string_expr)
* ~~~~~~~~~~~~~~~~~~~~~~
*
* return:double_expr
*
* @author duanyy
* @version 1.0.0
*/
public static class ToDouble extends Function{
public ToDouble() {
super("to_double");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_double function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_double function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
return new ExprValue(Double.valueOf(value));
}
}
public static class ToBoolean extends Function{
public ToBoolean() {
super("to_bool");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_double function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_double function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
return new ExprValue(BooleanUtils.toBoolean(value));
}
}
public static class Round extends Function{
public Round() {
super("round");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_double function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_double function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
double doubleValue = Double.parseDouble(value);
return new ExprValue(Math.round(doubleValue));
}
}
public static class Ceil extends Function{
public Ceil() {
super("ceil");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_double function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_double function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
Double doubleValue = Math.ceil(Double.parseDouble(value));
return new ExprValue(doubleValue.longValue());
}
}
public static class Floor extends Function{
public Floor() {
super("floor");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_double function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_double function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
Double doubleValue = Math.floor(Double.parseDouble(value));
return new ExprValue(doubleValue.longValue());
}
}
/**
* 自动类型转换函数
*
* @since 1.6.12.57 [20200103]
*/
public static class AutoType extends Function{
public static final Pattern lType = Pattern.compile("^[\\+\\-]?[0-9]*$");
public static final Pattern dType = Pattern.compile("^[\\+\\-]?[0-9]*\\.?[0-9]*$");
public static final Pattern eType = Pattern.compile("^[\\+\\-]?[0-9]+[\\.][0-9]*?[Ee][+-]?[0-9]+?$");
public AutoType() {
super("t");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_long function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_long function need 1 argument.");
}
String value = getArgument(0).getValue(provider).getString();
if (StringUtils.isEmpty(value)){
return new ExprValue(0);
}
if (isLong(value)){
return new ExprValue(getLong(value,0));
}
if (isDouble(value)){
return new ExprValue(getDouble(value,0.0));
}
return value != null ? new ExprValue(value) : null;
}
public static boolean isLong(String v){
return lType.matcher(v).find();
}
public static long getLong(String v,long dft){
try{
return Long.parseLong(v);
}catch (NumberFormatException ex){
return dft;
}
}
public static boolean isDouble(String v){
return dType.matcher(v).find() || eType.matcher(v).find();
}
public static double getDouble(String v,double dft){
try{
return Double.parseDouble(v);
}catch (NumberFormatException ex){
return dft;
}
}
}
/**
* Convert other value to string value
*
*
Convert other value to string value.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~
* to_string(expr)
* ~~~~~~~~~~~~~~~~~~
*
* return:string_expr
* @author duanyy
* @version 1.0.0
*/
public static class ToString extends Function{
public ToString() {
super("to_string");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("to_string function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("to_string function need 1 argument.");
}
String value = getArgument(0).getValue(provider).toString();
return new ExprValue(value);
}
}
/**
* Get string length
*
*
Get string length.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~
* strlen(str_expr)
* ~~~~~~~~~~~~~~~~~
*
* return:long
* @author duanyy
* @version 1.0.0
*/
public static class StrLen extends Function{
public StrLen() {
super("strlen");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 1){
throw new FormulaException("strlen function only supports 1 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 1){
throw new FormulaException("strlen function need 1 argument.");
}
String value = getArgument(0).getValue(provider).toString();
return new ExprValue(value.length());
}
}
/**
* Get sub string from source string
*
*
Get sub string from source string
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* substr(src_str,start_offset,length)
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:substring
* @author duanyy
* @version 1.0.0
*/
public static class SubStr extends Function{
public SubStr() {
super("substr");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 3){
throw new FormulaException("substr function only supports 3 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 3){
throw new FormulaException("substr function need 3 argument.");
}
String string = getArgument(0).getValue(provider).getString();
int startOffset = getArgument(1).getValue(provider).getInt();
int length = getArgument(2).getValue(provider).getInt();
startOffset = startOffset < 0 ? 0 : startOffset >= string.length()?string.length() - 1:startOffset;
length = string.length() - startOffset < length ? string.length() - startOffset:length;
return new ExprValue(string.substring(startOffset, startOffset + length));
}
}
/**
* Find index in source string when child string is matched.
*
*
Find index in source string when child string is matched.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~
* instr(src_str,child_str)
* ~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:index of child string,-1 if child string is not matched.
* @author duanyy
* @version 1.0.0
*/
public static class InStr extends Function{
public InStr() {
super("instr");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 2){
throw new FormulaException("instr function only supports 2 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 2){
throw new FormulaException("substr function need 2 argument.");
}
String srcString = getArgument(0).getValue(provider).getString();
String childString = getArgument(1).getValue(provider).getString();
return new ExprValue(srcString.indexOf(childString));
}
}
/**
* Test whether string matches the given regular expression.
*
* Test whether string matches the given regular expression.
*
Syntax:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~
* match(src_str,regex)
* ~~~~~~~~~~~~~~~~~~~~~~~~
*
* return:true when src_str matches regex.
* @author duanyy
* @version 1.0.0
*/
public static class Match extends Function{
public Match() {
super("match");
}
public void checkArgument(Expression arg) throws FormulaException {
if (getArgumentCount() > 2){
throw new FormulaException("match function only supports 2 argument.");
}
}
public ExprValue getValue(DataProvider provider)
throws FormulaException {
if (getArgumentCount() != 2){
throw new FormulaException("match function need 2 argument.");
}
String srcString = getArgument(0).getValue(provider).getString();
String regex = getArgument(1).getValue(provider).getString();
return new ExprValue(srcString.matches(regex));
}
}
}