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    }