1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess.impl;
18
19 import java.io.IOException;
20 import java.math.BigDecimal;
21 import java.text.DecimalFormat;
22 import java.time.LocalDateTime;
23 import java.time.ZoneId;
24 import java.time.format.DateTimeFormatter;
25 import java.util.Collection;
26 import java.util.EnumMap;
27 import java.util.Locale;
28 import java.util.Map;
29 import javax.script.Bindings;
30
31 import com.healthmarketscience.jackcess.DataType;
32 import com.healthmarketscience.jackcess.JackcessException;
33 import com.healthmarketscience.jackcess.expr.EvalContext;
34 import com.healthmarketscience.jackcess.expr.EvalException;
35 import com.healthmarketscience.jackcess.expr.Expression;
36 import com.healthmarketscience.jackcess.expr.Identifier;
37 import com.healthmarketscience.jackcess.expr.LocaleContext;
38 import com.healthmarketscience.jackcess.expr.NumericConfig;
39 import com.healthmarketscience.jackcess.expr.TemporalConfig;
40 import com.healthmarketscience.jackcess.expr.Value;
41 import com.healthmarketscience.jackcess.impl.expr.Expressionator;
42 import com.healthmarketscience.jackcess.impl.expr.ValueSupport;
43
44
45
46
47
48 public abstract class BaseEvalContext implements EvalContext
49 {
50
51 private static final Map<DataType,Value.Type> TYPE_MAP =
52 new EnumMap<DataType,Value.Type>(DataType.class);
53
54 static {
55 TYPE_MAP.put(DataType.BOOLEAN,Value.Type.LONG);
56 TYPE_MAP.put(DataType.BYTE,Value.Type.LONG);
57 TYPE_MAP.put(DataType.INT,Value.Type.LONG);
58 TYPE_MAP.put(DataType.LONG,Value.Type.LONG);
59 TYPE_MAP.put(DataType.MONEY,Value.Type.DOUBLE);
60 TYPE_MAP.put(DataType.FLOAT,Value.Type.DOUBLE);
61 TYPE_MAP.put(DataType.DOUBLE,Value.Type.DOUBLE);
62 TYPE_MAP.put(DataType.SHORT_DATE_TIME,Value.Type.DATE_TIME);
63 TYPE_MAP.put(DataType.NUMERIC,Value.Type.BIG_DEC);
64 TYPE_MAP.put(DataType.BIG_INT,Value.Type.BIG_DEC);
65 }
66
67 private final DBEvalContext _dbCtx;
68 private Expression _expr;
69
70 protected BaseEvalContext(DBEvalContext dbCtx) {
71 _dbCtx = dbCtx;
72 }
73
74 void setExpr(Expressionator.Type exprType, String exprStr) {
75 _expr = new RawExpr(exprType, exprStr);
76 }
77
78 protected DatabaseImpl getDatabase() {
79 return _dbCtx.getDatabase();
80 }
81
82 @Override
83 public Locale getLocale() {
84 return _dbCtx.getLocale();
85 }
86
87 @Override
88 public TemporalConfig getTemporalConfig() {
89 return _dbCtx.getTemporalConfig();
90 }
91
92 @Override
93 public DateTimeFormatter createDateFormatter(String formatStr) {
94 return _dbCtx.createDateFormatter(formatStr);
95 }
96
97 @Override
98 public ZoneId getZoneId() {
99 return _dbCtx.getZoneId();
100 }
101
102 @Override
103 public NumericConfig getNumericConfig() {
104 return _dbCtx.getNumericConfig();
105 }
106
107 @Override
108 public DecimalFormat createDecimalFormat(String formatStr) {
109 return _dbCtx.createDecimalFormat(formatStr);
110 }
111
112 @Override
113 public float getRandom(Integer seed) {
114 return _dbCtx.getRandom(seed);
115 }
116
117 @Override
118 public Value.Type getResultType() {
119 return null;
120 }
121
122 @Override
123 public Value getThisColumnValue() {
124 throw new UnsupportedOperationException();
125 }
126
127 @Override
128 public Value getIdentifierValue(Identifier identifier) {
129 throw new UnsupportedOperationException();
130 }
131
132 @Override
133 public Bindings getBindings() {
134 return _dbCtx.getBindings();
135 }
136
137 @Override
138 public Object get(String key) {
139 return _dbCtx.getBindings().get(key);
140 }
141
142 @Override
143 public void put(String key, Object value) {
144 _dbCtx.getBindings().put(key, value);
145 }
146
147 public Object eval() throws IOException {
148 try {
149 return _expr.eval(this);
150 } catch(Exception e) {
151 String msg = withErrorContext(e.getMessage());
152 throw new JackcessException(msg, e);
153 }
154 }
155
156 public void collectIdentifiers(Collection<Identifier> identifiers) {
157 _expr.collectIdentifiers(identifiers);
158 }
159
160 @Override
161 public String toString() {
162 return _expr.toString();
163 }
164
165 protected Value toValue(Object val, DataType dType) {
166 try {
167
168
169 val = ColumnImpl.toInternalValue(dType, val, getDatabase(),
170 ColumnImpl.LDT_DATE_TIME_FACTORY);
171 if(val == null) {
172 return ValueSupport.NULL_VAL;
173 }
174
175 Value.Type vType = toValueType(dType);
176 switch(vType) {
177 case STRING:
178 return ValueSupport.toValue(val.toString());
179 case DATE:
180 case TIME:
181 case DATE_TIME:
182 return ValueSupport.toValue(vType, (LocalDateTime)val);
183 case LONG:
184 Integer i = ((val instanceof Integer) ? (Integer)val :
185 ((Number)val).intValue());
186 return ValueSupport.toValue(i);
187 case DOUBLE:
188 Double d = ((val instanceof Double) ? (Double)val :
189 ((Number)val).doubleValue());
190 return ValueSupport.toValue(d);
191 case BIG_DEC:
192 BigDecimal bd = ColumnImpl.toBigDecimal(val, getDatabase());
193 return ValueSupport.toValue(bd);
194 default:
195 throw new RuntimeException("Unexpected type " + vType);
196 }
197 } catch(IOException e) {
198 throw new EvalException("Failed converting value to type " + dType, e);
199 }
200 }
201
202 public static Value.Type toValueType(DataType dType) {
203 Value.Type type = TYPE_MAP.get(dType);
204 return ((type == null) ? Value.Type.STRING : type);
205 }
206
207 protected abstract String withErrorContext(String msg);
208
209 private class RawExpr implements Expression
210 {
211 private final Expressionator.Type _exprType;
212 private final String _exprStr;
213
214 private RawExpr(Expressionator.Type exprType, String exprStr) {
215 _exprType = exprType;
216 _exprStr = exprStr;
217 }
218
219 private Expression getExpr() {
220
221 Expression expr = Expressionator.parse(
222 _exprType, _exprStr, getResultType(), _dbCtx);
223 _expr = expr;
224 return expr;
225 }
226
227 @Override
228 public Object eval(EvalContext ctx) {
229 return getExpr().eval(ctx);
230 }
231
232 @Override
233 public String toDebugString(LocaleContext ctx) {
234 return getExpr().toDebugString(ctx);
235 }
236
237 @Override
238 public String toRawString() {
239 return _exprStr;
240 }
241
242 @Override
243 public String toCleanString(LocaleContext ctx) {
244 return getExpr().toCleanString(ctx);
245 }
246
247 @Override
248 public boolean isConstant() {
249 return getExpr().isConstant();
250 }
251
252 @Override
253 public void collectIdentifiers(Collection<Identifier> identifiers) {
254 getExpr().collectIdentifiers(identifiers);
255 }
256
257 @Override
258 public String toString() {
259 return toRawString();
260 }
261 }
262 }