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 Command createCreateCopyCommand(EditingDomain domain, EObject owner, CopyCommand.Helper helper)
892   {
893     return new CreateCopyCommand(domain, owner, helper);
894   }
895
896   /**
897    * This creates a primitive {@link org.eclipse.emf.edit.command.InitializeCopyCommand}.
898    */

899   protected Command createInitializeCopyCommand(EditingDomain domain, EObject owner, CopyCommand.Helper helper)
900   {
901     return new InitializeCopyCommand(domain, owner, helper);
902   }
903
904   /**
905    * This creates a primitive {@link org.eclipse.emf.edit.command.RemoveCommand}.
906    */

907   protected Command createRemoveCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Collection JavaDoc collection)
908   {
909     if (feature instanceof EReference)
910     {
911       return createRemoveCommand(domain, owner, (EReference)feature, collection);
912     }
913     return new RemoveCommand(domain, owner, feature, collection);
914   }
915
916   /**
917    * This returned a primitive {@link org.eclipse.emf.edit.command.RemoveCommand}, but it has been replaced since
918    * this command is now used on attributes, too. The replacement method still calls this method for references, to
919    * provide backwards compatibility.
920    * @deprecated As of EMF 2.0, replaced by {@link #createRemoveCommand(EditingDomain, EObject, EStructuralFeature, Collection)
921    * createRemoveCommand}.
922    */

923   protected Command createRemoveCommand(EditingDomain domain, EObject owner, EReference feature, Collection JavaDoc collection)
924   {
925     return new RemoveCommand(domain, owner, feature, collection);
926   }
927
928   /**
929    * This creates a primitive {@link org.eclipse.emf.edit.command.ReplaceCommand}.
930    */

931   protected Command createReplaceCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, EObject value, Collection JavaDoc collection)
932   {
933     if (feature instanceof EReference)
934     {
935       return createReplaceCommand(domain, owner, (EReference)feature, value, collection);
936     }
937     return new ReplaceCommand(domain, owner, feature, value, collection);
938   }
939
940   /**
941    * This returned a primitive {@link org.eclipse.emf.edit.command.ReplaceCommand}, but it has been replaced since
942    * this command is now used on attributes, too. The replacement method still calls this method for references, to
943    * provide backwards compatibility.
944    * @deprecated As of EMF 2.0, replaced by {@link #createReplaceCommand(EditingDomain, EObject, EStructuralFeature, EObject, Collection)
945    * createReplaceCommand}.
946    */

947   protected Command createReplaceCommand(EditingDomain domain, EObject owner, EReference feature, EObject value, Collection JavaDoc collection)
948   {
949     return new ReplaceCommand(domain, owner, feature, value, collection);
950   }
951
952   /**
953    * This creates a primitive {@link org.eclipse.emf.edit.command.AddCommand}.
954    */

955   protected Command createAddCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Collection JavaDoc collection, int index)
956   {
957     if (feature instanceof EReference)
958     {
959       return createAddCommand(domain, owner, (EReference)feature, collection, index);
960     }
961     return new AddCommand(domain, owner, feature, collection, index);
962   }
963
964   /**
965    * This returned a primitive {@link org.eclipse.emf.edit.command.AddCommand}, but it has been replaced since
966    * this command is now used on attributes, too. The replacement method still calls this method for references, to
967    * provide backwards compatibility.
968    * @deprecated As of EMF 2.0, replaced by {@link #createAddCommand(EditingDomain, EObject, EStructuralFeature, Collection, int)
969    * createAddCommand}.
970    */

971   protected Command createAddCommand(EditingDomain domain, EObject owner, EReference feature, Collection JavaDoc collection, int index)
972   {
973     return new AddCommand(domain, owner, feature, collection, index);
974   }
975
976   /**
977    * This creates a primitive {@link org.eclipse.emf.edit.command.MoveCommand}.
978    */

979   protected Command createMoveCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Object JavaDoc value, int index)
980   {
981     if (feature instanceof EReference && value instanceof EObject)
982     {
983       return createMoveCommand(domain, owner, (EReference)feature, (EObject)value, index);
984     }
985     return new MoveCommand(domain, owner, feature, value, index);
986   }
987
988   /**
989    * This returned a primitive {@link org.eclipse.emf.edit.command.MoveCommand}, but it has been replaced since
990    * this command is now used on attributes, too. The replacement method still calls this method for references, to
991    * provide backwards compatibility.
992    * @deprecated As of EMF 2.0, replaced by {@link #createMoveCommand(EditingDomain, EObject, EStructuralFeature, Object, int)
993    * createMoveCommand}.
994    */

995   protected Command createMoveCommand(EditingDomain domain, EObject owner, EReference feature, EObject value, int index)
996   {
997     return new MoveCommand(domain, owner, feature, value, index);
998   }
999
1000  /**
1001   * This creates a primitive {@link org.eclipse.emf.edit.command.DragAndDropCommand}.
1002   */

1003  protected Command createDragAndDropCommand
1004    (EditingDomain domain, Object JavaDoc owner, float location, int operations, int operation, Collection JavaDoc collection)
1005  {
1006    return new DragAndDropCommand(domain, owner, location, operations, operation, collection);
1007  }
1008
1009  /**
1010   * This creates a primitive {@link org.eclipse.emf.edit.command.CreateChildCommand}.
1011   */

1012  protected Command createCreateChildCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Object JavaDoc value, int index, Collection JavaDoc collection)
1013  {
1014    if (feature instanceof EReference && value instanceof EObject)
1015    {
1016      return createCreateChildCommand(domain, owner, (EReference)feature, (EObject)value, index, collection);
1017    }
1018    return new CreateChildCommand(domain, owner, feature, value, index, collection, this);
1019  }
1020
1021  /**
1022   * This returned a primitive {@link org.eclipse.emf.edit.command.CreateChildCommand}, but it has been replaced since
1023   * this command is now used on attributes, too. The replacement method still calls this method for references, to
1024   * provide backwards compatibility.
1025   * @deprecated As of EMF 2.0, replaced by {@link #createCreateChildCommand(EditingDomain, EObject, EStructuralFeature, Object, int, Collection)
1026   * createCreateChildCommand}.
1027   */

1028  protected Command createCreateChildCommand(EditingDomain domain, EObject owner, EReference feature, EObject value, int index, Collection JavaDoc collection)
1029  {
1030    return new CreateChildCommand(domain, owner, feature, value, index, collection, this);
1031  }
1032
1033  /**
1034   * This method factors a {@link org.eclipse.emf.edit.command.RemoveCommand} for a collection of objects
1035   * into one or more primitive remove commands,
1036   * i.e., one per unique feature.
1037   */

1038  protected Command factorRemoveCommand(EditingDomain domain, CommandParameter commandParameter)
1039  {
1040    if (commandParameter.getCollection() == null || commandParameter.getCollection().isEmpty())
1041    {
1042      return UnexecutableCommand.INSTANCE;
1043    }
1044
1045    final EObject eObject = commandParameter.getEOwner();
1046    final List JavaDoc list = new ArrayList JavaDoc(commandParameter.getCollection());
1047
1048    CompoundCommand removeCommand = new CompoundCommand(CompoundCommand.MERGE_COMMAND_ALL);
1049      
1050    // Iterator over all the child references to factor each child to the right reference.
1051
//
1052
for (Iterator JavaDoc childrenFeatures = getAnyChildrenFeatures(eObject).iterator(); childrenFeatures.hasNext(); )
1053    {
1054      EStructuralFeature feature = (EStructuralFeature)childrenFeatures.next();
1055
1056      // If it is a list type value...
1057
//
1058
if (feature.isMany())
1059      {
1060        List JavaDoc value = (List JavaDoc)getFeatureValue(eObject, feature);
1061
1062        // These will be the children beloging to this feature.
1063
//
1064
Collection JavaDoc childrenOfThisFeature = new ArrayList JavaDoc();
1065        for (ListIterator JavaDoc objects = list.listIterator(); objects.hasNext(); )
1066        {
1067          Object JavaDoc o = objects.next();
1068
1069          // Is this object in this feature...
1070
//
1071
if (value.contains(o))
1072          {
1073            // Add it to the list and remove it from the other list.
1074
//
1075
childrenOfThisFeature.add(o);
1076            objects.remove();
1077          }
1078        }
1079
1080        // If we have children to remove for this feature, create a command for it.
1081
//
1082
if (!childrenOfThisFeature.isEmpty())
1083        {
1084          removeCommand.append(createRemoveCommand(domain, eObject, feature, childrenOfThisFeature));
1085        }
1086      }
1087      else
1088      {
1089        // It's just a single value
1090
//
1091
final Object JavaDoc value = getFeatureValue(eObject, feature);
1092        for (ListIterator JavaDoc objects = list.listIterator(); objects.hasNext(); )
1093        {
1094          Object JavaDoc o = objects.next();
1095
1096          // Is this object in this feature...
1097
//
1098
if (o == value)
1099          {
1100            // Create a command to set this to null and remove the object from the other list.
1101
//
1102
Command setCommand = createSetCommand(domain, eObject, feature, null);
1103            removeCommand.append
1104              (new CommandWrapper(setCommand)
1105               {
1106                 protected Collection JavaDoc affected;
1107
1108                 public void execute()
1109                 {
1110                   super.execute();
1111                   affected = Collections.singleton(eObject);
1112                 }
1113
1114                 public void undo()
1115                 {
1116                   super.undo();
1117                   affected = Collections.singleton(value);
1118                 }
1119
1120                 public void redo()
1121                 {
1122                   super.redo();
1123                   affected = Collections.singleton(eObject);
1124                 }
1125
1126                 public Collection JavaDoc getResult()
1127                 {
1128                   return Collections.singleton(value);
1129                 }
1130
1131                 public Collection JavaDoc getAffectedObjects()
1132                 {
1133                   return affected;
1134                 }
1135               });
1136            objects.remove();
1137            break;
1138          }
1139        }
1140      }
1141    }
1142
1143    // If all the objects are used up by the above, then we can't do the command.
1144
//
1145
if (list.isEmpty())
1146    {
1147      return removeCommand.unwrap();
1148    }
1149    else
1150    {
1151      removeCommand.dispose();
1152      return UnexecutableCommand.INSTANCE;
1153    }
1154  }
1155
1156  /**
1157   * This method factors an {@link org.eclipse.emf.edit.command.AddCommand} for a collection of objects
1158   * into one or more primitive add command,
1159   * i.e., one per unique feature.
1160   */

1161  protected Command factorAddCommand(EditingDomain domain, CommandParameter commandParameter)
1162  {
1163    if (commandParameter.getCollection() == null || commandParameter.getCollection().isEmpty())
1164    {
1165      return UnexecutableCommand.INSTANCE;
1166    }
1167
1168    final EObject eObject = commandParameter.getEOwner();
1169    final List JavaDoc list = new ArrayList JavaDoc(commandParameter.getCollection());
1170    int index = commandParameter.getIndex();
1171
1172    CompoundCommand addCommand = new CompoundCommand(CompoundCommand.MERGE_COMMAND_ALL);
1173      
1174    while (!list.isEmpty())
1175    {
1176      Iterator JavaDoc children = list.listIterator();
1177      final Object JavaDoc firstChild = children.next();
1178      EStructuralFeature childFeature = getChildFeature(eObject, firstChild);
1179
1180      if (childFeature == null)
1181      {
1182        break;
1183      }
1184      // If it is a list type value...
1185
//
1186
else if (childFeature.isMany())
1187      {
1188        // Correct the index, if necessary.
1189
//
1190
if (index != CommandParameter.NO_INDEX)
1191        {
1192          for (Iterator JavaDoc childrenFeatures = getAnyChildrenFeatures(eObject).iterator(); childrenFeatures.hasNext(); )
1193          {
1194            EStructuralFeature feature = (EStructuralFeature)childrenFeatures.next();
1195            if (feature == childFeature)
1196            {
1197              break;
1198            }
1199
1200            if (feature.isMany())
1201            {
1202              index -= ((List JavaDoc)(eObject).eGet(feature)).size();
1203            }
1204            else if (eObject.eGet(feature) != null)
1205            {
1206              index -= 1;
1207            }
1208          }
1209          if (index < 0)
1210          {
1211            break;
1212          }
1213        }
1214
1215        // These will be the children belonging to this feature.
1216
//
1217
Collection JavaDoc childrenOfThisFeature = new ArrayList JavaDoc();
1218        childrenOfThisFeature.add(firstChild);
1219        children.remove();
1220
1221        // Consume the rest of the appropriate children.
1222
//
1223
while (children.hasNext())
1224        {
1225          Object JavaDoc child = children.next();
1226          
1227          // Is this child in this feature...
1228
//
1229
if (getChildFeature(eObject, child) == childFeature)
1230          {
1231            // Add it to the list and remove it from the other list.
1232
//
1233
childrenOfThisFeature.add(child);
1234            children.remove();
1235          }
1236        }
1237
1238        // Create a command for this feature,
1239
//
1240
addCommand.append(createAddCommand(domain, eObject, childFeature, childrenOfThisFeature, index));
1241
1242        if (index >= childrenOfThisFeature.size())
1243        {
1244          index -= childrenOfThisFeature.size();
1245        }
1246        else
1247        {
1248          index = CommandParameter.NO_INDEX;
1249        }
1250      }
1251      else if (eObject.eGet(childFeature) == null)
1252      {
1253        Command setCommand = createSetCommand(domain, eObject, childFeature, firstChild);
1254        addCommand.append
1255          (new CommandWrapper(setCommand)
1256           {
1257             protected Collection JavaDoc affected;
1258
1259             public void execute()
1260             {
1261               super.execute();
1262               affected = Collections.singleton(firstChild);
1263             }
1264
1265             public void undo()
1266             {
1267               super.undo();
1268               affected = Collections.singleton(eObject);
1269             }
1270
1271             public void redo()
1272             {
1273               super.redo();
1274               affected = Collections.singleton(firstChild);
1275             }
1276
1277             public Collection JavaDoc getResult()
1278             {
1279               return Collections.singleton(firstChild);
1280             }
1281
1282             public Collection JavaDoc getAffectedObjects()
1283             {
1284               return affected;
1285             }
1286           });
1287        children.remove();
1288      }
1289      else
1290      {
1291        break;
1292      }
1293    }
1294
1295    // If all the objects aren't used up by the above, then we can't do the command.
1296
//
1297
if (list.isEmpty())
1298    {
1299      return addCommand.unwrap();
1300    }
1301    else
1302    {
1303      addCommand.dispose();
1304      return UnexecutableCommand.INSTANCE;
1305    }
1306  }
1307
1308  /**
1309   * This method factors a {@link org.eclipse.emf.edit.command.MoveCommand} to determine the feature.
1310   */

1311  protected Command factorMoveCommand(EditingDomain domain, CommandParameter commandParameter)
1312  {
1313    final EObject eObject = commandParameter.getEOwner();
1314    final Object JavaDoc value = commandParameter.getValue();
1315    int index = commandParameter.getIndex();
1316
1317    EStructuralFeature childFeature = getChildFeature(eObject, value);
1318
1319    if (childFeature != null && childFeature.isMany())
1320    {
1321      // Compute the relative index as best as possible.
1322
//
1323
for (Iterator JavaDoc i = getAnyChildrenFeatures(eObject).iterator(); i.hasNext(); )
1324      {
1325        EStructuralFeature feature = (EStructuralFeature)i.next();
1326        if (feature == childFeature)
1327        {
1328          break;
1329        }
1330
1331        if (feature.isMany())
1332        {
1333          index -= ((List JavaDoc)(eObject).eGet(feature)).size();
1334        }
1335        else if (eObject.eGet(feature) != null)
1336        {
1337          index -= 1;
1338        }
1339      }
1340
1341      // Create a command for this feature,
1342
//
1343
return createMoveCommand(domain, eObject, childFeature, value, index);
1344    }
1345    else
1346    {
1347      return UnexecutableCommand.INSTANCE;
1348    }
1349  }
1350
1351  public void setTarget(Notifier target)
1352  {
1353    // All this logic is so that we only create a list if the adapter is set to more than one target.
1354
//
1355
if (this.target != null)
1356    {
1357      if (this.target != target)
1358      {
1359        if (targets == null)
1360        {
1361          targets = new ArrayList JavaDoc();
1362        }
1363        targets.add(this.target);
1364        super.setTarget(target);
1365      }
1366    }
1367    else
1368    {
1369      super.setTarget(target);
1370    }
1371  }
1372
1373  public void unsetTarget(Notifier target)
1374  {
1375    if (target == this.target)
1376    {
1377      if (targets == null || targets.isEmpty())
1378      {
1379        super.setTarget(null);
1380      }
1381      else
1382      {
1383        super.setTarget((Notifier)targets.remove(targets.size() - 1));
1384      }
1385    }
1386    else if (targets != null)
1387    {
1388      targets.remove(target);
1389    }
1390  }
1391
1392  /**
1393   * This will remove this adapter from all its the targets and dispose any
1394   * remainging children wrappers in the children store.
1395   */

1396  public void dispose()
1397  {
1398    Notifier oldTarget = target;
1399    target = null;
1400
1401    List JavaDoc oldTargets = targets;
1402    targets = null;
1403
1404    if (oldTarget != null)
1405    {
1406      oldTarget.eAdapters().remove(this);
1407    }
1408
1409    if (oldTargets != null)
1410    {
1411      for (Iterator JavaDoc i = oldTargets.iterator(); i.hasNext(); )
1412      {
1413        Notifier otherTarget = (Notifier)i.next();
1414        otherTarget.eAdapters().remove(this);
1415      }
1416    }
1417
1418    // Dispose the child wrappers.
1419
//
1420
if (wrappers != null)
1421    {
1422      wrappers.dispose();
1423    }
1424  }
1425
1426  /**
1427   * This is a convenience method that creates a <code>CommandParameter</code>
1428   * for a given parent feature and child object.
1429   */

1430  protected CommandParameter createChildParameter(Object JavaDoc feature, Object JavaDoc child)
1431  {
1432    return new CommandParameter(null, feature, child);
1433  }
1434
1435  /**
1436   * This returns the result collection for {@link CreateChildCommand}.
1437   */

1438  public Collection JavaDoc getCreateChildResult(Object JavaDoc child)
1439  {
1440    return Collections.singletonList(child);
1441  }
1442
1443  /**
1444   * This returns the label for {@link CreateChildCommand}.
1445   */

1446  public String JavaDoc getCreateChildText(Object JavaDoc owner, Object JavaDoc feature, Object JavaDoc child, Collection JavaDoc selection)
1447  {
1448    if (feature instanceof EStructuralFeature && FeatureMapUtil.isFeatureMap((EStructuralFeature)feature))
1449    {
1450      FeatureMap.Entry entry = (FeatureMap.Entry)child;
1451      feature = entry.getEStructuralFeature();
1452      child = entry.getValue();
1453    }
1454
1455    String JavaDoc childType = feature instanceof EAttribute ? getTypeText((EAttribute)feature) : getTypeText(child);
1456
1457    // The try/catch provides backwards compatibility with the old resource
1458
// key, "_UI_CreateChild_label", and should be removed at the next
1459
// release, when we can expect users to do a regen.
1460
//
1461
try
1462    {
1463      return
1464        getResourceLocator().getString
1465          (feature instanceof EAttribute ? "_UI_CreateChild_text3" : "_UI_CreateChild_text",
1466           new Object JavaDoc[] { childType, getFeatureText(feature), getTypeText(owner) });
1467    }
1468    catch (MissingResourceException JavaDoc e)
1469    {
1470      return
1471        getResourceLocator().getString
1472          ("_UI_CreateChild_label",
1473           new Object JavaDoc[] { childType, getFeatureText(feature), getTypeText(owner) });
1474    }
1475  }
1476
1477  /**
1478   * This returns the description for {@link CreateChildCommand}.
1479   */

1480  public String JavaDoc getCreateChildDescription(Object JavaDoc owner, Object JavaDoc feature, Object JavaDoc child, Collection JavaDoc selection)
1481  {
1482    if (feature instanceof EStructuralFeature && FeatureMapUtil.isFeatureMap((EStructuralFeature)feature))
1483    {
1484      FeatureMap.Entry entry = (FeatureMap.Entry)child;
1485      feature = entry.getEStructuralFeature();
1486      child = entry.getValue();
1487    }
1488
1489    String JavaDoc childType = feature instanceof EAttribute ? getTypeText((EAttribute)feature) : getTypeText(child);
1490    Object JavaDoc selectionObject = selection == null || selection.isEmpty() ? null : selection.iterator().next();
1491
1492    if (selectionObject == owner)
1493    {
1494      return
1495        getResourceLocator().getString
1496          ("_UI_CreateChild_description",
1497           new Object JavaDoc[] { childType, getFeatureText(feature), getTypeText(owner) });
1498    }
1499
1500    Object JavaDoc sibling = selectionObject;
1501    Object JavaDoc siblingFeature = getChildFeature(owner, sibling);
1502
1503    if (siblingFeature instanceof EStructuralFeature && FeatureMapUtil.isFeatureMap((EStructuralFeature)siblingFeature))
1504    {
1505      FeatureMap.Entry entry = (FeatureMap.Entry)sibling;
1506      siblingFeature = entry.getEStructuralFeature();
1507      sibling = entry.getValue();
1508    }
1509
1510    String JavaDoc siblingType = siblingFeature instanceof EAttribute ? getTypeText((EAttribute)siblingFeature) : getTypeText(sibling);
1511    return
1512      getResourceLocator().getString
1513        ("_UI_CreateSibling_description",
1514         new Object JavaDoc[] { childType, getFeatureText(feature), siblingType });
1515  }
1516
1517  /**
1518   * This returns the tool tip text for {@link CreateChildCommand}.
1519   */

1520  public String JavaDoc getCreateChildToolTipText(Object JavaDoc owner, Object JavaDoc feature, Object JavaDoc child, Collection JavaDoc selection)
1521  {
1522    if (feature instanceof EStructuralFeature && FeatureMapUtil.isFeatureMap((EStructuralFeature)feature))
1523    {
1524      FeatureMap.Entry entry = (FeatureMap.Entry)child;
1525      feature = entry.getEStructuralFeature();
1526      child = entry.getValue();
1527    }
1528
1529    String JavaDoc childType = feature instanceof EAttribute ? getTypeText((EAttribute)feature) : getTypeText(child);
1530    return
1531      getResourceLocator().getString
1532        ("_UI_CreateChild_tooltip",
1533         new Object JavaDoc[] {childType , getFeatureText(feature), getTypeText(owner) });
1534  }
1535
1536  /**
1537   * This returns the icon image for {@link org.eclipse.emf.edit.command.CreateChildCommand}.
1538   */

1539  public Object JavaDoc getCreateChildImage(Object JavaDoc owner, Object JavaDoc feature, Object JavaDoc child, Collection JavaDoc selection)
1540  {
1541    if (feature instanceof EStructuralFeature && FeatureMapUtil.isFeatureMap((EStructuralFeature)feature))
1542    {
1543      FeatureMap.Entry entry = (FeatureMap.Entry)child;
1544      feature = entry.getEStructuralFeature();
1545      child = entry.getValue();
1546    }
1547
1548    if (feature instanceof EReference) //EStructuralFeature)
1549
{
1550      EStructuralFeature eFeature = (EStructuralFeature)feature;
1551      String JavaDoc name = "full/ctool16/Create" + eFeature.getEContainingClass().getName() + "_" + eFeature.getName();
1552
1553      if (child instanceof EObject)
1554      {
1555        name += "_" + ((EObject)child).eClass().getName();
1556      }
1557
1558      try
1559      {
1560        return getResourceLocator().getImage(name);
1561      }
1562      catch (Exception JavaDoc e)
1563      {
1564        System.out.println(name);
1565      }
1566    }
1567
1568    return EMFEditPlugin.INSTANCE.getImage("full/ctool16/CreateChild");
1569  }
1570
1571  /**
1572   * This looks up the name of the type of the specified object.
1573   */

1574  protected String JavaDoc getTypeText(Object JavaDoc object)
1575  {
1576    if (object instanceof EObject)
1577    {
1578      String JavaDoc typeKey = ((EObject)object).eClass().getName();
1579      try
1580      {
1581        return getResourceLocator(object).getString("_UI_" + typeKey + "_type");
1582      }
1583      catch (MissingResourceException JavaDoc e)
1584      {
1585        return typeKey;
1586      }
1587    }
1588    return getString("_UI_Unknown_type");
1589  }
1590
1591  /**
1592   * This looks up the name of the type of the specified attribute.
1593   */

1594  protected String JavaDoc getTypeText(EAttribute attribute)
1595  {
1596    String JavaDoc typeKey = attribute.getEAttributeType().getName();
1597    try
1598    {
1599      return getString("_UI_" + typeKey + "_datatype");
1600    }
1601    catch (MissingResourceException JavaDoc e)
1602    {
1603    }
1604    return getString("_UI_Unknown_datatype");
1605  }
1606
1607  /**
1608   * This looks up the name of the specified feature.
1609   */

1610  protected String JavaDoc getFeatureText(Object JavaDoc feature)
1611  {
1612    String JavaDoc featureKey;
1613    if (feature instanceof EStructuralFeature)
1614    {
1615      EStructuralFeature eFeature = (EStructuralFeature)feature;
1616      featureKey = eFeature.getEContainingClass().getName() + "_" + eFeature.getName();
1617    }
1618    else
1619    {
1620      featureKey = "Unknown";
1621    }
1622    return getResourceLocator().getString("_UI_" + featureKey + "_feature");
1623  }
1624
1625  /**
1626   * Get the resource locator for this adapter's resources.
1627   */

1628  protected ResourceLocator getResourceLocator()
1629  {
1630    return EMFEditPlugin.INSTANCE;
1631  }
1632
1633  /**
1634   * Get the resource locator from the adapter of the object, if possible.
1635   * it can be any object,
1636   * i.e., it may not the type object for which this adapter is applicable.
1637   */

1638  protected ResourceLocator getResourceLocator(Object JavaDoc anyObject)
1639  {
1640    if (adapterFactory instanceof ComposeableAdapterFactory)
1641    {
1642      Object JavaDoc adapter = ((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory().adapt(anyObject, IItemLabelProvider.class);
1643      if (adapter instanceof ResourceLocator)
1644      {
1645        return (ResourceLocator)adapter;
1646      }
1647    }
1648
1649    return getResourceLocator();
1650  }
1651
1652  /**
1653   * Gets the root factory if this local adapter factory is composed,
1654   * otherwise just the local one.
1655   */

1656  protected AdapterFactory getRootAdapterFactory()
1657  {
1658    if (adapterFactory instanceof ComposeableAdapterFactory)
1659    {
1660      return ((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory();
1661    }
1662
1663    return adapterFactory;
1664  }
1665
1666  /**
1667   * Get the base URL from the resource locator.
1668   */

1669  public URL JavaDoc getBaseURL()
1670  {
1671    return getResourceLocator().getBaseURL();
1672  }
1673
1674  /**
1675   * Get an image from the resource locator.
1676   */

1677  public Object JavaDoc getImage(String JavaDoc key)
1678  {
1679    return getResourceLocator().getImage(key);
1680  }
1681
1682  /**
1683   * Indicates whether strings should be translated by default.
1684   *
1685   * @return <code>true</code> if strings should be translated by default; <code>false</code> otherwise.
1686   */

1687  protected boolean shouldTranslate()
1688  {
1689    return true;
1690  }
1691
1692  /**
1693   * Get a translated string from the resource locator.
1694   */

1695  public String JavaDoc getString(String JavaDoc key)
1696  {
1697    return getString(key, shouldTranslate());
1698  }
1699  
1700  /**
1701   * Get a translated string from the resource locator.
1702   */

1703  public String JavaDoc getString(String JavaDoc key, boolean translate)
1704  {
1705    return getResourceLocator().getString(key, translate);
1706  }
1707
1708  /**
1709   * Get a translated string from the resource locator, with substitutions.
1710   */

1711  public String JavaDoc getString(String JavaDoc key, Object JavaDoc [] substitutions)
1712  {
1713    return getString(key, substitutions, shouldTranslate());
1714  }
1715  
1716  /**
1717   * Get a translated string from the resource locator, with substitutions.
1718   */

1719  public String JavaDoc getString(String JavaDoc key, Object JavaDoc [] substitutions, boolean translate)
1720  {
1721    return getResourceLocator().getString(key, substitutions, translate);
1722  }
1723
1724  /**
1725   * Get a translated string from the resource locator, substituting another
1726   * such translated string.
1727   */

1728  protected String JavaDoc getString(String JavaDoc key, String JavaDoc s0)
1729  {
1730    return getString(key, s0, shouldTranslate());
1731  }
1732  
1733  /**
1734   * Get a translated string from the resource locator, substituting another
1735   * such translated string.
1736   */

1737  protected String JavaDoc getString(String JavaDoc key, String JavaDoc s0, boolean translate)
1738  {
1739    ResourceLocator resourceLocator = getResourceLocator();
1740    return resourceLocator.getString(key, new Object JavaDoc[] { resourceLocator.getString(s0, translate) }, translate);
1741  }
1742
1743  /**
1744   * Get a translated string from the resource locator, substituting two
1745   * other such translated strings.
1746   */

1747  protected String JavaDoc getString(String JavaDoc key, String JavaDoc s0, String JavaDoc s1)
1748  {
1749    return getString(key, s0, s1, shouldTranslate());
1750  }
1751  
1752  /**
1753   * Get a translated string from the resource locator, substituting two
1754   * other such translated strings.
1755   */

1756  protected String JavaDoc getString(String JavaDoc key, String JavaDoc s0, String JavaDoc s1, boolean translate)
1757  {
1758    ResourceLocator resourceLocator = getResourceLocator();
1759    return resourceLocator.getString(key, new Object JavaDoc[] { resourceLocator.getString(s0, translate), resourceLocator.getString(s1, translate) }, translate);
1760  }
1761
1762  /**
1763   * Returns whether this item provider may need to use wrappers for some or all of the values it returns as {@link
1764   * #getChildren children}. This is used to determine whether to use a store to keep track of children and whether to
1765   * use command wrappers that re-wrap results and affected objects. The default implementation of {@link
1766   * #createWrapper createWrapper} also tests this method and will not create any wrappers if it returns
1767   * <code>false</code>.
1768   *
1769   * <p>This implementation consults {@link #getChildrenFeatures getChildrenFeatures}, returning true if any feature
1770   * map or simple attributes contribute children. This provides backwards compatibility with pre-2.0 subclasses
1771   * and enables the more useful new default behaviour for attributes, which were previously not allowed. Subclasses
1772   * may override this to enable wrapping of cross-referenced model objects, or to immediately return <code>true</code>
1773   * or <code>false</code>, as desired. This is a convenient way to disable all of the new wrapping features in 2.0.
1774   */

1775  protected boolean isWrappingNeeded(Object JavaDoc object)
1776  {
1777    if (wrappingNeeded == null)
1778    {
1779      wrappingNeeded = Boolean.FALSE;
1780      
1781      for (Iterator JavaDoc i = getAnyChildrenFeatures(object).iterator(); i.hasNext(); )
1782      {
1783        EStructuralFeature f = (EStructuralFeature)i.next();
1784        if (f instanceof EAttribute)
1785        {
1786          wrappingNeeded = Boolean.TRUE;
1787        }
1788      }
1789    }
1790    return wrappingNeeded.booleanValue();
1791  }
1792
1793  /**
1794   * Returns the store for the children of the given object, or null if no such store is being maintained.
1795   */

1796  protected ChildrenStore getChildrenStore(Object JavaDoc object)
1797  {
1798    return childrenStoreMap == null ? null : (ChildrenStore)childrenStoreMap.get(object);
1799  }
1800
1801  /**
1802   * Consults {@link #isWrappingNeeded isWrappingNeeded} to decide whether to create a store for the children of the
1803   * given object. If so, the new store is created, added to the collection being maintained, and returned. If not,
1804   * null is returned.
1805   */

1806  protected ChildrenStore createChildrenStore(Object JavaDoc object)
1807  {
1808    ChildrenStore store = null;
1809
1810    if (isWrappingNeeded(object))
1811    {
1812      if (childrenStoreMap == null)
1813      {
1814        childrenStoreMap = new HashMap JavaDoc();
1815      }
1816      store = new ChildrenStore(getAnyChildrenFeatures(object));
1817      childrenStoreMap.put(object, store);
1818    }
1819    return store;
1820  }
1821
1822  /**
1823   * A <code>ChildrenStore</code> stores a number of objects that are to be presented as the children of an object.
1824   * Each of a set of {@link org.eclipse.emf.ecore.EStructuralFeature feature}s may have either one or any number
1825   * of children objects associated with it, depending on its multiplicity. The objects associated with a
1826   * multiplicity-many feature are accessed and manipulated as an {@link org.eclipse.emf.common.util.EList},
1827   * typically mirroring the actual values of that feature, with some or all in wrappers, as necessary. The object
1828   * associated with a multiplicity-1 feature is typically accessed and set directly, although a modifiable, singleton
1829   * list view is available. This class provides a number of convenient methods for access by feature, as well as
1830   * a method, {@link #getChildren getChildren} that returns the complete collection of children from all features as
1831   * an unmodifiable list.
1832   */

1833  protected static class ChildrenStore
1834  {
1835    /**
1836     * An <code>Entry</code> represents the children from a feature.
1837     */

1838    protected static class Entry
1839    {
1840      public EStructuralFeature feature;
1841      public EList list;
1842
1843      public Entry(EStructuralFeature feature)
1844      {
1845        this.feature = feature;
1846      }
1847    }
1848
1849    protected Entry[] entries;
1850
1851    /**
1852     * Creates a store for the children of the given features.
1853     */

1854    public ChildrenStore(Collection JavaDoc features)
1855    {
1856      entries = new Entry[features.size()];
1857      int i = 0;
1858      for (Iterator JavaDoc iter = features.iterator(); iter.hasNext(); )
1859      {
1860        entries[i++] = new Entry((EStructuralFeature)iter.next());
1861      }
1862    }
1863
1864    protected Entry getEntry(EStructuralFeature feature)
1865    {
1866      for (int i = 0; i < entries.length; i++)
1867      {
1868        if (entries[i].feature == feature) return entries[i];
1869      }
1870      return null;
1871    }
1872
1873    /**
1874     * Returns a list, either a full list implementation or a fixed-sized modifiable singleton list, depending
1875     * on the multiplicity of the feature. Before accessing an entry's list, the store should always check if it is
1876     * null and if so, allocate it using this method.
1877     */

1878    protected EList createList(EStructuralFeature feature)
1879    {
1880      return feature.isMany() ?
1881        (EList)(new BasicEList()) :
1882        (EList)(new ModifiableSingletonEList());
1883    }
1884
1885    /**
1886     * Returns whether the store handles children of the specified feature.
1887     */

1888    public boolean contains(EStructuralFeature feature)
1889    {
1890      return getEntry(feature) != null;
1891    }
1892
1893    /**
1894     * Returns the list view of the specified feature, or null if the store does not handle the feature.
1895     */

1896    public EList getList(EStructuralFeature feature)
1897    {
1898      Entry entry = getEntry(feature);
1899      if (entry == null) return null;
1900
1901      if (entry.list == null)
1902      {
1903        entry.list = createList(feature);
1904      }
1905      return entry.list;
1906    }
1907
1908    /**
1909     * Returns the value view of the specified feature. For a single-valued feature, this is the value itself, which
1910     * may be null. For a multi-valued feature, it is just the whole list.
1911     */

1912    public Object JavaDoc getValue(EStructuralFeature feature)
1913    {
1914      Entry entry = getEntry(feature);
1915      if (entry == null) return null;
1916      Object JavaDoc result = null;
1917
1918      if (feature.isMany())
1919      {
1920        if (entry.list == null)
1921        {
1922          entry.list = createList(feature);
1923        }
1924        result = entry.list;
1925      }
1926      else if (entry.list != null)
1927      {
1928        result = entry.list.get(0);
1929      }
1930      return result;
1931    }
1932
1933    /**
1934     * Sets the value of the specified feature. For a multi-valued feature, the specified value is treated as a
1935     * {@link java.util.Collection}, and all of its elements are added to the emptied list.
1936     */

1937    public boolean setValue(EStructuralFeature feature, Object JavaDoc value)
1938    {
1939      Entry entry = getEntry(feature);
1940      if (entry == null) return false;
1941
1942      if (entry.list == null && value != null)
1943      {
1944        entry.list = createList(feature);
1945      }
1946
1947      if (entry.list != null)
1948      {
1949        if (feature.isMany())
1950        {
1951          entry.list.clear();
1952          if (value != null) entry.list.addAll((Collection JavaDoc)value);
1953        }
1954        else
1955        {
1956          entry.list.set(0, value);
1957        }
1958      }
1959      return true;
1960    }
1961
1962    /**
1963     * Returns either a single element of the specified feature or, if index is -1, the value view.
1964     */

1965    public Object JavaDoc get(EStructuralFeature feature, int index)
1966    {
1967      if (index == -1) return getValue(feature);
1968      EList list = getList(feature);
1969      return list != null ? list.get(index) : null;
1970    }
1971
1972    /**
1973     * Sets either a single element of the specified feature or, if the index is -1, the value of the feature.
1974     */

1975    public boolean set(EStructuralFeature feature, int index, Object JavaDoc object)
1976    {
1977      if (index == -1) return setValue(feature, object);
1978      EList list = getList(feature);
1979
1980      if (list != null)
1981      {
1982        list.set(index, object);
1983        return true;
1984      }
1985      return false;
1986    }
1987
1988    /**
1989     * Returns a list containing all children of all features in the store. Null, single-valued features are excluded.
1990     * The list can be freely modified without affecting the store.
1991     */

1992    public List JavaDoc getChildren()
1993    {
1994      int size = 0;
1995      for (int i = 0; i < entries.length; i++)
1996      {
1997        if (entries[i].list != null)
1998        {
1999          size += entries[i].feature.isMany() ?
2000            entries[i].list.size() :
2001            entries[i].list.get(0) != null ? 1 : 0;
2002        }
2003      }
2004      List JavaDoc result = new ArrayList JavaDoc(size);
2005      for (int i = 0; i < entries.length; i++)
2006      {
2007        if (entries[i].list != null)
2008        {
2009          if (entries[i].feature.isMany())
2010          {
2011            result.addAll(entries[i].list);
2012          }
2013          else if (entries[i].list.get(0) != null)
2014          {
2015            result.add(entries[i].list.get(0));
2016          }
2017        }
2018      }
2019      return result;
2020    }
2021
2022    /**
2023     * Returns the offset in the list returned by {@link #getChildren getChildren} of given feature's children.
2024     */

2025    public int getOffset(EStructuralFeature feature)
2026    {
2027      for (int i = 0, offset = 0; i < entries.length; i++)
2028      {
2029        if (entries[i].feature == feature) return offset;
2030        if (entries[i].list != null)
2031        {
2032          offset += entries[i].feature.isMany() ?
2033            entries[i].list.size() :
2034            entries[i].list.get(0) != null ? 1 : 0;
2035        }
2036      }
2037      return -1;
2038    }
2039
2040    /**
2041     * Clears the children of all features in the store. Multi-valued features are cleared, and single-valued features
2042     * are set to null.
2043     */

2044    public void clear()
2045    {
2046      for (int i = 0; i < entries.length; i++)
2047      {
2048        if (entries[i].list != null)
2049        {
2050          if (entries[i].feature.isMany())
2051          {
2052            entries[i].list.clear();
2053          }
2054          else
2055          {
2056            entries[i].list.set(0, null);
2057          }
2058        }
2059      }
2060    }
2061  }
2062
2063  /**
2064   * A single-element implementation of {@link org.eclipse.emf.common.util.EList}. The element can be modified, but
2065   * the size of the list may not be changed.
2066   */

2067  protected static class ModifiableSingletonEList extends AbstractList JavaDoc
2068  implements EList
2069  {
2070    private Object JavaDoc singleElement;
2071
2072    ModifiableSingletonEList()
2073    {
2074      singleElement = null;
2075    }
2076
2077    ModifiableSingletonEList(Object JavaDoc element)
2078    {
2079      singleElement = element;
2080    }
2081
2082    public int size()
2083    {
2084      return 1;
2085    }
2086
2087    public Object JavaDoc get(int index)
2088    {
2089      if (index != 0)
2090      {
2091        throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=1");
2092      }
2093      return singleElement;
2094    }
2095
2096    public Object JavaDoc set(int index, Object JavaDoc element)
2097    {
2098      if (index != 0)
2099      {
2100        throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=1");
2101      }
2102      Object JavaDoc oldElement = singleElement;
2103      singleElement = element;
2104      return oldElement;
2105    }
2106
2107    public boolean contains(Object JavaDoc o)
2108    {
2109      return o == null ? singleElement == null : o.equals(singleElement);
2110    }
2111
2112    public void move(int index, Object JavaDoc o)
2113    {
2114      if (index != 0 || !contains(o))
2115      {
2116        throw new IndexOutOfBoundsException JavaDoc("index=" + index + ", size=1");
2117      }
2118    }
2119
2120    public Object JavaDoc move(int targetIndex, int sourceIndex)
2121    {
2122      if (targetIndex != 0)
2123      {
2124        throw new IndexOutOfBoundsException JavaDoc("targetIndex=" + targetIndex + ", size=1");
2125      }
2126      if (sourceIndex != 0)
2127      {
2128        throw new IndexOutOfBoundsException JavaDoc("sourceIndex=" + sourceIndex + ", size=1");
2129      }
2130      return singleElement;
2131    }
2132  }
2133
2134  /**
2135   * Wraps a value, if needed, and keeps the wrapper for disposal along with the item provider. This method actually
2136   * calls {@link #createWrapper createWrapper} to determine if the given value, at the given index in the given
2137   * feature of the given object, should be wrapped and to obtain the wrapper. If a wrapper is obtained, it is recorded
2138   * and returned. Otherwise, the orginal value is returned. Subclasses may override {@link #createWrapper
2139   * createWrapper} to specify when and with what to wrap values.
2140   */

2141  protected Object JavaDoc wrap(EObject object, EStructuralFeature feature, Object JavaDoc value, int index)
2142  {
2143    if (!feature.isMany() && index != CommandParameter.NO_INDEX)
2144    {
2145      System.out.println("Bad wrap index.");
2146      System.out.println(" object: " + object);
2147      System.out.println(" feature: " + feature);
2148      System.out.println(" value: " + value);
2149      System.out.println(" index: " + index);
2150      (new IllegalArgumentException JavaDoc("Bad wrap index.")).printStackTrace();
2151    }
2152
2153    Object JavaDoc wrapper = createWrapper(object, feature, value, index);
2154    if (wrapper == null)
2155    {
2156      wrapper = value;
2157    }
2158    else if (wrapper != value)
2159    {
2160      if (wrappers == null)
2161      {
2162        wrappers = new Disposable();
2163      }
2164      wrappers.add(wrapper);
2165    }
2166    return wrapper;
2167  }
2168
2169  /**
2170   * Creates and returns a wrapper for the given value, at the given index in the given feature of the given object
2171   * if such a wrapper is needed; otherwise, returns the original value. This implementation consults {@link
2172   * #isWrappingNeeded isWrappingNeeded} and, if it is <code>true</code>, creates different wrappers that implement
2173   * {@link IWrapperItemProvider} for feature maps, simple attributes, and cross references.
2174   *
2175   * By default, {@link #isWrappingNeeded isWrappingNeeded} does not return <code>true</code> unless there is at
2176   * least one feature map or simple attribute that contributes children, in order to maintain backwards compatibility.
2177   * As a result, it may be necessary to override that method in order to wrap cross-referenced model objects here.
2178   * Subclasses may also override this method, in order to create their own specialized wrappers.
2179   */

2180  protected Object JavaDoc createWrapper(EObject object, EStructuralFeature feature, Object JavaDoc value, int index)
2181  {
2182    if (!isWrappingNeeded(object)) return value;
2183
2184    if (FeatureMapUtil.isFeatureMap(feature))
2185    {
2186      value = new FeatureMapEntryWrapperItemProvider((FeatureMap.Entry)value, object, (EAttribute)feature, index, adapterFactory, getResourceLocator());
2187    }
2188    else if (feature instanceof EAttribute)
2189    {
2190      value = new AttributeValueWrapperItemProvider(value, object, (EAttribute)feature, index, adapterFactory, getResourceLocator());
2191    }
2192    else if (!((EReference)feature).isContainment())
2193    {
2194      value = new DelegatingWrapperItemProvider(value, object, feature, index, adapterFactory);
2195    }
2196
2197    return value;
2198  }
2199
2200  /**
2201   * If the given object implements {@link IWrapperItemProvider}, it is unwrapped by obtaining a value from {@link
2202   * IWrapperItemProvider#getValue getValue}. The unwrapping continues until a non-wrapper value is returned. This
2203   * iterative unwrapping is required because values may be repeatedly wrapped, as children of a delegating wrapper.
2204   */

2205  protected Object JavaDoc unwrap(Object JavaDoc object)
2206  {
2207    while (object instanceof IWrapperItemProvider)
2208    {
2209      object = ((IWrapperItemProvider)object).getValue();
2210    }
2211    return object;
2212  }
2213
2214  /**
2215   * If the given object implements {@link IWrapperItemProvider}, it is disposed by calling {@link
2216   * IWrapperItemProvider#dispose dispose}. It is also removed from {@link #wrappers}, as it will longer need to be
2217   * disposed along with this item provider.
2218   */

2219  protected void disposeWrapper(Object JavaDoc object)
2220  {
2221    if (object instanceof IWrapperItemProvider)
2222    {
2223      ((IWrapperItemProvider)object).dispose();
2224      if (wrappers != null)
2225      {
2226        wrappers.remove(object);
2227      }
2228    }
2229  }
2230
2231  /**
2232   * Each element of the given list that implements {@link IWrapperItemProvider} is disposed by calling
2233   * IWrapperItemProvider#dispose dispose} and is removed from {@link #wrappers}.
2234   */

2235  protected void disposeWrappers(List JavaDoc objects)
2236  {
2237    for (Iterator JavaDoc i = objects.iterator(); i.hasNext(); )
2238    {
2239      disposeWrapper(i.next());
2240    }
2241  }
2242
2243  /**
2244   * If the given object implements {@link IWrapperItemProvider} and specifies an index, that index is adjusted by the
2245   * given increment.
2246   */

2247  protected void adjustWrapperIndex(Object JavaDoc object, int increment)
2248  {
2249    if (object instanceof IWrapperItemProvider)
2250    {
2251      IWrapperItemProvider wrapper = (IWrapperItemProvider)object;
2252      int index = wrapper.getIndex();
2253
2254      if (index != CommandParameter.NO_INDEX)
2255      {
2256        wrapper.setIndex(index + increment);
2257      }
2258    }
2259  }
2260
2261  /**
2262   * For each element of the given list, starting at <code>from</code>, that implements {@link IWrapperItemProvider}
2263   * and specifies an index, that index is adjusted by the given increment.
2264   */

2265  protected void adjustWrapperIndices(List JavaDoc objects, int from, int increment)
2266  {
2267    for (Iterator JavaDoc i = objects.listIterator(from); i.hasNext(); )
2268    {
2269      adjustWrapperIndex(i.next(), increment);
2270    }
2271  }
2272
2273  /**
2274   * For each element of the given list, between <code>from</code> and <code>to</code>, that implements {@link
2275   * IWrapperItemProvider} and specifies an index, that index is adjusted by the given increment.
2276   */

2277  protected void adjustWrapperIndices(List JavaDoc objects, int from, int to, int increment)
2278  {
2279    for (Iterator JavaDoc i = objects.listIterator(from); from < to && i.hasNext(); from++)
2280    {
2281      adjustWrapperIndex(i.next(), increment);
2282    }
2283  }
2284
2285  /**
2286   * Updates any cached children based on the given notification. If a {@link ChildrenStore} exists for its notifier,
2287   * then the children of the specified feature are updated.
2288   *
2289   * <p>Existing children in the store that correspond to any set, removed or unset values are {@link
2290   * #disposeWrapper disposed} before being removed from the store. When children are added to, removed from, or moved
2291   * within a feature, the indices of any others affected are {@link #adjustWrapperIndex adjusted}. Since this method
2292   * is typically called from {@link #notifyChanged notifyChanged}, which, in subclasses, is often invoked repeatedly
2293   * up the inheritance chain, it can be safely called repeatedly for a single notification, and only the first such
2294   * call will have an effect. Such repeated calls may not, however, safely be interleaved with calls for another
2295   * notification.
2296   */

2297  protected void updateChildren(Notification notification)
2298  {
2299    EObject object = (EObject)notification.getNotifier();
2300    ChildrenStore childrenStore = getChildrenStore(object);
2301
2302    if (childrenStore != null)
2303    {
2304      EStructuralFeature feature = (EStructuralFeature)notification.getFeature();
2305      EList children = childrenStore.getList(feature);
2306      if (children != null)
2307      {
2308        int index = notification.getPosition();
2309
2310        switch (notification.getEventType())
2311        {
2312          case Notification.UNSET:
2313          {
2314            // Ignore the unset notification for an isMany feature; the value is boolean in this case.
2315
//
2316
if (feature.isMany())
2317            {
2318              break;
2319            }
2320            
2321            // continue to next case
2322
}
2323          case Notification.SET:
2324          {
2325            Object JavaDoc oldChild = childrenStore.get(feature, index);
2326            Object JavaDoc newValue = notification.getNewValue();
2327
2328            if (unwrap(oldChild) != newValue)
2329            {
2330              if (feature.isMany() && index == Notification.NO_INDEX)
2331              {
2332                disposeWrappers((List JavaDoc)oldChild);
2333              }
2334              else
2335              {
2336                disposeWrapper(oldChild);
2337              }
2338              Object JavaDoc newChild = newValue == null && index == Notification.NO_INDEX ?
2339                  null : wrap(object, feature, newValue, index);
2340              childrenStore.set(feature, index, newChild);
2341            }
2342            break;
2343          }
2344          case Notification.ADD:
2345          {
2346            EList values = (EList)object.eGet(feature);
2347
2348            if (children.size() != values.size())
2349            {
2350              Object JavaDoc newValue = notification.getNewValue();
2351              adjustWrapperIndices(children, index, 1);
2352              children.add(index, wrap(object, feature, newValue, index));
2353            }
2354            break;
2355          }
2356          case Notification.REMOVE:
2357          {
2358            EList values = (EList)object.eGet(feature);
2359
2360            if (children.size() != values.size())
2361            {
2362              disposeWrapper(children.remove(index));
2363              adjustWrapperIndices(children, index, -1);
2364            }
2365            break;
2366          }
2367          case Notification.ADD_MANY:
2368          {
2369            EList values = (EList)object.eGet(feature);
2370
2371            if (children.size() != values.size())
2372            {
2373              if (notification.getOldValue() != null)
2374              {
2375                throw new IllegalArgumentException JavaDoc("No old value expected");
2376              }
2377              List JavaDoc newValues = (List JavaDoc)notification.getNewValue();
2378              List JavaDoc newChildren = new ArrayList JavaDoc(newValues.size());
2379              int offset = 0;
2380              for (Iterator JavaDoc i = newValues.iterator(); i.hasNext(); offset++)
2381              {
2382                newChildren.add(wrap(object, feature, i.next(), index+offset));
2383              }
2384              adjustWrapperIndices(children, index, offset);
2385              children.addAll(index, newChildren);
2386            }
2387            break;
2388          }
2389          case Notification.REMOVE_MANY:
2390          {
2391            // No index specified when removing all elements.
2392
//
2393
if (index == Notification.NO_INDEX) index = 0;
2394            EList values = (EList)object.eGet(feature);
2395
2396            if (children.size() != values.size())
2397            {
2398              if (notification.getNewValue() instanceof int[])
2399              {
2400                int[] indices = (int[])notification.getNewValue();
2401                for (int i = indices.length - 1; i >= 0; i--)
2402                {
2403                  disposeWrapper(children.remove(indices[i]));
2404                  adjustWrapperIndices(children, indices[i], -1);
2405                }
2406              }
2407              else
2408              {
2409                int len = ((List JavaDoc)notification.getOldValue()).size();
2410                List JavaDoc sl = children.subList(index, index + len);
2411                disposeWrappers(sl);
2412                sl.clear();
2413                adjustWrapperIndices(children, index, -len);
2414              }
2415            }
2416            break;
2417          }
2418          case Notification.MOVE:
2419          {
2420            int oldIndex = ((Integer JavaDoc)notification.getOldValue()).intValue();
2421            EList values = (EList)object.eGet(feature);
2422            boolean didMove = true;
2423
2424            for (int i = Math.min(oldIndex, index), end = Math.max(oldIndex, index); didMove && i <= end; i++)
2425            {
2426              didMove = unwrap(children.get(i)) == values.get(i);
2427            }
2428            
2429            if (!didMove)
2430            {
2431              int delta = index - oldIndex;
2432              if (delta < 0)
2433              {
2434                adjustWrapperIndices(children, index, oldIndex, 1);
2435              }
2436              children.move(index, oldIndex);
2437              adjustWrapperIndex(children.get(index), delta);
2438              if (delta > 0)
2439              {
2440                adjustWrapperIndices(children, oldIndex, index, -1);
2441              }
2442            }
2443            break;
2444          }
2445        }
2446      }
2447    }
2448  }
2449
2450  /**
2451   * If the given command parameter contains wrapped values that need to be unwrapped for the given command class to
2452   * operate on, a new command parameter will be returned, with those values unwrapped; otherwise, the original one is
2453   * returned. For most commands, any objects in the {@link org.eclipse.emf.edit.command.CommandParameter#getCollection
2454   * collection} or in the {@link org.eclipse.emf.edit.command.CommandParameter#getValue value} that implement {@link
2455   * IWrapperItemProvider} will be {@link #unwrap unwrapped}. {@link org.eclipse.emf.edit.command.DragAndDropCommand}
2456   * is never unwrapped.
2457   */

2458  protected CommandParameter unwrapCommandValues(CommandParameter commandParameter, Class JavaDoc commandClass)
2459  {
2460    // We need the wrapper, not the item provider, to handle a DragAndDropCommand; the move, add, remove, etc. commands
2461
// that implement it will have their values unwrapped as usual.
2462
//
2463
if (commandClass == DragAndDropCommand.class)
2464    {
2465      return commandParameter;
2466    }
2467    
2468    ArrayList JavaDoc newCollection = null;
2469    Collection JavaDoc oldCollection = commandParameter.getCollection();
2470    
2471    // Unwrap collection.
2472
//
2473
if (oldCollection != null)
2474    {
2475      for (Iterator JavaDoc i = oldCollection.iterator(); i.hasNext(); )
2476      {
2477        Object JavaDoc oldValue = i.next();
2478        Object JavaDoc newValue = unwrap(oldValue);
2479
2480        // If the first wrapped value is found...
2481
//
2482
if (newValue != oldValue && newCollection == null)
2483        {
2484          // Allocate the new collection, and populate it up to this point.
2485
//
2486
newCollection = new ArrayList JavaDoc(oldCollection.size());
2487          for (Iterator JavaDoc j = oldCollection.iterator(); j.hasNext(); )
2488          {
2489            Object JavaDoc o = j.next();
2490            if (o == oldValue) break;
2491            newCollection.add(o);
2492          }
2493        }
2494
2495        // If a new collection was allocated, continue to populate it.
2496
//
2497
if (newCollection != null)
2498        {
2499          newCollection.add(newValue);
2500        }
2501      }
2502    }
2503
2504    // Unwrap value.
2505
//
2506
Object JavaDoc oldValue = commandParameter.getValue();
2507    Object JavaDoc newValue = unwrap(oldValue);
2508
2509    if (newCollection != null || newValue != oldValue)
2510    {
2511      commandParameter = new CommandParameter(
2512        commandParameter.owner,
2513        commandParameter.feature,
2514        newValue,
2515        newCollection,
2516        commandParameter.index);
2517    }
2518
2519    return commandParameter;
2520  }
2521
2522  /**
2523   * Returns a version of the given command that automatically re-wraps values that have been unwrapped when returning
2524   * them as the command's result or affected objects. This is only done if {@link #isWrappingNeeded isWrappingNeeded}
2525   * returns <code>true</code>, and never for a {@link org.eclipse.emf.edit.command.DragAndDropCommand}.
2526   */

2527  protected Command wrapCommand(Command command, Object JavaDoc object, Class JavaDoc commandClass, CommandParameter commandParameter, CommandParameter oldCommandParameter)
2528  {
2529    if (isWrappingNeeded(object) && commandClass != DragAndDropCommand.class)
2530    {
2531      // Wrappers from the old command parameter must be considered in order for cut and paste to work.
2532
//
2533
Collection JavaDoc oldWrappers = commandParameter != oldCommandParameter ?
2534        getWrappedValues(oldCommandParameter) : Collections.EMPTY_LIST;
2535
2536      command = command instanceof CommandActionDelegate ?
2537        new ResultAndAffectedObjectsWrappingCommandActionDelegate((CommandActionDelegate)command, oldWrappers) :
2538        new ResultAndAffectedObjectsWrappingCommand(command, oldWrappers);
2539    }
2540    return command;
2541  }
2542  
2543  /**
2544   * Returns a collection of any objects in the given command parameter's {@link
2545   * org.eclipse.emf.edit.command.CommandParameter#getCollection collection} and {@link
2546   * org.eclipse.emf.edit.command.CommandParameter#getValue value}, that implement {@link IWrapperItemProvider}.
2547   */

2548  protected Collection JavaDoc getWrappedValues(CommandParameter commandParameter)
2549  {
2550    Collection JavaDoc collection = commandParameter.getCollection();
2551    Object JavaDoc value = commandParameter.getValue();
2552
2553    if (collection != null)
2554    {
2555      List JavaDoc result = new ArrayList JavaDoc(collection.size() + 1);
2556      for (Iterator JavaDoc i = collection.iterator(); i.hasNext(); )
2557      {
2558        Object JavaDoc o = i.next();
2559        if (o instanceof IWrapperItemProvider)
2560        {
2561          result.add(o);
2562        }
2563      }
2564
2565      if (value instanceof IWrapperItemProvider)
2566      {
2567        result.add(value);
2568      }
2569
2570      return result;
2571    }
2572    else if (value instanceof IWrapperItemProvider)
2573    {
2574      return Collections.singletonList(value);
2575    }
2576    return Collections.EMPTY_LIST;
2577  }
2578
2579  /**
2580   * This creates an item provider descriptor that uses a resource locator; specifies a static image, a category, and filter flags;
2581   * and determines the cell editor from the type of the structural feature.
2582   */

2583  protected ItemPropertyDescriptor createItemPropertyDescriptor(
2584    AdapterFactory adapterFactory,
2585    ResourceLocator resourceLocator,
2586    String JavaDoc displayName,
2587    String JavaDoc description,
2588    EStructuralFeature feature,
2589    boolean isSettable,
2590    Object JavaDoc staticImage,
2591    String JavaDoc category,
2592    String JavaDoc[] filterFlags)
2593  {
2594    return new ItemPropertyDescriptor(
2595      adapterFactory,
2596      resourceLocator,
2597      displayName,
2598      description,
2599      feature,
2600      isSettable,
2601      staticImage,
2602      category,
2603      filterFlags);
2604  }
2605  
2606  /**
2607   * A <code>ResultAndAffectedObjectsWrappingCommand</code> wraps another command to substitute {@link
2608   * IWrapperItemProvider}s for their values in the command's result and affected objects. This is needed
2609   * as the values have been unwrapped for the command to operate on properly.
2610   * <p>
2611   * A list of wrappers from which to substitute is formed by calling {@link #getChildren getChildren} on the command's
2612   * owner(s). Additional wrappers to be considered for the result can by specified in the two-argument constructor.
2613   * The first wrapper whose {@link IWrapperItemProvider#getValue value} matches a given value in the result or
2614   * affected objects is substitued for it.
2615   */

2616  public class ResultAndAffectedObjectsWrappingCommand extends CommandWrapper
2617  {
2618    protected List JavaDoc owners;
2619    protected Collection JavaDoc additionalWrappers;
2620
2621    public ResultAndAffectedObjectsWrappingCommand(Command command)
2622    {
2623      super(command);
2624    }
2625
2626    public ResultAndAffectedObjectsWrappingCommand(Command command, Collection JavaDoc additionalResultWrappers)
2627    {
2628      super(command);
2629      additionalWrappers = additionalResultWrappers;
2630    }
2631
2632    public Collection JavaDoc getResult()
2633    {
2634      return wrapValues(super.getResult(), true);
2635    }
2636
2637    public Collection JavaDoc getAffectedObjects()
2638    {
2639      return wrapValues(super.getAffectedObjects(), false);
2640    }
2641
2642    protected Collection JavaDoc wrapValues(Collection JavaDoc unwrappedValues, boolean useAdditionalWrappers)
2643    {
2644      List JavaDoc result = new ArrayList JavaDoc(unwrappedValues);
2645      List JavaDoc wrappers = new ArrayList JavaDoc();
2646
2647      // If the adapter factory is composeable, we'll adapt using the root.
2648
//
2649
AdapterFactory af = adapterFactory instanceof ComposeableAdapterFactory ?
2650        ((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory() :
2651        adapterFactory;
2652
2653      // Build list of wrapped children from the appropriate adapters.
2654
//
2655
for (Iterator JavaDoc i = getOwners().iterator(); i.hasNext(); )
2656      {
2657        Object JavaDoc owner = i.next();
2658        Collection JavaDoc children = Collections.EMPTY_LIST;
2659
2660        // Either the IEditingDomainItemProvider or ITreeItemContentProvider item provider interface can give us
2661
// the children.
2662
//
2663
Object JavaDoc adapter = af.adapt(owner, IEditingDomainItemProvider.class);
2664        if (adapter instanceof IEditingDomainItemProvider)
2665        {
2666          children = ((IEditingDomainItemProvider)adapter).getChildren(owner);
2667        }
2668        else
2669        {
2670          adapter = af.adapt(owner, ITreeItemContentProvider.class);
2671          if (adapter instanceof ITreeItemContentProvider)
2672          {
2673            children = ((ITreeItemContentProvider)adapter).getChildren(owner);
2674          }
2675        }
2676
2677        for (Iterator JavaDoc j = children.iterator(); j.hasNext(); )
2678        {
2679          Object JavaDoc child = j.next();
2680          if (child instanceof IWrapperItemProvider)
2681          {
2682            wrappers.add(child);
2683          }
2684        }
2685      }
2686
2687      // Add in additional wrappers to search.
2688
//
2689
if (useAdditionalWrappers && additionalWrappers != null)
2690      {
2691        wrappers.addAll(additionalWrappers);
2692      }
2693
2694      // Look for each unwrapped object as a value of a wrapper, replacing it with the first one found.
2695
//
2696
for (ListIterator JavaDoc i = result.listIterator(); i.hasNext(); )
2697      {
2698        Object JavaDoc resultObject = i.next();
2699
2700        Iterator JavaDoc j = wrappers.iterator();
2701        while (j.hasNext())
2702        {
2703          IWrapperItemProvider wrapper = (IWrapperItemProvider)j.next();
2704
2705          if (isEquivalentValue(unwrap(wrapper), resultObject))
2706          {
2707            i.set(wrapper);
2708            break;
2709          }
2710        }
2711      }
2712      return result;
2713    }
2714
2715    /**
2716     * Returns any owners from the wrapped command. If it is a compound command, or a wrapped compound command, it may
2717     * have multiple owners. This returns and caches a list of them.
2718     */

2719    public List JavaDoc getOwners()
2720    {
2721      if (owners == null)
2722      {
2723        owners = new UniqueEList();
2724        addOwners(getCommand());
2725      }
2726      return owners;
2727    }
2728
2729    /**
2730     * Helper method that builds the list of owners, recursively for command wrappers and/or compound commands.
2731     */

2732    protected void addOwners(Command command)
2733    {
2734      if (command instanceof CommandWrapper)
2735      {
2736        addOwners(((CommandWrapper)command).getCommand());
2737      }
2738      else if (command instanceof CompoundCommand)
2739      {
2740        CompoundCommand compoundCommand = (CompoundCommand)command;
2741        List JavaDoc commandList = compoundCommand.getCommandList();
2742        int resultIndex = compoundCommand.getResultIndex();
2743
2744        if (resultIndex == CompoundCommand.MERGE_COMMAND_ALL)
2745        {
2746          for (Iterator JavaDoc i = commandList.iterator(); i.hasNext(); )
2747          {
2748            addOwners((Command)i.next());
2749          }
2750        }
2751        else
2752        {
2753          if (resultIndex == CompoundCommand.LAST_COMMAND_ALL)
2754          {
2755            resultIndex = commandList.size() - 1;
2756          }
2757        
2758          if (resultIndex >= 0)
2759          {
2760            addOwners((Command)commandList.get(resultIndex));
2761          }
2762        }
2763      }
2764      else if (command instanceof AddCommand)
2765      {
2766        owners.add(((AddCommand)command).getOwner());
2767      }
2768      else if (command instanceof CreateCopyCommand)
2769      {
2770        owners.add(((CreateCopyCommand)command).getOwner());
2771      }
2772      else if (command instanceof InitializeCopyCommand)
2773      {
2774        owners.add(((InitializeCopyCommand)command).getOwner());
2775      }
2776      else if (command instanceof MoveCommand)
2777      {
2778        owners.add(((MoveCommand)command).getOwner());
2779      }
2780      else if (command instanceof RemoveCommand)
2781      {
2782        owners.add(((RemoveCommand)command).getOwner());
2783      }
2784      else if (command instanceof ReplaceCommand)
2785      {
2786        owners.add(((ReplaceCommand)command).getOwner());
2787      }
2788      else if (command instanceof SetCommand)
2789      {
2790        owners.add(((SetCommand)command).getOwner());
2791      }
2792    }
2793  }
2794
2795  /**
2796   * A <code>ResultAndAffectedObjectsWrappingCommandActionDelegate</code> wraps another command that also implements
2797   * <code>CommandActionDelegate</code>, to substitute {@link IWrapperItemProvider}s for its values, which have been
2798   * unwrapped for the command to operate on properly. This substitution is performed exactly as by a
2799   * <code>ResultAndAffectedObjectsWrappingComand</code>, and action delegate methods are delegated directly to the
2800   * wrapped command.
2801   */

2802  public class ResultAndAffectedObjectsWrappingCommandActionDelegate extends ResultAndAffectedObjectsWrappingCommand
2803    implements CommandActionDelegate
2804  {
2805    CommandActionDelegate commandActionDelegate;
2806    
2807    /**
2808     * Returns a new <code>ResultAndAffectedObjectsWrappingCommandActionDelegate</code> for the given command.
2809     * @exception ClassCastException If the specified command does not implement {@link org.eclipse.emf.common.command.Command}.
2810     */

2811    public ResultAndAffectedObjectsWrappingCommandActionDelegate(CommandActionDelegate command)
2812    {
2813      super((Command)command);
2814      commandActionDelegate = command;
2815    }
2816
2817    /**
2818     * Returns a new <code>ResultAndAffectedObjectsWrappingCommandActionDelegate</code> for the given command and list
2819     * of additional wrappers.
2820     * @exception ClassCastException If the specified command does not implement {@link org.eclipse.emf.common.command.Command}.
2821     */

2822    public ResultAndAffectedObjectsWrappingCommandActionDelegate(CommandActionDelegate command, Collection JavaDoc additionalWrappers)
2823    {
2824      super((Command)command, additionalWrappers);
2825      commandActionDelegate = command;
2826    }
2827
2828    public Object JavaDoc getImage()
2829    {
2830      return commandActionDelegate.getImage();
2831    }
2832
2833    public String JavaDoc getText()
2834    {
2835      return commandActionDelegate.getText();
2836    }
2837
2838    public String JavaDoc getDescription()
2839    {
2840      return commandActionDelegate.getDescription();
2841    }
2842
2843    public String JavaDoc getToolTipText()
2844    {
2845      return commandActionDelegate.getToolTipText();
2846    }
2847  }
2848}
2849
Popular Tags