1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.caleigo.core;
20
21
22 import java.util.*;
23
24 import org.caleigo.core.event.*;
25 import org.caleigo.core.exception.*;
26
27 /*** <Description for ProxySelection>
28 *
29 * @author Dennis Zikovic
30 * @version 1.00
31 *
32 *//*
33 *
34 * WHEN WHO WHY & WHAT
35 * -----------------------------------------------------------------------------
36 * 2001-11-23 Dennis Zikovic Creation
37 */
38 public class ProxySelection implements IProxySelection
39 {
40
41 private ISelection mRemoteSelection;
42 private IEntityDescriptor mEntityDescriptor;
43
44 private transient RelayListener mEntityRelayListener;
45 private transient ISelectionListener mSelectionListener;
46 private transient IEntityListener mEntityListener;
47 private transient IEntityChangeListener mEntityChangeListener;
48 private transient IProxyListener mProxyListener;
49
50
51
52 /*** Creates new ProxySelection
53 */
54 public ProxySelection(IEntityDescriptor entityDescriptor)
55 {
56 mEntityDescriptor = entityDescriptor;
57 }
58
59 /*** Creates new ProxySelection
60 */
61 public ProxySelection(ISelection selection)
62 {
63
64 if(selection==null)
65 throw new InvalidSelectionException("ProxySelection can not be instatiated with a null selecltion.");
66
67
68 mEntityDescriptor = selection.getEntityDescriptor();
69 this.setRemoteSelection(selection);
70 }
71
72
73
74 /*** Return true if any (one or more) of the collections's contained
75 * entities has the DIRTY flag set to true that is have unsaved changes.
76 */
77 public boolean isDirty()
78 {
79 if(mRemoteSelection!=null)
80 return mRemoteSelection.isDirty();
81 else
82 return false;
83 }
84
85 /*** Stores all contained entities that have the DIRTY flag set to true.
86 * The entities are stored in a single transaction meaning that if one
87 * store fails then all fails.
88 */
89 public void storeAll()
90 {
91 if(mRemoteSelection!=null)
92 mRemoteSelection.storeAll();
93 }
94
95 /*** Deletes all contained entities. The entities are deleted in a single
96 * transaction meaning that if one delete fails then all fails.
97 * USE THIS METHOD WITH CAUTION.
98 */
99 public void deleteAll()
100 {
101 if(mRemoteSelection!=null)
102 mRemoteSelection.deleteAll();
103 }
104
105 /*** Performs a refresh on all contained entities. The refresh is batched
106 * to save performance.
107 */
108 public void refreshAll()
109 {
110 if(mRemoteSelection!=null)
111 mRemoteSelection.refreshAll();
112 }
113
114 /*** Adds the provided IEntity object to the end of selection object.
115 * If an entity with the same identity already exists in the selection the
116 * requeat is ignored and false is returned.
117 */
118 public boolean addEntity(IEntity entity)
119 {
120 if(mRemoteSelection!=null)
121 return mRemoteSelection.addEntity(entity);
122 else
123 return false;
124 }
125
126 /*** Adds the provided IEntity object to at the specified index in the
127 * selection object. If an entity with the same identity already exists
128 * in the selection the requeat is ignored and false is returned.
129 */
130 public boolean addEntity(int index, IEntity entity)
131 {
132 if(mRemoteSelection!=null)
133 return mRemoteSelection.addEntity(index, entity);
134 else
135 return false;
136 }
137
138 /*** Access method that returns the contained IEntity object with the
139 * specified index.
140 */
141 public IEntity getEntity(int index)
142 {
143 if(mRemoteSelection!=null)
144 return mRemoteSelection.getEntity(index);
145 else
146 return null;
147 }
148
149 /*** Mutation method that removes the provided entity from the selection.
150 * Returns true if the entity was found and removed otherwise false is
151 * returned.
152 */
153 public boolean removeEntity(IEntity entity)
154 {
155 if(mRemoteSelection!=null)
156 return mRemoteSelection.removeEntity(entity);
157 else
158 return false;
159 }
160
161 /*** Mutation method that removes the indexed entity from the selection.
162 * Returns the indexed entity if it was found and removed otherwise null
163 * is returned. The entities are not effecte in any other way.
164 */
165 public IEntity removeEntity(int index)
166 {
167 if(mRemoteSelection!=null)
168 return mRemoteSelection.removeEntity(index);
169 else
170 return null;
171 }
172
173 /*** Returns a java.util.Iterator object that iterates over all entities
174 * in the selection. The iterator should be read only and should not
175 * support the remove method. The entities are not effected in any other way.
176 */
177 public Iterator iterator()
178 {
179 if(mRemoteSelection!=null)
180 return mRemoteSelection.iterator();
181 else
182 return null;
183 }
184
185 /*** Mutation method the removes all entities currently stored in the
186 * selection. The entities are not effected in any other way.
187 */
188 public void clear()
189 {
190 if(mRemoteSelection!=null)
191 mRemoteSelection.clear();
192 }
193
194 /*** Access method that reurns the number entities currently contained in
195 * the selection object.
196 */
197 public int size()
198 {
199 if(mRemoteSelection!=null)
200 return mRemoteSelection.size();
201 else
202 return 0;
203 }
204
205 /*** Boolean access method that return true if the selection is empty.
206 */
207 public boolean isEmpty()
208 {
209 if(mRemoteSelection!=null)
210 return mRemoteSelection.isEmpty();
211 else
212 return true;
213 }
214
215 /*** Access method that views the selection objct as a grid where row is
216 * the entity index and column is the field index for the stored entities.
217 */
218 public Object getData(int row, int column)
219 {
220 if(mRemoteSelection!=null)
221 return mRemoteSelection.getData(row, column);
222 else
223 return mEntityDescriptor.getFieldDescriptor(column).getDefaultValue();
224 }
225
226 /*** Mutation method that views the selection objct as a grid where row is
227 * the entity index and column is the field index for the stored entities.
228 */
229 public void setData(int row, int column, Object dataValue)
230 {
231 if(mRemoteSelection!=null)
232 mRemoteSelection.setData(row, column, dataValue);
233 }
234
235 /*** Access method that returns the IEntityDescriptor for the selection.
236 * The selection object will only support entities of that type.
237 */
238 public IEntityDescriptor getEntityDescriptor()
239 {
240 return mEntityDescriptor;
241 }
242
243 /*** Adds an ISelectionListener to receive notifiactions of changes
244 * in the entity content of the collection object.
245 */
246 public void addSelectionListener(ISelectionListener listener)
247 {
248 if(mSelectionListener==null && mRemoteSelection!=null)
249 mRemoteSelection.addSelectionListener(this.getRelayListener());
250 mSelectionListener = (ISelectionListener)CELEventMulticaster.add(mSelectionListener, listener);
251 }
252
253 /*** Removes an ISelectionListener from the collection object.
254 */
255 public void removeSelectionListener(ISelectionListener listener)
256 {
257 mSelectionListener = (ISelectionListener)CELEventMulticaster.remove(mSelectionListener, listener);
258 if(mSelectionListener==null && mRemoteSelection!=null)
259 mRemoteSelection.removeSelectionListener(this.getRelayListener());
260 }
261
262 /*** Adds IEntityListener to receive notifications of performed
263 * data operations on all entities contained in the collection object.
264 */
265 public void addEntityListener(IEntityListener listener)
266 {
267 if(mEntityListener==null && mRemoteSelection!=null)
268 mRemoteSelection.addEntityListener(this.getRelayListener());
269 mEntityListener = (IEntityListener)CELEventMulticaster.add(mEntityListener, listener);
270 }
271
272 /*** Removes the specified IEntityListener from the collection object.
273 */
274 public void removeEntityListener(IEntityListener listener)
275 {
276 mEntityListener = (IEntityListener)CELEventMulticaster.remove(mEntityListener, listener);
277 if(mEntityChangeListener==null && mRemoteSelection!=null)
278 mRemoteSelection.removeEntityListener(this.getRelayListener());
279 }
280
281 /*** Adds IEntityChangeListener to receive notifications of performed
282 * data operations on all entities contained in the collection object.
283 * Note that changes can in specific situations like during end-user
284 * editation be very frequent.
285 */
286 public void addEntityChangeListener(IEntityChangeListener listener)
287 {
288 if(mEntityChangeListener==null && mRemoteSelection!=null)
289 mRemoteSelection.addEntityChangeListener(this.getRelayListener());
290 mEntityChangeListener = (IEntityChangeListener)CELEventMulticaster.add(mEntityChangeListener, listener);
291 }
292
293 /*** Removes the specified IEntityListener from the collection object.
294 */
295 public void removeEntityChangeListener(IEntityChangeListener listener)
296 {
297 mEntityChangeListener = (IEntityChangeListener)CELEventMulticaster.remove(mEntityChangeListener, listener);
298 if(mEntityChangeListener==null && mRemoteSelection!=null)
299 mRemoteSelection.removeEntityChangeListener(this.getRelayListener());
300 }
301
302 /*** Creates a sub selection with the indexed entities in the called
303 * selection. The created selection that should be independant of changes
304 * in the source/called selection after the time of creation.
305 */
306 public ISelection createSubSelection(int[] indexArray)
307 {
308 if(mRemoteSelection!=null)
309 return mRemoteSelection.createSubSelection(indexArray);
310 else
311 throw new IndexOutOfBoundsException();
312 }
313
314 /*** Creates a sub selection with all qualified entities in the called
315 * selection. The created selection that should be independant of changes
316 * in the source/called selection after the time of creation.
317 */
318 public ISelection createSubSelection(Qualifier qualifier)
319 {
320 if(mRemoteSelection!=null)
321 return mRemoteSelection.createSubSelection(qualifier);
322 else
323 return new Selection(this.getEntityDescriptor());
324 }
325
326 /*** Help method that returns true if the provided IEntity object exists in
327 * the selection otherwise false is returned.
328 */
329 public boolean contains(IEntity entity)
330 {
331 if(mRemoteSelection!=null)
332 return mRemoteSelection.contains(entity);
333 else
334 return false;
335 }
336
337 /*** Help method that returns the index of the provided IEntity object in
338 * the selection if it exists othewise a negative value is returned.
339 */
340 public int indexOf(IEntity entity)
341 {
342 if(mRemoteSelection!=null)
343 return mRemoteSelection.indexOf(entity);
344 else
345 return -1;
346 }
347
348 /*** Help method that returns the index of the the first entity object in
349 * the selection with the specified field set to the specified value.
350 */
351 public int indexOf(IFieldDescriptor fieldDescriptor, Object fieldData)
352 {
353 if(mRemoteSelection!=null)
354 return mRemoteSelection.indexOf(fieldDescriptor, fieldData);
355 else
356 return -1;
357 }
358
359 /*** Help method that returns true if the provided IEntity object will be
360 * accepted by the selection if added or inserted to it. Reasons for not
361 * accepting an entity is wrong type (IEntityDescriptor), already included
362 * or if selection is qualified the entity may fail qualification.
363 */
364 public boolean doesAccept(IEntity entity)
365 {
366 if(mRemoteSelection!=null)
367 return mRemoteSelection.doesAccept(entity);
368 else
369 return false;
370 }
371
372 /*** This method sorts the called selection using the provided comparator.
373 * One single content change event will be fired when this method is called.
374 * Note that if the provided Comparator does not support IEntity objects
375 * an exeption will be thrown.
376 * @see EntityCollator
377 */
378 public void sort(Comparator comparator)
379 {
380 if(mRemoteSelection!=null)
381 mRemoteSelection.sort(comparator);
382 }
383
384 /*** Returns a Set that acts as a wrapper for the selection. The Set object
385 * should reflect changes to and from the wrapped selection.
386 */
387 public Set asSet()
388 {
389 if(mRemoteSelection!=null)
390 return mRemoteSelection.asSet();
391 else
392 return null;
393 }
394
395 /*** Returns a List that acts as a wrapper for the selection. The List
396 * object should reflect changes to and from the wrapped selection.
397 */
398 public List asList()
399 {
400 if(mRemoteSelection!=null)
401 return mRemoteSelection.asList();
402 else
403 return null;
404 }
405
406
407
408 /*** Boolean access method that returns true if the proxy has a remote
409 * selection if false then getRemoteSelection() will return null.
410 */
411 public boolean hasRemoteSelection()
412 {
413 return this.getRemoteSelection()!=null;
414 }
415
416 /*** Access method that returns the remote selection of the proxy.
417 * May return null if the proxy does not currently have a remote.
418 */
419 public ISelection getRemoteSelection()
420 {
421 return mRemoteSelection;
422 }
423
424 /*** Boolean access method that returns true if the proxy has a source
425 * selection if false then getSourceSelection() will return null.
426 */
427 public boolean hasSourceSelection()
428 {
429 return this.getSourceSelection()!=null;
430 }
431
432 /*** Access method that returns the source selection of the proxy.
433 * May return null if the proxy does not currently have a source entity.
434 */
435 public ISelection getSourceSelection()
436 {
437 if(mRemoteSelection==null)
438 return null;
439 if(mRemoteSelection instanceof IProxySelection)
440 return ((IProxySelection)mRemoteSelection).getSourceSelection();
441 else
442 return this.getRemoteSelection();
443 }
444
445 /*** Optional mutation method that throws an UnsupportedOperationException
446 * if the implementing class does not support the method.
447 */
448 public void setRemoteSelection(ISelection selection)
449 {
450
451 if(mRemoteSelection==selection)
452 return;
453
454
455 if(selection!=null && selection.getEntityDescriptor()!=mEntityDescriptor)
456 throw new InvalidSelectionException("ProxySelection with type \""+mEntityDescriptor.getCodeName()+"\" was asigned entity of type \""+selection.getEntityDescriptor().getCodeName()+"\".");
457
458
459 if(mRemoteSelection!=null)
460 {
461 if(mSelectionListener!=null)
462 mRemoteSelection.removeSelectionListener(this.getRelayListener());
463 if(mEntityListener!=null)
464 mRemoteSelection.removeEntityListener(this.getRelayListener());
465 if(mEntityChangeListener!=null)
466 mRemoteSelection.removeEntityChangeListener(this.getRelayListener());
467 if(mProxyListener!=null && mRemoteSelection instanceof IProxySelection)
468 ((IProxySelection)mRemoteSelection).removeProxyListener(this.getRelayListener());
469 }
470
471
472 mRemoteSelection = selection;
473 this.doAfterRemoteChange();
474
475
476 if(mRemoteSelection!=null)
477 {
478 if(mSelectionListener!=null)
479 mRemoteSelection.addSelectionListener(this.getRelayListener());
480 if(mEntityListener!=null)
481 mRemoteSelection.addEntityListener(this.getRelayListener());
482 if(mEntityChangeListener!=null)
483 mRemoteSelection.addEntityChangeListener(this.getRelayListener());
484 if(mProxyListener!=null && mRemoteSelection instanceof IProxySelection)
485 ((IProxySelection)mRemoteSelection).addProxyListener(this.getRelayListener());
486 }
487
488
489 this.fireProxyEvent(ProxyEvent.CHANGED);
490 if(mSelectionListener!=null)
491 mSelectionListener.contentsChanged(new SelectionEvent(this));
492 }
493
494 /*** Adds an IProxyListener to receive notifications of changes of
495 * the remote object.
496 */
497 public void addProxyListener(IProxyListener listener)
498 {
499 if(mProxyListener==null && mRemoteSelection!=null && mRemoteSelection instanceof IProxyEntity)
500 ((IProxyEntity)mRemoteSelection).addProxyListener(this.getRelayListener());
501 mProxyListener = (IProxyListener)CELEventMulticaster.add(mProxyListener, listener);
502 }
503
504 /*** Removes the specified IProxyListener from the remote object.
505 */
506 public void removeProxyListener(IProxyListener listener)
507 {
508 mProxyListener = (IProxyListener)CELEventMulticaster.remove(mProxyListener, listener);
509 if(mProxyListener==null && mRemoteSelection!=null && mRemoteSelection instanceof IProxySelection)
510 ((IProxySelection)mRemoteSelection).removeProxyListener(this.getRelayListener());
511 }
512
513
514
515 /*** Help method to fire a SelectionEvent to all registered
516 * SelectionListeners for notification of generally changed contents.
517 */
518 protected void fireContentsChanged()
519 {
520 if(mSelectionListener!=null)
521 mSelectionListener.contentsChanged(new SelectionEvent(this));
522 }
523
524 /*** Help method to fire a SelectionEvent to all registered
525 * SelectionListeners for notification of an added entity.
526 */
527 protected void fireEntityAdded(IEntity entity, int row)
528 {
529 if(mSelectionListener!=null)
530 mSelectionListener.entityAdded(new SelectionEvent(this, SelectionEvent.ENTITY_ADDED, entity, row));
531 }
532
533 /*** Help method to fire a SelectionEvent to all registered
534 * SelectionListeners for notification of an removed entity.
535 */
536 protected void fireEntityRemoved(IEntity entity, int row)
537 {
538 if(mSelectionListener!=null)
539 mSelectionListener.entityRemoved(new SelectionEvent(this, SelectionEvent.ENTITY_REMOVED, entity, row));
540 }
541
542 /*** Fires a ProxyEvent with the provided operation type to all registered
543 * IProxyListener objects.
544 */
545 protected void fireProxyEvent(int eventType)
546 {
547 if(mProxyListener==null)
548 return;
549 else if(eventType == ProxyEvent.CHANGED)
550 mProxyListener.remoteChanged(new ProxyEvent(this, eventType));
551 else if(eventType == ProxyEvent.EXPANDED)
552 mProxyListener.remoteExpanded(new ProxyEvent(this, eventType));
553 }
554
555 /*** Fires an EntityChangeEvent with the provided operation type to all
556 * registered IEntityChangeListener objects.
557 */
558 protected void fireStatusChangedEvent(IEntity entity, int statusType, boolean newState)
559 {
560 if(mEntityChangeListener!=null)
561 mEntityChangeListener.statusChanged(new EntityChangeEvent(entity, statusType, newState));
562 }
563
564 /*** Help method that returns the selections relay listener.
565 */
566 protected RelayListener getRelayListener()
567 {
568 if(mEntityRelayListener==null)
569 mEntityRelayListener = this.createRelayListener();
570 return mEntityRelayListener;
571 }
572
573 /*** Help method that creates a new relay listener. Can be used by subclasses
574 * replace or extend the RelayListener.
575 */
576 protected RelayListener createRelayListener()
577 {
578 return new RelayListener();
579 }
580
581 /*** Empty help method provided for sub class customization. The method is
582 * called directly after the remote object has been changed but before any
583 * listeners has been registered or events been fired.
584 */
585 protected void doAfterRemoteChange()
586 {
587 }
588
589
590
591 protected class RelayListener implements ISelectionListener, IEntityListener, IEntityChangeListener, IProxyListener
592 {
593
594 public void entityRemoved(SelectionEvent event)
595 {
596 if(mSelectionListener!=null)
597 mSelectionListener.entityRemoved(event);
598 }
599
600 public void entityAdded(SelectionEvent event)
601 {
602 if(mSelectionListener!=null)
603 mSelectionListener.entityAdded(event);
604 }
605
606 public void contentsChanged(SelectionEvent event)
607 {
608 if(mSelectionListener!=null)
609 mSelectionListener.contentsChanged(event);
610 }
611
612
613 public void storePerformed(EntityEvent event)
614 {
615 if(mEntityListener!=null)
616 mEntityListener.storePerformed(event);
617 }
618
619 public void deletePerformed(EntityEvent event)
620 {
621 if(mEntityListener!=null)
622 mEntityListener.deletePerformed(event);
623 }
624
625 public void refreshPerformed(EntityEvent event)
626 {
627 if(mEntityListener!=null)
628 mEntityListener.refreshPerformed(event);
629 }
630
631
632 public void dataChanged(EntityChangeEvent event)
633 {
634 if(mEntityChangeListener!=null)
635 mEntityChangeListener.dataChanged(event);
636 }
637
638 public void statusChanged(EntityChangeEvent event)
639 {
640 if(mEntityChangeListener!=null)
641 mEntityChangeListener.statusChanged(event);
642 }
643
644
645 public void remoteChanged(ProxyEvent event)
646 {
647 if(mProxyListener!=null)
648 mProxyListener.remoteChanged(event);
649 }
650
651 public void remoteExpanded(ProxyEvent event)
652 {
653 if(mProxyListener!=null)
654 mProxyListener.remoteExpanded(event);
655 }
656 }
657 }