001 /**
002 * <copyright>
003 *
004 * Copyright (c) 2002-2006 IBM Corporation and others.
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the Eclipse Public License v1.0
007 * which accompanies this distribution, and is available at
008 * http://www.eclipse.org/legal/epl-v10.html
009 *
010 * Contributors:
011 * IBM - Initial API and implementation
012 *
013 * </copyright>
014 *
015 * $Id: NotificationImpl.java,v 1.11 2008/12/22 14:25:28 emerks Exp $
016 */
017 package org.eclipse.emf.common.notify.impl;
018
019
020 import java.util.List;
021
022 import org.eclipse.emf.common.notify.Notification;
023 import org.eclipse.emf.common.notify.NotificationChain;
024 import org.eclipse.emf.common.notify.Notifier;
025 import org.eclipse.emf.common.util.BasicEList;
026
027
028 /**
029 * An extensible notification implementation.
030 */
031 public class NotificationImpl implements Notification, NotificationChain
032 {
033 /**
034 * An {@link #primitiveType indicator} that the feature is not a primitive type.
035 * @see #primitiveType
036 */
037 public static final int PRIMITIVE_TYPE_OBJECT = -1;
038
039 /**
040 * An {@link #primitiveType indicator} that the feature is a <code>boolean</code>.
041 * @see #primitiveType
042 */
043 public static final int PRIMITIVE_TYPE_BOOLEAN = 0;
044
045 /**
046 * An {@link #primitiveType indicator} that the feature is a <code>byte</code>.
047 * @see #primitiveType
048 */
049 public static final int PRIMITIVE_TYPE_BYTE = 1;
050
051 /**
052 * An {@link #primitiveType indicator} that the feature is a <code>char</code>.
053 * @see #primitiveType
054 */
055 public static final int PRIMITIVE_TYPE_CHAR = 2;
056
057 /**
058 * An {@link #primitiveType indicator} that the feature is a <code>double</code>.
059 * @see #primitiveType
060 */
061 public static final int PRIMITIVE_TYPE_DOUBLE = 3;
062
063 /**
064 * An {@link #primitiveType indicator} that the feature is a <code>float</code>.
065 * @see #primitiveType
066 */
067 public static final int PRIMITIVE_TYPE_FLOAT = 4;
068
069 /**
070 * An {@link #primitiveType indicator} that the feature is a <code>int</code>.
071 * @see #primitiveType
072 */
073 public static final int PRIMITIVE_TYPE_INT = 5;
074
075 /**
076 * An {@link #primitiveType indicator} that the feature is a <code>long</code>.
077 * @see #primitiveType
078 */
079 public static final int PRIMITIVE_TYPE_LONG = 6;
080
081 /**
082 * An {@link #primitiveType indicator} that the feature is a <code>short</code>.
083 * @see #primitiveType
084 */
085 public static final int PRIMITIVE_TYPE_SHORT = 7;
086
087 /**
088 * A {@link #position position} value which indicates that {@link #isTouch} should return <code>false</code>.
089 * @see #primitiveType
090 */
091 protected static final int IS_SET_CHANGE_INDEX = NO_INDEX - 1;
092
093 /**
094 * The type of the feature.
095 * @see #PRIMITIVE_TYPE_OBJECT
096 * @see #PRIMITIVE_TYPE_BOOLEAN
097 * @see #PRIMITIVE_TYPE_BYTE
098 * @see #PRIMITIVE_TYPE_CHAR
099 * @see #PRIMITIVE_TYPE_DOUBLE
100 * @see #PRIMITIVE_TYPE_FLOAT
101 * @see #PRIMITIVE_TYPE_INT
102 * @see #PRIMITIVE_TYPE_LONG
103 * @see #PRIMITIVE_TYPE_SHORT
104 */
105 protected int primitiveType;
106
107 /**
108 * The type of the change.
109 * @see #getEventType()
110 */
111 protected int eventType;
112
113 /**
114 * The old value for the case of {@link #PRIMITIVE_TYPE_OBJECT}.
115 * @see #getOldValue()
116 */
117 protected Object oldValue;
118
119 /**
120 * The new value for the case of {@link #PRIMITIVE_TYPE_OBJECT}.
121 * @see #getNewValue()
122 */
123 protected Object newValue;
124
125 /**
126 * The old value for the case of
127 * {@link #PRIMITIVE_TYPE_BOOLEAN},
128 * {@link #PRIMITIVE_TYPE_BYTE},
129 * {@link #PRIMITIVE_TYPE_CHAR},
130 * {@link #PRIMITIVE_TYPE_INT},
131 * {@link #PRIMITIVE_TYPE_LONG},
132 * and {@link #PRIMITIVE_TYPE_SHORT}.
133 * @see #getOldValue()
134 * @see #getOldBooleanValue()
135 * @see #getOldByteValue()
136 * @see #getOldCharValue()
137 * @see #getOldIntValue()
138 * @see #getOldLongValue()
139 * @see #getOldShortValue()
140 */
141 protected long oldSimplePrimitiveValue;
142
143 /**
144 * The new value for the case of
145 * {@link #PRIMITIVE_TYPE_BOOLEAN},
146 * {@link #PRIMITIVE_TYPE_BYTE},
147 * {@link #PRIMITIVE_TYPE_CHAR},
148 * {@link #PRIMITIVE_TYPE_INT},
149 * {@link #PRIMITIVE_TYPE_LONG},
150 * and {@link #PRIMITIVE_TYPE_SHORT}.
151 * @see #getNewValue()
152 * @see #getNewBooleanValue()
153 * @see #getNewByteValue()
154 * @see #getNewCharValue()
155 * @see #getNewIntValue()
156 * @see #getNewLongValue()
157 * @see #getNewShortValue()
158 */
159 protected long newSimplePrimitiveValue;
160
161 /**
162 * The old value for the case of
163 * {@link #PRIMITIVE_TYPE_DOUBLE},
164 * and {@link #PRIMITIVE_TYPE_FLOAT}.
165 * @see #getOldValue()
166 * @see #getOldDoubleValue()
167 * @see #getOldFloatValue()
168 */
169 protected double oldIEEEPrimitiveValue;
170
171 /**
172 * The old value for the case of
173 * {@link #PRIMITIVE_TYPE_DOUBLE},
174 * and {@link #PRIMITIVE_TYPE_FLOAT}.
175 * @see #getOldValue()
176 * @see #getOldDoubleValue()
177 * @see #getOldFloatValue()
178 */
179 protected double newIEEEPrimitiveValue;
180
181 /**
182 * The position.
183 * @see #getPosition()
184 */
185 protected int position;
186
187 /**
188 * The internal chain.
189 */
190 protected NotificationChain next;
191
192 /**
193 * Creates an instance.
194 * @param eventType the type of the change.
195 * @param oldValue the old value before the change.
196 * @param newValue the new value after the change.
197 */
198 public NotificationImpl(int eventType, Object oldValue, Object newValue)
199 {
200 this(eventType, oldValue, newValue, NO_INDEX);
201 }
202
203 /**
204 * Creates an instance.
205 * @param eventType the type of the change.
206 * @param oldValue the old value before the change.
207 * @param newValue the new value after the change.
208 * @param isSetChange the indication of whether the state has changed.
209 */
210 public NotificationImpl(int eventType, Object oldValue, Object newValue, boolean isSetChange)
211 {
212 this(eventType, oldValue, newValue, isSetChange ? IS_SET_CHANGE_INDEX : NO_INDEX);
213 }
214
215 /**
216 * Creates an instance.
217 * @param eventType the type of the change.
218 * @param oldValue the old value before the change.
219 * @param newValue the new value after the change.
220 */
221 public NotificationImpl(int eventType, Object oldValue, Object newValue, int position)
222 {
223 this.eventType = eventType;
224 this.oldValue = oldValue;
225 this.newValue = newValue;
226 this.position = position;
227 this.primitiveType = PRIMITIVE_TYPE_OBJECT;
228 }
229
230 /**
231 * Creates an instance.
232 * @param eventType the type of the change.
233 * @param oldValue the old value before the change.
234 * @param newValue the new value after the change.
235 * @param wasSet whether the feature was set before the change.
236 */
237 public NotificationImpl(int eventType, Object oldValue, Object newValue, int position, boolean wasSet)
238 {
239 this.eventType = eventType;
240 this.oldValue = oldValue;
241 this.newValue = newValue;
242 this.position = position;
243 this.primitiveType = PRIMITIVE_TYPE_OBJECT;
244 if (!wasSet)
245 {
246 this.position = IS_SET_CHANGE_INDEX - position - 1;
247 }
248 }
249
250 /**
251 * Creates an instance.
252 * @param eventType the type of the change.
253 * @param oldBooleanValue the old value before the change.
254 * @param newBooleanValue the new value after the change.
255 * @param isSetChange the indication of whether the state has changed.
256 */
257 public NotificationImpl(int eventType, boolean oldBooleanValue, boolean newBooleanValue, boolean isSetChange)
258 {
259 this(eventType, oldBooleanValue, newBooleanValue);
260 if (isSetChange)
261 {
262 this.position = IS_SET_CHANGE_INDEX;
263 }
264 }
265
266 /**
267 * Creates an instance.
268 * @param eventType the type of the change.
269 * @param oldBooleanValue the old value before the change.
270 * @param newBooleanValue the new value after the change.
271 */
272 public NotificationImpl(int eventType, boolean oldBooleanValue, boolean newBooleanValue)
273 {
274 this.eventType = eventType;
275 this.oldSimplePrimitiveValue = oldBooleanValue ? 1 : 0;
276 this.newSimplePrimitiveValue = newBooleanValue ? 1 : 0;
277 this.position = NO_INDEX;
278 this.primitiveType = PRIMITIVE_TYPE_BOOLEAN;
279 }
280
281 /**
282 * Creates an instance.
283 * @param eventType the type of the change.
284 * @param oldByteValue the old value before the change.
285 * @param newByteValue the new value after the change.
286 * @param isSetChange the indication of whether the state has changed.
287 */
288 public NotificationImpl(int eventType, byte oldByteValue, byte newByteValue, boolean isSetChange)
289 {
290 this(eventType, oldByteValue, newByteValue);
291 if (isSetChange)
292 {
293 this.position = IS_SET_CHANGE_INDEX;
294 }
295 }
296
297 /**
298 * Creates an instance.
299 * @param eventType the type of the change.
300 * @param oldByteValue the old value before the change.
301 * @param newByteValue the new value after the change.
302 */
303 public NotificationImpl(int eventType, byte oldByteValue, byte newByteValue)
304 {
305 this.eventType = eventType;
306 this.oldSimplePrimitiveValue = oldByteValue;
307 this.newSimplePrimitiveValue = newByteValue;
308 this.position = Notification.NO_INDEX;
309 this.primitiveType = PRIMITIVE_TYPE_BYTE;
310 }
311
312 /**
313 * Creates an instance.
314 * @param eventType the type of the change.
315 * @param oldCharValue the old value before the change.
316 * @param newCharValue the new value after the change.
317 * @param isSetChange the indication of whether the state has changed.
318 */
319 public NotificationImpl(int eventType, char oldCharValue, char newCharValue, boolean isSetChange)
320 {
321 this(eventType, oldCharValue, newCharValue);
322 if (isSetChange)
323 {
324 this.position = IS_SET_CHANGE_INDEX;
325 }
326 }
327
328 /**
329 * Creates an instance.
330 * @param eventType the type of the change.
331 * @param oldCharValue the old value before the change.
332 * @param newCharValue the new value after the change.
333 */
334 public NotificationImpl(int eventType, char oldCharValue, char newCharValue)
335 {
336 this.eventType = eventType;
337 this.oldSimplePrimitiveValue = oldCharValue;
338 this.newSimplePrimitiveValue = newCharValue;
339 this.position = Notification.NO_INDEX;
340 this.primitiveType = PRIMITIVE_TYPE_CHAR;
341 }
342
343 /**
344 * Creates an instance.
345 * @param eventType the type of the change.
346 * @param oldDoubleValue the old value before the change.
347 * @param newDoubleValue the new value after the change.
348 * @param isSetChange the indication of whether the state has changed.
349 */
350 public NotificationImpl(int eventType, double oldDoubleValue, double newDoubleValue, boolean isSetChange)
351 {
352 this(eventType, oldDoubleValue, newDoubleValue);
353 if (isSetChange)
354 {
355 this.position = IS_SET_CHANGE_INDEX;
356 }
357 }
358
359 /**
360 * Creates an instance.
361 * @param eventType the type of the change.
362 * @param oldDoubleValue the old value before the change.
363 * @param newDoubleValue the new value after the change.
364 */
365 public NotificationImpl(int eventType, double oldDoubleValue, double newDoubleValue)
366 {
367 this.eventType = eventType;
368 this.oldIEEEPrimitiveValue = oldDoubleValue;
369 this.newIEEEPrimitiveValue = newDoubleValue;
370 this.position = Notification.NO_INDEX;
371 this.primitiveType = PRIMITIVE_TYPE_DOUBLE;
372 }
373
374 /**
375 * Creates an instance.
376 * @param eventType the type of the change.
377 * @param oldFloatValue the old value before the change.
378 * @param newFloatValue the new value after the change.
379 * @param isSetChange the indication of whether the state has changed.
380 */
381 public NotificationImpl(int eventType, float oldFloatValue, float newFloatValue, boolean isSetChange)
382 {
383 this(eventType, oldFloatValue, newFloatValue);
384 if (isSetChange)
385 {
386 this.position = IS_SET_CHANGE_INDEX;
387 }
388 }
389
390 /**
391 * Creates an instance.
392 * @param eventType the type of the change.
393 * @param oldFloatValue the old value before the change.
394 * @param newFloatValue the new value after the change.
395 */
396 public NotificationImpl(int eventType, float oldFloatValue, float newFloatValue)
397 {
398 this.eventType = eventType;
399 this.oldIEEEPrimitiveValue = oldFloatValue;
400 this.newIEEEPrimitiveValue = newFloatValue;
401 this.position = Notification.NO_INDEX;
402 this.primitiveType = PRIMITIVE_TYPE_FLOAT;
403 }
404
405 /**
406 * Creates an instance.
407 * @param eventType the type of the change.
408 * @param oldIntValue the old value before the change.
409 * @param newIntValue the new value after the change.
410 * @param isSetChange the indication of whether the state has changed.
411 */
412 public NotificationImpl(int eventType, int oldIntValue, int newIntValue, boolean isSetChange)
413 {
414 this(eventType, oldIntValue, newIntValue);
415 if (isSetChange)
416 {
417 this.position = IS_SET_CHANGE_INDEX;
418 }
419 }
420
421 /**
422 * Creates an instance.
423 * @param eventType the type of the change.
424 * @param oldIntValue the old value before the change.
425 * @param newIntValue the new value after the change.
426 */
427 public NotificationImpl(int eventType, int oldIntValue, int newIntValue)
428 {
429 this.eventType = eventType;
430 this.oldSimplePrimitiveValue = oldIntValue;
431 this.newSimplePrimitiveValue = newIntValue;
432 this.position = Notification.NO_INDEX;
433 this.primitiveType = PRIMITIVE_TYPE_INT;
434 }
435
436 /**
437 * Creates an instance.
438 * @param eventType the type of the change.
439 * @param oldLongValue the old value before the change.
440 * @param newLongValue the new value after the change.
441 * @param isSetChange the indication of whether the state has changed.
442 */
443 public NotificationImpl(int eventType, long oldLongValue, long newLongValue, boolean isSetChange)
444 {
445 this(eventType, oldLongValue, newLongValue);
446 if (isSetChange)
447 {
448 this.position = IS_SET_CHANGE_INDEX;
449 }
450 }
451
452 /**
453 * Creates an instance.
454 * @param eventType the type of the change.
455 * @param oldLongValue the old value before the change.
456 * @param newLongValue the new value after the change.
457 */
458 public NotificationImpl(int eventType, long oldLongValue, long newLongValue)
459 {
460 this.eventType = eventType;
461 this.oldSimplePrimitiveValue = oldLongValue;
462 this.newSimplePrimitiveValue = newLongValue;
463 this.position = Notification.NO_INDEX;
464 this.primitiveType = PRIMITIVE_TYPE_LONG;
465 }
466
467 /**
468 * Creates an instance.
469 * @param eventType the type of the change.
470 * @param oldShortValue the old value before the change.
471 * @param newShortValue the new value after the change.
472 * @param isSetChange the indication of whether the state has changed.
473 */
474 public NotificationImpl(int eventType, short oldShortValue, short newShortValue, boolean isSetChange)
475 {
476 this(eventType, oldShortValue, newShortValue);
477 if (isSetChange)
478 {
479 this.position = IS_SET_CHANGE_INDEX;
480 }
481 }
482
483 /**
484 * Creates an instance.
485 * @param eventType the type of the change.
486 * @param oldShortValue the old value before the change.
487 * @param newShortValue the new value after the change.
488 */
489 public NotificationImpl(int eventType, short oldShortValue, short newShortValue)
490 {
491 this.eventType = eventType;
492 this.oldSimplePrimitiveValue = oldShortValue;
493 this.newSimplePrimitiveValue = newShortValue;
494 this.position = Notification.NO_INDEX;
495 this.primitiveType = PRIMITIVE_TYPE_SHORT;
496 }
497
498 public Object getNotifier()
499 {
500 return null;
501 }
502
503 public int getEventType()
504 {
505 return eventType;
506 }
507
508 public Object getFeature()
509 {
510 return null;
511 }
512
513 public int getFeatureID(Class<?> expectedClass)
514 {
515 return NO_FEATURE_ID;
516 }
517
518 public Object getOldValue()
519 {
520 if (oldValue == null)
521 {
522 switch (primitiveType)
523 {
524 case PRIMITIVE_TYPE_BOOLEAN:
525 oldValue = getOldBooleanValue() ? Boolean.TRUE : Boolean.FALSE;
526 break;
527 case PRIMITIVE_TYPE_BYTE:
528 oldValue = getOldByteValue();
529 break;
530 case PRIMITIVE_TYPE_CHAR:
531 oldValue = getOldCharValue();
532 break;
533 case PRIMITIVE_TYPE_DOUBLE:
534 oldValue = getOldDoubleValue();
535 break;
536 case PRIMITIVE_TYPE_FLOAT:
537 oldValue = getOldFloatValue();
538 break;
539 case PRIMITIVE_TYPE_LONG:
540 oldValue = getOldLongValue();
541 break;
542 case PRIMITIVE_TYPE_INT:
543 oldValue = getOldIntValue();
544 break;
545 case PRIMITIVE_TYPE_SHORT:
546 oldValue = getOldShortValue();
547 break;
548 }
549 }
550 return oldValue;
551 }
552
553 public Object getNewValue()
554 {
555 if (newValue == null)
556 {
557 switch (primitiveType)
558 {
559 case PRIMITIVE_TYPE_BOOLEAN:
560 newValue = getNewBooleanValue() ? Boolean.TRUE : Boolean.FALSE;
561 break;
562 case PRIMITIVE_TYPE_BYTE:
563 newValue = getNewByteValue();
564 break;
565 case PRIMITIVE_TYPE_CHAR:
566 newValue = getNewCharValue();
567 break;
568 case PRIMITIVE_TYPE_DOUBLE:
569 newValue = getNewDoubleValue();
570 break;
571 case PRIMITIVE_TYPE_FLOAT:
572 newValue = getNewFloatValue();
573 break;
574 case PRIMITIVE_TYPE_LONG:
575 newValue = getNewLongValue();
576 break;
577 case PRIMITIVE_TYPE_INT:
578 newValue = getNewIntValue();
579 break;
580 case PRIMITIVE_TYPE_SHORT:
581 newValue = getNewShortValue();
582 break;
583 }
584 }
585 return newValue;
586 }
587
588 public boolean isTouch()
589 {
590 switch (eventType)
591 {
592 case Notification.RESOLVE:
593 case Notification.REMOVING_ADAPTER:
594 {
595 return true;
596 }
597 case Notification.ADD:
598 case Notification.ADD_MANY:
599 case Notification.REMOVE:
600 case Notification.REMOVE_MANY:
601 {
602 return false;
603 }
604 case Notification.MOVE:
605 {
606 return (Integer)getOldValue() == position;
607 }
608 case Notification.SET:
609 case Notification.UNSET:
610 {
611 if (position == IS_SET_CHANGE_INDEX)
612 {
613 return false;
614 }
615 else
616 {
617 switch (primitiveType)
618 {
619 case PRIMITIVE_TYPE_BOOLEAN:
620 case PRIMITIVE_TYPE_BYTE:
621 case PRIMITIVE_TYPE_CHAR:
622 case PRIMITIVE_TYPE_LONG:
623 case PRIMITIVE_TYPE_INT:
624 case PRIMITIVE_TYPE_SHORT:
625 {
626 return oldSimplePrimitiveValue == newSimplePrimitiveValue;
627 }
628 case PRIMITIVE_TYPE_DOUBLE:
629 case PRIMITIVE_TYPE_FLOAT:
630 {
631 return oldIEEEPrimitiveValue == newIEEEPrimitiveValue;
632 }
633 default:
634 {
635 return oldValue == null ? newValue == null : oldValue.equals(newValue);
636 }
637 }
638 }
639 }
640 default:
641 {
642 return false;
643 }
644 }
645 }
646
647 public boolean isReset()
648 {
649 switch (eventType)
650 {
651 case Notification.SET:
652 Object defaultValue = getFeatureDefaultValue();
653 switch (primitiveType)
654 {
655 case PRIMITIVE_TYPE_BOOLEAN:
656 return defaultValue != null && (Boolean)defaultValue == (newSimplePrimitiveValue != 0);
657 case PRIMITIVE_TYPE_BYTE:
658 return defaultValue != null && (Byte)defaultValue == (byte)newSimplePrimitiveValue;
659 case PRIMITIVE_TYPE_CHAR:
660 return defaultValue != null && (Character)defaultValue == (char)newSimplePrimitiveValue;
661 case PRIMITIVE_TYPE_LONG:
662 return defaultValue != null && (Long)defaultValue == newSimplePrimitiveValue;
663 case PRIMITIVE_TYPE_INT:
664 return defaultValue != null && (Integer)defaultValue == (int)newSimplePrimitiveValue;
665 case PRIMITIVE_TYPE_SHORT:
666 return defaultValue != null && (Short)defaultValue == (short)newSimplePrimitiveValue;
667 case PRIMITIVE_TYPE_DOUBLE:
668 return defaultValue != null && (Double)defaultValue == newIEEEPrimitiveValue;
669 case PRIMITIVE_TYPE_FLOAT:
670 return defaultValue != null && (Float)defaultValue == (float)newIEEEPrimitiveValue;
671 default:
672 return defaultValue == null ? newValue == null : defaultValue.equals(newValue);
673 }
674 case Notification.UNSET:
675 return true;
676 default:
677 return false;
678 }
679 }
680
681 public boolean wasSet()
682 {
683 switch (eventType)
684 {
685 case Notification.SET:
686 {
687 if (isFeatureUnsettable())
688 {
689 return position != IS_SET_CHANGE_INDEX;
690 }
691 break;
692 }
693 case Notification.UNSET:
694 {
695 if (isFeatureUnsettable())
696 {
697 return position == IS_SET_CHANGE_INDEX;
698 }
699 break;
700 }
701 case Notification.ADD:
702 case Notification.ADD_MANY:
703 case Notification.REMOVE:
704 case Notification.REMOVE_MANY:
705 case Notification.MOVE:
706 {
707 return position > IS_SET_CHANGE_INDEX;
708 }
709 default:
710 {
711 return false;
712 }
713 }
714
715 Object defaultValue = getFeatureDefaultValue();
716 switch (primitiveType)
717 {
718 case PRIMITIVE_TYPE_BOOLEAN:
719 return defaultValue != null && (Boolean)defaultValue != (oldSimplePrimitiveValue != 0);
720 case PRIMITIVE_TYPE_BYTE:
721 return defaultValue != null && (Byte)defaultValue != (byte)oldSimplePrimitiveValue;
722 case PRIMITIVE_TYPE_CHAR:
723 return defaultValue != null && (Character)defaultValue != (char)oldSimplePrimitiveValue;
724 case PRIMITIVE_TYPE_LONG:
725 return defaultValue != null && (Long)defaultValue != oldSimplePrimitiveValue;
726 case PRIMITIVE_TYPE_INT:
727 return defaultValue != null && (Integer)defaultValue != (int)oldSimplePrimitiveValue;
728 case PRIMITIVE_TYPE_SHORT:
729 return defaultValue != null && (Short)defaultValue != (short)oldSimplePrimitiveValue;
730 case PRIMITIVE_TYPE_DOUBLE:
731 return defaultValue != null && (Double)defaultValue != oldIEEEPrimitiveValue;
732 case PRIMITIVE_TYPE_FLOAT:
733 return defaultValue != null && (Float)defaultValue != (float)oldIEEEPrimitiveValue;
734 default:
735 return defaultValue == null ? oldValue != null : !defaultValue.equals(oldValue);
736 }
737 }
738
739 protected boolean isFeatureUnsettable()
740 {
741 return false;
742 }
743
744 protected Object getFeatureDefaultValue()
745 {
746 return null;
747 }
748
749 public int getPosition()
750 {
751 return position < 0 ? position < IS_SET_CHANGE_INDEX ? IS_SET_CHANGE_INDEX - position - 1 : NO_INDEX : position;
752 }
753
754 public boolean merge(Notification notification)
755 {
756 switch (eventType)
757 {
758 case Notification.SET:
759 case Notification.UNSET:
760 {
761 int notificationEventType = notification.getEventType();
762 switch (notificationEventType)
763 {
764 case Notification.SET:
765 case Notification.UNSET:
766 {
767 Object notificationNotifier = notification.getNotifier();
768 if (notificationNotifier == getNotifier() && getFeatureID(null) == notification.getFeatureID(null))
769 {
770 newValue = notification.getNewValue();
771 if (notification.getEventType() == Notification.SET)
772 {
773 eventType = Notification.SET;
774 }
775 return true;
776 }
777 }
778 }
779 }
780 case Notification.REMOVE:
781 {
782 int notificationEventType = notification.getEventType();
783 switch (notificationEventType)
784 {
785 case Notification.REMOVE:
786 {
787 Object notificationNotifier = notification.getNotifier();
788 if (notificationNotifier == getNotifier() && getFeatureID(null) == notification.getFeatureID(null))
789 {
790 boolean originalWasSet = wasSet();
791 int originalPosition = getPosition();
792 int notificationPosition = notification.getPosition();
793
794 eventType = Notification.REMOVE_MANY;
795 BasicEList<Object> removedValues = new BasicEList<Object>(2);
796 if (originalPosition <= notificationPosition)
797 {
798 removedValues.add(oldValue);
799 removedValues.add(notification.getOldValue());
800 newValue = new int [] { position = originalPosition, notificationPosition + 1 };
801 }
802 else
803 {
804 removedValues.add(notification.getOldValue());
805 removedValues.add(oldValue);
806 newValue = new int [] { position = notificationPosition, originalPosition };
807 }
808 oldValue = removedValues;
809
810 if (!originalWasSet)
811 {
812 position = IS_SET_CHANGE_INDEX - position - 1;
813 }
814
815 return true;
816 }
817 break;
818 }
819 }
820 break;
821 }
822 case Notification.REMOVE_MANY:
823 {
824 int notificationEventType = notification.getEventType();
825 switch (notificationEventType)
826 {
827 case Notification.REMOVE:
828 {
829 Object notificationNotifier = notification.getNotifier();
830 if (notificationNotifier == getNotifier() && getFeatureID(null) == notification.getFeatureID(null))
831 {
832 boolean originalWasSet = wasSet();
833 int notificationPosition = notification.getPosition();
834
835 int [] positions = (int [])newValue;
836 int [] newPositions = new int [positions.length + 1];
837
838 int index = 0;
839 while (index < positions.length)
840 {
841 int oldPosition = positions[index];
842 if (oldPosition <= notificationPosition)
843 {
844 newPositions[index++] = oldPosition;
845 ++notificationPosition;
846 }
847 else
848 {
849 break;
850 }
851 }
852
853 @SuppressWarnings("unchecked") List<Object> list = (List<Object>)oldValue;
854 list.add(index, notification.getOldValue());
855 newPositions[index] = notificationPosition;
856
857 while (++index < newPositions.length)
858 {
859 newPositions[index] = positions[index - 1];
860 }
861
862 newValue = newPositions;
863
864 if (!originalWasSet)
865 {
866 position = IS_SET_CHANGE_INDEX - newPositions[0];
867 }
868
869 return true;
870 }
871 break;
872 }
873 }
874 break;
875 }
876 }
877
878 return false;
879 }
880
881 public boolean getOldBooleanValue()
882 {
883 if (primitiveType != PRIMITIVE_TYPE_BOOLEAN) throw new IllegalStateException();
884 return oldSimplePrimitiveValue != 0;
885 }
886
887 public boolean getNewBooleanValue()
888 {
889 if (primitiveType != PRIMITIVE_TYPE_BOOLEAN) throw new IllegalStateException();
890 return newSimplePrimitiveValue != 0;
891 }
892
893 public byte getOldByteValue()
894 {
895 if (primitiveType != PRIMITIVE_TYPE_BYTE) throw new IllegalStateException();
896 return (byte)oldSimplePrimitiveValue;
897 }
898
899 public byte getNewByteValue()
900 {
901 if (primitiveType != PRIMITIVE_TYPE_BYTE) throw new IllegalStateException();
902 return (byte)newSimplePrimitiveValue;
903 }
904
905 public char getOldCharValue()
906 {
907 if (primitiveType != PRIMITIVE_TYPE_CHAR) throw new IllegalStateException();
908 return (char)oldSimplePrimitiveValue;
909 }
910
911 public char getNewCharValue()
912 {
913 if (primitiveType != PRIMITIVE_TYPE_CHAR) throw new IllegalStateException();
914 return (char)newSimplePrimitiveValue;
915 }
916
917 public double getOldDoubleValue()
918 {
919 if (primitiveType != PRIMITIVE_TYPE_DOUBLE) throw new IllegalStateException();
920 return oldIEEEPrimitiveValue;
921 }
922
923 public double getNewDoubleValue()
924 {
925 if (primitiveType != PRIMITIVE_TYPE_DOUBLE) throw new IllegalStateException();
926 return newIEEEPrimitiveValue;
927 }
928
929 public float getOldFloatValue()
930 {
931 if (primitiveType != PRIMITIVE_TYPE_FLOAT) throw new IllegalStateException();
932 return (float)oldIEEEPrimitiveValue;
933 }
934
935 public float getNewFloatValue()
936 {
937 if (primitiveType != PRIMITIVE_TYPE_FLOAT) throw new IllegalStateException();
938 return (float)newIEEEPrimitiveValue;
939 }
940
941 public int getOldIntValue()
942 {
943 if (primitiveType != PRIMITIVE_TYPE_INT) throw new IllegalStateException();
944 return (int)oldSimplePrimitiveValue;
945 }
946
947 public int getNewIntValue()
948 {
949 if (primitiveType != PRIMITIVE_TYPE_INT) throw new IllegalStateException();
950 return (int)newSimplePrimitiveValue;
951 }
952
953 public long getOldLongValue()
954 {
955 if (primitiveType != PRIMITIVE_TYPE_LONG) throw new IllegalStateException();
956 return oldSimplePrimitiveValue;
957 }
958
959 public long getNewLongValue()
960 {
961 if (primitiveType != PRIMITIVE_TYPE_LONG) throw new IllegalStateException();
962 return newSimplePrimitiveValue;
963 }
964
965 public short getOldShortValue()
966 {
967 if (primitiveType != PRIMITIVE_TYPE_SHORT) throw new IllegalStateException();
968 return (short)oldSimplePrimitiveValue;
969 }
970
971 public short getNewShortValue()
972 {
973 if (primitiveType != PRIMITIVE_TYPE_SHORT) throw new IllegalStateException();
974 return (short)newSimplePrimitiveValue;
975 }
976
977 public String getOldStringValue()
978 {
979 return oldValue == null ? null : oldValue.toString();
980 }
981
982 public String getNewStringValue()
983 {
984 return newValue == null ? null : newValue.toString();
985 }
986
987 /**
988 * Adds or merges a new notification.
989 * @param newNotification a notification.
990 * @return <code>true</code> when the notification is added and <code>false</code> when it is merged.
991 */
992 public boolean add(Notification newNotification)
993 {
994 if (newNotification == null)
995 {
996 return false;
997 }
998 else
999 {
1000 if (merge(newNotification))
1001 {
1002 return false;
1003 }
1004
1005 if (next == null)
1006 {
1007 if (newNotification instanceof NotificationImpl)
1008 {
1009 next = (NotificationImpl)newNotification;
1010 return true;
1011 }
1012 else
1013 {
1014 next = new NotificationChainImpl();
1015 return next.add(newNotification);
1016 }
1017 }
1018 else
1019 {
1020 return next.add(newNotification);
1021 }
1022 }
1023 }
1024
1025 /*
1026 * Javadoc copied from interface.
1027 */
1028 public void dispatch()
1029 {
1030 Object notifier = getNotifier();
1031 if (notifier != null && getEventType() != -1)
1032 {
1033 ((Notifier)notifier).eNotify(this);
1034 }
1035
1036 if (next != null)
1037 {
1038 next.dispatch();
1039 }
1040 }
1041
1042 @Override
1043 public String toString()
1044 {
1045 StringBuffer result = new StringBuffer(super.toString());
1046 result.append(" (eventType: ");
1047 switch (eventType)
1048 {
1049 case Notification.SET:
1050 {
1051 result.append("SET");
1052 break;
1053 }
1054 case Notification.UNSET:
1055 {
1056 result.append("UNSET");
1057 break;
1058 }
1059 case Notification.ADD:
1060 {
1061 result.append("ADD");
1062 break;
1063 }
1064 case Notification.ADD_MANY:
1065 {
1066 result.append("ADD_MANY");
1067 break;
1068 }
1069 case Notification.REMOVE:
1070 {
1071 result.append("REMOVE");
1072 break;
1073 }
1074 case Notification.REMOVE_MANY:
1075 {
1076 result.append("REMOVE_MANY");
1077 break;
1078 }
1079 case Notification.MOVE:
1080 {
1081 result.append("MOVE");
1082 break;
1083 }
1084 case Notification.REMOVING_ADAPTER:
1085 {
1086 result.append("REMOVING_ADAPTER");
1087 break;
1088 }
1089 case Notification.RESOLVE:
1090 {
1091 result.append("RESOLVE");
1092 break;
1093 }
1094 default:
1095 {
1096 result.append(eventType);
1097 break;
1098 }
1099 }
1100 if (isTouch())
1101 {
1102 result.append(", touch: true");
1103 }
1104 result.append(", position: ");
1105 result.append(getPosition());
1106 result.append(", notifier: ");
1107 result.append(getNotifier());
1108 result.append(", feature: ");
1109 result.append(getFeature());
1110 result.append(", oldValue: ");
1111 result.append(getOldValue());
1112 result.append(", newValue: ");
1113 if (eventType == Notification.REMOVE_MANY && newValue instanceof int [])
1114 {
1115 int [] positions = (int [])newValue;
1116 result.append("[");
1117 for (int i = 0; i < positions.length; )
1118 {
1119 result.append(positions[i]);
1120 if (++i < positions.length)
1121 {
1122 result.append(", ");
1123 }
1124 }
1125 result.append("]");
1126 }
1127 else
1128 {
1129 result.append(getNewValue());
1130 }
1131
1132 result.append(", isTouch: ");
1133 result.append(isTouch());
1134 result.append(", wasSet: ");
1135 result.append(wasSet());
1136 result.append(")");
1137
1138 return result.toString();
1139 }
1140 }