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