2 * Copyright 2003-2007 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.codehaus
.groovy
.grails
.orm
.hibernate
.support
18 import org
.hibernate
.EmptyInterceptor
19 import org
.hibernate
.type
.Type
20 import org
.codehaus
.groovy
.grails
.commons
.GrailsDomainClassProperty
21 import org
.codehaus
.groovy
.grails
.orm
.hibernate
.cfg
.Mapping
22 import org
.codehaus
.groovy
.grails
.orm
.hibernate
.cfg
.GrailsDomainBinder
23 import org
.springframework
.context
.ApplicationContextAware
24 import org
.springframework
.context
.ApplicationContext
25 import org
.springframework
.beans
.factory
.config
.AutowireCapableBeanFactory
28 * <p>An interceptor that invokes closure events on domain entities such as beforeInsert, beforeUpdate and beforeDelete
30 * <p>This class also deals with auto time stamping of domain classes that have properties named 'lastUpdated' and/or 'dateCreated'
32 * @author Graeme Rocher
35 class ClosureEventTriggeringInterceptor
extends EmptyInterceptor
implements ApplicationContextAware
{
37 static final String ONLOAD_EVENT
= 'onLoad'
38 static final String BEFORE_INSERT_EVENT
= 'beforeInsert'
39 static final String BEFORE_UPDATE_EVENT
= 'beforeUpdate'
40 static final String BEFORE_DELETE_EVENT
= 'beforeDelete'
42 private transient ApplicationContext applicationContext
44 public void setApplicationContext(ApplicationContext applicationContext
) {
45 this.applicationContext
= applicationContext
48 public boolean onLoad(Object entity
, Serializable id
, Object
[] state
, String
[] propertyNames
, Type
[] types
) {
49 applicationContext?
.autowireCapableBeanFactory?
.autowireBeanProperties(entity
,AutowireCapableBeanFactory
.AUTOWIRE_BY_NAME
, false)
50 return triggerEvent(ONLOAD_EVENT
, entity
, state
, propertyNames
.toList())
52 public boolean onSave(Object entity
, Serializable id
, Object
[] state
, String
[] propertyNames
, Type
[] types
) {
53 def propertyList
= propertyNames
.toList()
54 def modified
= triggerEvent(BEFORE_INSERT_EVENT
, entity
, state
, propertyList
)
56 def metaClass
= entity
.metaClass
57 Mapping m
= GrailsDomainBinder
.getMapping(entity
.getClass())
58 boolean shouldTimestamp
= m
&& !m
.autoTimestamp ?
false : true
60 MetaProperty property
= metaClass
.hasProperty(entity
, GrailsDomainClassProperty
.DATE_CREATED
)
61 def time
= System
.currentTimeMillis()
62 if(property
&& shouldTimestamp
) {
63 def now
= property
.getType().newInstance([time
] as Object
[] )
64 modifyStateForProperty(propertyList
, property
.name
, state
, now
)
67 property
= metaClass
.hasProperty(entity
,GrailsDomainClassProperty
.LAST_UPDATED
)
68 if(property
&& shouldTimestamp
) {
69 def now
= property
.getType().newInstance([time
] as Object
[] )
70 modifyStateForProperty(propertyList
, GrailsDomainClassProperty
.LAST_UPDATED
, state
, now
)
75 private modifyStateForProperty(List propertyList
, String propertyName
, state
, value
) {
76 def i
= propertyList
.indexOf(propertyName
)
83 public void onDelete(Object entity
, Serializable id
, Object
[] state
, String
[] propertyNames
, Type
[] types
) {
84 triggerEvent(BEFORE_DELETE_EVENT
, entity
, state
, propertyNames
.toList())
87 public boolean onFlushDirty(Object entity
, Serializable id
, Object
[] currentState
, Object
[] previousState
, String
[] propertyNames
, Type
[] types
) {
88 List propertyList
= propertyNames
.toList()
89 boolean modified
= triggerEvent(BEFORE_UPDATE_EVENT
, entity
, currentState
, propertyList
)
90 Mapping m
= GrailsDomainBinder
.getMapping(entity
.getClass())
91 boolean shouldTimestamp
= m
&& !m
.autoTimestamp ?
false : true
92 MetaProperty property
= entity
.metaClass
.hasProperty(entity
, GrailsDomainClassProperty
.LAST_UPDATED
)
93 if(property
&& shouldTimestamp
) {
94 def now
= property
.getType().newInstance([System
.currentTimeMillis()] as Object
[] )
95 modifyStateForProperty(propertyList
, GrailsDomainClassProperty
.LAST_UPDATED
, currentState
, now
)
102 private boolean triggerEvent(event
, entity
, state
, propertyList
) {
103 if(entity
.metaClass
.hasProperty(entity
, event
)) {
104 def callable
= entity
."$event"
105 callable
.resolveStrategy
= Closure
.DELEGATE_FIRST
106 def capturedProperties
= [:]
107 for(i in
0..<propertyList
.size()) {
108 capturedProperties
[propertyList
[i
]] = state
[i
]
110 callable
.delegate
= capturedProperties
112 boolean stateModified
= false
113 for(entry in capturedProperties
) {
114 def i
= propertyList
.indexOf(entry
.key
)
116 state
[i
] = entry
.value