1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.melati.poem;
47
48 import java.sql.PreparedStatement;
49 import java.sql.ResultSet;
50 import java.sql.SQLException;
51 import java.util.Enumeration;
52
53 import org.melati.poem.dbms.Dbms;
54 import org.melati.poem.util.ConsEnumeration;
55
56
57
58
59 public abstract class BasePoemType<T> implements SQLPoemType<T>, Cloneable {
60 private int sqlTypeCode;
61 protected boolean nullable;
62
63 private Comparable<T> low = null, limit = null;
64
65 BasePoemType(int sqlTypeCode, boolean nullable) {
66 this.sqlTypeCode = sqlTypeCode;
67 this.nullable = nullable;
68 }
69
70
71
72
73
74
75 public void setRawRange(Comparable<T> low, Comparable<T> limit) {
76 this.low = low;
77 this.limit = limit;
78 }
79
80 protected Comparable<T> getLowRaw() {
81 return low;
82 }
83
84 protected Comparable<T> getLimitRaw() {
85 return limit;
86 }
87
88 protected abstract void _assertValidRaw(Object raw)
89 throws ValidationPoemException;
90
91 @SuppressWarnings("unchecked")
92 private void assertRawInRange(Object raw) {
93
94
95
96 T asComparable;
97 try {
98
99
100 asComparable = (T)raw;
101
102 if ((low != null && low.compareTo(asComparable) > 0) ||
103 (limit != null && limit.compareTo(asComparable) <= 0))
104 throw new ValidationPoemException(
105 this, raw, new OutsideRangePoemException(low, limit, raw));
106 } catch (ClassCastException e) {
107 throw new NotComparablePoemException(raw, this);
108 }
109 }
110
111
112
113
114
115 public final void assertValidRaw(Object raw)
116 throws ValidationPoemException {
117 if (raw == null) {
118 if (!nullable)
119 throw new NullTypeMismatchPoemException(this);
120 }
121 else {
122 if (low != null || limit != null)
123 assertRawInRange(raw);
124 _assertValidRaw(raw);
125 }
126 }
127
128
129
130
131
132 private void doubleCheckValidRaw(Object raw) {
133 try {
134 assertValidRaw(raw);
135 }
136 catch (ValidationPoemException e) {
137 throw new UnexpectedValidationPoemException(e);
138 }
139 }
140
141 protected abstract T _getRaw(ResultSet rs, int col)
142 throws SQLException;
143
144
145
146
147
148 public final T getRaw(ResultSet rs, int col)
149 throws ValidationPoemException {
150 T o;
151 try {
152 o = (T) _getRaw(rs, col);
153 }
154 catch (SQLException e) {
155 throw new SQLSeriousPoemException(e);
156 }
157
158 assertValidRaw(o);
159 return o;
160 }
161
162 protected abstract void _setRaw(PreparedStatement ps, int col,
163 Object raw)
164 throws SQLException;
165
166
167
168
169
170 public final void setRaw(PreparedStatement ps, int col, Object raw) {
171 doubleCheckValidRaw(raw);
172 try {
173 if (raw == null)
174 ps.setNull(col, sqlTypeCode());
175 else
176 _setRaw(ps, col, raw);
177 }
178 catch (SQLException e) {
179 throw new SQLSeriousPoemException(e);
180 }
181 }
182
183 protected Enumeration<T> _possibleRaws() {
184 return null;
185 }
186
187
188
189
190
191 public Enumeration<T> possibleRaws() {
192 Enumeration<T> them = _possibleRaws();
193 return them == null ? null :
194 getNullable() ? new ConsEnumeration<T>(null, them) :
195 them;
196 }
197
198 protected abstract String _stringOfRaw(Object raw);
199
200
201
202
203
204
205 public final String stringOfRaw(Object raw)
206 throws ValidationPoemException {
207 return raw == null ? null : _stringOfRaw(raw);
208 }
209
210
211
212
213
214
215
216 protected abstract T _rawOfString(String string)
217 throws ParsingPoemException;
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public final T rawOfString(String string)
232 throws ParsingPoemException, ValidationPoemException {
233 T raw = string == null ? null : _rawOfString(string);
234 assertValidRaw(raw);
235 return raw;
236 }
237
238 protected abstract void _assertValidCooked(Object cooked)
239 throws ValidationPoemException;
240
241
242
243
244
245 public final void assertValidCooked(Object cooked)
246 throws ValidationPoemException {
247 if (cooked == null) {
248 if (!nullable)
249 throw new NullTypeMismatchPoemException(this);
250 }
251 else {
252 _assertValidCooked(cooked);
253 if (low != null || limit != null)
254 assertRawInRange(_rawOfCooked(cooked));
255 }
256 }
257
258
259
260
261
262
263 final void doubleCheckValidCooked(Object cooked) {
264 try {
265 assertValidCooked(cooked);
266 }
267 catch (ValidationPoemException e) {
268 throw new UnexpectedValidationPoemException(e);
269 }
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283 protected abstract Object _cookedOfRaw(Object raw) throws PoemException;
284
285
286
287
288
289
290
291
292
293
294
295 public final Object cookedOfRaw(Object raw) throws PoemException {
296 doubleCheckValidRaw(raw);
297 return raw == null ? null : _cookedOfRaw(raw);
298 }
299
300 protected abstract T _rawOfCooked(Object raw) throws PoemException;
301
302
303
304
305
306 public final T rawOfCooked(Object cooked) {
307 doubleCheckValidCooked(cooked);
308 return cooked == null ? null : _rawOfCooked(cooked);
309 }
310
311 protected abstract String _stringOfCooked(Object cooked,
312 PoemLocale locale, int style)
313 throws PoemException;
314
315
316
317
318
319
320 public final String stringOfCooked(Object cooked,
321 PoemLocale locale, int style)
322 throws PoemException {
323 doubleCheckValidCooked(cooked);
324 return cooked == null ? "" : _stringOfCooked(cooked, locale, style);
325 }
326
327
328
329
330
331 public final boolean getNullable() {
332 return nullable;
333 }
334
335
336
337
338
339 public final int sqlTypeCode() {
340 return sqlTypeCode;
341 }
342
343 protected abstract String _sqlDefinition(Dbms dbms);
344
345
346
347
348
349
350
351
352
353 public String sqlDefinition(Dbms dbms) {
354 return sqlTypeDefinition(dbms) + (nullable ? " NULL" : " NOT NULL");
355 }
356
357
358
359
360 public String sqlTypeDefinition(Dbms dbms) {
361 return _sqlDefinition(dbms);
362 }
363 protected abstract boolean _canRepresent(SQLPoemType<?> other);
364
365
366
367
368
369 public <O>PoemType<O> canRepresent(PoemType<O> other) {
370
371
372 if (!(other instanceof SQLPoemType))
373
374 return null;
375 else {
376 SQLPoemType<O> q = (SQLPoemType<O>)other;
377 return
378 !(!nullable && q.getNullable()) &&
379 _canRepresent(q) ?
380 q : null;
381 }
382 }
383
384
385
386
387
388 @SuppressWarnings("unchecked")
389 public final PoemType<T> withNullable(boolean nullableP) {
390 if (this.nullable == nullableP)
391 return this;
392 else {
393 BasePoemType<T> it = (BasePoemType<T>)clone();
394 it.nullable = nullableP;
395 return it;
396 }
397 }
398
399 protected abstract void _saveColumnInfo(ColumnInfo info)
400 throws AccessPoemException;
401
402
403
404
405
406 public void saveColumnInfo(ColumnInfo info) throws AccessPoemException {
407 info.setNullable(nullable);
408 info.setSize(0);
409 info.setRangelow_string(
410 getLowRaw() == null ? null : stringOfRaw(getLowRaw()));
411
412 info.setRangelimit_string(
413 getLimitRaw() == null ? null : stringOfRaw(getLimitRaw()));
414 _saveColumnInfo(info);
415 }
416
417 protected abstract String _quotedRaw(Object raw);
418
419
420
421
422
423 public String quotedRaw(Object raw) throws ValidationPoemException {
424 assertValidRaw(raw);
425 return raw == null ? "NULL" : _quotedRaw(raw);
426 }
427
428 protected abstract String _toString();
429
430
431
432
433
434
435
436
437
438
439
440 public String toString() {
441 return (nullable ? "nullable " : "") + _toString() +
442 " (" + this.getClass().getName() + ")";
443 }
444
445
446
447
448
449 protected Object clone() {
450 try {
451 return super.clone();
452 }
453 catch (CloneNotSupportedException e) {
454 throw new PoemBugPoemException();
455 }
456 }
457 }