1 package org.itracker.persistence.dao;
2
3 import org.apache.log4j.Logger;
4 import org.hibernate.EmptyInterceptor;
5 import org.hibernate.type.Type;
6 import org.itracker.model.AbstractEntity;
7
8 import java.io.Serializable;
9 import java.util.Date;
10
11 /**
12 * A Hibernate Interceptor that automatically sets the <code>createDate</code>
13 * and <code>lastModifiedDate</code> of any AbstractEntity instance that is
14 * inserted or updated.
15 *
16 * @author johnny
17 */
18 public class TimestampInterceptor extends EmptyInterceptor {
19
20 /**
21 *
22 */
23 private static final long serialVersionUID = 1L;
24
25 /**
26 * The name of the AbstractEntity.createDate property
27 */
28 private static final String CREATE_DATE_PROPERTY = "createDate";
29
30 /**
31 * The name of the AbstractEntity.lastModifiedDate property
32 */
33 private static final String LAST_MODIFIED_DATE_PROPERTY = "lastModifiedDate";
34
35 @SuppressWarnings("unused")
36 private static final transient Logger logger = Logger.getLogger(TimestampInterceptor.class);
37
38 /**
39 *
40 */
41 public TimestampInterceptor() {
42 }
43
44 /**
45 * Called before inserting an item in the datastore.
46 * <p/>
47 * <p>The interceptor may modify the state, which will be used for
48 * the SQL INSERT and propagated to the persistent object. </p>
49 * <p/>
50 * <p>Automatically sets the createDate and lastModifiedDate properties. </p>
51 *
52 * @return true if the timestamp was set and thus the state was modified
53 */
54 public boolean onSave(Object entity, Serializable id,
55 Object[] state, String[] propertyNames, Type[] types) {
56
57 if (entity instanceof AbstractEntity) {
58 final Date timestamp = new Date();
59
60 // Number of properties to set.
61 int propertiesSet = 0;
62
63 // Find createDate property to set.
64 for (int i = 0; i < propertyNames.length; i++) {
65
66 if (CREATE_DATE_PROPERTY.equals(propertyNames[i])
67 || LAST_MODIFIED_DATE_PROPERTY.equals(propertyNames[i])) {
68 state[i] = timestamp;
69
70 // if (this.logger.isDebugEnabled()) {
71 // this.logger.debug("Setting " + propertyNames[i]
72 // + " property of " + entity);
73 // }
74
75 if (++propertiesSet == 2) {
76 break;
77 }
78 }
79 }
80 return (propertiesSet > 0);
81 }
82 return false;
83 }
84
85 /**
86 * Called before updating the datastore.
87 * <p/>
88 * <p>Called when an object is detected to be dirty, during a flush.
89 * The interceptor may modify the detected currentState, which will be
90 * propagated to both the database and the persistent object. <br>
91 * Note that not all flushes end in actual synchronization
92 * with the database, in which case the new currentState will be
93 * propagated to the object, but not necessarily (immediately)
94 * to the database. It is strongly recommended that the interceptor
95 * not modify the previousState. </p>
96 * <p/>
97 * <p>Automatically sets the lastModifiedDate property. </p>
98 *
99 * @return true if the timestamp was set and thus the currentState was modified
100 */
101 public boolean onFlushDirty(Object entity, Serializable id,
102 Object[] currentState, Object[] previousState,
103 String[] propertyNames, Type[] types) {
104
105 if (entity instanceof AbstractEntity) {
106 final Date timestamp = new Date();
107
108 // Find lastModifiedDate property to set.
109 for (int i = 0; i < propertyNames.length; i++) {
110
111 if (LAST_MODIFIED_DATE_PROPERTY.equals(propertyNames[i])) {
112 currentState[i] = timestamp;
113
114 // if (this.logger.isDebugEnabled()) {
115 // this.logger.debug("Setting " + propertyNames[i]
116 // + " property of " + entity);
117 // }
118 return true;
119 }
120 }
121 }
122 return false;
123 }
124
125 }