Browse Source

refactor support for working with Value instances

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1192 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-2.2.0
James Ahlborn 5 years ago
parent
commit
1236f27d91

+ 7
- 7
src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java View File

@@ -33,8 +33,8 @@ import com.healthmarketscience.jackcess.expr.Expression;
import com.healthmarketscience.jackcess.expr.Identifier;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.expr.BuiltinOperators;
import com.healthmarketscience.jackcess.impl.expr.Expressionator;
import com.healthmarketscience.jackcess.impl.expr.ValueSupport;

/**
*
@@ -132,28 +132,28 @@ public abstract class BaseEvalContext implements EvalContext
try {
val = ColumnImpl.toInternalValue(dType, val, getDatabase());
if(val == null) {
return BuiltinOperators.NULL_VAL;
return ValueSupport.NULL_VAL;
}

Value.Type vType = toValueType(dType);
switch(vType) {
case STRING:
return BuiltinOperators.toValue(val.toString());
return ValueSupport.toValue(val.toString());
case DATE:
case TIME:
case DATE_TIME:
return BuiltinOperators.toValue(this, vType, (Date)val);
return ValueSupport.toValue(this, vType, (Date)val);
case LONG:
Integer i = ((val instanceof Integer) ? (Integer)val :
((Number)val).intValue());
return BuiltinOperators.toValue(i);
return ValueSupport.toValue(i);
case DOUBLE:
Double d = ((val instanceof Double) ? (Double)val :
((Number)val).doubleValue());
return BuiltinOperators.toValue(d);
return ValueSupport.toValue(d);
case BIG_DEC:
BigDecimal bd = ColumnImpl.toBigDecimal(val, getDatabase());
return BuiltinOperators.toValue(bd);
return ValueSupport.toValue(bd);
default:
throw new RuntimeException("Unexpected type " + vType);
}

+ 1
- 131
src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java View File

@@ -17,15 +17,13 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Date;
import java.util.regex.Pattern;

import com.healthmarketscience.jackcess.expr.EvalContext;
import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import com.healthmarketscience.jackcess.impl.NumberFormatter;
import static com.healthmarketscience.jackcess.impl.expr.ValueSupport.*;


/**
@@ -39,27 +37,6 @@ public class BuiltinOperators
private static final double MIN_INT = Integer.MIN_VALUE;
private static final double MAX_INT = Integer.MAX_VALUE;

public static final Value NULL_VAL = new BaseValue() {
@Override public boolean isNull() {
return true;
}
public Type getType() {
return Type.NULL;
}
public Object get() {
return null;
}
};
// access seems to like -1 for true and 0 for false (boolean values are
// basically an illusion)
public static final Value TRUE_VAL = new LongValue(-1);
public static final Value FALSE_VAL = new LongValue(0);
public static final Value EMPTY_STR_VAL = new StringValue("");
public static final Value ZERO_VAL = FALSE_VAL;
public static final Value NEG_ONE_VAL = TRUE_VAL;
public static final Value ONE_VAL = new LongValue(1);


private enum CoercionType {
SIMPLE(true, true), GENERAL(false, true), COMPARE(false, false);

@@ -578,95 +555,6 @@ public class BuiltinOperators
}
}

public static Value toValue(boolean b) {
return (b ? TRUE_VAL : FALSE_VAL);
}

public static Value toValue(String s) {
return new StringValue(s);
}

public static Value toValue(int i) {
return new LongValue(i);
}

public static Value toValue(Integer i) {
return new LongValue(i);
}

public static Value toValue(float f) {
return new DoubleValue((double)f);
}

public static Value toValue(double s) {
return new DoubleValue(s);
}

public static Value toValue(Double s) {
return new DoubleValue(s);
}

public static Value toValue(BigDecimal s) {
return new BigDecimalValue(normalize(s));
}

public static Value toValue(Value.Type type, double dd, DateFormat fmt) {
return toValue(type, new Date(ColumnImpl.fromDateDouble(
dd, fmt.getCalendar())), fmt);
}

public static Value toValue(EvalContext ctx, Value.Type type, Date d) {
return toValue(type, d, getDateFormatForType(ctx, type));
}

public static Value toValue(Value.Type type, Date d, DateFormat fmt) {
switch(type) {
case DATE:
return new DateValue(d, fmt);
case TIME:
return new TimeValue(d, fmt);
case DATE_TIME:
return new DateTimeValue(d, fmt);
default:
throw new EvalException("Unexpected date/time type " + type);
}
}

static Value toDateValue(EvalContext ctx, Value.Type type, double v,
Value param1, Value param2)
{
DateFormat fmt = null;
if((param1 instanceof BaseDateValue) && (param1.getType() == type)) {
fmt = ((BaseDateValue)param1).getFormat();
} else if((param2 instanceof BaseDateValue) && (param2.getType() == type)) {
fmt = ((BaseDateValue)param2).getFormat();
} else {
fmt = getDateFormatForType(ctx, type);
}

Date d = new Date(ColumnImpl.fromDateDouble(v, fmt.getCalendar()));

return toValue(type, d, fmt);
}

static DateFormat getDateFormatForType(EvalContext ctx, Value.Type type) {
String fmtStr = null;
switch(type) {
case DATE:
fmtStr = ctx.getTemporalConfig().getDefaultDateFormat();
break;
case TIME:
fmtStr = ctx.getTemporalConfig().getDefaultTimeFormat();
break;
case DATE_TIME:
fmtStr = ctx.getTemporalConfig().getDefaultDateTimeFormat();
break;
default:
throw new EvalException("Unexpected date/time type " + type);
}
return ctx.createDateFormat(fmtStr);
}

private static Value.Type getMathTypePrecedence(
Value param1, Value param2, CoercionType cType)
{
@@ -779,22 +667,4 @@ public class BuiltinOperators
return ((d == id) && (d >= MIN_INT) && (d <= MAX_INT) &&
!Double.isInfinite(d) && !Double.isNaN(d));
}

/**
* Converts the given BigDecimal to the minimal scale >= 0;
*/
static BigDecimal normalize(BigDecimal bd) {
if(bd.scale() == 0) {
return bd;
}
// handle a bug in the jdk which doesn't strip zero values
if(bd.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
bd = bd.stripTrailingZeros();
if(bd.scale() < 0) {
bd = bd.setScale(0);
}
return bd;
}
}

+ 26
- 26
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java View File

@@ -56,9 +56,9 @@ public class DefaultDateFunctions
public static final Function DATE = registerFunc(new Func0("Date") {
@Override
protected Value eval0(EvalContext ctx) {
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.DATE);
double dd = dateOnly(currentTimeDouble(fmt));
return BuiltinOperators.toValue(Value.Type.DATE, dd, fmt);
return ValueSupport.toValue(Value.Type.DATE, dd, fmt);
}
});

@@ -70,8 +70,8 @@ public class DefaultDateFunctions
return dv;
}
double dd = dateOnly(dv.getAsDouble());
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE);
return BuiltinOperators.toValue(Value.Type.DATE, dd, fmt);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.DATE);
return ValueSupport.toValue(Value.Type.DATE, dd, fmt);
}
});

@@ -87,7 +87,7 @@ public class DefaultDateFunctions
year += ((year <= 29) ? 2000 : 1900);
}

DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.DATE);
Calendar cal = fmt.getCalendar();
cal.clear();

@@ -96,24 +96,24 @@ public class DefaultDateFunctions
cal.set(Calendar.MONTH, month - 1);
cal.set(Calendar.DAY_OF_MONTH, day);

return BuiltinOperators.toValue(Value.Type.DATE, cal.getTime(), fmt);
return ValueSupport.toValue(Value.Type.DATE, cal.getTime(), fmt);
}
});

public static final Function NOW = registerFunc(new Func0("Now") {
@Override
protected Value eval0(EvalContext ctx) {
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.DATE_TIME);
return BuiltinOperators.toValue(Value.Type.DATE_TIME, new Date(), fmt);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.DATE_TIME);
return ValueSupport.toValue(Value.Type.DATE_TIME, new Date(), fmt);
}
});

public static final Function TIME = registerFunc(new Func0("Time") {
@Override
protected Value eval0(EvalContext ctx) {
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.TIME);
double dd = timeOnly(currentTimeDouble(fmt));
return BuiltinOperators.toValue(Value.Type.TIME, dd, fmt);
return ValueSupport.toValue(Value.Type.TIME, dd, fmt);
}
});

@@ -125,17 +125,17 @@ public class DefaultDateFunctions
return dv;
}
double dd = timeOnly(dv.getAsDouble());
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
return BuiltinOperators.toValue(Value.Type.TIME, dd, fmt);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.TIME);
return ValueSupport.toValue(Value.Type.TIME, dd, fmt);
}
});

public static final Function TIMER = registerFunc(new Func0("Timer") {
@Override
protected Value eval0(EvalContext ctx) {
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.TIME);
double dd = timeOnly(currentTimeDouble(fmt)) * DSECONDS_PER_DAY;
return BuiltinOperators.toValue(dd);
return ValueSupport.toValue(dd);
}
});

@@ -156,16 +156,16 @@ public class DefaultDateFunctions
totalSeconds %= SECONDS_PER_DAY;
}

DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, Value.Type.TIME);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, Value.Type.TIME);
double dd = totalSeconds / DSECONDS_PER_DAY;
return BuiltinOperators.toValue(Value.Type.TIME, dd, fmt);
return ValueSupport.toValue(Value.Type.TIME, dd, fmt);
}
});

public static final Function HOUR = registerFunc(new Func1NullIsNull("Hour") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(
return ValueSupport.toValue(
nonNullToCalendarField(ctx, param1, Calendar.HOUR_OF_DAY));
}
});
@@ -173,7 +173,7 @@ public class DefaultDateFunctions
public static final Function MINUTE = registerFunc(new Func1NullIsNull("Minute") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(
return ValueSupport.toValue(
nonNullToCalendarField(ctx, param1, Calendar.MINUTE));
}
});
@@ -181,7 +181,7 @@ public class DefaultDateFunctions
public static final Function SECOND = registerFunc(new Func1NullIsNull("Second") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(
return ValueSupport.toValue(
nonNullToCalendarField(ctx, param1, Calendar.SECOND));
}
});
@@ -189,7 +189,7 @@ public class DefaultDateFunctions
public static final Function YEAR = registerFunc(new Func1NullIsNull("Year") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(
return ValueSupport.toValue(
nonNullToCalendarField(ctx, param1, Calendar.YEAR));
}
});
@@ -198,7 +198,7 @@ public class DefaultDateFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
// convert from 0 based to 1 based value
return BuiltinOperators.toValue(
return ValueSupport.toValue(
nonNullToCalendarField(ctx, param1, Calendar.MONTH) + 1);
}
});
@@ -206,7 +206,7 @@ public class DefaultDateFunctions
public static final Function DAY = registerFunc(new Func1NullIsNull("Day") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(
return ValueSupport.toValue(
nonNullToCalendarField(ctx, param1, Calendar.DAY_OF_MONTH));
}
});
@@ -234,7 +234,7 @@ public class DefaultDateFunctions
// back to 1 based to return the result
day = (((day - 1) - (firstDay - 1) + 7) % 7) + 1;

return BuiltinOperators.toValue(day);
return ValueSupport.toValue(day);
}
});

@@ -292,14 +292,14 @@ public class DefaultDateFunctions

Value.Type type = (hasDate ? (hasTime ? Value.Type.DATE_TIME : Value.Type.DATE) :
Value.Type.TIME);
DateFormat fmt = BuiltinOperators.getDateFormatForType(ctx, type);
return BuiltinOperators.toValue(type, dd, fmt);
DateFormat fmt = ValueSupport.getDateFormatForType(ctx, type);
return ValueSupport.toValue(type, dd, fmt);
}

private static DateFormat getDateValueFormat(EvalContext ctx, Value param) {
return ((param instanceof BaseDateValue) ?
((BaseDateValue)param).getFormat() :
BuiltinOperators.getDateFormatForType(ctx, param.getType()));
ValueSupport.getDateFormatForType(ctx, param.getType()));
}

private static double dateOnly(double dd) {

+ 9
- 9
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFinancialFunctions.java View File

@@ -65,7 +65,7 @@ public class DefaultFinancialFunctions
result += calculateAnnuityPaymentPeriods(rate, pmt, fv, pmtType);
}

return BuiltinOperators.toValue(result);
return ValueSupport.toValue(result);
}
});

@@ -92,7 +92,7 @@ public class DefaultFinancialFunctions

double result = calculateFutureValue(rate, nper, pmt, pmtType);

return BuiltinOperators.toValue(result);
return ValueSupport.toValue(result);
}
});

@@ -119,7 +119,7 @@ public class DefaultFinancialFunctions

double result = calculatePresentValue(rate, nper, pmt, pmtType);

return BuiltinOperators.toValue(result);
return ValueSupport.toValue(result);
}
});

@@ -146,7 +146,7 @@ public class DefaultFinancialFunctions
result += calculateAnnuityPayment(rate, nper, fv, pmtType);
}

return BuiltinOperators.toValue(result);
return ValueSupport.toValue(result);
}
});

@@ -177,7 +177,7 @@ public class DefaultFinancialFunctions

// double result = calculateInterestPayment(pmt, rate, per, pv, pmtType);

// return BuiltinOperators.toValue(result);
// return ValueSupport.toValue(result);
// }
// });

@@ -209,7 +209,7 @@ public class DefaultFinancialFunctions
// double result = pmt - calculateInterestPayment(pmt, rate, per, pv,
// pmtType);

// return BuiltinOperators.toValue(result);
// return ValueSupport.toValue(result);
// }
// });

@@ -255,7 +255,7 @@ public class DefaultFinancialFunctions
// cost -= result;
// }

// return BuiltinOperators.toValue(result);
// return ValueSupport.toValue(result);
// }
// });

@@ -269,7 +269,7 @@ public class DefaultFinancialFunctions

// double result = calculateStraightLineDepreciation(cost, salvage, life);

// return BuiltinOperators.toValue(result);
// return ValueSupport.toValue(result);
// }
// });

@@ -285,7 +285,7 @@ public class DefaultFinancialFunctions
// double result = calculateSumOfYearsDepreciation(
// cost, salvage, life, period);

// return BuiltinOperators.toValue(result);
// return ValueSupport.toValue(result);
// }
// });


+ 20
- 20
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java View File

@@ -69,10 +69,10 @@ public class DefaultFunctions
protected Value eval1(EvalContext ctx, Value param1) {
if((param1.getType() == Value.Type.STRING) &&
(param1.getAsString().length() == 0)) {
return BuiltinOperators.ZERO_VAL;
return ValueSupport.ZERO_VAL;
}
int lv = param1.getAsLongInt();
return BuiltinOperators.toValue(Integer.toHexString(lv).toUpperCase());
return ValueSupport.toValue(Integer.toHexString(lv).toUpperCase());
}
});

@@ -89,7 +89,7 @@ public class DefaultFunctions
Value.Type resultType = ctx.getResultType();
return (((resultType == null) ||
(resultType == Value.Type.STRING)) ?
BuiltinOperators.EMPTY_STR_VAL : BuiltinOperators.ZERO_VAL);
ValueSupport.EMPTY_STR_VAL : ValueSupport.ZERO_VAL);
}
});

@@ -99,7 +99,7 @@ public class DefaultFunctions
Value param1 = params[0];
int idx = param1.getAsLongInt();
if((idx < 1) || (idx >= params.length)) {
return BuiltinOperators.NULL_VAL;
return ValueSupport.NULL_VAL;
}
return params[idx];
}
@@ -116,7 +116,7 @@ public class DefaultFunctions
return params[i + 1];
}
}
return BuiltinOperators.NULL_VAL;
return ValueSupport.NULL_VAL;
}
});

@@ -125,10 +125,10 @@ public class DefaultFunctions
protected Value eval1(EvalContext ctx, Value param1) {
if((param1.getType() == Value.Type.STRING) &&
(param1.getAsString().length() == 0)) {
return BuiltinOperators.ZERO_VAL;
return ValueSupport.ZERO_VAL;
}
int lv = param1.getAsLongInt();
return BuiltinOperators.toValue(Integer.toOctalString(lv));
return ValueSupport.toValue(Integer.toOctalString(lv));
}
});

@@ -136,7 +136,7 @@ public class DefaultFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
boolean b = param1.getAsBoolean();
return BuiltinOperators.toValue(b);
return ValueSupport.toValue(b);
}
});

@@ -147,7 +147,7 @@ public class DefaultFunctions
if((lv < 0) || (lv > 255)) {
throw new EvalException("Byte code '" + lv + "' out of range ");
}
return BuiltinOperators.toValue(lv);
return ValueSupport.toValue(lv);
}
});

@@ -156,7 +156,7 @@ public class DefaultFunctions
protected Value eval1(EvalContext ctx, Value param1) {
BigDecimal bd = param1.getAsBigDecimal();
bd = bd.setScale(4, NumberFormatter.ROUND_MODE);
return BuiltinOperators.toValue(bd);
return ValueSupport.toValue(bd);
}
});

@@ -174,7 +174,7 @@ public class DefaultFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
Double dv = param1.getAsDouble();
return BuiltinOperators.toValue(dv);
return ValueSupport.toValue(dv);
}
});

@@ -182,7 +182,7 @@ public class DefaultFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
BigDecimal bd = param1.getAsBigDecimal();
return BuiltinOperators.toValue(bd);
return ValueSupport.toValue(bd);
}
});

@@ -193,7 +193,7 @@ public class DefaultFunctions
if((lv < Short.MIN_VALUE) || (lv > Short.MAX_VALUE)) {
throw new EvalException("Int value '" + lv + "' out of range ");
}
return BuiltinOperators.toValue(lv);
return ValueSupport.toValue(lv);
}
});

@@ -201,7 +201,7 @@ public class DefaultFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
int lv = param1.getAsLongInt();
return BuiltinOperators.toValue(lv);
return ValueSupport.toValue(lv);
}
});

@@ -212,14 +212,14 @@ public class DefaultFunctions
if((dv < Float.MIN_VALUE) || (dv > Float.MAX_VALUE)) {
throw new EvalException("Single value '" + dv + "' out of range ");
}
return BuiltinOperators.toValue(dv.floatValue());
return ValueSupport.toValue(dv.floatValue());
}
});

public static final Function CSTR = registerFunc(new Func1("CStr") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(param1.getAsString());
return ValueSupport.toValue(param1.getAsString());
}
});

@@ -233,14 +233,14 @@ public class DefaultFunctions
public static final Function ISNULL = registerFunc(new Func1("IsNull") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(param1.isNull());
return ValueSupport.toValue(param1.isNull());
}
});

public static final Function ISDATE = registerFunc(new Func1("IsDate") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(
return ValueSupport.toValue(
!param1.isNull() &&
(DefaultDateFunctions.nonNullToDateValue(ctx, param1) != null));
}
@@ -281,7 +281,7 @@ public class DefaultFunctions
default:
throw new EvalException("Unknown type " + type);
}
return BuiltinOperators.toValue(vType);
return ValueSupport.toValue(vType);
}
});

@@ -314,7 +314,7 @@ public class DefaultFunctions
default:
throw new EvalException("Unknown type " + type);
}
return BuiltinOperators.toValue(tName);
return ValueSupport.toValue(tName);
}
});


+ 18
- 18
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java View File

@@ -50,14 +50,14 @@ public class DefaultNumberFunctions
case DATE_TIME:
// dates/times get converted to date doubles for arithmetic
double result = Math.abs(param1.getAsDouble());
return BuiltinOperators.toDateValue(ctx, mathType, result, param1, null);
return ValueSupport.toDateValue(ctx, mathType, result, param1, null);
case LONG:
return BuiltinOperators.toValue(Math.abs(param1.getAsLongInt()));
return ValueSupport.toValue(Math.abs(param1.getAsLongInt()));
case DOUBLE:
return BuiltinOperators.toValue(Math.abs(param1.getAsDouble()));
return ValueSupport.toValue(Math.abs(param1.getAsDouble()));
case STRING:
case BIG_DEC:
return BuiltinOperators.toValue(param1.getAsBigDecimal().abs(
return ValueSupport.toValue(param1.getAsBigDecimal().abs(
NumberFormatter.DEC_MATH_CONTEXT));
default:
throw new EvalException("Unexpected type " + mathType);
@@ -68,21 +68,21 @@ public class DefaultNumberFunctions
public static final Function ATAN = registerFunc(new Func1("Atan") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(Math.atan(param1.getAsDouble()));
return ValueSupport.toValue(Math.atan(param1.getAsDouble()));
}
});

public static final Function COS = registerFunc(new Func1("Cos") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(Math.cos(param1.getAsDouble()));
return ValueSupport.toValue(Math.cos(param1.getAsDouble()));
}
});

public static final Function EXP = registerFunc(new Func1("Exp") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(Math.exp(param1.getAsDouble()));
return ValueSupport.toValue(Math.exp(param1.getAsDouble()));
}
});

@@ -92,7 +92,7 @@ public class DefaultNumberFunctions
if(param1.getType().isIntegral()) {
return param1;
}
return BuiltinOperators.toValue(param1.getAsDouble().intValue());
return ValueSupport.toValue(param1.getAsDouble().intValue());
}
});

@@ -102,14 +102,14 @@ public class DefaultNumberFunctions
if(param1.getType().isIntegral()) {
return param1;
}
return BuiltinOperators.toValue((int)Math.floor(param1.getAsDouble()));
return ValueSupport.toValue((int)Math.floor(param1.getAsDouble()));
}
});

public static final Function LOG = registerFunc(new Func1("Log") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(Math.log(param1.getAsDouble()));
return ValueSupport.toValue(Math.log(param1.getAsDouble()));
}
});

@@ -121,7 +121,7 @@ public class DefaultNumberFunctions
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
Integer seed = ((params.length > 0) ? params[0].getAsLongInt() : null);
return BuiltinOperators.toValue(ctx.getRandom(seed));
return ValueSupport.toValue(ctx.getRandom(seed));
}
});

@@ -141,7 +141,7 @@ public class DefaultNumberFunctions
}
BigDecimal bd = param1.getAsBigDecimal()
.setScale(scale, NumberFormatter.ROUND_MODE);
return BuiltinOperators.toValue(bd);
return ValueSupport.toValue(bd);
}
});

@@ -154,9 +154,9 @@ public class DefaultNumberFunctions
} else {
val = param1.getAsBigDecimal().signum();
}
return ((val > 0) ? BuiltinOperators.ONE_VAL :
((val < 0) ? BuiltinOperators.NEG_ONE_VAL :
BuiltinOperators.ZERO_VAL));
return ((val > 0) ? ValueSupport.ONE_VAL :
((val < 0) ? ValueSupport.NEG_ONE_VAL :
ValueSupport.ZERO_VAL));
}
});

@@ -167,21 +167,21 @@ public class DefaultNumberFunctions
if(dv < 0.0d) {
throw new EvalException("Invalid value '" + dv + "'");
}
return BuiltinOperators.toValue(Math.sqrt(dv));
return ValueSupport.toValue(Math.sqrt(dv));
}
});

public static final Function SIN = registerFunc(new Func1("Sin") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(Math.sin(param1.getAsDouble()));
return ValueSupport.toValue(Math.sin(param1.getAsDouble()));
}
});

public static final Function TAN = registerFunc(new Func1("Tan") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
return BuiltinOperators.toValue(Math.tan(param1.getAsDouble()));
return ValueSupport.toValue(Math.tan(param1.getAsDouble()));
}
});


+ 30
- 30
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java View File

@@ -51,7 +51,7 @@ public class DefaultTextFunctions
throw new EvalException("Character code '" + lv +
"' out of range ");
}
return BuiltinOperators.toValue(lv);
return ValueSupport.toValue(lv);
}
});

@@ -64,7 +64,7 @@ public class DefaultTextFunctions
throw new EvalException("No characters in string");
}
int lv = str.charAt(0);
return BuiltinOperators.toValue(lv);
return ValueSupport.toValue(lv);
}
});

@@ -77,7 +77,7 @@ public class DefaultTextFunctions
"' out of range ");
}
char[] cs = Character.toChars(lv);
return BuiltinOperators.toValue(new String(cs));
return ValueSupport.toValue(new String(cs));
}
});

@@ -86,7 +86,7 @@ public class DefaultTextFunctions
protected Value eval1(EvalContext ctx, Value param1) {
int lv = param1.getAsLongInt();
char[] cs = Character.toChars(lv);
return BuiltinOperators.toValue(new String(cs));
return ValueSupport.toValue(new String(cs));
}
});

@@ -98,7 +98,7 @@ public class DefaultTextFunctions
if(bd.compareTo(BigDecimal.ZERO) >= 0) {
str = " " + str;
}
return BuiltinOperators.toValue(str);
return ValueSupport.toValue(str);
}
});

@@ -119,7 +119,7 @@ public class DefaultTextFunctions
String s1 = param1.getAsString();
int s1Len = s1.length();
if(s1Len == 0) {
return BuiltinOperators.ZERO_VAL;
return ValueSupport.ZERO_VAL;
}
Value param2 = params[idx++];
if(param2.isNull()) {
@@ -129,7 +129,7 @@ public class DefaultTextFunctions
int s2Len = s2.length();
if(s2Len == 0) {
// 1 based offsets
return BuiltinOperators.toValue(start + 1);
return ValueSupport.toValue(start + 1);
}
boolean ignoreCase = true;
if(params.length > 3) {
@@ -139,11 +139,11 @@ public class DefaultTextFunctions
while(start < end) {
if(s1.regionMatches(ignoreCase, start, s2, 0, s2Len)) {
// 1 based offsets
return BuiltinOperators.toValue(start + 1);
return ValueSupport.toValue(start + 1);
}
++start;
}
return BuiltinOperators.ZERO_VAL;
return ValueSupport.ZERO_VAL;
}
});

@@ -157,7 +157,7 @@ public class DefaultTextFunctions
String s1 = param1.getAsString();
int s1Len = s1.length();
if(s1Len == 0) {
return BuiltinOperators.ZERO_VAL;
return ValueSupport.ZERO_VAL;
}
Value param2 = params[1];
if(param2.isNull()) {
@@ -168,7 +168,7 @@ public class DefaultTextFunctions
int start = s1Len - 1;
if(s2Len == 0) {
// 1 based offsets
return BuiltinOperators.toValue(start + 1);
return ValueSupport.toValue(start + 1);
}
if(params.length > 2) {
start = params[2].getAsLongInt();
@@ -186,11 +186,11 @@ public class DefaultTextFunctions
while(start >= 0) {
if(s1.regionMatches(ignoreCase, start, s2, 0, s2Len)) {
// 1 based offsets
return BuiltinOperators.toValue(start + 1);
return ValueSupport.toValue(start + 1);
}
--start;
}
return BuiltinOperators.ZERO_VAL;
return ValueSupport.ZERO_VAL;
}
});

@@ -198,7 +198,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(str.toLowerCase());
return ValueSupport.toValue(str.toLowerCase());
}
});

@@ -206,7 +206,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(str.toUpperCase());
return ValueSupport.toValue(str.toUpperCase());
}
});

@@ -218,7 +218,7 @@ public class DefaultTextFunctions
}
String str = param1.getAsString();
int len = Math.min(str.length(), param2.getAsLongInt());
return BuiltinOperators.toValue(str.substring(0, len));
return ValueSupport.toValue(str.substring(0, len));
}
});

@@ -231,7 +231,7 @@ public class DefaultTextFunctions
String str = param1.getAsString();
int strLen = str.length();
int len = Math.min(strLen, param2.getAsLongInt());
return BuiltinOperators.toValue(str.substring(strLen - len, strLen));
return ValueSupport.toValue(str.substring(strLen - len, strLen));
}
});

@@ -249,7 +249,7 @@ public class DefaultTextFunctions
int len = Math.min(
((params.length > 2) ? params[2].getAsLongInt() : strLen),
(strLen - start));
return BuiltinOperators.toValue(str.substring(start, start + len));
return ValueSupport.toValue(str.substring(start, start + len));
}
});

@@ -257,7 +257,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(str.length());
return ValueSupport.toValue(str.length());
}
});

@@ -265,7 +265,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(trim(str, true, false));
return ValueSupport.toValue(trim(str, true, false));
}
});

@@ -273,7 +273,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(trim(str, false, true));
return ValueSupport.toValue(trim(str, false, true));
}
});

@@ -281,7 +281,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(trim(str, true, true));
return ValueSupport.toValue(trim(str, true, true));
}
});

@@ -289,7 +289,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
int lv = param1.getAsLongInt();
return BuiltinOperators.toValue(nchars(lv, ' '));
return ValueSupport.toValue(nchars(lv, ' '));
}
});

@@ -299,7 +299,7 @@ public class DefaultTextFunctions
Value param1 = params[0];
Value param2 = params[1];
if(param1.isNull() || param2.isNull()) {
return BuiltinOperators.NULL_VAL;
return ValueSupport.NULL_VAL;
}
String s1 = param1.getAsString();
String s2 = param2.getAsString();
@@ -310,9 +310,9 @@ public class DefaultTextFunctions
int cmp = (ignoreCase ?
s1.compareToIgnoreCase(s2) : s1.compareTo(s2));
// stupid java doesn't return 1, -1, 0...
return ((cmp < 0) ? BuiltinOperators.NEG_ONE_VAL :
((cmp > 0) ? BuiltinOperators.ONE_VAL :
BuiltinOperators.ZERO_VAL));
return ((cmp < 0) ? ValueSupport.NEG_ONE_VAL :
((cmp > 0) ? ValueSupport.ONE_VAL :
ValueSupport.ZERO_VAL));
}
});

@@ -320,11 +320,11 @@ public class DefaultTextFunctions
@Override
protected Value eval2(EvalContext ctx, Value param1, Value param2) {
if(param1.isNull() || param2.isNull()) {
return BuiltinOperators.NULL_VAL;
return ValueSupport.NULL_VAL;
}
int lv = param1.getAsLongInt();
char c = (char)(param2.getAsString().charAt(0) % 256);
return BuiltinOperators.toValue(nchars(lv, c));
return ValueSupport.toValue(nchars(lv, c));
}
});

@@ -332,7 +332,7 @@ public class DefaultTextFunctions
@Override
protected Value eval1(EvalContext ctx, Value param1) {
String str = param1.getAsString();
return BuiltinOperators.toValue(
return ValueSupport.toValue(
new StringBuilder(str).reverse().toString());
}
});

+ 7
- 7
src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java View File

@@ -401,11 +401,11 @@ public class Expressionator
private static final Expr THIS_COL_VALUE = new EThisValue();

private static final Expr NULL_VALUE = new EConstValue(
BuiltinOperators.NULL_VAL, "Null");
ValueSupport.NULL_VAL, "Null");
private static final Expr TRUE_VALUE = new EConstValue(
BuiltinOperators.TRUE_VAL, "True");
ValueSupport.TRUE_VAL, "True");
private static final Expr FALSE_VALUE = new EConstValue(
BuiltinOperators.FALSE_VAL, "False");
ValueSupport.FALSE_VAL, "False");


private Expressionator() {}
@@ -1302,7 +1302,7 @@ public class Expressionator
{
switch(valType) {
case STRING:
return BuiltinOperators.toValue((String)value);
return ValueSupport.toValue((String)value);
case DATE:
return new DateValue((Date)value, sdf);
case TIME:
@@ -1310,11 +1310,11 @@ public class Expressionator
case DATE_TIME:
return new DateTimeValue((Date)value, sdf);
case LONG:
return BuiltinOperators.toValue((Integer)value);
return ValueSupport.toValue((Integer)value);
case DOUBLE:
return BuiltinOperators.toValue((Double)value);
return ValueSupport.toValue((Double)value);
case BIG_DEC:
return BuiltinOperators.toValue((BigDecimal)value);
return ValueSupport.toValue((BigDecimal)value);
default:
throw new ParseException("unexpected literal type " + valType);
}

+ 1
- 1
src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java View File

@@ -75,7 +75,7 @@ public class StringValue extends BaseValue
if(_num == null) {
// see if it is parseable as a number
try {
_num = BuiltinOperators.normalize(new BigDecimal(_val));
_num = ValueSupport.normalize(new BigDecimal(_val));
return (BigDecimal)_num;
} catch(NumberFormatException nfe) {
_num = NOT_A_NUMBER;

+ 162
- 0
src/main/java/com/healthmarketscience/jackcess/impl/expr/ValueSupport.java View File

@@ -0,0 +1,162 @@
/*
Copyright (c) 2018 James Ahlborn

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.healthmarketscience.jackcess.impl.expr;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Date;

import com.healthmarketscience.jackcess.expr.EvalContext;
import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.ColumnImpl;

/**
*
* @author James Ahlborn
*/
public class ValueSupport
{
public static final Value NULL_VAL = new BaseValue() {
@Override public boolean isNull() {
return true;
}
public Type getType() {
return Type.NULL;
}
public Object get() {
return null;
}
};
// access seems to like -1 for true and 0 for false (boolean values are
// basically an illusion)
public static final Value TRUE_VAL = new LongValue(-1);
public static final Value FALSE_VAL = new LongValue(0);
public static final Value EMPTY_STR_VAL = new StringValue("");
public static final Value ZERO_VAL = FALSE_VAL;
public static final Value NEG_ONE_VAL = TRUE_VAL;
public static final Value ONE_VAL = new LongValue(1);

private ValueSupport() {}

public static Value toValue(boolean b) {
return (b ? TRUE_VAL : FALSE_VAL);
}

public static Value toValue(String s) {
return new StringValue(s);
}

public static Value toValue(int i) {
return new LongValue(i);
}

public static Value toValue(Integer i) {
return new LongValue(i);
}

public static Value toValue(float f) {
return new DoubleValue((double)f);
}

public static Value toValue(double s) {
return new DoubleValue(s);
}

public static Value toValue(Double s) {
return new DoubleValue(s);
}

public static Value toValue(BigDecimal s) {
return new BigDecimalValue(normalize(s));
}

public static Value toValue(Value.Type type, double dd, DateFormat fmt) {
return toValue(type, new Date(ColumnImpl.fromDateDouble(
dd, fmt.getCalendar())), fmt);
}

public static Value toValue(EvalContext ctx, Value.Type type, Date d) {
return toValue(type, d, getDateFormatForType(ctx, type));
}

public static Value toValue(Value.Type type, Date d, DateFormat fmt) {
switch(type) {
case DATE:
return new DateValue(d, fmt);
case TIME:
return new TimeValue(d, fmt);
case DATE_TIME:
return new DateTimeValue(d, fmt);
default:
throw new EvalException("Unexpected date/time type " + type);
}
}

static Value toDateValue(EvalContext ctx, Value.Type type, double v,
Value param1, Value param2)
{
DateFormat fmt = null;
if((param1 instanceof BaseDateValue) && (param1.getType() == type)) {
fmt = ((BaseDateValue)param1).getFormat();
} else if((param2 instanceof BaseDateValue) && (param2.getType() == type)) {
fmt = ((BaseDateValue)param2).getFormat();
} else {
fmt = getDateFormatForType(ctx, type);
}

Date d = new Date(ColumnImpl.fromDateDouble(v, fmt.getCalendar()));

return toValue(type, d, fmt);
}

static DateFormat getDateFormatForType(EvalContext ctx, Value.Type type) {
String fmtStr = null;
switch(type) {
case DATE:
fmtStr = ctx.getTemporalConfig().getDefaultDateFormat();
break;
case TIME:
fmtStr = ctx.getTemporalConfig().getDefaultTimeFormat();
break;
case DATE_TIME:
fmtStr = ctx.getTemporalConfig().getDefaultDateTimeFormat();
break;
default:
throw new EvalException("Unexpected date/time type " + type);
}
return ctx.createDateFormat(fmtStr);
}

/**
* Converts the given BigDecimal to the minimal scale >= 0;
*/
static BigDecimal normalize(BigDecimal bd) {
if(bd.scale() == 0) {
return bd;
}
// handle a bug in the jdk which doesn't strip zero values
if(bd.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
bd = bd.stripTrailingZeros();
if(bd.scale() < 0) {
bd = bd.setScale(0);
}
return bd;
}
}

+ 2
- 2
src/test/java/com/healthmarketscience/jackcess/PropertyExpressionTest.java View File

@@ -26,9 +26,9 @@ import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.FunctionLookup;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.expr.BuiltinOperators;
import com.healthmarketscience.jackcess.impl.expr.DefaultFunctions;
import com.healthmarketscience.jackcess.impl.expr.FunctionSupport;
import com.healthmarketscience.jackcess.impl.expr.ValueSupport;
import junit.framework.TestCase;

import static com.healthmarketscience.jackcess.Database.*;
@@ -354,7 +354,7 @@ public class PropertyExpressionTest extends TestCase
@Override
protected Value eval0(EvalContext ctx) {
Object val = ctx.get("someKey");
return BuiltinOperators.toValue("FOO_" + val);
return ValueSupport.toValue("FOO_" + val);
}
};
}

+ 4
- 4
src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java View File

@@ -429,12 +429,12 @@ public class ExpressionatorTest extends TestCase
TestContext tc = new TestContext() {
@Override
public Value getThisColumnValue() {
return BuiltinOperators.toValue(23.0);
return ValueSupport.toValue(23.0);
}

@Override
public Value getIdentifierValue(Identifier identifier) {
return BuiltinOperators.toValue(23.0);
return ValueSupport.toValue(23.0);
}
};

@@ -536,7 +536,7 @@ public class ExpressionatorTest extends TestCase
}

private static Boolean evalCondition(String exprStr, String thisVal) {
TestContext tc = new TestContext(BuiltinOperators.toValue(thisVal));
TestContext tc = new TestContext(ValueSupport.toValue(thisVal));
Expression expr = Expressionator.parse(
Expressionator.Type.FIELD_VALIDATOR, exprStr, null, tc);
return (Boolean)expr.eval(tc);
@@ -552,7 +552,7 @@ public class ExpressionatorTest extends TestCase
}

static BigDecimal toBD(BigDecimal bd) {
return BuiltinOperators.normalize(bd);
return ValueSupport.normalize(bd);
}

private static class TestContext

Loading…
Cancel
Save