--- /dev/null
+/*
+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.expr;
+
+
+/**
+ * Base class for exceptions thrown during expression evaluation.
+ *
+ * @author James Ahlborn
+ */
+public class EvalException extends IllegalStateException
+{
+ private static final long serialVersionUID = 20180330L;
+
+ public EvalException(String message) {
+ super(message);
+ }
+
+ public EvalException(Throwable cause) {
+ super(cause);
+ }
+
+ public EvalException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
--- /dev/null
+/*
+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.expr;
+
+/**
+ * Exception thrown when expression parsing fails.
+ *
+ * @author James Ahlborn
+ */
+public class ParseException extends EvalException
+{
+ private static final long serialVersionUID = 20180330L;
+
+ public ParseException(String message) {
+ super(message);
+ }
+
+ public ParseException(Throwable cause) {
+ super(cause);
+ }
+
+ public ParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.expr.EvalContext;
+import com.healthmarketscience.jackcess.expr.EvalException;
/**
*
throw invalidConversion(Value.Type.BIG_DEC);
}
- private UnsupportedOperationException invalidConversion(Value.Type newType) {
- return new UnsupportedOperationException(
+ private EvalException invalidConversion(Value.Type newType) {
+ return new EvalException(
getType() + " value cannot be converted to " + newType);
}
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;
case BIG_DEC:
return toValue(param1.getAsBigDecimal().negate());
default:
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
}
case BIG_DEC:
return toValue(param1.getAsBigDecimal().add(param2.getAsBigDecimal()));
default:
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
}
case BIG_DEC:
return toValue(param1.getAsBigDecimal().subtract(param2.getAsBigDecimal()));
default:
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
}
case BIG_DEC:
return toValue(param1.getAsBigDecimal().multiply(param2.getAsBigDecimal()));
default:
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
}
case BIG_DEC:
return toValue(param1.getAsBigDecimal().divide(param2.getAsBigDecimal()));
default:
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
}
Value.Type mathType = getMathTypePrecedence(param1, param2,
CoercionType.GENERAL);
if(mathType == Value.Type.STRING) {
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
return toValue(param1.getAsLongInt() / param2.getAsLongInt());
}
CoercionType.GENERAL);
if(mathType == Value.Type.STRING) {
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
return toValue(param1.getAsLongInt() % param2.getAsLongInt());
}
case STRING:
// string comparison is only valid if _both_ params are strings
if(param1.getType() != param2.getType()) {
- throw new RuntimeException("Unexpected type " + compareType);
+ throw new EvalException("Unexpected type " + compareType);
}
return param1.getAsString().compareToIgnoreCase(param2.getAsString());
// case DATE: break; promoted to double
case BIG_DEC:
return param1.getAsBigDecimal().compareTo(param2.getAsBigDecimal());
default:
- throw new RuntimeException("Unexpected type " + compareType);
+ throw new EvalException("Unexpected type " + compareType);
}
}
case DATE_TIME:
return new DateTimeValue(d, fmt);
default:
- throw new RuntimeException("Unexpected date/time type " + type);
+ throw new EvalException("Unexpected date/time type " + type);
}
}
fmtStr = ctx.getTemporalConfig().getDefaultDateTimeFormat();
break;
default:
- throw new RuntimeException("Unexpected date/time type " + type);
+ throw new EvalException("Unexpected date/time type " + type);
}
return ctx.createDateFormat(fmtStr);
}
import java.util.Date;
import com.healthmarketscience.jackcess.expr.EvalContext;
+import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
param = nonNullToDateValue(ctx, param);
if(param == null) {
// not a date/time
- throw new IllegalStateException("Invalid date/time expression '" + param + "'");
+ throw new EvalException("Invalid date/time expression '" + param + "'");
}
Calendar cal = getDateValueFormat(ctx, param).getCalendar();
import java.util.Map;
import com.healthmarketscience.jackcess.expr.EvalContext;
+import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
if((num < _minParams) || (num > _maxParams)) {
String range = ((_minParams == _maxParams) ? "" + _minParams :
_minParams + " to " + _maxParams);
- throw new IllegalArgumentException(
+ throw new EvalException(
"Invalid number of parameters " +
num + " passed, expected " + range);
}
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
if((params.length % 2) != 0) {
- throw new IllegalStateException("Odd number of parameters");
+ throw new EvalException("Odd number of parameters");
}
for(int i = 0; i < params.length; i+=2) {
if(params[i].getAsBoolean()) {
protected Value eval1(EvalContext ctx, Value param1) {
int lv = param1.getAsLongInt();
if((lv < 0) || (lv > 255)) {
- throw new IllegalStateException("Byte code '" + lv + "' out of range ");
+ throw new EvalException("Byte code '" + lv + "' out of range ");
}
return BuiltinOperators.toValue(lv);
}
protected Value eval1(EvalContext ctx, Value param1) {
int lv = param1.getAsLongInt();
if((lv < Short.MIN_VALUE) || (lv > Short.MAX_VALUE)) {
- throw new IllegalStateException("Int value '" + lv + "' out of range ");
+ throw new EvalException("Int value '" + lv + "' out of range ");
}
return BuiltinOperators.toValue(lv);
}
protected Value eval1(EvalContext ctx, Value param1) {
Double dv = param1.getAsDouble();
if((dv < Float.MIN_VALUE) || (dv > Float.MAX_VALUE)) {
- throw new IllegalStateException("Single value '" + dv + "' out of range ");
+ throw new EvalException("Single value '" + dv + "' out of range ");
}
return BuiltinOperators.toValue(dv.floatValue());
}
vType = 14;
break;
default:
- throw new RuntimeException("Unknown type " + type);
+ throw new EvalException("Unknown type " + type);
}
return BuiltinOperators.toValue(vType);
}
tName = "Decimal";
break;
default:
- throw new RuntimeException("Unknown type " + type);
+ throw new EvalException("Unknown type " + type);
}
return BuiltinOperators.toValue(tName);
}
import java.math.BigDecimal;
import com.healthmarketscience.jackcess.expr.EvalContext;
+import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
case BIG_DEC:
return BuiltinOperators.toValue(param1.getAsBigDecimal().abs());
default:
- throw new RuntimeException("Unexpected type " + mathType);
+ throw new EvalException("Unexpected type " + mathType);
}
}
});
protected Value eval1(EvalContext ctx, Value param1) {
double dv = param1.getAsDouble();
if(dv < 0.0d) {
- throw new IllegalStateException("Invalid value '" + dv + "'");
+ throw new EvalException("Invalid value '" + dv + "'");
}
return BuiltinOperators.toValue(Math.sqrt(dv));
}
import java.math.BigDecimal;
import com.healthmarketscience.jackcess.expr.EvalContext;
+import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
String str = param1.getAsString();
int len = str.length();
if(len == 0) {
- throw new IllegalStateException("No characters in string");
+ throw new EvalException("No characters in string");
}
int lv = str.charAt(0);
if((lv < 0) || (lv > 255)) {
- throw new IllegalStateException("Character code '" + lv +
+ throw new EvalException("Character code '" + lv +
"' out of range ");
}
return BuiltinOperators.toValue(lv);
String str = param1.getAsString();
int len = str.length();
if(len == 0) {
- throw new IllegalStateException("No characters in string");
+ throw new EvalException("No characters in string");
}
int lv = str.charAt(0);
return BuiltinOperators.toValue(lv);
protected Value eval1(EvalContext ctx, Value param1) {
int lv = param1.getAsLongInt();
if((lv < 0) || (lv > 255)) {
- throw new IllegalStateException("Character code '" + lv +
+ throw new EvalException("Character code '" + lv +
"' out of range ");
}
char[] cs = Character.toChars(lv);
return true;
default:
// vbDatabaseCompare -> unsupported
- throw new IllegalStateException("Unsupported compare type " + cmpType);
+ throw new EvalException("Unsupported compare type " + cmpType);
}
}
import java.text.DateFormat;
import java.text.FieldPosition;
-import java.text.ParseException;
import java.text.ParsePosition;
import java.util.AbstractMap;
import java.util.ArrayList;
import static com.healthmarketscience.jackcess.impl.expr.Expressionator.*;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
+import com.healthmarketscience.jackcess.expr.ParseException;
/**
tokens.add(new Token(TokenType.OBJ_NAME, parseObjNameString(buf)));
break;
default:
- throw new IllegalArgumentException(
+ throw new ParseException(
"Invalid leading quote character " + c + " " + buf);
}
}
if(!complete) {
- throw new IllegalArgumentException("Missing closing '" + QUOTED_STR_CHAR +
- "' for quoted string " + buf);
+ throw new ParseException("Missing closing '" + QUOTED_STR_CHAR +
+ "' for quoted string " + buf);
}
return sb.toString();
break;
} else if((startChar != null) &&
(startChar == c)) {
- throw new IllegalArgumentException("Missing closing '" + endChar +
- "' for quoted string " + buf);
+ throw new ParseException("Missing closing '" + endChar +
+ "' for quoted string " + buf);
}
sb.append(c);
}
if(!complete) {
- throw new IllegalArgumentException("Missing closing '" + endChar +
- "' for quoted string " + buf);
+ throw new ParseException("Missing closing '" + endChar +
+ "' for quoted string " + buf);
}
return sb.toString();
sdf = (hasAmPm ? buf.getTimeFormat12() : buf.getTimeFormat24());
valType = Value.Type.TIME;
} else {
- throw new IllegalArgumentException("Invalid date time literal " + dateStr +
- " " + buf);
+ throw new ParseException("Invalid date time literal " + dateStr +
+ " " + buf);
}
try {
return new Token(TokenType.LITERAL, sdf.parse(dateStr), dateStr, valType,
sdf);
- } catch(ParseException pe) {
- throw new IllegalArgumentException(
+ } catch(java.text.ParseException pe) {
+ throw new ParseException(
"Invalid date time literal " + dateStr + " " + buf, pe);
}
}
return new Token(TokenType.LITERAL, num, numStr,
(isFp ? Value.Type.DOUBLE : Value.Type.LONG));
} catch(NumberFormatException ne) {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Invalid number literal " + numStr + " " + buf, ne);
}
DateFormat df = _ctx.createDateFormat(BASE_DATE_FMT);
baseDate = getDateFormat().format(df.parse(baseDate));
} catch(Exception e) {
- throw new IllegalStateException("Could not parse base date", e);
+ throw new ParseException("Could not parse base date", e);
}
}
_baseDate = baseDate + " ";
import com.healthmarketscience.jackcess.expr.Expression;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
+import com.healthmarketscience.jackcess.expr.ParseException;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.expr.ExpressionTokenizer.Token;
import com.healthmarketscience.jackcess.impl.expr.ExpressionTokenizer.TokenType;
WordType wordType = getWordType(t);
if(wordType == null) {
// shouldn't happen
- throw new RuntimeException("Invalid operator " + t);
+ throw new ParseException("Invalid operator " + t);
}
// this can only be an OP or a COMP (those are the only words that the
break;
default:
- throw new RuntimeException("Unexpected OP word type " + wordType);
+ throw new ParseException("Unexpected OP word type " + wordType);
}
break;
break;
default:
- throw new RuntimeException("Unexpected STRING word type "
+ throw new ParseException("Unexpected STRING word type "
+ wordType);
}
}
break;
default:
- throw new RuntimeException("unknown token type " + t);
+ throw new ParseException("unknown token type " + t);
}
if(singleExpr && buf.hasPendingExpr()) {
Expr expr = buf.takePendingExpr();
if(expr == null) {
- throw new IllegalArgumentException("No expression found? " + buf);
+ throw new ParseException("No expression found? " + buf);
}
return expr;
}
if(atSep || (objNames.size() > 3)) {
- throw new IllegalArgumentException("Invalid object reference " + buf);
+ throw new ParseException("Invalid object reference " + buf);
}
// names are in reverse order
// the only "top-level" delim we expect to find is open paren, and
// there shouldn't be any pending expression
if(!isDelim(firstTok, OPEN_PAREN) || buf.hasPendingExpr()) {
- throw new IllegalArgumentException("Unexpected delimiter " +
+ throw new ParseException("Unexpected delimiter " +
firstTok.getValue() + " " + buf);
}
String funcName = firstTok.getValueStr();
Function func = buf.getFunction(funcName);
if(func == null) {
- throw new IllegalArgumentException("Could not find function '" +
+ throw new ParseException("Could not find function '" +
funcName + "' " + buf);
}
buf.setPendingExpr(new EFunc(func, params));
}
}
- throw new IllegalArgumentException("Missing closing '" + CLOSE_PAREN
+ throw new ParseException("Missing closing '" + CLOSE_PAREN
+ " " + buf);
}
} else if(isEitherOp(t, "-", "+")) {
parseUnaryOpExpression(t, buf);
} else {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Missing left expression for binary operator " + t.getValue() +
" " + buf);
}
// the current field value for the left value
buf.setPendingExpr(THIS_COL_VALUE);
} else {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Missing left expression for comparison operator " +
firstTok.getValue() + " " + buf);
}
private static void parseLogicalOpExpression(Token firstTok, TokBuf buf) {
if(!buf.hasPendingExpr()) {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Missing left expression for logical operator " +
firstTok.getValue() + " " + buf);
}
// the current field value for the left value
buf.setPendingExpr(THIS_COL_VALUE);
} else {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Missing left expression for comparison operator " +
specOp + " " + buf);
}
Token t = buf.next();
if((t.getType() != TokenType.LITERAL) ||
(t.getValueType() != Value.Type.STRING)) {
- throw new IllegalArgumentException("Missing Like pattern " + buf);
+ throw new ParseException("Missing Like pattern " + buf);
}
String patternStr = t.getValueStr();
specOpExpr = new ELikeOp(specOp, expr, patternStr);
if(tmpT == null) {
// ran out of expression?
- throw new IllegalArgumentException(
+ throw new ParseException(
"Missing 'And' for 'Between' expression " + buf);
}
t = buf.next();
}
if(!isDelim(t, OPEN_PAREN)) {
- throw new IllegalArgumentException("Malformed In expression " + buf);
+ throw new ParseException("Malformed In expression " + buf);
}
List<Expr> exprs = findParenExprs(buf, true);
break;
default:
- throw new RuntimeException("Unexpected special op " + specOp);
+ throw new ParseException("Unexpected special op " + specOp);
}
buf.setPendingExpr(specOpExpr);
return SpecOp.NOT;
}
- throw new IllegalArgumentException(
+ throw new ParseException(
"Malformed special operator " + opStr + " " + buf);
}
} else if("null".equalsIgnoreCase(firstTok.getValueStr())) {
constExpr = NULL_VALUE;
} else {
- throw new RuntimeException("Unexpected CONST word "
+ throw new ParseException("Unexpected CONST word "
+ firstTok.getValue());
}
buf.setPendingExpr(constExpr);
return op;
}
}
- throw new IllegalArgumentException("Unexpected op string " + t.getValueStr());
+ throw new ParseException("Unexpected op string " + t.getValueStr());
}
private static final class TokBuf
public Token next() {
if(!hasNext()) {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Unexpected end of expression " + this);
}
return _tokens.get(_pos++);
public void setPendingExpr(Expr expr) {
if(_pendingExpr != null) {
- throw new IllegalArgumentException(
+ throw new ParseException(
"Found multiple expressions with no operator " + this);
}
_pendingExpr = expr.resolveOrderOfOperations();
case BIG_DEC:
return new BigDecimalValue((BigDecimal)value);
default:
- throw new RuntimeException("unexpected literal type " + valType);
+ throw new ParseException("unexpected literal type " + valType);
}
}
case RECORD_VALIDATOR:
return evalCondition(ctx);
default:
- throw new RuntimeException("unexpected expression type " + _type);
+ throw new ParseException("unexpected expression type " + _type);
}
}
case BIG_DEC:
return val.getAsBigDecimal();
default:
- throw new IllegalStateException("unexpected result type " +
- ctx.getResultType());
+ throw new IllegalStateException("unexpected result type " + resultType);
}
}
package com.healthmarketscience.jackcess.impl.expr;
import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import com.healthmarketscience.jackcess.DatabaseBuilder;
-import com.healthmarketscience.jackcess.TestUtil;
-import com.healthmarketscience.jackcess.expr.EvalContext;
-import com.healthmarketscience.jackcess.expr.Expression;
-import com.healthmarketscience.jackcess.expr.Function;
-import com.healthmarketscience.jackcess.expr.TemporalConfig;
-import com.healthmarketscience.jackcess.expr.Value;
+
+import com.healthmarketscience.jackcess.expr.EvalException;
import junit.framework.TestCase;
import static com.healthmarketscience.jackcess.impl.expr.ExpressionatorTest.eval;
try {
eval("=Str$(Null)");
- fail("UnsupportedOperationException should have been thrown");
- } catch(UnsupportedOperationException expected) {
+ fail("EvalException should have been thrown");
+ } catch(EvalException expected) {
// success
}