KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > ecore > util > BasicFeatureMap


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2003-2004 IBM Corporation and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * IBM - Initial API and implementation
12  *
13  * </copyright>
14  *
15  * $Id: BasicFeatureMap.java,v 1.18 2005/06/12 13:29:22 emerks Exp $
16  */

17 package org.eclipse.emf.ecore.util;
18
19
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.ListIterator JavaDoc;
25
26 import org.eclipse.emf.common.notify.Notification;
27 import org.eclipse.emf.common.notify.NotificationChain;
28 import org.eclipse.emf.common.notify.impl.NotificationImpl;
29 import org.eclipse.emf.common.util.BasicEList;
30 import org.eclipse.emf.common.util.EList;
31 import org.eclipse.emf.ecore.EObject;
32 import org.eclipse.emf.ecore.EReference;
33 import org.eclipse.emf.ecore.EStructuralFeature;
34 import org.eclipse.emf.ecore.InternalEObject;
35 import org.eclipse.emf.ecore.impl.ENotificationImpl;
36
37
38
39 public class BasicFeatureMap extends EDataTypeEList implements FeatureMap.Internal
40 {
41   protected final FeatureMapUtil.Validator featureMapValidator;
42
43   public BasicFeatureMap(InternalEObject owner, int featureID)
44   {
45     super(Entry.class, owner, featureID);
46
47     featureMapValidator = FeatureMapUtil.getValidator(owner.eClass(), getEStructuralFeature());
48   }
49
50   protected Object JavaDoc validate(int index, Object JavaDoc object)
51   {
52     Object JavaDoc result = super.validate(index, object);
53     EStructuralFeature eStructuralFeature = ((Entry)object).getEStructuralFeature();
54     if (!eStructuralFeature.isChangeable() || !featureMapValidator.isValid(eStructuralFeature))
55     {
56       throw
57         new RuntimeException JavaDoc
58           ("Invalid entry feature '" + eStructuralFeature.getEContainingClass().getName() + "." + eStructuralFeature.getName() + "'");
59     }
60     return result;
61   }
62
63   protected FeatureMap.Entry createEntry(EStructuralFeature eStructuralFeature, Object JavaDoc value)
64   {
65     return FeatureMapUtil.createEntry(eStructuralFeature, value);
66   }
67
68   protected NotificationImpl createNotification
69     (int eventType, EStructuralFeature feature, Object JavaDoc oldObject, Object JavaDoc newObject, int index, boolean wasSet)
70   {
71     return new FeatureMapUtil.FeatureENotificationImpl(owner, eventType, feature, oldObject, newObject, index, wasSet);
72   }
73
74   protected boolean isMany(EStructuralFeature feature)
75   {
76     return FeatureMapUtil.isMany(owner, feature);
77   }
78
79   protected boolean hasInverse()
80   {
81     return true;
82   }
83
84   protected boolean hasShadow()
85   {
86     return true;
87   }
88
89   protected int entryIndex(EStructuralFeature feature, int index)
90   {
91     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
92     int count = 0;
93     int result = size;
94     Entry [] entries = (Entry[])data;
95     for (int i = 0; i < size; ++i)
96     {
97       Entry entry = entries[i];
98       if (validator.isValid(entry.getEStructuralFeature()))
99       {
100         if (index == count)
101         {
102           return i;
103         }
104         ++count;
105         result = i + 1;
106       }
107     }
108
109     if (index == count)
110     {
111       return result;
112     }
113     else
114     {
115       throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=" + count);
116     }
117   }
118
119   protected boolean isResolveProxies(EStructuralFeature feature)
120   {
121     return feature instanceof EReference && ((EReference)feature).isResolveProxies();
122   }
123
124   public Object JavaDoc resolveProxy(EStructuralFeature feature, int entryIndex, int index, Object JavaDoc object)
125   {
126     EObject resolved = resolveProxy((EObject)object);
127     if (resolved != object)
128     {
129       Object JavaDoc oldObject = data[entryIndex];
130       Entry entry = createEntry(feature, resolved);
131       assign(entryIndex, validate(entryIndex, entry));
132       didSet(entryIndex, entry, oldObject);
133
134       if (isNotificationRequired())
135       {
136         NotificationImpl notifications =
137           createNotification
138             (Notification.RESOLVE,
139              entry.getEStructuralFeature(),
140              object,
141              resolved,
142              index,
143              false);
144
145         notifications.add(createNotification(Notification.RESOLVE, oldObject, entry, index, false));
146         notifications.dispatch();
147       }
148
149       return resolved;
150     }
151
152     return object;
153   }
154
155   protected EObject resolveProxy(EObject eObject)
156   {
157     return owner.eResolveProxy((InternalEObject)eObject);
158   }
159
160   public int getModCount()
161   {
162     return modCount;
163   }
164
165   public EStructuralFeature getEStructuralFeature(int index)
166   {
167     return ((Entry)get(index)).getEStructuralFeature();
168   }
169
170   public Object JavaDoc getValue(int index)
171   {
172     return ((Entry)get(index)).getValue();
173   }
174
175   public Object JavaDoc setValue(int index, Object JavaDoc value)
176   {
177     return ((Entry)set(index, createEntry(getEStructuralFeature(index), value))).getValue();
178   }
179
180   public NotificationChain shadowAdd(Object JavaDoc object, NotificationChain notifications)
181   {
182     if (isNotificationRequired())
183     {
184       Entry entry = (Entry)object;
185       EStructuralFeature feature = entry.getEStructuralFeature();
186       Object JavaDoc value = entry.getValue();
187       // EATM must fix isSet bits.
188
NotificationImpl notification =
189         feature.isMany() ?
190           createNotification
191             (Notification.ADD,
192              feature,
193              null,
194              value,
195              indexOf(feature, value),
196              true) :
197           createNotification
198             (Notification.SET,
199              feature,
200              feature.getDefaultValue(),
201              value,
202              Notification.NO_INDEX,
203              true);
204   
205       if (notifications != null)
206       {
207         notifications.add(notification);
208       }
209       else
210       {
211         notifications = notification;
212       }
213     }
214     return notifications;
215   }
216
217   public NotificationChain inverseAdd(Object JavaDoc object, NotificationChain notifications)
218   {
219     Entry entry = (Entry)object;
220     EStructuralFeature feature = entry.getEStructuralFeature();
221     if (feature instanceof EReference)
222     {
223       EReference eReference = (EReference)feature;
224       EReference eOpposite = eReference.getEOpposite();
225       if (eOpposite != null)
226       {
227         InternalEObject internalEObject = (InternalEObject)entry.getValue();
228
229         if (internalEObject != null)
230         {
231           notifications =
232             internalEObject.eInverseAdd
233               (owner,
234                internalEObject.eClass().getFeatureID(eOpposite),
235                null,
236                notifications);
237         }
238       }
239       else if (eReference.isContainment())
240       {
241         InternalEObject internalEObject = (InternalEObject)entry.getValue();
242         if (internalEObject != null)
243         {
244           int containmentFeatureID = owner.eClass().getFeatureID(eReference);
245           notifications =
246             internalEObject.eInverseAdd
247               (owner,
248                InternalEObject.EOPPOSITE_FEATURE_BASE - (containmentFeatureID == -1 ? featureID : containmentFeatureID),
249                null,
250                notifications);
251         }
252       }
253     }
254
255     return notifications;
256   }
257
258   public NotificationChain shadowRemove(Object JavaDoc object, NotificationChain notifications)
259   {
260     if (isNotificationRequired())
261     {
262       Entry entry = (Entry)object;
263       EStructuralFeature feature = entry.getEStructuralFeature();
264       Object JavaDoc value = entry.getValue();
265       NotificationImpl notification =
266         feature.isMany() ?
267           createNotification
268             (Notification.REMOVE,
269              feature,
270              value,
271              null,
272              indexOf(feature, value),
273              true) :
274           createNotification
275             (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
276              feature,
277              value,
278              feature.getDefaultValue(),
279              Notification.NO_INDEX,
280              true);
281
282       if (notifications != null)
283       {
284         notifications.add(notification);
285       }
286       else
287       {
288         notifications = notification;
289       }
290     }
291     return notifications;
292   }
293
294   public NotificationChain inverseRemove(Object JavaDoc object, NotificationChain notifications)
295   {
296     Entry entry = (Entry)object;
297     EStructuralFeature feature = entry.getEStructuralFeature();
298     if (feature instanceof EReference)
299     {
300       EReference eReference = (EReference)feature;
301       EReference eOpposite = eReference.getEOpposite();
302       if (eOpposite != null)
303       {
304         InternalEObject internalEObject = (InternalEObject)entry.getValue();
305         if (internalEObject != null)
306         {
307           notifications =
308             internalEObject.eInverseRemove
309               (owner,
310                internalEObject.eClass().getFeatureID(eOpposite),
311                null,
312                notifications);
313         }
314       }
315       else if (eReference.isContainment())
316       {
317         InternalEObject internalEObject = (InternalEObject)entry.getValue();
318         if (internalEObject != null)
319         {
320           int containmentFeatureID = owner.eClass().getFeatureID(eReference);
321           notifications =
322             internalEObject.eInverseRemove
323               (owner,
324                InternalEObject.EOPPOSITE_FEATURE_BASE - (containmentFeatureID == -1 ? featureID : containmentFeatureID),
325                null,
326                notifications);
327         }
328       }
329     }
330     return notifications;
331   }
332
333   public NotificationChain shadowSet(Object JavaDoc oldObject, Object JavaDoc newObject, NotificationChain notifications)
334   {
335     if (isNotificationRequired())
336     {
337       Entry entry = (Entry)oldObject;
338       EStructuralFeature feature = entry.getEStructuralFeature();
339       Object JavaDoc oldValue = entry.getValue();
340       Object JavaDoc newValue = ((Entry)newObject).getValue();
341       NotificationImpl notification =
342         createNotification
343           (Notification.SET,
344            feature,
345            oldValue,
346            newValue,
347            feature.isMany() ? indexOf(feature, newValue) : Notification.NO_INDEX,
348            true);
349
350       if (notifications != null)
351       {
352         notifications.add(notification);
353       }
354       else
355       {
356         notifications = notification;
357       }
358     }
359     return notifications;
360   }
361
362   public NotificationChain inverseTouch(Object JavaDoc object, NotificationChain notifications)
363   {
364     if (isNotificationRequired())
365     {
366       Entry entry = (Entry)object;
367       EStructuralFeature feature = entry.getEStructuralFeature();
368       Object JavaDoc value = entry.getValue();
369       NotificationImpl notification =
370         createNotification
371           (Notification.SET,
372            feature,
373            value,
374            value,
375            feature.isMany() ? indexOf(feature, value) : Notification.NO_INDEX,
376            true);
377   
378       if (notifications != null)
379       {
380         notifications.add(notification);
381       }
382       else
383       {
384         notifications = notification;
385       }
386     }
387
388     return notifications;
389   }
390
391   public Object JavaDoc move(int targetIndex, int sourceIndex)
392   {
393     if (isNotificationRequired())
394     {
395       Entry [] entries = (Entry[])data;
396       Entry sourceEntry = entries[sourceIndex];
397       EStructuralFeature feature = sourceEntry.getEStructuralFeature();
398       if (isMany(feature))
399       {
400         FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
401         int featureTargetIndex = -1;
402         int featureSourceIndex = -1;
403         int count = 0;
404         for (int i = 0; i < size; ++i)
405         {
406           Entry entry = entries[i];
407           if (i == targetIndex)
408           {
409             featureTargetIndex = count;
410           }
411           if (i == sourceIndex)
412           {
413             featureSourceIndex = count;
414           }
415           if (validator.isValid(entry.getEStructuralFeature()))
416           {
417             ++count;
418           }
419         }
420
421         Object JavaDoc result = doMove(targetIndex, sourceIndex);
422         if (featureSourceIndex != featureTargetIndex)
423         {
424           dispatchNotification
425             (new ENotificationImpl
426                (owner,
427                 Notification.MOVE,
428                 feature,
429                 new Integer JavaDoc(featureSourceIndex),
430                 sourceEntry.getValue(),
431                 featureTargetIndex));
432         }
433         return result;
434       }
435       else
436       {
437         return doMove(targetIndex, sourceIndex);
438       }
439     }
440     else
441     {
442       return doMove(targetIndex, sourceIndex);
443     }
444   }
445
446   protected Object JavaDoc doMove(int targetIndex, int sourceIndex)
447   {
448     return super.move(targetIndex, sourceIndex);
449   }
450
451   public Object JavaDoc set(int index, Object JavaDoc object)
452   {
453     Entry entry = (Entry)object;
454     EStructuralFeature entryFeature = entry.getEStructuralFeature();
455     if (isMany(entryFeature))
456     {
457       if (entryFeature.isUnique())
458       {
459         Entry [] entries = (Entry[])data;
460         for (int i = 0; i < size; ++i)
461         {
462           Entry otherEntry = entries[i];
463           if (otherEntry.equals(entry) && i != index)
464           {
465             throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
466           }
467         }
468       }
469     }
470     else
471     {
472       FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
473       Entry [] entries = (Entry[])data;
474       for (int i = 0; i < size; ++i)
475       {
476         Entry otherEntry = entries[i];
477         if (validator.isValid(otherEntry.getEStructuralFeature()) && i != index)
478         {
479           throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
480         }
481       }
482     }
483
484     return doSet(index, object);
485   }
486
487   public Object JavaDoc doSet(int index, Object JavaDoc object)
488   {
489     return super.set(index, object);
490   }
491
492   public boolean add(Object JavaDoc object)
493   {
494     Entry entry = (Entry)object;
495     EStructuralFeature entryFeature = entry.getEStructuralFeature();
496     if (isMany(entryFeature))
497     {
498       if (entryFeature.isUnique() && contains(entryFeature, entry.getValue()))
499       {
500         return false;
501       }
502     }
503     else
504     {
505       FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
506       Entry [] entries = (Entry[])data;
507       for (int i = 0; i < size; ++i)
508       {
509         Entry otherEntry = entries[i];
510         if (validator.isValid(otherEntry.getEStructuralFeature()))
511         {
512           if (otherEntry.equals(entry))
513           {
514             return false;
515           }
516           else
517           {
518             doSet(i, object);
519             return true;
520           }
521         }
522       }
523     }
524
525     return doAdd(object);
526   }
527
528   protected boolean doAdd(Object JavaDoc object)
529   {
530     return super.add(object);
531   }
532
533   public void add(int index, Object JavaDoc object)
534   {
535     Entry entry = (Entry)object;
536     EStructuralFeature entryFeature = entry.getEStructuralFeature();
537     if (isMany(entryFeature))
538     {
539       if (entryFeature.isUnique())
540       {
541         Entry [] entries = (Entry[])data;
542         for (int i = 0; i < size; ++i)
543         {
544           Entry otherEntry = entries[i];
545           if (otherEntry.equals(entry) && i != index)
546           {
547             throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
548           }
549         }
550       }
551     }
552     else
553     {
554       FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
555       Entry [] entries = (Entry[])data;
556       for (int i = 0; i < size; ++i)
557       {
558         Entry otherEntry = entries[i];
559         if (validator.isValid(otherEntry.getEStructuralFeature()))
560         {
561           throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
562         }
563       }
564     }
565
566     doAdd(index, object);
567   }
568
569   public void doAdd(int index, Object JavaDoc object)
570   {
571     super.add(index, object);
572   }
573
574   public boolean addAll(Collection JavaDoc collection)
575   {
576     Collection JavaDoc uniqueCollection = new BasicEList(collection.size());
577     for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
578     {
579       Entry entry = (Entry)i.next();
580       EStructuralFeature entryFeature = entry.getEStructuralFeature();
581       if (isMany(entryFeature))
582       {
583         if (!entryFeature.isUnique() || !contains(entryFeature, entry.getValue()) && !uniqueCollection.contains(entry))
584         {
585           uniqueCollection.add(entry);
586         }
587       }
588       else
589       {
590         FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
591         Entry [] entries = (Entry[])data;
592         boolean include = true;
593         for (int j = 0; j < size; ++j)
594         {
595           Entry otherEntry = entries[j];
596           if (validator.isValid(otherEntry.getEStructuralFeature()))
597           {
598             doSet(j, entry);
599             include = false;
600             break;
601           }
602         }
603         if (include)
604         {
605           uniqueCollection.add(entry);
606         }
607       }
608     }
609
610     return doAddAll(uniqueCollection);
611   }
612
613   public boolean doAddAll(Collection JavaDoc collection)
614   {
615     return super.addAll(collection);
616   }
617
618   public boolean addAll(int index, Collection JavaDoc collection)
619   {
620     Collection JavaDoc uniqueCollection = new BasicEList(collection.size());
621     for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
622     {
623       Entry entry = (Entry)i.next();
624       EStructuralFeature entryFeature = entry.getEStructuralFeature();
625       if (isMany(entryFeature))
626       {
627         if (!entryFeature.isUnique() || !contains(entryFeature, entry.getValue()) && !uniqueCollection.contains(entry))
628         {
629           uniqueCollection.add(entry);
630         }
631       }
632       else
633       {
634         FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
635         Entry [] entries = (Entry[])data;
636         boolean include = true;
637         for (int j = 0; j < size; ++j)
638         {
639           Entry otherEntry = entries[j];
640           if (validator.isValid(otherEntry.getEStructuralFeature()))
641           {
642             doSet(j, entry);
643             include = false;
644             break;
645           }
646         }
647         if (include)
648         {
649           uniqueCollection.add(entry);
650         }
651       }
652     }
653
654     return doAddAll(index, uniqueCollection);
655   }
656
657   public boolean doAddAll(int index, Collection JavaDoc collection)
658   {
659     return super.addAll(index, collection);
660   }
661
662   public int size(EStructuralFeature feature)
663   {
664     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
665     int result = 0;
666     Entry [] entries = (Entry[])data;
667     for (int i = 0; i < size; ++i)
668     {
669       Entry entry = entries[i];
670       if (validator.isValid(entry.getEStructuralFeature()))
671       {
672         ++result;
673       }
674     }
675     return result;
676   }
677
678   public boolean isEmpty(EStructuralFeature feature)
679   {
680     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
681     Entry [] entries = (Entry[])data;
682     for (int i = 0; i < size; ++i)
683     {
684       Entry entry = entries[i];
685       if (validator.isValid(entry.getEStructuralFeature()))
686       {
687         return false;
688       }
689     }
690     return true;
691   }
692
693   public boolean contains(EStructuralFeature feature, Object JavaDoc object)
694   {
695     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
696     Entry [] entries = (Entry[])data;
697     if (FeatureMapUtil.isFeatureMap(feature))
698     {
699       for (int i = 0; i < size; ++i)
700       {
701         Entry entry = entries[i];
702         if (validator.isValid(entry.getEStructuralFeature()) && entry.equals(object))
703         {
704           return true;
705         }
706       }
707     }
708     else if (object != null)
709     {
710       for (int i = 0; i < size; ++i)
711       {
712         Entry entry = entries[i];
713         if (validator.isValid(entry.getEStructuralFeature()) && object.equals(entry.getValue()))
714         {
715           return true;
716         }
717       }
718     }
719     else
720     {
721       for (int i = 0; i < size; ++i)
722       {
723         Entry entry = entries[i];
724         if (validator.isValid(entry.getEStructuralFeature()) && entry.getValue() == null)
725         {
726           return false;
727         }
728       }
729     }
730
731     return false;
732   }
733
734   public boolean containsAll(EStructuralFeature feature, Collection JavaDoc collection)
735   {
736     for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
737     {
738       if (!contains(feature, i.next()))
739       {
740         return false;
741       }
742     }
743
744     return true;
745   }
746
747   public int indexOf(EStructuralFeature feature, Object JavaDoc object)
748   {
749     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
750     int result = 0;
751     Entry [] entries = (Entry[])data;
752     if (FeatureMapUtil.isFeatureMap(feature))
753     {
754       for (int i = 0; i < size; ++i)
755       {
756         Entry entry = entries[i];
757         if (validator.isValid(entry.getEStructuralFeature()))
758         {
759           if (entry.equals(object))
760           {
761             return result;
762           }
763           ++result;
764         }
765       }
766     }
767     else if (object != null)
768     {
769       for (int i = 0; i < size; ++i)
770       {
771         Entry entry = entries[i];
772         if (validator.isValid(entry.getEStructuralFeature()))
773         {
774           if (object.equals(entry.getValue()))
775           {
776             return result;
777           }
778           ++result;
779         }
780       }
781     }
782     else
783     {
784       for (int i = 0; i < size; ++i)
785       {
786         Entry entry = entries[i];
787         if (validator.isValid(entry.getEStructuralFeature()))
788         {
789           if (entry.getValue() == null)
790           {
791             return result;
792           }
793           ++result;
794         }
795       }
796     }
797
798     return -1;
799   }
800
801   public int lastIndexOf(EStructuralFeature feature, Object JavaDoc object)
802   {
803     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
804     int result = -1;
805     int count = 0;
806     Entry [] entries = (Entry[])data;
807     if (FeatureMapUtil.isFeatureMap(feature))
808     {
809       for (int i = 0; i < size; ++i)
810       {
811         Entry entry = entries[i];
812         if (validator.isValid(entry.getEStructuralFeature()))
813         {
814           if (entry.equals(object))
815           {
816             result = count;
817           }
818           ++count;
819         }
820       }
821     }
822     else if (object != null)
823     {
824       for (int i = 0; i < size; ++i)
825       {
826         Entry entry = entries[i];
827         if (validator.isValid(entry.getEStructuralFeature()))
828         {
829           if (object.equals(entry.getValue()))
830           {
831             result = count;
832           }
833           ++count;
834         }
835       }
836     }
837     else
838     {
839       for (int i = 0; i < size; ++i)
840       {
841         Entry entry = entries[i];
842         if (validator.isValid(entry.getEStructuralFeature()))
843         {
844           if (entry.getValue() == null)
845           {
846             result = count;
847           }
848           ++count;
849         }
850       }
851     }
852
853     return result;
854   }
855
856   public Iterator JavaDoc iterator(EStructuralFeature feature)
857   {
858     return
859       feature instanceof EReference && ((EReference)feature).isResolveProxies() ?
860         new ResolvingFeatureEIterator(feature, this) :
861         new FeatureEIterator(feature, this);
862   }
863
864   public ListIterator JavaDoc listIterator(EStructuralFeature feature)
865   {
866     return
867       feature instanceof EReference && ((EReference)feature).isResolveProxies() ?
868         new ResolvingFeatureEIterator(feature, this) :
869         new FeatureEIterator(feature, this);
870   }
871
872   public ListIterator JavaDoc listIterator(EStructuralFeature feature, int index)
873   {
874     ListIterator JavaDoc result =
875       feature instanceof EReference && ((EReference)feature).isResolveProxies() ?
876         new ResolvingFeatureEIterator(feature, this) :
877         new FeatureEIterator(feature, this);
878     for (int i = 0; i < index; ++i)
879     {
880       result.next();
881     }
882     return result;
883   }
884
885   public ValueListIterator valueListIterator()
886   {
887     return new ValueListIteratorImpl();
888   }
889   
890   public ValueListIterator valueListIterator(int index)
891   {
892     return new ValueListIteratorImpl(index);
893   }
894   
895   protected class ValueListIteratorImpl extends EListIterator implements ValueListIterator
896   {
897     public ValueListIteratorImpl()
898     {
899       super();
900     }
901     
902     public ValueListIteratorImpl(int index)
903     {
904       super(index);
905     }
906     
907     public EStructuralFeature feature()
908     {
909       if (lastCursor == -1)
910       {
911         throw new IllegalStateException JavaDoc();
912       }
913       return getEStructuralFeature(lastCursor);
914     }
915     
916     public Object JavaDoc next()
917     {
918       return ((Entry)super.next()).getValue();
919     }
920     
921     public Object JavaDoc previous()
922     {
923       return ((Entry)super.next()).getValue();
924     }
925
926     public void add(Object JavaDoc value)
927     {
928       super.add(FeatureMapUtil.createEntry(feature(), value));
929     }
930     
931     public void add(EStructuralFeature eStructuralFeature, Object JavaDoc value)
932     {
933       super.add(FeatureMapUtil.createEntry(eStructuralFeature, value));
934     }
935   }
936   
937 /*
938   public List subList(EStructuralFeature feature, int from, int to)
939   {
940     return null;
941   }
942 */

943
944   public EList list(EStructuralFeature feature)
945   {
946     return
947       FeatureMapUtil.isFeatureMap(feature) ?
948         new FeatureMapUtil.FeatureFeatureMap(feature, this) :
949         new FeatureMapUtil.FeatureEList(feature, this);
950   }
951
952   public EStructuralFeature.Setting setting(EStructuralFeature feature)
953   {
954     return
955       isMany(feature) ?
956         (EStructuralFeature.Setting)list(feature) :
957         (EStructuralFeature.Setting)new FeatureMapUtil.FeatureValue(feature, this);
958   }
959
960   public List JavaDoc basicList(final EStructuralFeature feature)
961   {
962     return new FeatureMapUtil.FeatureEList.Basic(feature, this);
963   }
964
965   public Iterator JavaDoc basicIterator(EStructuralFeature feature)
966   {
967     return new FeatureEIterator(feature, this);
968   }
969
970   public ListIterator JavaDoc basicListIterator(EStructuralFeature feature)
971   {
972     return new FeatureEIterator(feature, this);
973   }
974
975   public ListIterator JavaDoc basicListIterator(EStructuralFeature feature, int index)
976   {
977     ListIterator JavaDoc result = new FeatureEIterator(feature, this);
978     for (int i = 0; i < index; ++i)
979     {
980       result.next();
981     }
982     return result;
983   }
984
985   public Object JavaDoc[] toArray(EStructuralFeature feature)
986   {
987     List JavaDoc result = new BasicEList();
988     FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
989     Entry [] entries = (Entry[])data;
990     if (FeatureMapUtil.isFeatureMap(feature))
991     {
992       for (int i = 0; i < size; ++i)
993       {
994         Entry entry = entries[i];
995         if (validator.isValid(entry.getEStructuralFeature()))
996         {
997           result.add(entry);
998         }
999       }
1000    }
1001    else
1002    {
1003      for (int i = 0; i < size; ++i)
1004      {
1005        Entry entry = entries[i];
1006        if (validator.isValid(entry.getEStructuralFeature()))
1007        {
1008          result.add(entry.getValue());
1009        }
1010      }
1011    }
1012    return result.toArray();
1013  }
1014
1015  public Object JavaDoc[] toArray(EStructuralFeature feature, Object JavaDoc [] array)
1016  {
1017    List JavaDoc result = new BasicEList();
1018    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1019    Entry [] entries = (Entry[])data;
1020    if (FeatureMapUtil.isFeatureMap(feature))
1021    {
1022      for (int i = 0; i < size; ++i)
1023      {
1024        Entry entry = entries[i];
1025        if (validator.isValid(entry.getEStructuralFeature()))
1026        {
1027          result.add(entry);
1028        }
1029      }
1030    }
1031    else
1032    {
1033      for (int i = 0; i < size; ++i)
1034      {
1035        Entry entry = entries[i];
1036        if (validator.isValid(entry.getEStructuralFeature()))
1037        {
1038          result.add(entry.getValue());
1039        }
1040      }
1041    }
1042    return result.toArray(array);
1043  }
1044
1045  public void set(EStructuralFeature feature, Object JavaDoc object)
1046  {
1047    if (isMany(feature))
1048    {
1049      List JavaDoc list = list(feature);
1050      list.clear();
1051      list.addAll((Collection JavaDoc)object);
1052    }
1053    else
1054    {
1055      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1056      Entry [] entries = (Entry[])data;
1057      for (int i = 0; i < size; ++i)
1058      {
1059        Entry entry = entries[i];
1060        if (validator.isValid(entry.getEStructuralFeature()))
1061        {
1062          if (shouldUnset(feature, object))
1063          {
1064            remove(i);
1065          }
1066          else
1067          {
1068            doSet(i, FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
1069          }
1070          return;
1071        }
1072      }
1073  
1074      if (!shouldUnset(feature, object))
1075      {
1076        doAdd(FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
1077      }
1078    }
1079  }
1080
1081  protected boolean shouldUnset(EStructuralFeature feature, Object JavaDoc value)
1082  {
1083    if (feature.getUpperBound() != EStructuralFeature.UNSPECIFIED_MULTIPLICITY && !feature.isUnsettable())
1084    {
1085      Object JavaDoc defaultValue = feature.getDefaultValue();
1086      return defaultValue == null ? value == null : defaultValue.equals(value);
1087    }
1088    else
1089    {
1090      return false;
1091    }
1092  }
1093
1094  public void add(int index, EStructuralFeature feature, Object JavaDoc object)
1095  {
1096    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1097    if (isMany(feature))
1098    {
1099      if (feature.isUnique() && contains(feature, object))
1100      {
1101        throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
1102      }
1103    }
1104    else
1105    {
1106      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1107      Entry [] entries = (Entry[])data;
1108      for (int i = 0; i < size; ++i)
1109      {
1110        Entry entry = entries[i];
1111        if (validator.isValid(entry.getEStructuralFeature()))
1112        {
1113          if (isFeatureMap ? entry.equals(object) : object == null ? entry.getValue() == null : object.equals(entry.getValue()))
1114          {
1115            throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
1116          }
1117        }
1118      }
1119    }
1120
1121    doAdd(index, isFeatureMap ? (Entry)object : createEntry(feature, object));
1122  }
1123
1124  public boolean add(EStructuralFeature feature, Object JavaDoc object)
1125  {
1126    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1127    if (isMany(feature))
1128    {
1129      if (feature.isUnique() && contains(feature, object))
1130      {
1131        return false;
1132      }
1133    }
1134    else
1135    {
1136      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1137      Entry [] entries = (Entry[])data;
1138      for (int i = 0; i < size; ++i)
1139      {
1140        Entry entry = entries[i];
1141        if (validator.isValid(entry.getEStructuralFeature()))
1142        {
1143          if (isFeatureMap ? entry.equals(object) : object == null ? entry.getValue() == null : object.equals(entry.getValue()))
1144          {
1145            return false;
1146          }
1147          else
1148          {
1149            doSet(i, isFeatureMap ? (Entry)object : createEntry(feature, object));
1150            return true;
1151          }
1152        }
1153      }
1154    }
1155
1156    return doAdd(isFeatureMap ? (Entry)object : createEntry(feature, object));
1157  }
1158
1159  public void add(EStructuralFeature feature, int index, Object JavaDoc object)
1160  {
1161    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1162    if (isMany(feature))
1163    {
1164      if (feature.isUnique() && contains(feature, object))
1165      {
1166        throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
1167      }
1168    }
1169    else
1170    {
1171      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1172      Entry [] entries = (Entry[])data;
1173      for (int i = 0; i < size; ++i)
1174      {
1175        Entry entry = entries[i];
1176        if (validator.isValid(entry.getEStructuralFeature()))
1177        {
1178          throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
1179        }
1180      }
1181    }
1182
1183    doAdd(entryIndex(feature, index), isFeatureMap ? (Entry)object : createEntry(feature, object));
1184  }
1185
1186  public boolean addAll(int index, EStructuralFeature feature, Collection JavaDoc collection)
1187  {
1188    if (collection.size() == 0)
1189    {
1190      return false;
1191    }
1192    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1193    Collection JavaDoc entryCollection = isFeatureMap ? collection : new BasicEList(collection.size());
1194    if (isMany(feature))
1195    {
1196      if (feature.isUnique())
1197      {
1198        for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1199        {
1200          Object JavaDoc object = i.next();
1201          if (!contains(feature, object))
1202          {
1203            Entry entry = createEntry(feature, object);
1204            if (!entryCollection.contains(entry))
1205            {
1206              entryCollection.add(entry);
1207            }
1208          }
1209        }
1210      }
1211      else if (!isFeatureMap)
1212      {
1213        for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1214        {
1215          Entry entry = createEntry(feature, i.next());
1216          entryCollection.add(entry);
1217        }
1218      }
1219    }
1220    else
1221    {
1222      if (collection.size() > 1)
1223      {
1224        throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
1225      }
1226
1227      if (isFeatureMap)
1228      {
1229        if (contains(feature, collection.iterator().next()))
1230        {
1231          return false;
1232        }
1233      }
1234      else
1235      {
1236        FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1237        Entry [] entries = (Entry[])data;
1238        for (int i = 0; i < size; ++i)
1239        {
1240          Entry entry = entries[i];
1241          if (validator.isValid(entry.getEStructuralFeature()))
1242          {
1243            if (collection.contains(entry.getValue()))
1244            {
1245              return false;
1246            }
1247            else
1248            {
1249              throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
1250            }
1251          }
1252        }
1253        Entry entry = createEntry(feature, collection.iterator().next());
1254        entryCollection.add(entry);
1255      }
1256    }
1257
1258    return doAddAll(index, entryCollection);
1259  }
1260
1261  public boolean addAll(EStructuralFeature feature, Collection JavaDoc collection)
1262  {
1263    if (collection.size() == 0)
1264    {
1265      return false;
1266    }
1267    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1268    Collection JavaDoc entryCollection = isFeatureMap ? collection : new BasicEList(collection.size());
1269    if (isMany(feature))
1270    {
1271      if (feature.isUnique())
1272      {
1273        for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1274        {
1275          Object JavaDoc object = i.next();
1276          if (!contains(feature, object))
1277          {
1278            Entry entry = createEntry(feature, object);
1279            if (!entryCollection.contains(entry))
1280            {
1281              entryCollection.add(entry);
1282            }
1283          }
1284        }
1285      }
1286      else if (!isFeatureMap)
1287      {
1288        for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1289        {
1290          Entry entry = createEntry(feature, i.next());
1291          entryCollection.add(entry);
1292        }
1293      }
1294    }
1295    else
1296    {
1297      if (collection.size() > 1)
1298      {
1299        throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
1300      }
1301
1302      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1303      Entry [] entries = (Entry[])data;
1304      for (int i = 0; i < size; ++i)
1305      {
1306        Entry entry = entries[i];
1307        if (validator.isValid(entry.getEStructuralFeature()))
1308        {
1309          if (collection.contains(isFeatureMap ? entry : entry.getValue()))
1310          {
1311            return false;
1312          }
1313          else
1314          {
1315            for (Iterator JavaDoc j = collection.iterator(); j.hasNext(); )
1316            {
1317              doSet(i, isFeatureMap ? j.next() : createEntry(feature, j.next()));
1318            }
1319            return true;
1320          }
1321        }
1322      }
1323      if (!isFeatureMap)
1324      {
1325        Entry entry = createEntry(feature, collection.iterator().next());
1326        entryCollection.add(entry);
1327      }
1328    }
1329
1330    return doAddAll(entryCollection);
1331  }
1332
1333  public boolean addAll(EStructuralFeature feature, int index, Collection JavaDoc collection)
1334  {
1335    if (collection.size() == 0)
1336    {
1337      return false;
1338    }
1339    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1340    Collection JavaDoc entryCollection = isFeatureMap ? collection : new BasicEList(collection.size());
1341    if (isMany(feature))
1342    {
1343      if (feature.isUnique())
1344      {
1345        for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1346        {
1347          Object JavaDoc object = i.next();
1348          if (!contains(feature, object))
1349          {
1350            Entry entry = createEntry(feature, object);
1351            entryCollection.add(entry);
1352          }
1353        }
1354      }
1355      else if (!isFeatureMap)
1356      {
1357        for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
1358        {
1359          Entry entry = createEntry(feature, i.next());
1360          entryCollection.add(entry);
1361        }
1362      }
1363    }
1364    else
1365    {
1366      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1367      Entry [] entries = (Entry[])data;
1368      for (int i = 0; i < size; ++i)
1369      {
1370        Entry entry = entries[i];
1371        if (validator.isValid(entry.getEStructuralFeature()))
1372        {
1373          throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
1374        }
1375      }
1376
1377      if (collection.size() > 1)
1378      {
1379        throw new IllegalArgumentException JavaDoc("The multiplicity constraint is violated");
1380      }
1381
1382      if (!isFeatureMap)
1383      {
1384        Entry entry = createEntry(feature, collection.iterator().next());
1385        entryCollection.add(entry);
1386      }
1387    }
1388
1389    return doAddAll(entryIndex(feature, index), entryCollection);
1390  }
1391
1392  public void addUnique(EStructuralFeature feature, Object JavaDoc object)
1393  {
1394    addUnique(createEntry(feature, object));
1395  }
1396
1397  public void addUnique(EStructuralFeature feature, int index, Object JavaDoc object)
1398  {
1399    addUnique(entryIndex(feature, index), createEntry(feature, object));
1400  }
1401
1402  public NotificationChain basicAdd(EStructuralFeature feature, Object JavaDoc object, NotificationChain notifications)
1403  {
1404    if (object == null)
1405    {
1406      Entry [] entries = (Entry[])data;
1407      for (int i = 0; i < size; ++i)
1408      {
1409        Entry entry = entries[i];
1410        if (entry.getEStructuralFeature() == feature)
1411        {
1412          return super.basicRemove(entry, notifications);
1413        }
1414      }
1415    }
1416
1417    Entry entry = FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object);
1418
1419    if (isNotificationRequired())
1420    {
1421      boolean oldIsSet = !isEmpty(feature);
1422      notifications = basicAdd(entry, notifications);
1423      NotificationImpl notification =
1424        feature.isMany() ?
1425          createNotification
1426            (Notification.ADD,
1427             feature,
1428             null,
1429             object,
1430             indexOf(feature, object),
1431             oldIsSet) :
1432          createNotification
1433            (Notification.SET,
1434             feature,
1435             feature.getDefaultValue(),
1436             object,
1437             Notification.NO_INDEX,
1438             oldIsSet);
1439
1440      if (notifications != null)
1441      {
1442        notifications.add(notification);
1443      }
1444      else
1445      {
1446        notifications = notification;
1447      }
1448    }
1449    else
1450    {
1451      notifications = basicAdd(entry, notifications);
1452    }
1453    return notifications;
1454  }
1455
1456  public boolean remove(EStructuralFeature feature, Object JavaDoc object)
1457  {
1458    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1459    Entry [] entries = (Entry[])data;
1460    if (FeatureMapUtil.isFeatureMap(feature))
1461    {
1462      for (int i = 0; i < size; ++i)
1463      {
1464        Entry entry = entries[i];
1465        if (validator.isValid(entry.getEStructuralFeature()))
1466        {
1467          if (entry.equals(object))
1468          {
1469            remove(i);
1470            return true;
1471          }
1472        }
1473      }
1474    }
1475    else if (object != null)
1476    {
1477      for (int i = 0; i < size; ++i)
1478      {
1479        Entry entry = entries[i];
1480        if (validator.isValid(entry.getEStructuralFeature()))
1481        {
1482          if (object.equals(entry.getValue()))
1483          {
1484            remove(i);
1485            return true;
1486          }
1487        }
1488      }
1489    }
1490    else
1491    {
1492      for (int i = 0; i < size; ++i)
1493      {
1494        Entry entry = entries[i];
1495        if (validator.isValid(entry.getEStructuralFeature()))
1496        {
1497          if (entry.getValue() == null)
1498          {
1499            remove(i);
1500            return true;
1501          }
1502        }
1503      }
1504    }
1505
1506    return false;
1507  }
1508
1509  public Object JavaDoc remove(EStructuralFeature feature, int index)
1510  {
1511    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1512    Entry [] entries = (Entry[])data;
1513    int count = 0;
1514    for (int i = 0; i < size; ++i)
1515    {
1516      Entry entry = entries[i];
1517      if (validator.isValid(entry.getEStructuralFeature()))
1518      {
1519        if (count == index)
1520        {
1521          remove(i);
1522          return FeatureMapUtil.isFeatureMap(feature) ? entry : entry.getValue();
1523        }
1524        ++count;
1525      }
1526    }
1527
1528    throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=" + count);
1529  }
1530
1531  public boolean removeAll(EStructuralFeature feature, Collection JavaDoc collection)
1532  {
1533    if (FeatureMapUtil.isFeatureMap(feature))
1534    {
1535      return removeAll(collection);
1536    }
1537    else
1538    {
1539      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1540      List JavaDoc entryCollection = new BasicEList(collection.size());
1541      Entry [] entries = (Entry[])data;
1542      for (int i = size; --i >= 0; )
1543      {
1544        Entry entry = entries[i];
1545        if (validator.isValid(entry.getEStructuralFeature()))
1546        {
1547          if (collection.contains(entry.getValue()))
1548          {
1549            entryCollection.add(entry);
1550          }
1551        }
1552      }
1553
1554      return removeAll(entryCollection);
1555    }
1556  }
1557
1558  public NotificationChain basicRemove(EStructuralFeature feature, Object JavaDoc object, NotificationChain notifications)
1559  {
1560    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1561    int count = 0;
1562    Entry [] entries = (Entry[])data;
1563    Entry match = null;
1564    if (FeatureMapUtil.isFeatureMap(feature))
1565    {
1566      for (int i = 0; i < size; ++i)
1567      {
1568        Entry entry = entries[i];
1569        if (validator.isValid(entry.getEStructuralFeature()))
1570        {
1571          if (entry.equals(object))
1572          {
1573            match = entry;
1574            break;
1575          }
1576          ++count;
1577        }
1578      }
1579    }
1580    else if (object != null)
1581    {
1582      for (int i = 0; i < size; ++i)
1583      {
1584        Entry entry = entries[i];
1585        if (validator.isValid(entry.getEStructuralFeature()))
1586        {
1587          if (object.equals(entry.getValue()))
1588          {
1589            match = entry;
1590            break;
1591          }
1592          ++count;
1593        }
1594      }
1595    }
1596    else
1597    {
1598      for (int i = 0; i < size; ++i)
1599      {
1600        Entry entry = entries[i];
1601        if (validator.isValid(entry.getEStructuralFeature()))
1602        {
1603          if (entry.getValue() == null)
1604          {
1605            match = entry;
1606            break;
1607          }
1608          ++count;
1609        }
1610      }
1611    }
1612
1613    if (match != null)
1614    {
1615      if (isNotificationRequired())
1616      {
1617        NotificationImpl notification =
1618          feature.isMany() ?
1619            createNotification
1620              (Notification.REMOVE,
1621               feature,
1622               object,
1623               null,
1624               count,
1625               true) :
1626            createNotification
1627              (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
1628               feature,
1629               object,
1630               feature.getDefaultValue(),
1631               Notification.NO_INDEX,
1632               true);
1633  
1634        if (notifications != null)
1635        {
1636          notifications.add(notification);
1637        }
1638        else
1639        {
1640          notifications = notification;
1641        }
1642      }
1643      notifications = basicRemove(match, notifications);
1644    }
1645
1646    return notifications;
1647  }
1648
1649  public boolean retainAll(EStructuralFeature feature, Collection JavaDoc collection)
1650  {
1651    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
1652    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1653    List JavaDoc entryCollection = new BasicEList(collection.size());
1654    Entry [] entries = (Entry[])data;
1655    for (int i = size; --i >= 0; )
1656    {
1657      Entry entry = entries[i];
1658      if (validator.isValid(entry.getEStructuralFeature()))
1659      {
1660        if (!collection.contains(isFeatureMap ? entry : entry.getValue()))
1661        {
1662          entryCollection.add(entry);
1663        }
1664      }
1665    }
1666
1667    return removeAll(entryCollection);
1668  }
1669
1670  public void clear(EStructuralFeature feature)
1671  {
1672    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1673    List JavaDoc entryCollection = new BasicEList();
1674    Entry [] entries = (Entry[])data;
1675    for (int i = size; --i >= 0; )
1676    {
1677      Entry entry = entries[i];
1678      if (validator.isValid(entry.getEStructuralFeature()))
1679      {
1680        entryCollection.add(entry);
1681      }
1682    }
1683
1684    if (!removeAll(entryCollection))
1685    {
1686      dispatchNotification
1687        (feature.isMany() ?
1688           createNotification
1689             (Notification.REMOVE_MANY,
1690              feature,
1691              Collections.EMPTY_LIST,
1692              null,
1693              Notification.NO_INDEX,
1694              false) :
1695           createNotification
1696             (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
1697              feature,
1698              null,
1699              null,
1700              Notification.NO_INDEX,
1701              false));
1702    }
1703  }
1704
1705  public void move(EStructuralFeature feature, int index, Object JavaDoc object)
1706  {
1707    move(feature, index, indexOf(feature, object));
1708  }
1709
1710  public Object JavaDoc move(EStructuralFeature feature, int targetIndex, int sourceIndex)
1711  {
1712    if (isMany(feature))
1713    {
1714      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1715      Entry [] entries = (Entry[])data;
1716      Object JavaDoc result = null;
1717      int entryTargetIndex = -1;
1718      int entrySourceIndex = -1;
1719      int count = 0;
1720      for (int i = 0; i < size; ++i)
1721      {
1722        Entry entry = entries[i];
1723        if (validator.isValid(entry.getEStructuralFeature()))
1724        {
1725          if (count == targetIndex)
1726          {
1727            entryTargetIndex = i;
1728          }
1729          if (count == sourceIndex)
1730          {
1731            entrySourceIndex = i;
1732            result = entry.getValue();
1733          }
1734          ++count;
1735        }
1736      }
1737      if (entryTargetIndex == -1)
1738      {
1739        throw new IndexOutOfBoundsException JavaDoc("targetIndex=" + targetIndex + ", size=" + count);
1740      }
1741      if (entrySourceIndex == -1)
1742      {
1743        throw new IndexOutOfBoundsException JavaDoc("sourceIndex=" + targetIndex + ", size=" + count);
1744      }
1745
1746      doMove(entryTargetIndex, entrySourceIndex);
1747
1748      if (isNotificationRequired())
1749      {
1750        dispatchNotification
1751          (createNotification
1752             (Notification.MOVE,
1753              feature,
1754              new Integer JavaDoc(sourceIndex),
1755              result,
1756              targetIndex,
1757              true));
1758      }
1759
1760      return result;
1761    }
1762    else
1763    {
1764      throw new IllegalArgumentException JavaDoc("The feature must be many-valued to support move");
1765    }
1766  }
1767
1768  public Object JavaDoc get(EStructuralFeature feature, boolean resolve)
1769  {
1770    Entry [] entries = (Entry[])data;
1771    if (isMany(feature))
1772    {
1773      return list(feature);
1774    }
1775    else
1776    {
1777      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1778      int count = 0;
1779      for (int i = 0; i < size; ++i)
1780      {
1781        Entry entry = entries[i];
1782        if (validator.isValid(entry.getEStructuralFeature()))
1783        {
1784          if (FeatureMapUtil.isFeatureMap(feature))
1785          {
1786            return entry;
1787          }
1788          else
1789          {
1790            Object JavaDoc value = entry.getValue();
1791            if (value != null && resolve && isResolveProxies(feature))
1792            {
1793              value = resolveProxy(feature, i, count, value);
1794            }
1795            return value;
1796          }
1797        }
1798        ++count;
1799      }
1800
1801      return feature.getDefaultValue();
1802    }
1803  }
1804
1805  public Object JavaDoc get(EStructuralFeature feature, int index, boolean resolve)
1806  {
1807    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1808    Entry [] entries = (Entry[])data;
1809    if (isMany(feature))
1810    {
1811      int count = 0;
1812      for (int i = 0; i < size; ++i)
1813      {
1814        Entry entry = entries[i];
1815        if (validator.isValid(entry.getEStructuralFeature()))
1816        {
1817          if (count == index)
1818          {
1819            if (FeatureMapUtil.isFeatureMap(feature))
1820            {
1821              return entry;
1822            }
1823            else
1824            {
1825              Object JavaDoc value = entry.getValue();
1826              if (value != null && resolve && isResolveProxies(feature))
1827              {
1828                value = resolveProxy(feature, i, count, value);
1829              }
1830              return value;
1831            }
1832          }
1833          ++count;
1834        }
1835      }
1836      throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=" + count);
1837    }
1838    else
1839    {
1840      int count = 0;
1841      for (int i = 0; i < size; ++i)
1842      {
1843        Entry entry = entries[i];
1844        if (validator.isValid(entry.getEStructuralFeature()))
1845        {
1846          if (FeatureMapUtil.isFeatureMap(feature))
1847          {
1848            return entry;
1849          }
1850          else
1851          {
1852            Object JavaDoc value = entry.getValue();
1853            if (value != null && resolve && isResolveProxies(feature))
1854            {
1855              value = resolveProxy(feature, i, count, value);
1856            }
1857            return value;
1858          }
1859        }
1860        ++count;
1861      }
1862
1863      return feature.getDefaultValue();
1864    }
1865  }
1866
1867  public Object JavaDoc set(EStructuralFeature feature, int index, Object JavaDoc object)
1868  {
1869    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1870    Entry [] entries = (Entry[])data;
1871    if (isMany(feature))
1872    {
1873      if (feature.isUnique())
1874      {
1875        int currentIndex = indexOf(feature, object);
1876        if (currentIndex >=0 && currentIndex != index)
1877        {
1878          throw new IllegalArgumentException JavaDoc("The 'no duplicates' constraint is violated");
1879        }
1880      }
1881
1882      int count = 0;
1883      for (int i = 0; i < size; ++i)
1884      {
1885        Entry entry = entries[i];
1886        if (validator.isValid(entry.getEStructuralFeature()))
1887        {
1888          if (count == index)
1889          {
1890            return doSet(i, FeatureMapUtil.isFeatureMap(feature) ? object : createEntry(feature, object));
1891          }
1892          ++count;
1893        }
1894      }
1895      throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=" + count);
1896    }
1897    else
1898    {
1899      // Index should be -1.
1900

1901      for (int i = 0; i < size; ++i)
1902      {
1903        Entry entry = entries[i];
1904        if (validator.isValid(entry.getEStructuralFeature()))
1905        {
1906          return FeatureMapUtil.isFeatureMap(feature) ? entry : entry.getValue();
1907        }
1908      }
1909
1910      return null;
1911    }
1912  }
1913
1914  public Object JavaDoc setUnique(EStructuralFeature feature, int index, Object JavaDoc object)
1915  {
1916    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1917    Entry [] entries = (Entry[])data;
1918    if (isMany(feature))
1919    {
1920      int count = 0;
1921      for (int i = 0; i < size; ++i)
1922      {
1923        Entry entry = entries[i];
1924        if (validator.isValid(entry.getEStructuralFeature()))
1925        {
1926          if (count == index)
1927          {
1928            return setUnique(i, FeatureMapUtil.isFeatureMap(feature) ? object : createEntry(feature, object));
1929          }
1930          ++count;
1931        }
1932      }
1933      throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=" + count);
1934    }
1935    else
1936    {
1937      // Index should be -1.
1938

1939      for (int i = 0; i < size; ++i)
1940      {
1941        Entry entry = entries[i];
1942        if (validator.isValid(entry.getEStructuralFeature()))
1943        {
1944          return setUnique(i, FeatureMapUtil.isFeatureMap(feature) ? object : createEntry(feature, object));
1945        }
1946      }
1947
1948      return feature.getDefaultValue();
1949    }
1950  }
1951
1952  public boolean isSet(EStructuralFeature feature)
1953  {
1954    return !isEmpty(feature);
1955  }
1956
1957  public void unset(EStructuralFeature feature)
1958  {
1959    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
1960    List JavaDoc removals = null;
1961    Entry [] entries = (Entry[])data;
1962    for (int i = 0; i < size; ++i)
1963    {
1964      Entry entry = entries[i];
1965      if (validator.isValid(entry.getEStructuralFeature()))
1966      {
1967        if (removals == null)
1968        {
1969          removals = new BasicEList();
1970        }
1971        removals.add(entry);
1972      }
1973    }
1974
1975    if (removals != null)
1976    {
1977      removeAll(removals);
1978    }
1979  }
1980
1981  public NotificationChain basicRemove(Object JavaDoc object, NotificationChain notifications)
1982  {
1983    // This may be called directly on an EObject for the case of a containment.
1984
//
1985
if (object instanceof FeatureMap.Entry)
1986    {
1987      return super.basicRemove(object, notifications);
1988    }
1989    else
1990    {
1991      Entry match = null;
1992      EStructuralFeature feature = null;
1993      Entry [] entries = (Entry[])data;
1994      for (int i = 0; i < size; ++i)
1995      {
1996        Entry entry = entries[i];
1997        if (object.equals(entry.getValue()))
1998        {
1999          feature = entry.getEStructuralFeature();
2000          if (feature instanceof EReference && ((EReference)feature).isContainment())
2001          {
2002            match = entry;
2003            break;
2004          }
2005        }
2006      }
2007
2008      if (match != null)
2009      {
2010        if (isNotificationRequired())
2011        {
2012          NotificationImpl notification =
2013            feature.isMany() ?
2014              createNotification
2015                (Notification.REMOVE,
2016                 feature,
2017                 object,
2018                 null,
2019                 indexOf(feature, object),
2020                 true) :
2021              createNotification
2022                (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
2023                 feature,
2024                 object,
2025                 feature.getDefaultValue(),
2026                 Notification.NO_INDEX,
2027                 true);
2028
2029          if (notifications != null)
2030          {
2031            notifications.add(notification);
2032          }
2033          else
2034          {
2035            notifications = notification;
2036          }
2037        }
2038        notifications = basicRemove(match, notifications);
2039      }
2040
2041      return notifications;
2042    }
2043  }
2044
2045  /**
2046   * -------------------------------------------
2047   */

2048  public static class FeatureEIterator extends FeatureMapUtil.BasicFeatureEIterator
2049  {
2050    public FeatureEIterator(EStructuralFeature eStructuralFeature, FeatureMap.Internal featureMap)
2051    {
2052      super(eStructuralFeature, featureMap);
2053    }
2054
2055    protected boolean scanNext()
2056    {
2057      int size = featureMap.size();
2058      Entry [] entries = (Entry [])((BasicEList)featureMap).data();
2059      while (entryCursor < size)
2060      {
2061        Entry entry = entries[entryCursor];
2062        if (validator.isValid(entry.getEStructuralFeature()))
2063        {
2064          preparedResult = extractValue(entry);
2065          prepared = 2;
2066          return true;
2067        }
2068        ++entryCursor;
2069      }
2070
2071      prepared = 1;
2072      lastCursor = -1;
2073      return false;
2074    }
2075
2076    protected boolean scanPrevious()
2077    {
2078      Entry [] entries = (Entry [])((BasicEList)featureMap).data();
2079      while (--entryCursor >= 0)
2080      {
2081        Entry entry = entries[entryCursor];
2082        if (validator.isValid(entry.getEStructuralFeature()))
2083        {
2084          preparedResult = extractValue(entry);
2085          prepared = -2;
2086          return true;
2087        }
2088      }
2089
2090      prepared = -1;
2091      lastCursor = -1;
2092      return false;
2093    }
2094  }
2095
2096  /**
2097   * -------------------------------------------
2098   */

2099  public static class ResolvingFeatureEIterator extends FeatureEIterator
2100  {
2101    public ResolvingFeatureEIterator(EStructuralFeature eStructuralFeature, FeatureMap.Internal featureMap)
2102    {
2103      super(eStructuralFeature, featureMap);
2104    }
2105
2106    protected boolean resolve()
2107    {
2108      return true;
2109    }
2110  }
2111
2112  /**
2113   * Temporary for testing purposes only.
2114   */

2115  public static class FeatureMapEObjectImpl extends org.eclipse.emf.ecore.impl.EObjectImpl
2116  {
2117    protected BasicFeatureMap featureMap = new BasicFeatureMap(this, -1);
2118
2119    public FeatureMapEObjectImpl()
2120    {
2121      super();
2122    }
2123
2124    public Object JavaDoc eDynamicGet(EStructuralFeature eFeature, boolean resolve)
2125    {
2126      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
2127      {
2128        return eSettingDelegate(eFeature).dynamicGet(this, null, -1, true);
2129      }
2130      else
2131      {
2132        return featureMap.setting(eFeature).get(resolve);
2133      }
2134    }
2135
2136    public void eDynamicSet(EStructuralFeature eFeature, Object JavaDoc newValue)
2137    {
2138      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
2139      {
2140        eSettingDelegate(eFeature).dynamicSet(this, null, -1, newValue);
2141      }
2142      else
2143      {
2144        if (!eFeature.isUnsettable())
2145        {
2146          Object JavaDoc defaultValue = eFeature.getDefaultValue();
2147          if (defaultValue == null ? newValue == null : defaultValue.equals(newValue))
2148          {
2149            featureMap.setting(eFeature).unset();
2150            return;
2151          }
2152        }
2153        featureMap.setting(eFeature).set(newValue);
2154      }
2155
2156/*
2157      if (eFeature instanceof EReference)
2158      {
2159        EReference eReference = (EReference)eFeature;
2160        EReference eOpposite = ((EReference)eFeature).getEOpposite();
2161        if (eOpposite != null)
2162        {
2163          if (!eReference.isContainment() && !eReference.isMany() && !eOpposite.isMany() && !eOpposite.isContainment())
2164          {
2165            if (eDynamicGet(eFeature, false) != newValue)
2166            {
2167              //Thread.dumpStack();
2168            }
2169            else if (newValue instanceof EObject && ((EObject)newValue).eGet(eOpposite) != this)
2170            {
2171              Thread.dumpStack();
2172            }
2173          }
2174        }
2175      }
2176*/

2177    }
2178
2179    public void eDynamicUnset(EStructuralFeature eFeature)
2180    {
2181      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
2182      {
2183        eSettingDelegate(eFeature).dynamicUnset(this, null, -1);
2184      }
2185      else
2186      {
2187        featureMap.setting(eFeature).unset();
2188      }
2189    }
2190
2191    public boolean eDynamicIsSet(EStructuralFeature eFeature)
2192    {
2193      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
2194      {
2195        return eSettingDelegate(eFeature).dynamicIsSet(this, null, -1);
2196      }
2197      else
2198      {
2199        return featureMap.setting(eFeature).isSet();
2200      }
2201    }
2202
2203    public NotificationChain eDynamicInverseAdd(InternalEObject otherEnd, int featureID, Class JavaDoc inverseClass, NotificationChain notifications)
2204    {
2205      EStructuralFeature.Internal feature = (EStructuralFeature.Internal)eClass().getEStructuralFeature(featureID);
2206      if (feature.isMany())
2207      {
2208        return featureMap.basicAdd(feature, otherEnd, notifications);
2209      }
2210      else if (feature instanceof EReference && ((EReference)feature).isContainer())
2211      {
2212        return eSettingDelegate(feature).dynamicInverseAdd(this, null, -1, otherEnd, notifications);
2213      }
2214      else
2215      {
2216        InternalEObject oldValue = (InternalEObject)eDynamicGet(feature, false);
2217        if (oldValue != null)
2218        {
2219          notifications = oldValue.eInverseRemove
2220            (this, oldValue.eClass().getFeatureID(((EReference)feature).getEOpposite()), null, notifications);
2221          notifications = featureMap.basicRemove(feature, oldValue, notifications);
2222        }
2223
2224        return featureMap.basicAdd(feature, otherEnd, notifications);
2225      }
2226    }
2227
2228    public NotificationChain eDynamicInverseRemove(InternalEObject otherEnd, int featureID, Class JavaDoc inverseClass, NotificationChain notifications)
2229    {
2230      EStructuralFeature.Internal feature = (EStructuralFeature.Internal)eClass().getEStructuralFeature(featureID);
2231      if (feature instanceof EReference && ((EReference)feature).isContainer())
2232      {
2233        return eSettingDelegate(feature).dynamicInverseRemove(this, null, -1, otherEnd, notifications);
2234      }
2235      else
2236      {
2237        return featureMap.basicRemove(feature, otherEnd, notifications);
2238      }
2239    }
2240
2241    public FeatureMap featureMap()
2242    {
2243      return featureMap;
2244    }
2245
2246    public void eNotify(Notification notification)
2247    {
2248      if (notification.getFeatureID(null) != -1)
2249      {
2250        super.eNotify(notification);
2251      }
2252    }
2253
2254    public String JavaDoc toString()
2255    {
2256      String JavaDoc result = super.toString();
2257      result = "org.eclipse.emf.ecore.impl.EObjectImpl" + result.substring(result.indexOf("@"));
2258      return result;
2259    }
2260  }
2261}
2262
Popular Tags