GRAILS-1019: Allowing expressions to be used with the 'disabled' attribute for g...
[grails.git] / src / groovy / org / codehaus / groovy / grails / orm / hibernate / support / ClosureEventTriggeringInterceptor.groovy
blob73116d6d1e4890b41c7528b65fb0aac8254c7a48
1 /*
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
27 /**
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
33 * @since 1.0
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)
65 modified = true
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)
72 modified
75 private modifyStateForProperty(List propertyList, String propertyName, state, value) {
76 def i = propertyList.indexOf(propertyName)
77 if(i > -1) {
78 state[i] = value
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)
96 modified = true
99 return modified
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
111 callable.call()
112 boolean stateModified = false
113 for(entry in capturedProperties) {
114 def i = propertyList.indexOf(entry.key)
115 if(i > -1) {
116 state[i] = entry.value
117 stateModified = true
120 return stateModified
122 return false