OSDN Git Service

Jumbo patch:
[pf3gnuchains/gcc-fork.git] / libjava / java / beans / beancontext / BeanContextChildSupport.java
1 /* java.beans.beancontext.BeanContextChildSupport
2    Copyright (C) 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10  
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 As a special exception, if you link this library with other files to
22 produce an executable, this library does not by itself cause the
23 resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why the
25 executable file might be covered by the GNU General Public License. */
26
27
28 package java.beans.beancontext;
29
30 import java.beans.PropertyChangeListener;
31 import java.beans.VetoableChangeListener;
32 import java.beans.PropertyVetoException;
33 import java.beans.PropertyChangeEvent;
34 import java.beans.PropertyChangeSupport;
35 import java.beans.VetoableChangeSupport;
36 import java.io.Serializable;
37
38 /**
39  * Support for creating a <code>BeanContextChild</code>.
40  * This class contains the most common implementations of the methods in
41  * the <code>BeanContextChild</code>
42  *
43  * @specnote This class is not very well specified.  I had to "fill in the
44  *           blanks" in most places with what I thought was reasonable
45  *           behavior.  If there are problems, let me know.
46  *
47  * @author John Keiser
48  * @since JDK1.2
49  * @see java.beans.beancontext.BeanContextChild
50  */
51
52 public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {
53         /**
54          * The peer on which to perform <code>set</code> actions.
55          * This is here so that this class can be used as a peer.
56          * <P>
57          *
58          * When extending this class, this variable will be set to
59          * <code>this</code>.
60          */
61         public BeanContextChild beanContextChildPeer;
62
63         /**
64          * The parent <code>BeanContext</code>.
65          */
66         protected transient BeanContext beanContext;
67
68         /**
69          * If <code>setBeanContext()</code> was vetoed once before, this
70          * is set to <code>true</code> so that the next time, vetoes will
71          * be ignored.
72          */
73         protected transient boolean rejectedSetBCOnce;
74
75         /**
76          * Listeners are registered here and events are fired through here.
77          */
78         protected PropertyChangeSupport pcSupport;
79
80         /**
81          * Listeners are registered here and events are fired through here.
82          */
83         protected VetoableChangeSupport vcSupport;
84
85
86         /**
87          * Create a new <code>BeanContextChildSupport</code> with itself as the peer.
88          * This is meant to be used when you subclass
89          * <code>BeanContextChildSupport</code> to create your child.
90          */
91         public BeanContextChildSupport() {
92                 this(null);
93         };
94
95         /**
96          * Create a new <code>BeanContextChildSupport</code> with the specified peer.
97          * @param peer the peer to use, or <code>null</code> to specify
98          *        <code>this</code>.
99          */
100         public BeanContextChildSupport(BeanContextChild peer) {
101                 if(peer == null) {
102                         peer = this;
103                 }
104
105                 beanContextChildPeer = peer;
106                 pcSupport = new PropertyChangeSupport(peer);
107                 vcSupport = new VetoableChangeSupport(peer);
108         }
109
110         /**
111          * Set the parent <code>BeanContext</code>.
112          * <P>
113          *
114          * When this Object is being added to a new BeanContext or moved
115          * from an old one, a non-null value will be passed in.
116          * <P>
117          *
118          * When this Object is being removed from the current
119          * <code>BeanContext</code>, <code>setBeanContext()</code> will
120          * receive the parameter <code>null</code>.
121          * <P>
122          *
123          * Order of events:
124          * <OL>
125          *   <LI>
126          *     If the new <code>BeanContext</code> is the same as the old
127          *     one, nothing happens.
128          *   </LI>
129          *   <LI>
130          *     If the change has not been rejected or vetoed before, call
131          *     <code>validatePendingSetBeanContext()</code>.  If this call
132          *     returns <code>false</code>, the change is rejected and a
133          *     <code>PropertyVetoException</code> is thrown.
134          *   </LI>
135          *   <LI>
136          *     If the change has not been rejected or vetoed before,
137          *     <code>VetoableChangeEvent</code>s are fired with the name
138          *     <code>"beanContext"</code>, using the
139          *     <code>fireVetoableChange()</code> method.  If a veto
140          *     occurs, reversion events are fired using the same method,
141          *     the change is rejected, and the veto is rethrown.
142          *   </LI>
143          *   <LI>
144          *     <code>releaseBeanContextResources()</code> is called.
145          *   </LI>
146          *   <LI>
147          *     The change is made.
148          *   </LI>
149          *   <LI>
150          *     <code>PropertyChangeEvent</code>s are fired using the
151          *     <code>firePropertyChange()</code> method.
152          *   </LI>
153          *   <LI>
154          *     <code>initializeBeanContextResources()</code> is called.
155          *   </LI>
156          * </OL>
157          * <P>
158          *
159          * @param newBeanContext the new parent for the
160          *        <code>BeanContextChild</code>, or <code>null</code> to
161          *        signify removal from a tree.
162          * @exception PropertyVetoException if the
163          *            <code>BeanContextChild</code> implementor does not
164          *            wish to have its parent changed.
165          */
166         public void setBeanContext(BeanContext newBeanContext)
167                 throws PropertyVetoException {
168                 synchronized(beanContextChildPeer) {
169                         if(newBeanContext == beanContext)
170                                 return;
171
172                         if(!rejectedSetBCOnce) {
173                                 if(!validatePendingSetBeanContext(newBeanContext)) {
174                                         rejectedSetBCOnce = true;
175                                         throw new PropertyVetoException("validatePendingSetBeanContext() rejected change",
176                                                 new PropertyChangeEvent(beanContextChildPeer, "beanContext", beanContext, newBeanContext));
177                                 }
178                                 try {
179                                         fireVetoableChange("beanContext", beanContext, newBeanContext);
180                                 } catch(PropertyVetoException e) {
181                                         rejectedSetBCOnce = true;
182                                         throw e;
183                                 }
184                         }
185
186                         releaseBeanContextResources();
187
188                         beanContext = newBeanContext;
189                         rejectedSetBCOnce = false;
190
191                         firePropertyChange("beanContext", beanContext, newBeanContext);
192
193                         initializeBeanContextResources();
194                 }
195         }
196
197         /**
198          * Get the parent <code>BeanContext</code>.
199          * @return the parent <code>BeanContext</code>.
200          */
201         public BeanContext getBeanContext() {
202                 return beanContext;
203         }
204
205         /**
206          * Get the peer (or <code>this</code> if there is no peer).
207          * @return the peer, or <code>this</code> if there is no peer.
208          */
209         public BeanContextChild getBeanContextChildPeer() {
210                 return beanContextChildPeer;
211         }
212
213         /**
214          * Determine whether there is a peer.
215          * This is true iff <code>getBeanContextChildPeer() == this</code>.
216          * @return whether there is a peer.
217          */
218         public boolean isDelegated() {
219                 return beanContextChildPeer == this;
220         }
221
222         /**
223          * Add a listener that will be notified when a specific property changes.
224          * @param propertyName the name of the property to listen on.
225          * @param listener the listener to listen on the property.
226          */
227         public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
228                 pcSupport.addPropertyChangeListener(propertyName, listener);
229         }
230
231         /**
232          * Remove a listener to a certain property.
233          * 
234          * @param propertyName the name of the property being listened on.
235          * @param listener the listener listening on the property.
236          */
237         public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
238                 pcSupport.removePropertyChangeListener(propertyName, listener);
239         }
240
241         /**
242          * Add a listener that will be notified when a specific property
243          * change is requested (a PropertyVetoException may be thrown) as
244          * well as after the change is successfully made.
245          *
246          * @param propertyName the name of the property to listen on.
247          * @param listener the listener to listen on the property.
248          */
249         public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
250                 vcSupport.addVetoableChangeListener(propertyName, listener);
251         }
252
253         /**
254          * Remove a listener to a certain property.
255          *
256          * @param propertyName the name of the property being listened on
257          * @param listener the listener listening on the property.
258          */
259         public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
260                 vcSupport.removeVetoableChangeListener(propertyName, listener);
261         }
262
263         /**
264          * Fire a property change.
265          *
266          * @param propertyName the name of the property that changed
267          * @param oldVal the old value of the property
268          * @param newVal the new value of the property
269          */
270         public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
271                 pcSupport.firePropertyChange(propertyName, oldVal, newVal);
272         }
273
274         /**
275          * Fire a vetoable property change.
276          *
277          * @param propertyName the name of the property that changed
278          * @param oldVal the old value of the property
279          * @param newVal the new value of the property
280          * @exception PropertyVetoException if the change is vetoed.
281          */
282         public void fireVetoableChange(String propertyName, Object oldVal, Object newVal)
283                         throws PropertyVetoException {
284                 vcSupport.fireVetoableChange(propertyName, oldVal, newVal);
285         }
286
287         /**
288          * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
289          * If you have a reference to such a service, it should be
290          * discarded and may no longer function properly.
291          * <code>getService()</code> will no longer work on the specified
292          * service class after this event has been fired.
293          * <P>
294          *
295          * <EM>This method is meant to be overriden.</EM>
296          * <code>BeanContextChildSupport</code>'s implementation does
297          * nothing.
298          *
299          * @param event the service revoked event.
300          * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
301          */
302         public void serviceRevoked(BeanContextServiceRevokedEvent event) {
303         }
304
305         /**
306          * Called by <code>BeanContextServices</code> whenever a service is made available.
307          * <P>
308          *
309          * <EM>This method is meant to be overriden.</EM>
310          * <code>BeanContextChildSupport</code>'s implementation does
311          * nothing.
312          *
313          * @param event the service revoked event, with useful information
314          *        about the new service.
315          */
316         public void serviceAvailable(BeanContextServiceAvailableEvent event) {
317         }
318
319         /**
320          * Called by <code>setBeanContext()</code> to determine whether the set should be rejected.
321          * <P>
322          *
323          * <EM>This method is meant to be overriden.</EM>
324          * <code>BeanContextChildSupport</code>'s implementation simply
325          * returns <code>true</code>.
326          *
327          * @param newBeanContext the new parent.
328          * @return whether to allow the parent to be changed to the new
329          *         value.
330          */
331         public boolean validatePendingSetBeanContext(BeanContext newBeanContext) {
332                 return true;
333         }
334
335         /**
336          * Called by <code>setBeanContext()</code> to release resources of a what will soon no longer be the parent.
337          * <P>
338          *
339          * <EM>This method is meant to be overriden.</EM>
340          * <code>BeanContextChildSupport</code>'s implementation does
341          * nothing.
342          */
343         protected void releaseBeanContextResources() {
344         }
345
346         /**
347          * Called by <code>setBeanContext()</code> to grab resources when the parent has been set.
348          * <P>
349          *
350          * <EM>This method is meant to be overriden.</EM>
351          * <code>BeanContextChildSupport</code>'s implementation does
352          * nothing.
353          */
354         protected void initializeBeanContextResources() {
355         }
356 }