1 /***
2 * Copyright (C) 2006 Philipp Mpalampanis
3 *
4 * License: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Alternatively, the contents of this file may be used under the terms of
17 * either the GNU General Public License Version 2 or later (the "GPL"), or
18 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19 * in which case the provisions of the GPL or the LGPL are applicable instead
20 * of those above. If you wish to allow use of your version of this file only
21 * under the terms of either the GPL or the LGPL, and not to allow others to
22 * use your version of this file under the terms of the MPL, indicate your
23 * decision by deleting the provisions above and replace them with the notice
24 * and other provisions required by the GPL or the LGPL. If you do not delete
25 * the provisions above, a recipient may use your version of this file under
26 * the terms of any one of the MPL, the GPL or the LGPL.
27 */
28 package net.sf.echobinding.binding;
29
30 import java.beans.*;
31 import java.io.Serializable;
32 import java.util.*;
33
34 import net.sf.echobinding.BoundControl;
35 import net.sf.echobinding.decorator.Decorator;
36 import net.sf.echobinding.format.Format;
37 import net.sf.echobinding.model.PresentationModel;
38
39 /***
40 *
41 */
42 public abstract class AbstractBindingContext implements BindingContext, Serializable {
43
44 private BindingContext _parent;
45 private Set<BindingContext> _childs;
46 protected HashMap<String, PropertyAdapter> _adapters = new HashMap<String, PropertyAdapter>();
47 private HashMap<String, BoundControl> _controls;
48 protected PropertyChangeSupport _changes = new PropertyChangeSupport(this);
49
50 private PresentationModel _presentationModel;
51
52
53
54
55
56
57
58 public BindingContext add(String id, PropertyAdapter binding) {
59 binding.setId(id);
60 _adapters.put(id, binding);
61 return this;
62 }
63
64
65
66
67
68
69 public PropertyAdapter remove(String id) {
70 return _adapters.remove(id);
71 }
72
73
74 /***
75 * Adds a child to the set of child contexts.
76 *
77 * @param child
78 */
79 public void addChild(BindingContext child) {
80 getChilds().add(child);
81 }
82
83 /***
84 * @return Returns the childs.
85 */
86 public Set<BindingContext> getChilds() {
87 if( _childs == null)
88 _childs = new HashSet<BindingContext>();
89 return _childs;
90 }
91
92 /***
93 * Sets the child contexts.
94 *
95 * @param childs The childs to set.
96 */
97 public void setChilds(Set<BindingContext> childs) {
98 _childs = childs;
99 }
100
101 /***
102 * @return Returns the parent binding context.
103 */
104 public BindingContext getParent() {
105 return _parent;
106 }
107
108 /***
109 * Sets the parent binding context.
110 *
111 * @param parent The parent binding context to set.
112 */
113 public void setParent(BindingContext parent) {
114 _parent = parent;
115 }
116
117 public List<PropertyAdapter> getPropertyAdapters() {
118 ArrayList<PropertyAdapter> list = new ArrayList<PropertyAdapter>();
119 for (String bindingId : _adapters.keySet()) {
120 list.add(_adapters.get(bindingId));
121 }
122 return list;
123 }
124
125 public Decorator getDecorator(String id) {
126 return getAdapter(id).getDecorator();
127 }
128
129 public Format getFormat(String id) {
130 return getAdapter(id).getFormat();
131 }
132
133 /***
134 * Adds a control to the list of registered controls and registers the
135 * control as PropertyChangeListener at this context.
136 */
137 public void registerControl(String id, BoundControl control) {
138 if( _controls == null )
139 _controls = new HashMap<String,BoundControl>();
140
141 addPropertyChangeListener(id, control);
142
143 _controls.put(id, control);
144 }
145
146 public void removeControl(BoundControl control) {
147 if( _controls != null )
148 _controls.remove(control);
149 }
150
151
152 public BoundControl getControl(String id) {
153 if( _controls == null )
154 return null;
155 return _controls.get(id);
156 }
157
158 public Set<BoundControl> getControls() {
159 if(_controls == null)
160 return new HashSet<BoundControl>();
161 return new HashSet<BoundControl>( _controls.values() );
162 }
163
164
165
166 /***
167 *
168 * @param bindingId
169 * @param oldValue
170 * @param newValue
171 * @throws BindingException
172 */
173 protected void firePropertyChange(String bindingId, Object oldValue, Object newValue) throws BindingException {
174
175 PropertyChangeEvent event = new PropertyChangeEvent(this, bindingId,
176 getValue(bindingId), newValue);
177
178
179 firePropertyChange(event);
180 }
181
182 protected void firePropertyChange(PropertyChangeEvent event) throws BindingException {
183
184 notifyPropertyChangeListener(event);
185
186 notifyParentContext( event );
187
188 notifiyChildContexts( event );
189 }
190
191
192
193 /***
194 * Sends a property change event to all child contexts.
195 *
196 * @param event
197 */
198 private void notifiyChildContexts(PropertyChangeEvent event) {
199 Object source = event.getSource();
200
201 PropertyChangeEvent newEvent = replaceSender( event );
202
203
204 for( BindingContext child : getChilds() ) {
205 if( ! (source==null || source.equals(child)))
206 child.propertyChange(newEvent);
207 }
208 }
209
210 /***
211 * Sends a property change event to the parent context.
212 *
213 * @param event
214 */
215 private void notifyParentContext(PropertyChangeEvent event) {
216
217 Object source = event.getSource();
218
219 PropertyChangeEvent newEvent = replaceSender( event );
220
221
222 if( ! ( getParent()==null || source.equals(getParent())) )
223 getParent().propertyChange(newEvent);
224 }
225
226 /***
227 * @param event
228 * @return
229 */
230 private PropertyChangeEvent replaceSender(PropertyChangeEvent event) {
231 if(event.getSource().equals(this))
232 return event;
233 PropertyChangeEvent newEvent = new PropertyChangeEvent(this, event.getPropertyName(), event.getOldValue(), event.getNewValue());
234 return newEvent;
235 }
236
237
238 /***
239 *
240 */
241 public void propertyChange(PropertyChangeEvent event) {
242
243 notifyPropertyChangeListener( event );
244
245 notifiyChildContexts(event);
246
247 notifyParentContext(event);
248 }
249
250 /***
251 *
252 */
253 private void notifyPropertyChangeListener(PropertyChangeEvent event) {
254 PropertyChangeEvent newEvent = replaceSender(event);
255
256
257 for (PropertyChangeListener listener : _changes.getPropertyChangeListeners(event.getPropertyName()) ) {
258 if (!listener.equals(event.getSource()))
259 listener.propertyChange(newEvent);
260 }
261
262 for (PropertyChangeListener listener : _changes.getPropertyChangeListeners() ) {
263 if (!listener.equals(event.getSource()))
264 listener.propertyChange(newEvent);
265 }
266
267
268 }
269
270
271
272 /***
273 *
274 */
275 public void addPropertyChangeListener(PropertyChangeListener listener) {
276 _changes.addPropertyChangeListener(listener);
277 }
278
279 /***
280 * Add listener for the specified property name.
281 *
282 * @param propertyName
283 * @param listener
284 */
285 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
286 _changes.addPropertyChangeListener(propertyName, listener);
287 }
288
289 /***
290 *
291 */
292 public void removePropertyChangeListener(PropertyChangeListener listener) {
293 _changes.removePropertyChangeListener(listener);
294 }
295
296 /***
297 * Remove listeners for the given property name.
298 *
299 * @param propertyName
300 * @param listener
301 */
302 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
303 _changes.removePropertyChangeListener(propertyName, listener);
304 }
305
306
307
308
309 public void synchronize() {
310
311 for(BoundControl widget: getControls()) {
312 widget.save();
313 }
314
315 for(BindingContext child: getChilds()) {
316 child.synchronize();
317 }
318 }
319
320
321
322
323 public boolean isValid() {
324
325
326 for(BoundControl widget: getControls()) {
327 if( ! widget.isValid() )
328 return false;
329 }
330
331 for(BindingContext child: getChilds()) {
332 if( ! child.isValid() )
333 return false;
334 }
335 return true;
336 }
337
338
339
340
341
342 public boolean isDirty() {
343
344 for(BoundControl widget: getControls()) {
345 if( widget.isDirty() )
346 return true;
347 }
348
349 for(BindingContext child: getChilds()) {
350 if( child.isDirty() )
351 return true;
352 }
353 return false;
354 }
355
356
357
358
359 public void update() {
360
361 for(BoundControl widget: getControls()) {
362 widget.update();
363 }
364
365 for(BindingContext child: getChilds()) {
366 child.update();
367 }
368 }
369
370
371
372
373
374
375 public void validate() {
376
377 for(BoundControl widget: getControls()) {
378 widget.validateInput();
379 }
380
381 for(BindingContext child: getChilds()) {
382 child.validate();
383 }
384 }
385
386 public boolean removeChild(BindingContext context) {
387 return _childs.remove(context);
388 }
389
390 /***
391 * @return Returns the presentationModel.
392 */
393 public PresentationModel getPresentationModel() {
394 return _presentationModel;
395 }
396
397 /***
398 * @param presentationModel The presentationModel to set.
399 */
400 public void setPresentationModel(PresentationModel presentationModel) {
401 _presentationModel = presentationModel;
402 _presentationModel.setContext(this);
403 }
404
405
406 }