1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package net.sf.beanform.binding;
16
17 import java.util.Map;
18 import java.util.Map.Entry;
19
20 import org.apache.hivemind.Location;
21 import org.apache.tapestry.IBinding;
22 import org.apache.tapestry.IComponent;
23
24 /***
25 * A special binding type that allows us to simulate adding and removing
26 * bindings to components. This binding behaves like a custom binding unless
27 * there is no custom binding, in which case it behaves like the standard
28 * (default) binding for a given binding name.
29 *
30 * @author Daniel Gredler
31 */
32 public class DualBinding implements IBinding {
33
34 private IBinding custom;
35 private IBinding standard;
36
37 public DualBinding( IBinding custom, IBinding standard ) {
38 this.custom = custom;
39 this.standard = standard;
40 }
41
42 public void setCustom( IBinding custom ) {
43 this.custom = custom;
44 }
45
46 public Object getObject() {
47 if( this.custom != null ) return this.custom.getObject();
48 else if( this.standard != null ) return this.standard.getObject();
49 else return null;
50 }
51
52 public Object getObject( Class type ) {
53 if( this.custom != null ) return this.custom.getObject( type );
54 else if( this.standard != null ) return this.standard.getObject( type );
55 else return null;
56 }
57
58 public boolean isInvariant() {
59 return false;
60 }
61
62 public void setObject( Object value ) {
63 if( this.custom != null ) this.custom.setObject( value );
64 else if( this.standard != null ) this.standard.setObject( value );
65 }
66
67 public String getDescription() {
68 if( this.custom != null ) return this.custom.getDescription();
69 else if( this.standard != null ) return this.standard.getDescription();
70 else return null;
71 }
72
73 public Location getLocation() {
74 if( this.custom != null ) return this.custom.getLocation();
75 else if( this.standard != null ) return this.standard.getLocation();
76 else return null;
77 }
78
79 /***
80 * Adds temporary custom bindings to a component by overriding the existing bindings
81 * with {@link DualBinding} instances whose behavior can later be reverted.
82 */
83 public static void addCustomBindings( IComponent component, Map<String, IBinding> bindings, boolean clearFirst ) {
84 if( clearFirst ) {
85 DualBinding.removeCustomBindings( component );
86 }
87 for( Entry<String, IBinding> entry : bindings.entrySet() ) {
88 String bindingName = entry.getKey();
89 IBinding custom = entry.getValue();
90 IBinding existing = component.getBinding( bindingName );
91 DualBinding dual;
92 if( existing instanceof DualBinding ) {
93 dual = (DualBinding) existing;
94 dual.setCustom( custom );
95 }
96 else {
97 dual = new DualBinding( custom, existing );
98 }
99 component.setBinding( bindingName, dual );
100 }
101 }
102
103 /***
104 * Reverts the behavior of the specified component's temporarily customized bindings to
105 * whatever it was prior to customization.
106 */
107 @SuppressWarnings( "unchecked" )
108 public static void removeCustomBindings( IComponent component ) {
109 Map<String, IBinding> bindings = component.getBindings();
110 for( IBinding binding : bindings.values() ) {
111 if( binding instanceof DualBinding ) {
112 DualBinding dual = (DualBinding) binding;
113 dual.setCustom( null );
114 }
115 }
116 }
117
118 }