`PropertyListener.java`
`01 /* 02 * Copyright 2010-2012 the original author or authors. 03 * 04 * Licensed under the Apache License, Version 2.0 (the "License") 05 * you may not use this file except in compliance with the License. 06 * You may obtain a copy of the License at 07 * 08 * http://www.apache.org/licenses/LICENSE-2.0 09 * 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. 15 */ 16 17 package griffon.transform; 18 19 import org.codehaus.groovy.transform.GroovyASTTransformationClass; 20 21 import java.lang.annotation.ElementType; 22 import java.lang.annotation.Retention; 23 import java.lang.annotation.RetentionPolicy; 24 import java.lang.annotation.Target; 25 26 /** 27 * <p>Annotates a class.</p> 28 * <p>This transformation provides a convenient way to register PropertyChangeListeners 29 * on an observable bean by leveraging Groovy's closures and the Groovy cast operator.</p> 30 * 31 * <p>The following code exemplifies what must be written by hand in order to register a pair 32 * of PropertyChangeListeners. One of them is a catch-all handler while the second is property specific. 33 * <pre> 34 * import groovy.beans.Bindable 35 * import java.beans.PropertyChangeListener 36 * 37 * class MyModel { 38 * &#064;Bindable String name 39 * &#064;Bindable String lastname 40 * 41 * def snoopAll = { evt -> ... } 42 * 43 * MyModel() { 44 * addPropertyChangeListener(snoopAll as PropertyChangeListener) 45 * addPropertyChangeListener('lastname', { 46 * controller.someAction(it) 47 * } as PropertyChangeListener) 48 * } 49 * } 50 * </pre> 51 * 52 * <p>Applying &#064;PropertyListener to the previous snippet results in the following code</p> 53 * <pre> 54 * import griffon.transform.PropertyListener 55 * import groovy.beans.Bindable 56 * 57 * &#064;PropertyListener(snoopAll) 58 * class MyModel { 59 * &#064;Bindable String name 60 * 61 * &#064;Bindable 62 * &#064;PropertyListener({controller.someAction(it)}) 63 * String lastname 64 * 65 * def snoopAll = { evt -> ... } 66 * } 67 * </pre> 68 * 69 * Any closures found as the annotation's value will be either transformed 70 * into inner classes that implement PropertyChangeListener (when the value 71 * is a closure defined in place) or be casted as a proxy of PropertyChangeListener 72 * (when the value is a property reference found in the same class).<p> 73 * List of closures are also supported. 74 * 75 * @author Andres Almiray 76 * @see org.codehaus.griffon.ast.PropertyListenerASTTransformation 77 */ 78 @Retention(RetentionPolicy.SOURCE) 79 @Target({ElementType.FIELD, ElementType.TYPE}) 80 @GroovyASTTransformationClass("org.codehaus.griffon.ast.PropertyListenerASTTransformation") 81 public @interface PropertyListener { 82 String value(); 83 }`