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