KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > edit > provider > ItemProviderAdapter


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2005 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: ItemProviderAdapter.java,v 1.19 2005/06/12 13:32:37 emerks Exp $
16  */

17 package org.eclipse.emf.edit.provider;
18
19
20 import java.net.URL JavaDoc;
21 import java.util.AbstractList JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.ListIterator JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.MissingResourceException JavaDoc;
31
32 import org.eclipse.emf.common.command.Command;
33 import org.eclipse.emf.common.command.CommandWrapper;
34 import org.eclipse.emf.common.command.CompoundCommand;
35 import org.eclipse.emf.common.command.UnexecutableCommand;
36 import org.eclipse.emf.common.notify.AdapterFactory;
37 import org.eclipse.emf.common.notify.Notification;
38 import org.eclipse.emf.common.notify.Notifier;
39 import org.eclipse.emf.common.notify.impl.AdapterImpl;
40 import org.eclipse.emf.common.util.BasicEList;
41 import org.eclipse.emf.common.util.EList;
42 import org.eclipse.emf.common.util.ResourceLocator;
43 import org.eclipse.emf.common.util.UniqueEList;
44 import org.eclipse.emf.ecore.EAttribute;
45 import org.eclipse.emf.ecore.EClassifier;
46 import org.eclipse.emf.ecore.EObject;
47 import org.eclipse.emf.ecore.EReference;
48 import org.eclipse.emf.ecore.EStructuralFeature;
49 import org.eclipse.emf.ecore.util.FeatureMap;
50 import org.eclipse.emf.ecore.util.FeatureMapUtil;
51 import org.eclipse.emf.edit.EMFEditPlugin;
52 import org.eclipse.emf.edit.command.AddCommand;
53 import org.eclipse.emf.edit.command.CommandActionDelegate;
54 import org.eclipse.emf.edit.command.CommandParameter;
55 import org.eclipse.emf.edit.command.CopyCommand;
56 import org.eclipse.emf.edit.command.CreateChildCommand;
57 import org.eclipse.emf.edit.command.CreateCopyCommand;
58 import org.eclipse.emf.edit.command.DragAndDropCommand;
59 import org.eclipse.emf.edit.command.InitializeCopyCommand;
60 import org.eclipse.emf.edit.command.MoveCommand;
61 import org.eclipse.emf.edit.command.RemoveCommand;
62 import org.eclipse.emf.edit.command.ReplaceCommand;
63 import org.eclipse.emf.edit.command.SetCommand;
64 import org.eclipse.emf.edit.domain.EditingDomain;
65
66
67 /**
68  * This adapter implementation provides a convenient reusable base for
69  * adapters that will be used as item providers.
70  * Default implementations for the following interfaces are provided:
71  * {@link IItemLabelProvider}, {@link IItemPropertySource},
72  * {@link IStructuredItemContentProvider},
73  * {@link ITreeItemContentProvider}, and {@link IEditingDomainItemProvider}.
74  * Also, {@link IUpdateableItemText#getUpdateableText} is implemented to delegate to {@link #getText};
75  * often the editable text will be just the text, in which case this is a good default implementation.
76  */

77 public class ItemProviderAdapter
78   extends AdapterImpl
79   implements
80     IChangeNotifier,
81     IDisposable,
82     CreateChildCommand.Helper,
83     ResourceLocator
84 {
85   /**
86    * This keeps track of the adapter factory that created this adaptor.
87    * It is also used as the key/type for this adapter.
88    */

89   protected AdapterFactory adapterFactory;
90
91   /**
92    * This is used to store all the property descriptors.
93    * Derived classes should add descriptors to this vector.
94    */

95   protected List JavaDoc itemPropertyDescriptors;
96
97   /**
98    * This is used to store all the children features. Derived classes should add features to this vector.
99    */

100   protected List JavaDoc childrenFeatures;
101
102   /**
103    * This stored the children references, but attributes may now contribute children, too. It is still present to
104    * support existing subclasses.
105    * @deprecated As of EMF 2.0, replaced by {@link #childrenFeatures}.
106    */

107   protected List JavaDoc childrenReferences;
108
109   /**
110    * This is used to implement {@link IChangeNotifier}.
111    */

112   protected IChangeNotifier changeNotifier;
113
114   /**
115    * This keeps track of all the targets to which this adapter is set.
116    */

117   protected List JavaDoc targets;
118
119   /**
120    * When {@link ChildrenStore}s are to be used to cache children (typically to hold wrappers for non-EObject
121    * children), this maps adapted objects to their corresponding stores. Stores should be accessed and created
122    * via {@link #getChildrenStore getChildrenStore} and {@link #createChildrenStore createChildrenStore}.
123    */

124   protected Map JavaDoc childrenStoreMap;
125
126   /**
127    * This holds children wrappers that are {@link #wrap created} by this item provider, so that they can be {@link
128    * #dispose disposed} with it.
129    */

130   protected Disposable wrappers;
131
132   /**
133    * This caches the result returned by {@link #isWrappingNeeded isWrappingNeeded} so that it need not be recomputed
134    * each time.
135    */

136   protected Boolean JavaDoc wrappingNeeded;
137
138   /**
139    * An instance is created from an adapter factory.
140    * The factory is used as a key so that we always know which factory created this adapter.
141    */

142   public ItemProviderAdapter(AdapterFactory adapterFactory)
143   {
144     this.adapterFactory = adapterFactory;
145   }
146
147   /**
148    * The adapter factory is used as the type key.
149    * This returns true, only if this adapter was created by the given factory.
150    */

151   public boolean isAdapterForType(Object JavaDoc type)
152   {
153     return type == adapterFactory;
154   }
155
156   /**
157    * This provides access to the factory.
158    */

159   public AdapterFactory getAdapterFactory()
160   {
161     return adapterFactory;
162   }
163
164   public void addListener(INotifyChangedListener listener)
165   {
166     if (changeNotifier == null)
167     {
168       changeNotifier = new ChangeNotifier();
169     }
170     changeNotifier.addListener(listener);
171   }
172
173   public void removeListener(INotifyChangedListener listener)
174   {
175     if (changeNotifier != null)
176     {
177       changeNotifier.removeListener(listener);
178     }
179   }
180
181   /**
182    * This convenience method converts the arguments into an appropriate update call on the viewer.
183    * The event type is a value from the static constants in {@link org.eclipse.emf.common.notify.Notifier}.
184    */

185   public void fireNotifyChanged(Notification notification)
186   {
187 /*
188     System.out.println("ItemProviderAdapterFactory.fireNotifyChanged");
189     System.out.println(" object = " + object);
190     System.out.println(" eventType = " + eventType);
191     if (oldValue instanceof Collection)
192     {
193       System.out.println(" oldValue = " + CommandParameter.collectionToString((Collection)oldValue));
194     }
195     else
196     {
197       System.out.println(" oldValue = " + oldValue);
198     }
199     if (newValue instanceof Collection)
200     {
201       System.out.println(" newValue = " + CommandParameter.collectionToString((Collection)newValue));
202     }
203     else
204     {
205       System.out.println(" newValue = " + newValue);
206     }
207 */

208
209     if (changeNotifier != null)
210     {
211       changeNotifier.fireNotifyChanged(notification);
212     }
213
214     if (adapterFactory instanceof IChangeNotifier)
215     {
216       IChangeNotifier changeNotifier = (IChangeNotifier)adapterFactory;
217       changeNotifier.fireNotifyChanged(notification);
218     }
219   }
220
221   /**
222    * This implements {@link IItemPropertySource#getEditableValue IItemPropertySource.getEditableValue}
223    * by simply returning the object itself.
224    */

225   public Object JavaDoc getEditableValue(Object JavaDoc object)
226   {
227     return object;
228   }
229
230   /**
231    * This implements {@link IItemPropertySource#getPropertyDescriptors IItemPropertySource.getPropertyDescriptors}
232    * by returning the locally stored vector of descriptors.
233    * This vector could be populated in the constructor of a derived class
234    * but it's probably more efficient to create them only on demand by overriding this method.
235    * You'll probably want to call super.getPropertyDescriptors if you do this,
236    * since you may have one adapter derive from another.
237    */

238   public List JavaDoc getPropertyDescriptors(Object JavaDoc object)
239   {
240     if (itemPropertyDescriptors == null)
241     {
242       itemPropertyDescriptors = new ArrayList JavaDoc();
243     }
244     return itemPropertyDescriptors;
245   }
246
247   /**
248    * This convenience method finds a particular descriptor given its property name.
249    */

250   public IItemPropertyDescriptor getPropertyDescriptor(Object JavaDoc object, Object JavaDoc propertyId)
251   {
252     for (Iterator JavaDoc i = getPropertyDescriptors(object).iterator(); i.hasNext(); )
253     {
254       IItemPropertyDescriptor itemPropertyDescriptor = (IItemPropertyDescriptor)i.next();
255       if (propertyId.equals(itemPropertyDescriptor.getId(object)))
256       {
257         return itemPropertyDescriptor;
258       }
259     }
260
261     return null;
262   }
263
264   /**
265    * This implements a PropertySource by delegating to the descriptor,
266    * which is assumed to support the IItemPropertyDescriptor interface
267    */

268   public Object JavaDoc getPropertyValue(Object JavaDoc object, String JavaDoc property)
269   {
270     return getPropertyDescriptor(object, property).getPropertyValue(object);
271   }
272
273   /**
274    * This implements PropertySource by delegating to the descriptor,
275    * which is assumed to support the IItemPropertyDescriptor interface
276    */

277   public boolean isPropertySet(Object JavaDoc object, String JavaDoc property)
278   {
279     return getPropertyDescriptor(object, property).isPropertySet(object);
280   }
281
282   /**
283    * This implements PropertySource.resetPropertyValue by delegating to the descriptor,
284    * which is assumed to support the IItemPropertyDescriptor interface
285    */

286   public void resetPropertyValue(Object JavaDoc object, String JavaDoc property)
287   {
288     getPropertyDescriptor(object, property).resetPropertyValue(object);
289   }
290
291   /**
292    * This implements PropertySource by delegating to the descriptor,
293    * which is assumed to support the IItemPropertyDescriptor interface
294    */

295   public void setPropertyValue(Object JavaDoc object, String JavaDoc property, Object JavaDoc value)
296   {
297     getPropertyDescriptor(object, property).setPropertyValue(object, value);
298   }
299   
300   /**
301    * This implements {@link IStructuredItemContentProvider#getElements IStructuredItemContentProvider.getElements}
302    * by forwarding the call to {@link #getChildren getChildren}.
303    * It seems that you almost always want getElements and getChildren to return the same thing, so this makes that easy.
304    */

305   public Collection JavaDoc getElements(Object JavaDoc object)
306   {
307     return getChildren(object);
308   }
309
310   /**
311    * This implements {@link ITreeItemContentProvider#getChildren ITreeItemContentProvider.getChildren}. If children are
312    * already cached in a {@link ChildrenStore}, they are returned. Otherwise, children are collected from the features
313    * returned by {@link #getChildrenFeatures getChildrenFeatures}. The collected children may or may not be cached,
314    * depending on the result of {@link #createChildrenStore createChildrenStore}; by default, no store is returned if
315    * {@link #getChildrenFeatures getChildrenFeatures} returns only containment references. All children are optionally
316    * {@link #wrap wrapped} before being cached and returned. Subclasses may override {@link #createWrapper
317    * createWrapper} to specify when and with what to wrap children.
318    */

319   public Collection JavaDoc getChildren(Object JavaDoc object)
320   {
321     ChildrenStore store = getChildrenStore(object);
322     if (store != null)
323     {
324       return store.getChildren();
325     }
326
327     store = createChildrenStore(object);
328     List JavaDoc result = store != null ? null : new ArrayList JavaDoc();
329     EObject eObject = (EObject)object;
330
331     for (Iterator JavaDoc i = getAnyChildrenFeatures(object).iterator(); i.hasNext();)
332     {
333       EStructuralFeature feature = (EStructuralFeature)i.next();
334       if (feature.isMany())
335       {
336         List JavaDoc children = (List JavaDoc)eObject.eGet(feature);
337         int index = 0;
338         for (Iterator JavaDoc ci = children.iterator(); ci.hasNext(); index++)
339         {
340           Object JavaDoc child = wrap(eObject, feature, ci.next(), index);
341           if (store != null)
342           {
343             store.getList(feature).add(child);
344           }
345           else
346           {
347             result.add(child);
348           }
349         }
350       }
351       else
352       {
353         Object JavaDoc child = eObject.eGet(feature);
354         if (child != null)
355         {
356           child = wrap(eObject, feature, child, CommandParameter.NO_INDEX);
357           if (store != null)
358           {
359             store.setValue(feature, child);
360           }
361           else
362           {
363             result.add(child);
364           }
365         }
366       }
367     }
368     return store != null ? store.getChildren() : result;
369   }
370         
371   /**
372    * This implements {@link ITreeItemContentProvider#hasChildren ITreeItemContentProvider.hasChildren}
373    * by simply testing whether {@link #getChildren getChildren} returns any children.
374    * This implementation will always be right, however, for efficiency you may want to override it to return false
375    * or to compute the result in some other efficient way.
376    */

377   public boolean hasChildren(Object JavaDoc object)
378   {
379     return !getChildren(object).isEmpty();
380   }
381
382   /**
383    * If this is defined to be something other than an empty list, it is used to implement {@link #getChildren
384    * getChildren}, including in determining whether to cache children and, if so, in setting up the store. It is also
385    * used to deduce the appropriate feature for an <code>AddCommand</code>, <code>RemoveCommand</code> or
386    * <code>MoveCommand</code> in {@link #createCommand createCommand}. If you override those methods, then you don't
387    * need to implement this.
388    */

389   protected Collection JavaDoc getChildrenFeatures(Object JavaDoc object)
390   {
391     if (childrenFeatures == null)
392     {
393       childrenFeatures = new ArrayList JavaDoc();
394     }
395     return childrenFeatures;
396   }
397
398   /**
399    * This returned the children references, but it has been replaced since attributes may now contribute children,
400    * too. If the replacement method is not overridden to return a non-empty list, this method will still be called to
401    * provide backwards compatibility.
402    * @deprecated As of EMF 2.0, replaced by {@link #getChildrenFeatures getChildrenFeatures}.
403    */

404   protected Collection JavaDoc getChildrenReferences(Object JavaDoc object)
405   {
406     if (childrenReferences == null)
407     {
408       childrenReferences = new ArrayList JavaDoc();
409     }
410     return childrenReferences;
411   }
412
413   /**
414    * This is a temporary way to get the structural features that contribute children. It first calls the new
415    * {link #getChildrenFeatues getChildrenFeatures} method and then, if the result is empty, tries the deprecated
416    * {@link #getChildrenReferences getChildrenReferences} method. It is used, instead of just the new method,
417    * throughout this class.
418    */

419   private Collection JavaDoc getAnyChildrenFeatures(Object JavaDoc object)
420   {
421     Collection JavaDoc result = getChildrenFeatures(object);
422     return result.isEmpty() ? getChildrenReferences(object) : result;
423   }
424
425   /**
426    * This method is called by {@link #factorRemoveCommand factorRemoveCommand} to retrieve the children objects of the
427    * features returned from {@link #getChildrenFeatures getChildrenFeatures}. For references, this default
428    * implementation calls the deprecated {@link #getReferenceValue getReferenceValue} to provide backwards
429    * compatibility.
430    */

431   protected Object JavaDoc getFeatureValue(EObject object, EStructuralFeature feature)
432   {
433     // Use an existing getReferenceValue() override.
434
//
435
if (feature instanceof EReference)
436     {
437       return getReferenceValue(object, (EReference)feature);
438     }
439
440     return object.eGet(feature);
441   }
442
443   /**
444    * This method returned the children objects of the given reference, but it has been replaced since attributes may
445    * now contribute children, too. The replacement method still calls this method for references, to provide backwards
446    * compatibility.
447    * @deprecated As of EMF 2.0, replaced by {@link #getFeatureValue getFeatureValue}.
448    */

449   protected Object JavaDoc getReferenceValue(EObject object, EReference reference)
450   {
451     return object.eGet(reference);
452   }
453
454   /**
455    * This returns the most appropriate feature of the object into which the given child could be added.
456    * This default implementation first calls the deprecated {@link #getChildReference getChildReference}, for backwards
457    * compatibility. If that does not yield a non-null result, it returns the first feature returned by {@link
458    * #getChildrenFeatures getChildrenFeatures} that has a type compatible with the child. You can override this to
459    * return a better result or to compute it more efficiently.
460    */

461   protected EStructuralFeature getChildFeature(Object JavaDoc object, Object JavaDoc child)
462   {
463     // First, try an existing implementation of getChildReference(). This provides backwards compatibility if that
464
// method, now deprecated, was overridden.
465
//
466
EStructuralFeature oldFeature = getChildReference(object, child);
467     if (oldFeature != null) return oldFeature;
468     
469     for (Iterator JavaDoc features = getAnyChildrenFeatures(object).iterator(); features.hasNext(); )
470     {
471       EStructuralFeature feature = (EStructuralFeature)features.next();
472       if (feature.getEType().isInstance(child))
473       {
474         return feature;
475       }
476     }
477     return null;
478   }
479
480   /**
481    * This returned the most appropriate reference for a given child, but has been replaced since attributes may now
482    * contribute children, too. The replacement first tries calling this method, for backwards compatibility.
483    * @deprecated As of EMF 2.0, replaced by {@link #getChildFeature getChildFeature}.
484    */

485   protected EReference getChildReference(Object JavaDoc object, Object JavaDoc child)
486   {
487     if (child instanceof EObject)
488     {
489       EObject eChild = (EObject)child;
490
491       // Iterate over all the child references to factor each child to the right reference.
492
//
493
for (Iterator JavaDoc childrenReferences = getChildrenReferences(object).iterator(); childrenReferences.hasNext(); )
494       {
495         EReference eReference = (EReference)childrenReferences.next();
496         EClassifier eType = eReference.getEType();
497
498         // If this object is compatible with this reference...
499
//
500
if (eType.isInstance(eChild))
501         {
502           return eReference;
503         }
504       }
505     }
506
507     return null;
508   }
509
510   /**
511    * If this is defined to be something other than an empty list, it is used to implement {@link #getSetFeature getSetFeature}
512    * and to deduce the EMF feature in the SetCommand {@link #createCommand createCommand}.
513    * If you override those, then you don't need to implement this.
514    */

515   protected Collection JavaDoc getSetFeatures(Object JavaDoc object)
516   {
517     return Collections.EMPTY_LIST;
518   }
519
520   /**
521    * This returns the most appropriate feature of the object into which the value be set.
522    * This default implementation returns the first feature returned by {@link #getSetFeatures getSetFeatures}
523    * that has a type compatible with the value.
524    * You can override this to return a better result or to compute it more efficiently.
525    */

526   protected EStructuralFeature getSetFeature(Object JavaDoc object, Object JavaDoc value)
527   {
528     // Iterate over all the set feature to factor each child to the right reference.
529
//
530
for (Iterator JavaDoc setFeatures = getSetFeatures(object).iterator(); setFeatures.hasNext(); )
531     {
532       EStructuralFeature eStructuralFeature = (EStructuralFeature)setFeatures.next();
533       EClassifier eType = eStructuralFeature.getEType();
534       if (eType.isInstance(value))
535       {
536         return eStructuralFeature;
537       }
538     }
539
540     return null;
541   }
542
543   /**
544    * This implements {@link ITreeItemContentProvider#getParent
545    * ITreeItemContentProvider.getParent} by returning the EMF object's
546    * container. This is used by certain commands to find an owner, where
547    * none is specified, and by the viewers, when trying to locate an
548    * arbitrary object within the view (i.e. during select and reveal
549    * operation).
550    */

551   public Object JavaDoc getParent(Object JavaDoc object)
552   {
553     EObject eObject = (EObject)object;
554     Object JavaDoc result = eObject.eContainer();
555     if (result == null)
556     {
557       result = eObject.eResource();
558     }
559     return result;
560   }
561
562   /**
563    * This implements {@link IItemLabelProvider#getImage IItemLabelProvider.getImage} by returning null.
564    * Most things really should have an icon, but not having one is technically correct too.
565    */

566   public Object JavaDoc getImage(Object JavaDoc object)
567   {
568     return null;
569   }
570
571   /**
572    * This implements {@link IItemLabelProvider#getText IItemLabelProvider.getText} by simply calling toString on the argument.
573    * This will often be correct as is.
574    */

575   public String JavaDoc getText(Object JavaDoc object)
576   {
577     return object.toString();
578   }
579
580   /**
581    * This implements {@link IUpdateableItemText#getUpdateableText IUpdateableItemText.getUpdateableText}
582    * by simply calling {@link #getText}.
583    * This will often be correct as is.
584    */

585   public String JavaDoc getUpdateableText(Object JavaDoc object)
586   {
587     return getText(object);
588   }
589
590   /**
591    * This implements {@link IEditingDomainItemProvider#getNewChildDescriptors
592    * IEditingDomainItemProvider.getNewChildDescriptors}, returning {@link
593    * org.eclipse.emf.edit.command.CommandParameter}s to describe all the possible children that can be added to the
594    * specified <code>object</code>.
595    *
596    * <p>This implementation invokes {@link #collectNewChildDescriptors collectNewChildDescriptors}, which should be
597    * overridden by derived classes, to build this collection.
598    *
599    * <p>If <code>sibling</code> is non-null, an <code>index</code> is added to each <code>CommandParameter</code> with
600    * a multi-valued <code>feature</code>, to ensure that the new child object gets added in the right position.
601    */

602   public Collection JavaDoc getNewChildDescriptors(Object JavaDoc object, EditingDomain editingDomain, Object JavaDoc sibling)
603   {
604     EObject eObject = (EObject)object;
605
606     // Build the collection of new child descriptors.
607
//
608
Collection JavaDoc newChildDescriptors = new ArrayList JavaDoc();
609     collectNewChildDescriptors(newChildDescriptors, object);
610
611     // If a sibling has been specified, add the best index possible to each CommandParameter.
612
//
613
if (sibling != null)
614     {
615       sibling = unwrap(sibling);
616
617       // Find the index of a feature containing the sibling, or an equivalent value, in the collection of children
618
// features.
619
//
620
Collection JavaDoc childrenFeatures = getAnyChildrenFeatures(object);
621       int siblingFeatureIndex = -1;
622       int i = 0;
623
624       FEATURES_LOOP:
625       for (Iterator JavaDoc features = childrenFeatures.iterator(); features.hasNext(); i++)
626       {
627         EStructuralFeature feature = (EStructuralFeature)features.next();
628         Object JavaDoc featureValue = eObject.eGet(feature);
629         if (feature.isMany())
630         {
631           for (Iterator JavaDoc values = ((Collection JavaDoc)featureValue).iterator(); values.hasNext(); )
632           {
633             Object JavaDoc value = values.next();
634             if (isEquivalentValue(sibling, value))
635             {
636               siblingFeatureIndex = i;
637               break FEATURES_LOOP;
638             }
639           }
640         }
641         else if (isEquivalentValue(sibling, featureValue))
642         {
643           siblingFeatureIndex = i;
644           break FEATURES_LOOP;
645         }
646       }
647
648       // For each CommandParameter with a non-null, multi-valued structural feature...
649
//
650
DESCRIPTORS_LOOP:
651       for (Iterator JavaDoc descriptors = newChildDescriptors.iterator(); descriptors.hasNext(); )
652       {
653         Object JavaDoc d = descriptors.next();
654         if (d instanceof CommandParameter)
655         {
656           CommandParameter parameter = (CommandParameter)d;
657           EStructuralFeature childFeature = parameter.getEStructuralFeature();
658           if (childFeature == null || !childFeature.isMany())
659           {
660             continue DESCRIPTORS_LOOP;
661           }
662
663           // Look for the sibling value or an equivalent in the new child's feature. If it is found, the child should
664
// immediately follow it.
665
//
666
i = 0;
667           for (Iterator JavaDoc values = ((Collection JavaDoc)eObject.eGet(childFeature)).iterator(); values.hasNext(); i++)
668           {
669             Object JavaDoc v = values.next();
670             if (isEquivalentValue(sibling, v))
671             {
672               parameter.index = i + 1;
673               continue DESCRIPTORS_LOOP;
674             }
675           }
676
677           // Otherwise, if a sibling feature was found, iterate through the children features to find the index of
678
// the child feature...
679
//
680
if (siblingFeatureIndex != -1)
681           {
682             i = 0;
683             for (Iterator JavaDoc features = childrenFeatures.iterator(); features.hasNext(); i++)
684             {
685               EStructuralFeature feature = (EStructuralFeature)features.next();
686             
687               if (feature == childFeature)
688               {
689                 // If the child feature follows the sibling feature, the child should be first in its feature.
690
//
691
if (i > siblingFeatureIndex)
692                 {
693                   parameter.index = 0;
694                 }
695                 continue DESCRIPTORS_LOOP;
696               }
697             }
698           }
699         }
700       }
701     }
702     return newChildDescriptors;
703   }
704
705   /**
706    * Returns whether the given value is to be considered equivalent to the given reference value.
707    * This is true if it is the reference value or if it is a feature map entry whose value is the reference value.
708    */

709   protected boolean isEquivalentValue(Object JavaDoc value, Object JavaDoc referenceValue)
710   {
711     if (value == referenceValue)
712     {
713       return true;
714     }
715       
716     if (value instanceof FeatureMap.Entry)
717     {
718       Object JavaDoc entryValue = ((FeatureMap.Entry)value).getValue();
719       if (entryValue == referenceValue)
720       {
721         return true;
722       }
723     }
724
725     return false;
726   }
727
728   /**
729    * This adds to <code>newChildDescriptors</code>, a collection of {@link
730    * org.eclipse.emf.edit.command.CommandParameter}s, parameters for
731    * possible children of the specified <code>object</code>, when viewed as
732    * an instance of the type for which this is an item provider. This
733    * implementation adds nothing to the collection, but derived classes
734    * should override this method, invoking the superclass implementation and
735    * then adding to the collection.
736    */

737   protected void collectNewChildDescriptors(Collection JavaDoc newChildDescriptors, Object JavaDoc object)
738   {
739     return;
740   }
741
742   /**
743    * This implements delegated command creation for the given object.
744    */

745   public Command createCommand(Object JavaDoc object, EditingDomain domain, Class JavaDoc commandClass, CommandParameter commandParameter)
746   {
747     // Commands should operate on the values, not their wrappers. If the command's values needed to be unwrapped,
748
// we'll back get a new CommandParameter.
749
//
750
CommandParameter oldCommandParameter = commandParameter;
751     commandParameter = unwrapCommandValues(commandParameter, commandClass);
752
753     Command result = UnexecutableCommand.INSTANCE;
754
755     if (commandClass == SetCommand.class)
756     {
757       result =
758         createSetCommand
759           (domain,
760            commandParameter.getEOwner(),
761            commandParameter.getEStructuralFeature() != null ?
762              commandParameter.getEStructuralFeature() :
763              getSetFeature(commandParameter.getEOwner(), commandParameter.getValue()),
764            commandParameter.getValue(),
765            commandParameter.getIndex());
766     }
767     else if (commandClass == CopyCommand.class)
768     {
769       result = createCopyCommand(domain, commandParameter.getEOwner(), (CopyCommand.Helper)commandParameter.getValue());
770     }
771     else if (commandClass == CreateCopyCommand.class)
772     {
773       result = createCreateCopyCommand(domain, commandParameter.getEOwner(), (CopyCommand.Helper)commandParameter.getValue());
774     }
775     else if (commandClass == InitializeCopyCommand.class)
776     {
777       result = createInitializeCopyCommand(domain, commandParameter.getEOwner(), (CopyCommand.Helper)commandParameter.getValue());
778     }
779     else if (commandClass == RemoveCommand.class)
780     {
781       if (commandParameter.getEStructuralFeature() != null)
782       {
783         result = createRemoveCommand(domain, commandParameter.getEOwner(), commandParameter.getEStructuralFeature(), commandParameter.getCollection());
784       }
785       else
786       {
787         result = factorRemoveCommand(domain, commandParameter);
788       }
789     }
790     else if (commandClass == AddCommand.class)
791     {
792       if (commandParameter.getEStructuralFeature() != null)
793       {
794         result =
795           createAddCommand
796             (domain,
797              commandParameter.getEOwner(),
798              commandParameter.getEStructuralFeature(),
799              commandParameter.getCollection(),
800              commandParameter.getIndex());
801       }
802       else
803       {
804         result = factorAddCommand(domain, commandParameter);
805       }
806     }
807     else if (commandClass == MoveCommand.class)
808     {
809       if (commandParameter.getEStructuralFeature() != null)
810       {
811         result =
812           createMoveCommand
813             (domain,
814              commandParameter.getEOwner(),
815              commandParameter.getEStructuralFeature(),
816              commandParameter.getEValue(),
817              commandParameter.getIndex());
818       }
819       else
820       {
821         result = factorMoveCommand(domain, commandParameter);
822       }
823     }
824     else if (commandClass == ReplaceCommand.class)
825     {
826       result =
827         createReplaceCommand
828           (domain, commandParameter.getEOwner(), commandParameter.getEStructuralFeature(), (EObject)commandParameter.getValue(), commandParameter.getCollection());
829     }
830     else if (commandClass == DragAndDropCommand.class)
831     {
832       DragAndDropCommand.Detail detail = (DragAndDropCommand.Detail)commandParameter.getFeature();
833       result =
834         createDragAndDropCommand
835           (domain, commandParameter.getOwner(), detail.location, detail.operations, detail.operation, commandParameter.getCollection());
836     }
837     else if (commandClass == CreateChildCommand.class)
838     {
839       CommandParameter newChildParameter = (CommandParameter)commandParameter.getValue();
840       result =
841         createCreateChildCommand
842           (domain,
843            commandParameter.getEOwner(),
844            newChildParameter.getEStructuralFeature(),
845            newChildParameter.getValue(),
846            newChildParameter.getIndex(),
847            commandParameter.getCollection());
848     }
849
850     // If necessary, get a command that replaces unwrapped values by their wrappers in the result and affected objects.
851
//
852
return wrapCommand(result, object, commandClass, commandParameter, oldCommandParameter);
853   }
854
855   /**
856    * This creates a primitive {@link org.eclipse.emf.edit.command.SetCommand}.
857    */

858   protected Command createSetCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Object JavaDoc value, int index)
859   {
860     if (index == CommandParameter.NO_INDEX)
861     {
862       return createSetCommand(domain, owner, feature, value);
863     }
864     return new SetCommand(domain, owner, feature, value, index);
865   }
866
867   /**
868    * This returned a primitive {@link org.eclipse.emf.edit.command.SetCommand}, but it has been replaced, since this
869    * command can now take an index. The replacement method still calls this method when invoked with {@link
870    * CommandParameter#NO_INDEX no index}, to provide backwards compatibility.
871    *
872    * <p>This method will soon be deprecated. New code should use or override the {@link
873    * #createSetCommand(EditingDomain, EObject, EStructuralFeature, Object, int) new form}, instead.
874    */

875   protected Command createSetCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Object JavaDoc value)
876   {
877     return new SetCommand(domain, owner, feature, value);
878   }
879
880   /**
881    * This creates a primitive {@link org.eclipse.emf.edit.command.CopyCommand}.
882    */

883   protected Command createCopyCommand(EditingDomain domain, EObject owner, CopyCommand.Helper helper)
884   {
885     return new CopyCommand(domain, owner, helper, domain.getOptimizeCopy());
886   }
887
888   /**
889    * This creates a primitive {@link org.eclipse.emf.edit.command.CreateCopyCommand}.
890    */

891   protected Comma