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