/*
* Copyright (c) 2013-2015 Josef Hardi <josef.hardi@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.obidea.semantika.expression.base;
import java.math.BigDecimal;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.obidea.semantika.datatype.DataType;
import com.obidea.semantika.exception.SemantikaRuntimeException;
import com.obidea.semantika.expression.ExpressionObjectFactory;
public enum BuiltInFunction
{
/*
* Boolean operators
*/
And(ExpressionConstant.AND, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
boolean result = Boolean.parseBoolean(value1) && Boolean.parseBoolean(value2);
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
Or(ExpressionConstant.OR, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
boolean result = Boolean.parseBoolean(value1) || Boolean.parseBoolean(value2);
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
Not(ExpressionConstant.NOT, 1, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
boolean result = !Boolean.parseBoolean(value1);
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
/*
* Arithmetic operators
*/
Add(ExpressionConstant.ADD, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
BigDecimal result = new BigDecimal(value1).add(new BigDecimal(value2));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.DECIMAL;
}
}),
Subtract(ExpressionConstant.SUBTRACT, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
BigDecimal result = new BigDecimal(value1).subtract(new BigDecimal(value2));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.DECIMAL;
}
}),
Multiply(ExpressionConstant.MULTIPLY, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
BigDecimal result = new BigDecimal(value1).multiply(new BigDecimal(value2));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.DECIMAL;
}
}),
Divide(ExpressionConstant.DIVIDE, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
BigDecimal result = new BigDecimal(value1).divide(new BigDecimal(value2));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.DECIMAL;
}
}),
/*
* Object comparison operators
*/
Equal(ExpressionConstant.EQUAL, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
boolean result = value1.equals(value2);
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
NotEqual(ExpressionConstant.NOT_EQUAL, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
boolean result = !value1.equals(value2);
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
/*
* Number comparison operators
*/
GreaterThan(ExpressionConstant.GREATER_THAN, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
int val = new BigDecimal(value1).compareTo(new BigDecimal(value2));
boolean result = (val == 1 ? new Boolean(true) : new Boolean(false));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
GreaterThanEqual(ExpressionConstant.GREATER_THAN_EQUAL, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
int val = new BigDecimal(value1).compareTo(new BigDecimal(value2));
boolean result = (val == 1 || val == 0 ? new Boolean(true) : new Boolean(false));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
LessThan(ExpressionConstant.LESS_THAN, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
int val = new BigDecimal(value1).compareTo(new BigDecimal(value2));
boolean result = (val == -1 ? new Boolean(true) : new Boolean(false));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
LessThanEqual(ExpressionConstant.LESS_THEN_EQUAL, 2, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String value1 = args.get(0).getLexicalValue();
String value2 = args.get(1).getLexicalValue();
int val = new BigDecimal(value1).compareTo(new BigDecimal(value2));
boolean result = (val == -1 || val == 0 ? new Boolean(true) : new Boolean(false));
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
/*
* Null comparison operators
*/
IsNull(ExpressionConstant.IS_NULL, 1, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
IConstant c = args.get(0);
boolean result = c.equals(new NullValue());
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
IsNotNull(ExpressionConstant.IS_NOT_NULL, 1, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
IConstant c = args.get(0);
boolean result = !c.equals(new NullValue());
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
}),
/*
* String manipulation operators
*/
Concat(ExpressionConstant.CONCAT, -1, new IFunctionOperation() { // -1 = N-ary
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
StringBuilder sb = new StringBuilder();
sb.append(args.get(0).getLexicalValue());
sb.append(args.get(1).getLexicalValue());
String result = sb.toString();
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.STRING;
}
}),
Regex(ExpressionConstant.REGEX, 3, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String text = args.get(0).getLexicalValue();
String pattern = args.get(1).getLexicalValue();
int flag = flag(args.get(2).getLexicalValue());
Pattern p = Pattern.compile(pattern, flag);
Matcher m = p.matcher(text);
boolean result = m.find();
return sExpressionFactory.getLiteral(result);
}
@Override
public String getReturnType()
{
return DataType.BOOLEAN;
}
private int flag(String flagCode)
{
// Reference: http://www.w3.org/TR/xpath-functions/#regex-syntax
if (flagCode.equals("s")) { //$NON-NLS-1$
return Pattern.DOTALL;
}
else if (flagCode.equalsIgnoreCase("m")) { //$NON-NLS-1$
return Pattern.MULTILINE;
}
else if (flagCode.equalsIgnoreCase("i")) { //$NON-NLS-1$
return Pattern.CASE_INSENSITIVE;
}
else if (flagCode.equalsIgnoreCase("x")) { //$NON-NLS-1$
return Pattern.COMMENTS;
}
throw new SemantikaRuntimeException("Unknown regular expression flag: " + flagCode); //$NON-NLS-1$
}
}),
Lang(ExpressionConstant.LANG, 1, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String text = args.get(0).getLexicalValue();
String lang = ""; //$NON-NLS-1$ // by default
if (text.contains("@")) { //$NON-NLS-1$
lang = text.substring(text.lastIndexOf('@') + 1); //$NON-NLS-1$
}
return sExpressionFactory.getLiteral(lang);
}
@Override
public String getReturnType()
{
return DataType.STRING;
}
}),
Str(ExpressionConstant.STR, 1, new IFunctionOperation() {
private static final long serialVersionUID = 629451L;
@Override
public ILiteral execute(List<? extends IConstant> args)
{
String text = args.get(0).getLexicalValue();
return sExpressionFactory.getLiteral(text);
}
@Override
public String getReturnType()
{
return DataType.STRING;
}
});
private static ExpressionObjectFactory sExpressionFactory = ExpressionObjectFactory.getInstance();
private final String mName;
private final int mArity;
private final IFunctionOperation mOperation;
BuiltInFunction(String name, int arity, IFunctionOperation op)
{
mName = name;
mArity = arity;
mOperation = op;
}
public String getName()
{
return mName;
}
public FunctionSymbol getFunctionSymbol()
{
return new FunctionSymbol(mName, mOperation);
}
public int getArity()
{
return mArity;
}
}