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
47
48
49
50
51
52
53
54 public class DefaultOutputRecord implements OutputRecord
55 {
56 /*** The persistent object. */
57 private Persistent object;
58
59 /*** The fields. */
60 private HashMap<String,Object> fields;
61
62 /***
63 * Constructs an <code>OutputRecordImpl</code>.
64 *
65 * @param object a Presistent object.
66 */
67 public DefaultOutputRecord(Persistent object)
68 {
69 fields = new HashMap<String,Object>();
70 this.object = object;
71 }
72
73 /***
74 * Sets a <code>boolean</code> field value.
75 *
76 * @param field the name of the field.
77 * @param value the value of the field.
78 * @throws PersistenceException if the field could not be set to the
79 * specified value.
80 */
81 public void setBoolean(String field, boolean value)
82 throws PersistenceException
83 {
84 fields.put(field, value ? Boolean.TRUE : Boolean.FALSE);
85 }
86
87 /***
88 * Sets a <code>byte</code> field value.
89 *
90 * @param field the name of the field.
91 * @param value the value of the field.
92 * @throws PersistenceException if the field could not be set to the
93 * specified value.
94 */
95 public void setByte(String field, byte value)
96 throws PersistenceException
97 {
98 fields.put(field, new Byte(value));
99 }
100
101 /***
102 * Sets a <code>short</code> field value.
103 *
104 * @param field the name of the field.
105 * @param value the value of the field.
106 * @throws PersistenceException if the field could not be set to the
107 * specified value.
108 */
109 public void setShort(String field, short value)
110 throws PersistenceException
111 {
112 fields.put(field, new Short(value));
113 }
114
115 /***
116 * Sets an <code>int</code> field value.
117 *
118 * @param field the name of the field.
119 * @param value the value of the field.
120 * @throws PersistenceException if the field could not be set to the
121 * specified value.
122 */
123 public void setInteger(String field, int value)
124 throws PersistenceException
125 {
126 fields.put(field, new Integer(value));
127 }
128
129 /***
130 * Sets a <code>long</code> field value.
131 *
132 * @param field the name of the field.
133 * @param value the value of the field.
134 * @throws PersistenceException if the field could not be set to the
135 * specified value.
136 */
137 public void setLong(String field, long value)
138 throws PersistenceException
139 {
140 fields.put(field, new Long(value));
141 }
142
143 /***
144 * Sets a <code>BigDecimal</code> field value.
145 *
146 * @param field the name of the field.
147 * @param value the value of the field.
148 * @throws PersistenceException if the field could not be set to the
149 * specified value.
150 */
151 public void setBigDecimal(String field, BigDecimal value)
152 throws PersistenceException
153 {
154 if(value == null)
155 {
156 setNull(field);
157 return;
158 }
159 fields.put(field, value);
160 }
161
162 /***
163 * Sets a <code>float</code> field value.
164 *
165 * @param field the name of the field.
166 * @param value the value of the field.
167 * @throws PersistenceException if the field could not be set to the
168 * specified value.
169 */
170 public void setFloat(String field, float value)
171 throws PersistenceException
172 {
173 fields.put(field, new Float(value));
174 }
175
176 /***
177 * Sets a <code>double</code> field value.
178 *
179 * @param field the name of the field.
180 * @param value the value of the field.
181 * @throws PersistenceException if the field could not be set to the
182 * specified value.
183 */
184 public void setDouble(String field, double value)
185 throws PersistenceException
186 {
187 fields.put(field, new Double(value));
188 }
189
190 /***
191 * Sets a <code>String</code> field value.
192 *
193 * @param field the name of the field.
194 * @param value the value of the field.
195 * @throws PersistenceException if the field could not be set to the
196 * specified value.
197 */
198 public void setString(String field, String value)
199 throws PersistenceException
200 {
201 if(value == null)
202 {
203 setNull(field);
204 return;
205 }
206 fields.put(field, value);
207 }
208
209 /***
210 * Sets a <code>byte</code> array field value.
211 *
212 * <p>String value read from the database will be BASE64 decoded to obtain
213 * byte array.</p>
214 *
215 * @param field the name of the field.
216 * @param value the value of the field.
217 * @throws PersistenceException if the field could not be set to the
218 * specified value.
219 */
220 public void setBytes(String field, byte[] value)
221 throws PersistenceException
222 {
223 try
224 {
225 sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
226 String encoded = encoder.encodeBuffer(value);
227 fields.put(field, encoded);
228 }
229 catch(Exception e)
230 {
231 throw new PersistenceException("Failed to encode field "+field, e);
232 }
233 }
234
235 /***
236 * Sets a <code>Date</code> field value.
237 *
238 * @param field the name of the field.
239 * @param value the value of the field.
240 * @throws PersistenceException if the field could not be set to the
241 * specified value.
242 */
243 public void setDate(String field, Date value)
244 throws PersistenceException
245 {
246 if(value == null)
247 {
248 setNull(field);
249 return;
250 }
251 fields.put(field, new java.sql.Date(value.getTime()));
252 }
253
254 /***
255 * Sets a <code>Time</code> field value.
256 *
257 * @param field the name of the field.
258 * @param value the value of the filed.
259 * @throws PersistenceException if the field could not be set to the
260 * specified value.
261 */
262 public void setTime(String field, Date value)
263 throws PersistenceException
264 {
265 if(value == null)
266 {
267 setNull(field);
268 return;
269 }
270 fields.put(field, new Time(value.getTime()));
271 }
272
273 /***
274 * Sets a <code>Timestamp</code> field value.
275 *
276 * @param field the name of the field.
277 * @param value the value of the filed.
278 * @throws PersistenceException if the field could not be set to the
279 * specified value.
280 */
281 public void setTimestamp(String field, Date value)
282 throws PersistenceException
283 {
284 if(value == null)
285 {
286 setNull(field);
287 return;
288 }
289 fields.put(field, new Timestamp(value.getTime()));
290 }
291
292 /***
293 * Sets a <code>Array</code> field value.
294 *
295 * @param field the name of the field.
296 * @param value the value of the filed.
297 * @throws PersistenceException if the field could not be set to the
298 * specified value.
299 */
300 public void setArray(String field, Array value)
301 throws PersistenceException
302 {
303 fields.put(field, value);
304 }
305
306 /***
307 * Sets a <code>Blob</code> field value.
308 *
309 * @param field the name of the field.
310 * @param value the value of the filed.
311 * @throws PersistenceException if the field could not be set to the
312 * specified value.
313 */
314 public void setBlob(String field, Blob value)
315 throws PersistenceException
316 {
317 fields.put(field, value);
318 }
319
320 /***
321 * Sets a <code>Clob</code> field value.
322 *
323 * @param field the name of the field.
324 * @param value the value of the filed.
325 * @throws PersistenceException if the field could not be set to the
326 * specified value.
327 */
328 public void setClob(String field, Clob value)
329 throws PersistenceException
330 {
331 fields.put(field, value);
332 }
333
334 /***
335 * Sets a <code>Ref</code> field value.
336 *
337 * @param field the name of the field.
338 * @param value the value of the filed.
339 * @throws PersistenceException if the field could not be set to the
340 * specified value.
341 */
342 public void setRef(String field, Ref value)
343 throws PersistenceException
344 {
345 fields.put(field, value);
346 }
347
348 /***
349 * Sets a <code>URL</code> field value.
350 *
351 * @param field the name of the field.
352 * @param value the value of the filed.
353 * @throws PersistenceException if the field could not be set to the
354 * specified value.
355 */
356 public void setURL(String field, URL value)
357 throws PersistenceException
358 {
359 fields.put(field, value);
360 }
361
362 /***
363 * Sets a <code>Object</code> field value.
364 *
365 * @param field the name of the field.
366 * @param value the value of the filed.
367 * @throws PersistenceException if the field could not be set to the
368 * specified value.
369 */
370 public void setObject(String field, Object value)
371 throws PersistenceException
372 {
373 fields.put(field, value);
374 }
375
376 /***
377 * Sets a field to <code>SQL NULL</code> value.
378 *
379 * @param field the name of the field.
380 * @throws PersistenceException if the field could not be set to the
381 * specified value.
382 */
383 public void setNull(String field)
384 throws PersistenceException
385 {
386 fields.put(field, null);
387 }
388
389
390
391 /***
392 * Builds <code>WHERE</code> clause with contained data.
393 *
394 * @return the where clause.
395 * @throws PersistenceException if the clause could not be built.
396 */
397 public String getWhereClause()
398 throws PersistenceException
399 {
400 Set keyFields = getKeyFields();
401 StringBuilder buff = new StringBuilder();
402 for(Iterator i = fields.keySet().iterator(); i.hasNext();)
403 {
404 String field = (String)i.next();
405 if(keyFields.contains(field))
406 {
407 buff.append(field);
408 Object value = fields.get(field);
409 buff.append(value == null ? " IS " : " = ");
410 appendValueString(buff, value);
411 buff.append(" AND ");
412 }
413 }
414
415 buff.setLength(buff.length() - 5);
416 return buff.toString();
417 }
418
419 /***
420 * Builds an insert statement with contained data.
421 *
422 * @param conn database connection.
423 * @return the statement.
424 * @throws PersistenceException if the statement could not be built.
425 * @throws SQLException if the statement could not be created.
426 */
427 public PreparedStatement getInsertStatement(Connection conn)
428 throws PersistenceException, SQLException
429 {
430 StringBuilder buff = new StringBuilder();
431 StringBuilder buff2 = new StringBuilder();
432 buff.append("INSERT INTO ");
433 buff.append(object.getTable());
434 buff.append(" (");
435 for(Iterator i = fields.keySet().iterator(); i.hasNext();)
436 {
437 String field = (String)i.next();
438 buff.append(field);
439 Object value = fields.get(field);
440 appendValueString(buff2, value);
441 if(i.hasNext())
442 {
443 buff.append(", ");
444 buff2.append(", ");
445 }
446 }
447 buff.append(") VALUES (");
448 buff.append(buff2.toString());
449 buff.append(")");
450 PreparedStatement stmt = conn.prepareStatement(buff.toString());
451 setValues(stmt, true, true);
452 return stmt;
453 }
454
455 /***
456 * Builds an update statement with contained data.
457 *
458 * @param conn database connection.
459 * @return the statement.
460 * @throws PersistenceException if the statement could not be built.
461 * @throws SQLException if the statement could not be created.
462 */
463 public PreparedStatement getUpdateStatement(Connection conn)
464 throws PersistenceException, SQLException
465 {
466 Set keyFields = getKeyFields();
467 StringBuilder buff = new StringBuilder();
468 buff.append("UPDATE ");
469 buff.append(object.getTable());
470 buff.append(" SET ");
471 Iterator i = fields.keySet().iterator();
472 while(i.hasNext())
473 {
474 String field = (String)i.next();
475 if(!keyFields.contains(field))
476 {
477 buff.append(field);
478 buff.append(" = ");
479 Object value = fields.get(field);
480 appendValueString(buff, value);
481 buff.append(", ");
482 }
483 }
484
485 buff.setLength(buff.length() - 2);
486 buff.append(" WHERE ");
487 buff.append(getWhereClause());
488 PreparedStatement stmt = conn.prepareStatement(buff.toString());
489
490 setValues(stmt, false, true);
491
492 setValues(stmt, true, false);
493 return stmt;
494 }
495
496 /***
497 * @return set of key field names.
498 */
499 private Set getKeyFields()
500 {
501 return new HashSet<String>(Arrays.asList(object.getKeyColumns()));
502 }
503
504 /***
505 * Appends string token apropriate for the value in the statement body to a given buffer.
506 *
507 * @param buff the buffer to append to.
508 * @param object the object.
509 */
510 private void appendValueString(StringBuilder buff, Object object)
511 {
512 if(object == null)
513 {
514 buff.append("NULL");
515 }
516 else
517 {
518 if(object instanceof Number)
519 {
520 buff.append(object.toString());
521 }
522 else
523 {
524 buff.append('?');
525 }
526 }
527 }
528
529 /***
530 * Builds a <code>DELETE</code> statement with contained data.
531 *
532 *
533 * @param conn database connection.
534 * @return the statement.
535 * @throws PersistenceException if the statement could not be built.
536 * @throws SQLException if the statement could not be created.
537 */
538 public PreparedStatement getDeleteStatement(Connection conn)
539 throws PersistenceException, SQLException
540 {
541 StringBuilder buff = new StringBuilder();
542 buff.append("DELETE FROM ");
543 buff.append(object.getTable());
544 buff.append(" WHERE ");
545 buff.append(getWhereClause());
546 PreparedStatement stmt = conn.prepareStatement(buff.toString());
547 setValues(stmt, true, false);
548 return stmt;
549 }
550
551 /***
552 * Returns a value of a field.
553 *
554 * <p>Note! String and Date values will be returned enclosed in single
555 * quotes, byte array values will be returned BASE64 encoded and enclosed
556 * in single quotes.</p>
557 *
558 * @param name the name of the field
559 * @return stringied and possibly quoted value of the field, or
560 * <code>null</code> if unset.
561 */
562 public String getField(String name)
563 {
564 return (String)fields.get(name);
565 }
566
567 /***
568 * Sets prepared statement's positional parameters to non-string field values.
569 *
570 * @param stmt the statement.
571 * @param includeKeys <code>true</code> to set key values.
572 * @param includeNonKeys <code>true</code> to set non-key values.
573 * @throws SQLException if a value couldn't be set.
574 */
575 public void setValues(PreparedStatement stmt, boolean includeKeys, boolean includeNonKeys)
576 throws SQLException
577 {
578 Set keyFields = getKeyFields();
579 int pos = 1;
580 for(Iterator i = fields.keySet().iterator(); i.hasNext();)
581 {
582 Object field = i.next();
583 boolean isKey = keyFields.contains(field);
584 if((isKey && includeKeys) || (!isKey && includeNonKeys))
585 {
586 Object value = fields.get(field);
587 if(value != null)
588 {
589 if(!(value instanceof Number))
590 {
591 setValue(pos++, value, stmt);
592 }
593 }
594 }
595 }
596 }
597
598 /***
599 * Sets prepared statement's positional parameters to non-string field values.
600 *
601 * @param pos parameter position (1 based).
602 * @param value parameter value.
603 * @param stmt the statement.
604 */
605 private void setValue(int pos, Object value, PreparedStatement stmt)
606 throws SQLException
607 {
608 if(value instanceof Array)
609 {
610 stmt.setArray(pos, (Array)value);
611 }
612 else if(value instanceof Blob)
613 {
614 stmt.setBlob(pos, (Blob)value);
615 }
616 else if(value instanceof Clob)
617 {
618 stmt.setClob(pos, (Clob)value);
619 }
620 else if(value instanceof java.sql.Date)
621 {
622 stmt.setDate(pos, (java.sql.Date)value);
623 }
624 else if(value instanceof Time)
625 {
626 stmt.setTime(pos, (Time)value);
627 }
628 else if(value instanceof Timestamp)
629 {
630 stmt.setTimestamp(pos, (Timestamp)value);
631 }
632 else if(value instanceof Ref)
633 {
634 stmt.setRef(pos, (Ref)value);
635 }
636 else if(value instanceof URL)
637 {
638 stmt.setURL(pos, (URL)value);
639 }
640 else if(value instanceof Boolean)
641 {
642 stmt.setInt(pos, ((Boolean)value).booleanValue() ? 1 : 0);
643 }
644 else if(value instanceof String)
645 {
646 stmt.setString(pos, (String)value);
647 }
648 else
649 {
650 stmt.setObject(pos, object);
651 }
652 }
653 }