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