KickJava   Java API By Example, From Geeks To Geeks.

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


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: EcoreUtil.java,v 1.28 2005/06/08 06:20:10 nickb Exp $
16  */

17 package org.eclipse.emf.ecore.util;
18
19
20 import java.io.PrintStream JavaDoc;
21 import java.security.SecureRandom JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.GregorianCalendar JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31
32 import org.eclipse.emf.common.notify.Adapter;
33 import org.eclipse.emf.common.notify.AdapterFactory;
34 import org.eclipse.emf.common.notify.Notifier;
35 import org.eclipse.emf.common.util.AbstractTreeIterator;
36 import org.eclipse.emf.common.util.ECollections;
37 import org.eclipse.emf.common.util.EList;
38 import org.eclipse.emf.common.util.TreeIterator;
39 import org.eclipse.emf.common.util.URI;
40 import org.eclipse.emf.ecore.EAnnotation;
41 import org.eclipse.emf.ecore.EAttribute;
42 import org.eclipse.emf.ecore.EClass;
43 import org.eclipse.emf.ecore.EClassifier;
44 import org.eclipse.emf.ecore.EDataType;
45 import org.eclipse.emf.ecore.EModelElement;
46 import org.eclipse.emf.ecore.EObject;
47 import org.eclipse.emf.ecore.EPackage;
48 import org.eclipse.emf.ecore.EReference;
49 import org.eclipse.emf.ecore.EStructuralFeature;
50 import org.eclipse.emf.ecore.EcoreFactory;
51 import org.eclipse.emf.ecore.EcorePackage;
52 import org.eclipse.emf.ecore.InternalEObject;
53 import org.eclipse.emf.ecore.impl.EPackageImpl;
54 import org.eclipse.emf.ecore.resource.Resource;
55 import org.eclipse.emf.ecore.resource.ResourceSet;
56
57
58 /**
59  * This class contains convenient static methods for working with EMF objects.
60  */

61 public class EcoreUtil
62 {
63   // // Suppress default constructor for noninstantiability.
64
// private EcoreUtil()
65
// {
66
// }
67

68   /**
69    * Returns the specified notifier's exisiting adapter of the specified type.
70    * @param notifier the adapted object.
71    * @param type the type of adapter.
72    * @return an adapter associated with the specified notifier or null.
73    */

74   public static Adapter getExistingAdapter(Notifier notifier, Object JavaDoc type)
75   {
76     return getAdapter(notifier.eAdapters(), type);
77   }
78
79   /**
80    * Returns the specified eObject's adapter of the specified type. If none exists, create and
81    * add a new adapter using a registered adapter factory if one exists for the specified type.
82    * @param eObject the adapted object.
83    * @param type the type of adapter.
84    * @return an adapter associated with the specified eObject or null.
85    */

86   public static Adapter getRegisteredAdapter(EObject eObject, Object JavaDoc type)
87   {
88     Adapter result = getExistingAdapter(eObject, type);
89     if (result == null)
90     {
91       Resource resource = eObject.eResource();
92       if (resource != null)
93       {
94         ResourceSet resourceSet = resource.getResourceSet();
95         if (resourceSet != null)
96         {
97           AdapterFactory factory = getAdapterFactory(resourceSet.getAdapterFactories(), type);
98           if (factory != null)
99           {
100             result = factory.adaptNew(eObject, type);
101           }
102         }
103       }
104     }
105     return result;
106   }
107
108   /**
109    * Returns the specified resource's adapter of the specified type. If none exists, create and
110    * add a new adapter using a registered adapter factory if one exists for the specified type.
111    * @param resource the adapted resource.
112    * @param type the type of adapter.
113    * @return an adapter associated with the specified eObject or null.
114    */

115   public static Adapter getRegisteredAdapter(Resource resource, Object JavaDoc type)
116   {
117     Adapter result = getExistingAdapter(resource, type);
118     if (result == null)
119     {
120       ResourceSet resourceSet = resource.getResourceSet();
121       if (resourceSet != null)
122       {
123         AdapterFactory factory = getAdapterFactory(resourceSet.getAdapterFactories(), type);
124         if (factory != null)
125         {
126           result = factory.adaptNew(resource, type);
127         }
128       }
129     }
130     return result;
131   }
132
133   /**
134    * Returns the adapter of the specified type.
135    * @param adapters list of adapters to search.
136    * @param type the type of adapter.
137    * @return an adapter from the list or null.
138    */

139   public static Adapter getAdapter(List JavaDoc adapters, Object JavaDoc type)
140   {
141     for (int i = 0, size = adapters.size(); i < size; ++i)
142     {
143       Adapter adapter = (Adapter)adapters.get(i);
144       if (adapter.isAdapterForType(type))
145       {
146         return adapter;
147       }
148     }
149     return null;
150   }
151
152   /**
153    * Returns the adapter factory for the specified adapter type.
154    * @param adapterFactories list of adapter factories to search.
155    * @param type the type of adapter.
156    * @return an adapter factory from the list or null.
157    */

158   public static AdapterFactory getAdapterFactory(List JavaDoc adapterFactories, Object JavaDoc type)
159   {
160     for (int i = 0, size = adapterFactories.size(); i < size; ++i)
161     {
162       AdapterFactory factory = (AdapterFactory)adapterFactories.get(i);
163       if (factory.isFactoryForType(type))
164       {
165         return factory;
166       }
167     }
168     return null;
169   }
170
171   /**
172    * Returns the resolved object represented by proxy. Proxy chains are followed.
173    * If resourceSet is null, the global package registry is consulted to obtain a
174    * package registered against the proxy URI, less its fragment, in the same manner
175    * as the default resource set implementation's fallback behaviour.
176    * @param proxy the proxy to be resolved.
177    * @param resourceSet the resource set in which to resolve.
178    * @return the resolved object, or the proxy if unable to resolve.
179    */

180   public static EObject resolve(EObject proxy, ResourceSet resourceSet)
181   {
182     URI proxyURI = ((InternalEObject)proxy).eProxyURI();
183     if (proxyURI != null)
184     {
185       try
186       {
187         EObject resolvedObject = null;
188
189         if (resourceSet != null)
190         {
191           resolvedObject = resourceSet.getEObject(proxyURI, true);
192         }
193         else
194         {
195           EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(proxyURI.trimFragment().toString());
196           if (ePackage != null)
197           {
198             Resource resource = ePackage.eResource();
199             if (resource != null)
200             {
201               resolvedObject = resource.getEObject(proxyURI.fragment().toString());
202             }
203           }
204         }
205
206         if (resolvedObject != null && resolvedObject != proxy)
207         {
208           return resolve(resolvedObject, resourceSet);
209         }
210       }
211       catch (RuntimeException JavaDoc exception)
212       {
213         // Failure to resolve is ignored.
214
}
215     }
216     return proxy;
217   }
218
219   /**
220    * Returns the resolved object represented by proxy. Proxy chains are followed.
221    * If resourceContext is null or not in a resource set, the global package registry is
222    * consulted to obtain a package registered against the proxy URI, less its fragment,
223    * in the same manner as the default resource set implementation's fallback behaviour.
224    * @param proxy the proxy to be resolved.
225    * @param resourceContext a context resource whose resource set is used for the resolve.
226    * @return the resolved object, or the proxy if unable to resolve.
227    */

228   public static EObject resolve(EObject proxy, Resource resourceContext)
229   {
230     return resolve(proxy, resourceContext != null ? resourceContext.getResourceSet() : null);
231   }
232
233   /**
234    * Returns the resolved object represented by proxy. Proxy chains are followed.
235    * If objectContext is null or not in a resource that is in a resource set, the
236    * global package registry is consulted to obtain a package registered against
237    * the proxy URI, less its fragment, in the same manner as the default resource
238    * set implementation's fallback behaviour.
239    * @param proxy the proxy to be resolved.
240    * @param objectContext a context object whose resource set is used for the resolve.
241    * @return the resolved object, or the proxy if unable to resolve.
242    */

243   public static EObject resolve(EObject proxy, EObject objectContext)
244   {
245     Resource resourceContext = objectContext != null ? objectContext.eResource() : null;
246     return resolve(proxy, resourceContext != null ? resourceContext.getResourceSet() : null);
247   }
248
249   /**
250    * Visits all proxies in the resource set and tries to resolve them.
251    * @param resourceSet the objects to visit.
252    */

253   public static void resolveAll(ResourceSet resourceSet)
254   {
255     List JavaDoc resources = resourceSet.getResources();
256     for (int i = 0; i < resources.size(); ++i)
257     {
258       resolveAll((Resource)resources.get(i));
259     }
260   }
261
262   /**
263    * Visits all proxies in the resource and tries to resolve them.
264    * @param resource the objects to visit.
265    */

266   public static void resolveAll(Resource resource)
267   {
268     for (Iterator JavaDoc i = resource.getAllContents(); i.hasNext(); )
269     {
270       EObject eObject = (EObject)i.next();
271       for (Iterator JavaDoc j = eObject.eCrossReferences().iterator(); j.hasNext(); j.next())
272       {
273       }
274     }
275   }
276
277   /**
278    * Visits all proxies referenced by the object or recursively any of it's contained object.
279    * @param eObject the object to visist.
280    */

281   public static void resolveAll(EObject eObject)
282   {
283     for (Iterator JavaDoc i = eObject.eAllContents(); i.hasNext(); )
284     {
285       EObject childEObject = (EObject)i.next();
286       for (Iterator JavaDoc j = childEObject.eCrossReferences().iterator(); j.hasNext(); j.next())
287       {
288       }
289     }
290   }
291
292   /**
293    * Returns the first collection member that {@link EClassifier#isInstance is an instance} of the type.
294    * @param objects a collection of objects to check.
295    * @param type the type of object to find.
296    * @return the first object of the specified type.
297    */

298   public static Object JavaDoc getObjectByType(Collection JavaDoc objects, EClassifier type)
299   {
300     for (Iterator JavaDoc i = objects.iterator(); i.hasNext();)
301     {
302       Object JavaDoc object = i.next();
303       if (type.isInstance(object))
304       {
305         return object;
306       }
307     }
308     return null;
309   }
310
311   /**
312    * Returns a collection containing each collection member that {@link EClassifier#isInstance is an instance} of the type.
313    * @param objects a collection of objects to check.
314    * @param type the type of object to find.
315    * @return a collection of objects of the specified type.
316    */

317   public static Collection JavaDoc getObjectsByType(Collection JavaDoc objects, EClassifier type)
318   {
319     Collection JavaDoc result = new ArrayList JavaDoc();
320     for (Iterator JavaDoc i = objects.iterator(); i.hasNext();)
321     {
322       Object JavaDoc object = i.next();
323       if (type.isInstance(object))
324       {
325         result.add(object);
326       }
327     }
328     return result;
329   }
330
331   /**
332    * Returns a self-contained copy of the eObject.
333    * @param eObject the object to copy.
334    * @return the copy.
335    * @see Copier
336    */

337   public static EObject copy(EObject eObject)
338   {
339     Copier copier = new Copier();
340     EObject result = copier.copy(eObject);
341     copier.copyReferences();
342     return result;
343   }
344
345   /**
346    * Returns a collection of the self-contained copies of each {@link EObject} in eObjects.
347    * @param eObjects the collection of objects to copy.
348    * @return the collection of copies.
349    * @see Copier
350    */

351   public static Collection JavaDoc copyAll(Collection JavaDoc eObjects)
352   {
353     Copier copier = new Copier();
354     Collection JavaDoc result = copier.copyAll(eObjects);
355     copier.copyReferences();
356     return result;
357   }
358
359   /**
360    * A mapping building traverser of a collection of {@link EObject#eAllContents content trees};
361    * the map is from {@link EObject} to <code>EObject</code>, i.e., from original to copy;
362    * use {@link EcoreUtil#copy EcoreUtil.copy} or {@link EcoreUtil#copyAll EcoreUtil.copyAll} to do routine copies.
363    * Since this implementation extends a Map implementation, it acts as the result of the over all copy.
364    * The client can call {@link #copy copy} and {@link #copyAll copyAll} repeatedly.
365    * When all the objects have been copied,
366    * the client should call {@link #copyReferences copyReferences}
367    * to copy the {@link #copyReference appropriate} {@link EObject#eCrossReferences cross references}.
368    *<pre>
369    * Copier copier = new Copier();
370    * EObject result = copier.copy(eObject);
371    * Collection results = copier.copyAll(eObjects);
372    * copier.copyReferences();
373    *</pre>
374    * The copier delegates to {@link #copyContainment copyContainment}, {@link #copyAttribute copyAttribute} during the copy phase
375    * and to {@link #copyReference copyReference}, during the cross reference phase.
376    * This allows tailored handling through derivation.
377    */

378   public static class Copier extends HashMap JavaDoc
379   {
380     /**
381      * Returns a collection containing a copy of each EObject in the given collection.
382      * @param eObjects the collection of objects to copy.
383      * @return the collection of copies.
384      */

385     public Collection JavaDoc copyAll(Collection JavaDoc eObjects)
386     {
387       Collection JavaDoc result = new ArrayList JavaDoc(eObjects.size());
388       for (Iterator JavaDoc i = eObjects.iterator(); i.hasNext();)
389       {
390         result.add(copy((EObject)i.next()));
391       }
392       return result;
393     }
394
395     /**
396      * Returns a copy of the given eObject.
397      * @param eObject the object to copy.
398      * @return the copy.
399      */

400     public EObject copy(EObject eObject)
401     {
402       EObject copyEObject = createCopy(eObject);
403       put(eObject, copyEObject);
404       EClass eClass = eObject.eClass();
405       for (int i = 0, size = eClass.getFeatureCount(); i < size; ++i)
406       {
407         EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(i);
408         if (eStructuralFeature.isChangeable() && !eStructuralFeature.isDerived())
409         {
410           if (eStructuralFeature instanceof EAttribute)
411           {
412             copyAttribute((EAttribute)eStructuralFeature, eObject, copyEObject);
413           }
414           else
415           {
416             EReference eReference = (EReference)eStructuralFeature;
417             if (eReference.isContainment())
418             {
419               copyContainment(eReference, eObject, copyEObject);
420             }
421           }
422         }
423       }
424
425       return copyEObject;
426     }
427
428     /**
429      * Returns a new instance of the object's target class.
430      * @param eObject the object to copy.
431      * @return a new instance of the target class.
432      * @see #getTarget(EClass)
433      * @see EcoreUtil#create(EClass)
434      */

435     protected EObject createCopy(EObject eObject)
436     {
437       return create(getTarget(eObject.eClass()));
438     }
439
440     /**
441      * Returns the target class used to create a copy instance for objects of the given source class.
442      * @param eClass the source class.
443      * @return the target class used to create a copy instance.
444      * @see #getTarget(EStructuralFeature)
445      */

446     protected EClass getTarget(EClass eClass)
447     {
448       return eClass;
449     }
450
451     /**
452      * Returns the target feature used to populate a copy instance from the given source feature.
453      * @param eStructuralFeature the source feature.
454      * @return the target feature used to populate a copy instance.
455      * @see #getTarget(EClass)
456      */

457     protected EStructuralFeature getTarget(EStructuralFeature eStructuralFeature)
458     {
459       return eStructuralFeature;
460     }
461
462     /**
463      * Called to handle the copying of a containment feature;
464      * this adds a list of copies or sets a single copy as appropriate for the multiplicity.
465      * @param eReference the feature to copy.
466      * @param eObject the object from which to copy.
467      * @param copyEObject the object to copy to.
468      */

469     protected void copyContainment(EReference eReference, EObject eObject, EObject copyEObject)
470     {
471       if (eObject.eIsSet(eReference))
472       {
473         if (eReference.isMany())
474         {
475           List JavaDoc source = (List JavaDoc)eObject.eGet(eReference);
476           List JavaDoc target = (List JavaDoc)copyEObject.eGet(getTarget(eReference));
477           if (source.isEmpty())
478           {
479             target.clear();
480           }
481           else
482           {
483             target.addAll(copyAll(source));
484           }
485         }
486         else
487         {
488           EObject childEObject = (EObject)eObject.eGet(eReference);
489           copyEObject.eSet(getTarget(eReference), childEObject == null ? null : copy(childEObject));
490         }
491       }
492     }
493
494     /**
495      * Called to handle the copying of an attribute;
496      * this adds a list of values or sets a single value as appropriate for the multiplicity.
497      * @param eAttribute the attribute to copy.
498      * @param eObject the object from which to copy.
499      * @param copyEObject the object to copy to.
500      */

501     protected void copyAttribute(EAttribute eAttribute, EObject eObject, EObject copyEObject)
502     {
503       if (eObject.eIsSet(eAttribute))
504       {
505         if (FeatureMapUtil.isFeatureMap(eAttribute))
506         {
507           FeatureMap featureMap = (FeatureMap)eObject.eGet(eAttribute);
508           for (int i = 0, size = featureMap.size(); i < size; ++i)
509           {
510             EStructuralFeature feature = featureMap.getEStructuralFeature(i);
511             if (feature instanceof EReference && ((EReference)feature).isContainment())
512             {
513               Object JavaDoc value = featureMap.getValue(i);
514               if (value != null)
515               {
516                 copy((EObject)value);
517               }
518             }
519           }
520         }
521         else if (eAttribute.isMany())
522         {
523           List JavaDoc source = (List JavaDoc)eObject.eGet(eAttribute);
524           List JavaDoc target = (List JavaDoc)copyEObject.eGet(getTarget(eAttribute));
525           if (source.isEmpty())
526           {
527             target.clear();
528           }
529           else
530           {
531             target.addAll(source);
532           }
533         }
534         else
535         {
536           copyEObject.eSet(getTarget(eAttribute), eObject.eGet(eAttribute));
537         }
538       }
539     }
540
541     /**
542      * Hooks up cross references; it delegates to {@link #copyReference copyReference}.
543      */

544     public void copyReferences()
545     {
546       for (Iterator JavaDoc i = entrySet().iterator(); i.hasNext();)
547       {
548         Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
549         EObject eObject = (EObject)entry.getKey();
550         EObject copyEObject = (EObject)entry.getValue();
551         EClass eClass = eObject.eClass();
552         for (int j = 0, size = eClass.getFeatureCount(); j < size; ++j)
553         {
554           EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(j);
555           if (eStructuralFeature.isChangeable() && !eStructuralFeature.isDerived())
556           {
557             if (eStructuralFeature instanceof EReference)
558             {
559               EReference eReference = (EReference)eStructuralFeature;
560               if (!eReference.isContainment())
561               {
562                 copyReference(eReference, eObject, copyEObject);
563               }
564             }
565             else if (FeatureMapUtil.isFeatureMap(eStructuralFeature))
566             {
567               FeatureMap featureMap = (FeatureMap)eObject.eGet(eStructuralFeature);
568               FeatureMap copyFeatureMap = (FeatureMap)copyEObject.eGet(getTarget(eStructuralFeature));
569               for (int k = 0, featureMapSize = featureMap.size(); k < featureMapSize; ++k)
570               {
571                 EStructuralFeature feature = featureMap.getEStructuralFeature(k);
572                 if (feature instanceof EReference)
573                 {
574                   Object JavaDoc referencedEObject = featureMap.getValue(k);
575                   Object JavaDoc copyReferencedEObject = get(referencedEObject);
576                   copyFeatureMap.add(feature, copyReferencedEObject == null ? referencedEObject : copyReferencedEObject);
577                 }
578                 else
579                 {
580                   copyFeatureMap.add(featureMap.get(k));
581                 }
582               }
583             }
584           }
585         }
586       }
587     }
588
589     /**
590      * Called to handle the copying of a cross reference;
591      * this adds values or sets a single value as appropriate for the multiplicity
592      * while omitting any bidirectional reference that isn't in the copy map.
593      * @param eReference the reference to copy.
594      * @param eObject the object from which to copy.
595      * @param copyEObject the object to copy to.
596      */

597     protected void copyReference(EReference eReference, EObject eObject, EObject copyEObject)
598     {
599       if (eObject.eIsSet(eReference))
600       {
601         if (eReference.isMany())
602         {
603           List JavaDoc source = (List JavaDoc)eObject.eGet(eReference);
604           InternalEList target = (InternalEList)copyEObject.eGet(getTarget(eReference));
605           if (source.isEmpty())
606           {
607             target.clear();
608           }
609           else
610           {
611             boolean isBidirectional = eReference.getEOpposite() != null;
612             int index = 0;
613             for (Iterator JavaDoc k = source.iterator(); k.hasNext();)
614             {
615               Object JavaDoc referencedEObject = k.next();
616               Object JavaDoc copyReferencedEObject = get(referencedEObject);
617               if (copyReferencedEObject == null)
618               {
619                 if (!isBidirectional)
620                 {
621                   target.addUnique(index, referencedEObject);
622                   ++index;
623                 }
624               }
625               else
626               {
627                 if (isBidirectional)
628                 {
629                   int position = target.indexOf(copyReferencedEObject);
630                   if (position == -1)
631                   {
632                     target.addUnique(index, copyReferencedEObject);
633                   }
634                   else if (index != position)
635                   {
636                     target.move(index, copyReferencedEObject);
637                   }
638                 }
639                 else
640                 {
641                   target.addUnique(index, copyReferencedEObject);
642                 }
643                 ++index;
644               }
645             }
646           }
647         }
648         else
649         {
650           Object JavaDoc referencedEObject = eObject.eGet(eReference);
651           if (referencedEObject == null)
652           {
653             copyEObject.eSet(getTarget(eReference), null);
654           }
655           else
656           {
657             Object JavaDoc copyReferencedEObject = get(referencedEObject);
658             if (copyReferencedEObject == null)
659             {
660               if (eReference.getEOpposite() == null)
661               {
662                 copyEObject.eSet(getTarget(eReference), referencedEObject);
663               }
664             }
665             else
666             {
667               copyEObject.eSet(getTarget(eReference), copyReferencedEObject);
668             }
669           }
670         }
671       }
672     }
673   }
674
675   /**
676    * Returns the root container;
677    * it may be this object itself
678    * and it will have a <code>null</code> {@link EObject#eContainer container}.
679    * <p>
680    * The root container must be {@link Resource#getContents directly contained} in a resource
681    * for its {@link EObject#eAllContents tree} to be {@link Resource#save(java.util.Map) serializable}.
682    * </p>
683    * @param eObject the object to get the root container for.
684    * @return the root container.
685    * @see EObject#eResource()
686    * @see EObject#eContainer()
687    */

688   public static EObject getRootContainer(EObject eObject)
689   {
690     EObject result = eObject;
691     for (EObject parent = eObject; parent != null; parent = parent.eContainer())
692     {
693       result = parent;
694     }
695     return result;
696   }
697
698   /**
699    * Returns whether the second object is directly or indirectly contained by the first object,
700    * i.e., whether the second object is in the {@link EObject#eContents content tree} of the first.
701    * @param ancestorEObject the ancestor object in question.
702    * @param eObject the object to test.
703    * @return whether the first object is an ancestor of the second object.
704    * @see EObject#eContainer
705    */

706   public static boolean isAncestor(EObject ancestorEObject, EObject eObject)
707   {
708     while (eObject != null)
709     {
710       if (eObject == ancestorEObject)
711       {
712         return true;
713       }
714       eObject = eObject.eContainer();
715     }
716
717     return false;
718   }
719
720   /**
721    * Returns whether the given resource is that of the object,
722    * i.e., whether the object is in the {@link Resource#getContents content tree} of the resource.
723    * @param ancestorResource the ancestor resource in question.
724    * @param eObject the object to test.
725    * @return whether the resource is an ancestor of the object.
726    * @see EObject#eContainer
727    * @see EObject#eResource
728    */

729   public static boolean isAncestor(Resource ancestorResource, EObject eObject)
730   {
731     return eObject.eResource() == ancestorResource;
732   }
733
734   /**
735    * Returns whether the given resource set is that of the object,
736    * i.e., whether the object is in the {@link Resource#getContents content tree} of the resource set.
737    * @param ancestorResourceSet the ancestor resource set in question.
738    * @param eObject the object to test.
739    * @return whether the resource set is an ancestor of the object.
740    * @see EObject#eContainer
741    * @see EObject#eResource
742    * @see Resource#getResourceSet
743    */

744   public static boolean isAncestor(ResourceSet ancestorResourceSet, EObject eObject)
745   {
746     Resource resource = eObject.eResource();
747     return resource != null && resource.getResourceSet() == ancestorResourceSet;
748   }
749
750   /**
751    * Returns whether any EObject, Resource, or ResourceSet in the collection is an ancestor of the EObject.
752    * @param ancestorEMFObjects the collection of ancestor objects in question.
753    * @param eObject the object to test.
754    * @return whether any object in the collection is an ancestor of the object.
755    */

756   public static boolean isAncestor(Collection JavaDoc ancestorEMFObjects, EObject eObject)
757   {
758     // Is it directly contained
759
//
760
if (ancestorEMFObjects.contains(eObject))
761     {
762       return true;
763     }
764
765     // Is the container contained.
766
//
767
for (EObject container = eObject.eContainer(); container != null; container = container.eContainer())
768     {
769       if (ancestorEMFObjects.contains(container))
770       {
771         return true;
772       }
773       eObject = container;
774     }
775
776     // Is the resource contained.
777
//
778
Resource resource = eObject.eResource();
779     if (resource != null)
780     {
781       if (ancestorEMFObjects.contains(resource))
782       {
783         return true;
784       }
785
786       // Is the resource set contained.
787
//
788
ResourceSet resourceSet = resource.getResourceSet();
789       if (resourceSet != null)
790       {
791         if (ancestorEMFObjects.contains(resourceSet))
792         {
793           return true;
794         }
795       }
796     }
797
798     // That's it then.
799
//
800
return false;
801   }
802
803   /**
804    * Returns a tree iterator over the content trees
805    * recursively defined by
806    * {@link ResourceSet#getResources()},
807    * {@link Resource#getContents()},
808    * and {@link EObject#eContents()}.
809    * It uses a special iterator for ResourceSet.getResources
810    * that is tolerant of growth in the underlying collection
811    * which result from demand loaded resources;
812    * the iterator will walk these additional resources.
813    * @param emfObjects the collection of objects to iterate over.
814    * @return a tree iterator over the objects and their contents.
815    * @see ContentTreeIterator
816    */

817   public static TreeIterator getAllContents(Collection JavaDoc emfObjects)
818   {
819     return new ContentTreeIterator(emfObjects);
820   }
821
822   /**
823    * An iterator over the tree contents of a collection of EObjects, Resources, and ResourceSets;
824    * use {@link EcoreUtil#getAllContents getAllContents} to create a new instance.
825    * It provides a special iterator for ResourceSet.getResources
826    * that is tolerant of growth in the underlying collection
827    * which result from demand loaded resources;
828    * the iterator will walk these additional resources.
829    */

830   public static class ContentTreeIterator extends AbstractTreeIterator
831   {
832     /**
833      * The collection of objects being iterated over.
834      */

835     protected Collection JavaDoc emfObjects;
836
837     /**
838      * The most recently created iterator over a resource set's resources.
839      * This iterator needs special handling because it returns <code>true</code> for <code>hasNext()</code>
840      * even when the list is exhausted.
841      * This ensures that any growth in the resources list will not be overlooked.
842      */

843     protected ResourcesIterator resourceSetIterator;
844
845     /**
846      * Creates an instance for the given collection of objects.
847      * @param emfObjects the collection of objects to iterate over.
848      */

849     protected ContentTreeIterator(Collection JavaDoc emfObjects)
850     {
851       super(emfObjects, false);
852       this.emfObjects = emfObjects;
853     }
854
855     /**
856      * Returns an iterator over the children of the given parent object.
857      * @param object the parent object.
858      * @return the children iterator.
859      */

860     public Iterator JavaDoc getChildren(Object JavaDoc object)
861     {
862       if (object instanceof EObject)
863       {
864         return getEObjectChildren((EObject)object);
865       }
866       else if (object instanceof Resource)
867       {
868         return getResourceChildren((Resource)object);
869       }
870       else if (object instanceof ResourceSet)
871       {
872         return getResourceSetChildren((ResourceSet)object);
873       }
874       else if (object == emfObjects)
875       {
876         return emfObjects.iterator();
877       }
878       else
879       {
880         return getObjectChildren(object);
881       }
882     }
883
884     /**
885      * Returns an iterator over the {@link EObject#eContents() children} of the given parent EObject.
886      * @param eObject the parent object.
887      * @return the children iterator.
888      */

889     protected Iterator JavaDoc getEObjectChildren(EObject eObject)
890     {
891       return eObject.eContents().iterator();
892     }
893
894     /**
895      * Returns an iterator over the {@link Resource#getContents() children} of the given parent resource.
896      * @param resource the parent resource.
897      * @return the children iterator.
898      */

899     protected Iterator JavaDoc getResourceChildren(Resource resource)
900     {
901       return resource.getContents().iterator();
902     }
903
904     /**
905      * Returns the next object and advances the iterator.
906      * This override handles the {@link #resourceSetIterator} in a special way,
907      * i.e., it skips the null object that iterator yields as the last fake item of the list.
908      * @return the next object.
909      */

910     public boolean hasNext()
911     {
912       Iterator JavaDoc iterator;
913       if (!includeRoot && data == null)
914       {
915         nextPruneIterator = getChildren(object);
916         add(nextPruneIterator);
917         iterator = nextPruneIterator;
918       }
919       else
920       {
921         // We don't create an iterator stack until the root mapping itself has been returned by next once.
922
// After that the stack should be non-empty and the top iterator should yield true for hasNext.
923
//
924
if (data == null)
925         {
926           return true;
927         }
928         else if (isEmpty())
929         {
930           return false;
931         }
932         else
933         {
934           iterator = (Iterator JavaDoc)data[size - 1];
935         }
936       }
937
938       // If we are on the special resource set iterator, and there isn't really a next object at this point...
939
//
940
if (iterator == resourceSetIterator && !resourceSetIterator.reallyHasNext())
941       {
942         // Skip the dummy null object and test again.
943
//
944
next();
945         return hasNext();
946       }
947       else
948       {
949         return iterator.hasNext();
950       }
951     }
952
953     /**
954      * A special iterator that's tolerant of growth in the list of resources
955      * which can result from demand loading when traversing the tree of contents.
956      */

957     protected static class ResourcesIterator implements Iterator JavaDoc
958     {
959       /**
960        * The resources to iterator over.
961        */

962       protected List JavaDoc resources;
963
964       /**
965        * The current index of the iterator.
966        */

967       protected int index = 0;
968
969       /**
970        * Constructs an instance.
971        * @param resources the list of resources.
972        */

973       public ResourcesIterator(List JavaDoc resources)
974       {
975         this.resources = resources;
976       }
977
978       /**
979        * Returns whether there really are any resources left.
980        * @return whether there really are any resources left.
981        */

982       public boolean reallyHasNext()
983       {
984         return index < resources.size();
985       }
986
987       /**
988        * Returns whether there might be resources left by the time we next check.
989        * This returns <code>true</code> when the index is equal to the size,
990        * because the tree iterator will still be set to yield the last of the contents of the resource,
991        * and accessing that may cause another resource to be loaded.
992        * @return whether there might be resources left by the time we next check.
993        */

994       public boolean hasNext()
995       {
996         return index <= resources.size();
997       }
998
999       /**
1000       * Returns the next item, or <code>null</code> if there isn't one.
1001       * @return the next item, or <code>null</code> if there isn't one.
1002       */

1003      public Object JavaDoc next()
1004      {
1005        if (index >= resources.size())
1006        {
1007          ++index;
1008          return null;
1009        }
1010        else
1011        {
1012          return resources.get(index++);
1013        }
1014      }
1015
1016      /**
1017       * @throws UnsupportedOperationException always.
1018       */

1019      public void remove()
1020      {
1021        throw new UnsupportedOperationException JavaDoc();
1022      }
1023    }
1024
1025    /**
1026     * Returns an iterator over the {@link ResourceSet#getResources() children} of the given parent resource set.
1027     * It also records the result in {@link #resourceSetIterator} for special handling in {@link #hasNext()}.
1028     * @param resourceSet the parent resource set.
1029     * @return the children iterator.
1030     */

1031    protected Iterator JavaDoc getResourceSetChildren(ResourceSet resourceSet)
1032    {
1033      return resourceSetIterator = new ResourcesIterator(resourceSet.getResources());
1034    }
1035
1036    /**
1037     * Returns an empty iterator; subclasses may override this method.
1038     * @param object the parent object.
1039     * @return the children iterator.
1040     */

1041    protected Iterator JavaDoc getObjectChildren(Object JavaDoc object)
1042    {
1043      return ECollections.EMPTY_ELIST.iterator();
1044    }
1045  }
1046
1047  /**
1048   * A mapping building traverser of a collection of {@link EcoreUtil#getAllContents content trees};
1049   * the map is from target {@link EObject object} to a collection of {@link org.eclipse.emf.ecore.EStructuralFeature.Setting}.
1050   * Since this implementation extends a Map implementation, it can yield itself as the result for most operations.
1051   * The traverser considers each EObject in the {@link EObject#eCrossReferences} of each EObject in the content tree,
1052   * and creates a setting for each positive match.
1053   * This default implementation {@link #find creates} a map of all cross references.
1054   */

1055  public static class CrossReferencer extends HashMap JavaDoc
1056  {
1057    /**
1058     * The collection of objects being cross referenced.
1059     */

1060    protected Collection JavaDoc emfObjects;
1061
1062    /**
1063     * Creates an instance for the given object.
1064     * @param eObject the object to cross reference.
1065     */

1066    protected CrossReferencer(EObject eObject)
1067    {
1068      this.emfObjects = Collections.singleton(eObject);
1069    }
1070
1071    /**
1072     * Creates an instance for the given resource.
1073     * @param resource the resource to cross reference.
1074     */

1075    protected CrossReferencer(Resource resource)
1076    {
1077      this.emfObjects = Collections.singleton(resource);
1078    }
1079
1080    /**
1081     * Creates an instance for the given resource set.
1082     * @param resourceSet the resource set to cross reference.
1083     */

1084    protected CrossReferencer(ResourceSet resourceSet)
1085    {
1086      this.emfObjects = Collections.singleton(resourceSet);
1087    }
1088
1089    /**
1090     * Creates an instance for the given collection of objects.
1091     * @param emfObjects the collection of objects to cross reference.
1092     */

1093    protected CrossReferencer(Collection JavaDoc emfObjects)
1094    {
1095      this.emfObjects = emfObjects;
1096    }
1097
1098    /**
1099     * Return true if the cross referencer should include references from children of the specified object.
1100     * @param eObject an object in the cross referencer's content tree.
1101     * @return if the cross referencer should include references from children of the object.
1102     */

1103    protected boolean containment(EObject eObject)
1104    {
1105      return true;
1106    }
1107
1108    /**
1109     * Return true if the specified eReference from eObject to crossReferencedEObject should be
1110     * considiered a cross reference by this cross referencer.
1111     * @param eObject an object in the cross referencer's content tree.
1112     * @param eReference a reference from the object.
1113     * @param crossReferencedEObject the target of the specified reference.
1114     * @return if the cross referencer should consider the specified reference a cross reference.
1115     */

1116    protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject)
1117    {
1118      return true;
1119    }
1120
1121    /**
1122     * Return true if cross references that are proxies should be resolved.
1123     * @return if the cross referencer should resolve proxies.
1124     */

1125    protected boolean resolve()
1126    {
1127      return true;
1128    }
1129
1130    /**
1131     * Return a collection to use for storing {@link org.eclipse.emf.ecore.EStructuralFeature.Setting settings}.
1132     * @return a collection for settings.
1133     */

1134    protected Collection JavaDoc newCollection()
1135    {
1136      return new ArrayList JavaDoc();
1137    }
1138
1139    /**
1140     * Return the collection of cross reference {@link org.eclipse.emf.ecore.EStructuralFeature.Setting settings}
1141     * for the specified key (target object).
1142     * @param key the key for the cross referencer's map.
1143     * @return the collection of settings.
1144     */

1145    protected Collection JavaDoc getCollection(Object JavaDoc key)
1146    {
1147      Collection JavaDoc result = (Collection JavaDoc)get(key);
1148      if (result == null)
1149      {
1150        put(key, result = newCollection());
1151      }
1152      return result;
1153    }
1154
1155    /**
1156     * Return a tree iterator over the content trees of this cross referencer's objects.
1157     * @return a tree iterator over content trees.
1158     */

1159    protected TreeIterator newContentsIterator()
1160    {
1161      return new ContentTreeIterator(emfObjects);
1162    }
1163
1164    /**
1165     * Compute the map of cross references.
1166     */

1167    protected void crossReference()
1168    {
1169      for (TreeIterator contents = newContentsIterator(); contents.hasNext();)
1170      {
1171        Object JavaDoc content = contents.next();
1172        if (content instanceof EObject)
1173        {
1174          EObject eObject = (EObject)content;
1175          if (containment(eObject))
1176          {
1177            handleCrossReference(eObject);
1178          }
1179          else
1180          {
1181            contents.prune();
1182          }
1183        }
1184      }
1185    }
1186
1187    protected EContentsEList.FeatureIterator getCrossReferences(EObject eObject)
1188    {
1189      return
1190        (EContentsEList.FeatureIterator)
1191          (resolve() ?
1192            eObject.eCrossReferences().iterator() :
1193            ((InternalEList)eObject.eCrossReferences()).basicIterator());
1194    }
1195
1196    protected void handleCrossReference(EObject eObject)
1197    {
1198      InternalEObject internalEObject = (InternalEObject)eObject;
1199      for (EContentsEList.FeatureIterator crossReferences = getCrossReferences(internalEObject); crossReferences.hasNext();)
1200      {
1201        EObject crossReferencedEObject = (EObject)crossReferences.next();
1202        if (crossReferencedEObject != null)
1203        {
1204          EReference eReference = (EReference)crossReferences.feature();
1205          if (crossReference(internalEObject, eReference, crossReferencedEObject))
1206          {
1207            getCollection(crossReferencedEObject).add(internalEObject.eSetting(eReference));
1208          }
1209        }
1210      }
1211    }
1212
1213    /**
1214     * Reset this cross referencer's object set.
1215     */

1216    protected void done()
1217    {
1218      emfObjects = null;
1219    }
1220
1221    /**
1222     * Returns a map of all cross references in the content tree.
1223     * @param emfObjects a collection of objects whose combined content trees should be considered.
1224     * @return a map of cross references.
1225     */

1226    public static Map JavaDoc find(Collection JavaDoc emfObjects)
1227    {
1228      CrossReferencer result = new CrossReferencer(emfObjects);
1229      result.crossReference();
1230      result.done();
1231      return result;
1232    }
1233
1234    /**
1235     * Returns a string representation of this cross referencer.
1236     * @return the string representation.
1237     */

1238    public String JavaDoc toString()
1239    {
1240      StringBuffer JavaDoc result = new StringBuffer JavaDoc("{"); // }
1241

1242      for (Iterator JavaDoc i = entrySet().iterator(); i.hasNext();)
1243      {
1244        Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
1245        EObject eObject = (EObject)entry.getKey();
1246        result.append(getIdentification(eObject));
1247        result.append("=[");
1248        Collection JavaDoc collection = (Collection JavaDoc)entry.getValue();
1249        for (Iterator JavaDoc j = collection.iterator(); j.hasNext();)
1250        {
1251          EStructuralFeature.Setting setting = (EStructuralFeature.Setting)j.next();
1252          EStructuralFeature eStructuralFeature = setting.getEStructuralFeature();
1253          result.append(eStructuralFeature.getName());
1254          result.append("<-");
1255          result.append(getIdentification(setting.getEObject()));
1256          if (j.hasNext())
1257          {
1258            result.append(", ");
1259          }
1260        }
1261        result.append(']');
1262      }
1263
1264      // {
1265
result.append('}');
1266      return result.toString();
1267    }
1268
1269    /**
1270     * Print the specified cross reference map to the specified stream.
1271     * @param out the stream to print to.
1272     * @param crossReferenceMap a map (cross referencer) to print.
1273     */

1274    public static void print(PrintStream JavaDoc out, Map JavaDoc crossReferenceMap)
1275    {
1276      out.println('{'); // }
1277

1278      for (Iterator JavaDoc i = crossReferenceMap.entrySet().iterator(); i.hasNext();)
1279      {
1280        Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
1281        EObject eObject = (EObject)entry.getKey();
1282        out.print(" ");
1283        out.print(getIdentification(eObject));
1284        Collection JavaDoc collection = (Collection JavaDoc)entry.getValue();
1285        if (collection.isEmpty())
1286        {
1287          out.println(" =[]");
1288        }
1289        else
1290        {
1291          out.println(" =[");
1292          for (Iterator JavaDoc j = collection.iterator(); j.hasNext();)
1293          {
1294            EStructuralFeature.Setting setting = (EStructuralFeature.Setting)j.next();
1295            EStructuralFeature eStructuralFeature = setting.getEStructuralFeature();
1296            out.print(" ");
1297            out.print(eStructuralFeature.getName());
1298            out.print("<-");
1299            out.print(getIdentification(setting.getEObject()));
1300            if (j.hasNext())
1301            {
1302              out.println(",");
1303            }
1304          }
1305          out.println(']');
1306        }
1307      }
1308
1309      // {
1310
out.println('}');
1311    }
1312
1313    /**
1314     * Print the specified collection of {@link org.eclipse.emf.ecore.EStructuralFeature.Setting settings}
1315     * to the specified stream.
1316     * @param out the stream to print to.
1317     * @param settings a collection of settings.
1318     */

1319    public static void print(PrintStream JavaDoc out, Collection JavaDoc settings)
1320    {
1321      if (settings.isEmpty())
1322      {
1323        out.println("[]");
1324      }
1325      else
1326      {
1327        out.println("[");
1328        for (Iterator JavaDoc j = settings.iterator(); j.hasNext();)
1329        {
1330          EStructuralFeature.Setting setting = (EStructuralFeature.Setting)j.next();
1331          EStructuralFeature eStructuralFeature = setting.getEStructuralFeature();
1332          out.print(" ");
1333          out.print(eStructuralFeature.getName());
1334          out.print("<-");
1335          out.print(getIdentification(setting.getEObject()));
1336          if (j.hasNext())
1337          {
1338            out.println(",");
1339          }
1340        }
1341        out.println(']');
1342      }
1343    }
1344  }
1345
1346  /**
1347   * A cross referencer that finds all references that are not contained within the content trees.
1348   */

1349  public static class ExternalCrossReferencer extends CrossReferencer
1350  {
1351    /**
1352     * Creates an instance for the given collection of objects.
1353     * @param emfObjects the collection of objects to cross reference.
1354     */

1355    protected ExternalCrossReferencer(Collection JavaDoc emfObjects)
1356    {
1357      super(emfObjects);
1358    }
1359
1360    /**
1361     * Creates an instance for the given object.
1362     * @param eObject the object to cross reference.
1363     */

1364    protected ExternalCrossReferencer(EObject eObject)
1365    {
1366      super(eObject);
1367    }
1368
1369    /**
1370     * Creates an instance for the given resource.
1371     * @param resource the resource to cross reference.
1372     */

1373    protected ExternalCrossReferencer(Resource resource)
1374    {
1375      super(Collections.singleton(resource));
1376    }
1377
1378    /**
1379     * Creates an instance for the given resource set.
1380     * @param resourceSet the resource set to cross reference.
1381     */

1382    protected ExternalCrossReferencer(ResourceSet resourceSet)
1383    {
1384      super(Collections.singleton(resourceSet));
1385    }
1386
1387    /**
1388     * Return true if the specified eReference from eObject to crossReferencedEObject should be
1389     * considiered a cross reference by this cross referencer.
1390     * @param eObject an object in the cross referencer's content tree.
1391     * @param eReference a reference from the object.
1392     * @param crossReferencedEObject the target of the specified reference.
1393     * @return if the cross referencer should consider the specified reference a cross reference.
1394     */

1395    protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject)
1396    {
1397      return !isAncestor(emfObjects, crossReferencedEObject);
1398    }
1399
1400    /**
1401     * Returns the map of external cross references for this cross referencer.
1402     * @return a map of cross references.
1403     */

1404    protected Map JavaDoc findExternalCrossReferences()
1405    {
1406      crossReference();
1407      done();
1408      return this;
1409    }
1410
1411    /**
1412     * Returns a map of all external cross references from the specified content tree.
1413     * @param eObject an object whose content trees should be considered.
1414     * @return a map of cross references.
1415     */

1416    public static Map JavaDoc find(EObject eObject)
1417    {
1418      return new ExternalCrossReferencer(eObject).findExternalCrossReferences();
1419    }
1420
1421    /**
1422     * Returns a map of all external cross references from the specified content tree.
1423     * @param resource a resource whose content tree should be considered.
1424     * @return a map of cross references.
1425     */

1426    public static Map JavaDoc find(Resource resource)
1427    {
1428      return new ExternalCrossReferencer(resource).findExternalCrossReferences();
1429    }
1430
1431    /**
1432     * Returns a map of all external cross references from the specified content tree.
1433     * @param resourceSet a resourceSet whose content tree should be considered.
1434     * @return a map of cross references.
1435     */

1436    public static Map JavaDoc find(ResourceSet resourceSet)
1437    {
1438      return new ExternalCrossReferencer(resourceSet).findExternalCrossReferences();
1439    }
1440
1441    /**
1442     * Returns a map of all external cross references from the combined content trees of the specified collection of objects.
1443     * @param emfObjectsToSearch a collection of objects whose combined content trees should be considered.
1444     * @return a map of cross references.
1445     */

1446    public static Map JavaDoc find(Collection JavaDoc emfObjectsToSearch)
1447    {
1448      return new ExternalCrossReferencer(emfObjectsToSearch).findExternalCrossReferences();
1449    }
1450  }
1451
1452  /**
1453   * Returns <code>true</code> if <code>eObject1</code> and <code>eObject2</code> are {@link EqualityHelper equal},
1454   * <code>false</code> otherwise.
1455   * @return whether <code>eObject1</code> and <code>eObject2</code> are equal.
1456   * @see EqualityHelper
1457   * @since 2.1.0
1458   */

1459  public static boolean equals(EObject eObject1, EObject eObject2)
1460  {
1461    EqualityHelper equalityHelper = new EqualityHelper();
1462    return equalityHelper.equals(eObject1, eObject2);
1463  }
1464
1465  /**
1466   * <p>
1467   * A helper for determining whether two {@link EObject}s are <em>structurally equal</em>.
1468   * Two EObjects, <code>eObject1</code> and <code>eObject2</code>, are structurally equal
1469   * if their {@link EObject.eClass() classes} are the same,
1470   * and if, for each {@link EStructuralFeature#isDerived non-derived} {@link EStructuralFeature feature} of the class,
1471   * the {@link EObject.eIsSet(EStructuralFeature) isSet} states are the same
1472   * and the corresponding {@link EObject#eGet(EStructuralFeature) values} are structurally equal
1473   * as appropriate for the type of feature.
1474   * For {@link FeatureMapUtil.isFeatureMap() feature map} features,
1475   * the positionally corresponding {@link FeatureMap.Entry entries}
1476   * must have the same {@link FeatureMap.Entry#getEStructuralFeature() entry feature}s
1477   * and must have structurally equal {@link FeatureMap.Entry#getValue() value}s
1478   * as appropriate for the type of entry's feature.
1479   * For {@link EReference reference} features,
1480   * the corresponding values must recursively be structurally equal according to this definition.
1481   * For {@link EAttribute attribute} features,
1482   * the corresponding values must be equal according to Java equality.
1483   * Note that container references are derived and hence are ignored.
1484   * </p>
1485   * <p>
1486   * During the recursive process of determining {@link EcoreUtil#equals(EObject,EObject) equality},
1487   * the helper instance is populated as a two way map
1488   * such that a given <code>eObject1</code> is considered to be equal to at most one other <code>eObject2</code>,
1489   * i.e., <code>get(eObject1) == eObject2 && get(eObject2) == eObject1</code>.
1490   * While their features are being compared, the two objects are assumed to be equal:
1491   *<pre>
1492   * put(eObject1, eObject2);
1493   * put(eObject2, eObject1);
1494   *</pre>
1495   * Once that correspondence is established, an <code>eObject1</code> considered equal to a different <code>eObject2</code>
1496   * will not even be considered equal to itself.
1497   * This ensures that two objects are structurally equal only if the graphs formed by all their referenced objects
1498   * have the same topology.
1499   * </p>
1500   * @see EcoreUtil#equals(EObject, EObject)
1501   * @see EqualityHelper#equals(EObject, EObject)
1502   */

1503  public static class EqualityHelper extends HashMap JavaDoc
1504  {
1505    /**
1506     * Returns whether <code>eObject1</code> and <code>eObject2</code> are {@link EqualityHelper equal}
1507     * in the context of this helper instance.
1508     * @return whether <code>eObject1</code> and <code>eObject2</code> are equal.
1509     * @since 2.1.0
1510     */

1511    public boolean equals(EObject eObject1, EObject eObject2)
1512    {
1513      // If the first object is null, the second object must be null.
1514
//
1515
if (eObject1 == null)
1516      {
1517        return eObject2 == null;
1518      }
1519      
1520      // We know the first object isn't null, so if the second one is, it can't be equal.
1521
//
1522
if (eObject2 == null)
1523      {
1524        return false;
1525      }
1526
1527      // Both eObject1 and eObject2 are not null.
1528
// If eObject1 has been compared already...
1529
//
1530
Object JavaDoc eObject1MappedValue = get(eObject1);
1531      if (eObject1MappedValue != null)
1532      {
1533        // Then eObject2 must be that previous match.
1534
//
1535
return eObject1MappedValue == eObject2;
1536      }
1537
1538      // If eObject2 has been compared already...
1539
//
1540
Object JavaDoc eObject2MappedValue = get(eObject2);
1541      if (eObject2MappedValue != null)
1542      {
1543        // Then eObject1 must be that match.
1544
//
1545
return eObject2MappedValue == eObject1;
1546      }
1547
1548      // Neither eObject1 nor eObject2 have been compared yet.
1549

1550      // If eObject1 and eObject2 are the same instance...
1551
//
1552
if (eObject1 == eObject2)
1553      {
1554        // Match them and return true.
1555
//
1556
put(eObject1, eObject2);
1557        put(eObject2, eObject1);
1558        return true;
1559      }
1560
1561      // If they don't have the same class, they can't be equal.
1562
//
1563
EClass eClass = eObject1.eClass();
1564      if (eClass != eObject2.eClass())
1565      {
1566        return false;
1567      }
1568
1569      // Assume from now on that they match.
1570
//
1571
put(eObject1, eObject2);
1572      put(eObject2, eObject1);
1573
1574      
1575      // Check all the values.
1576
//
1577
for (int i = 0, size = eClass.getFeatureCount(); i < size; ++i)
1578      {
1579        // Ignore derived features.
1580
//
1581
EStructuralFeature feature = eClass.getEStructuralFeature(i);
1582        if (!feature.isDerived())
1583        {
1584          // If the set states aren't the same, or the values of the feature are not the structurally equal, they aren't equal.
1585
//
1586
boolean eIsSet = eObject1.eIsSet(feature);
1587          if (eIsSet != eObject2.eIsSet(feature) ||
1588                (feature instanceof EReference ?
1589                  !haveEqualReference(eObject1, eObject2, (EReference)feature) :
1590                  !haveEqualAttribute(eObject1, eObject2, (EAttribute)feature)))
1591          {
1592            return false;
1593          }
1594        }
1595      }
1596      
1597      // There's no reason they aren't equal, so they are.
1598
//
1599
return true;
1600    }
1601
1602    /**
1603     * Returns whether <code>list1</code> and <code>list2</code> contain
1604     * {@link #equals(EObject, EObject) equal} {@link EObject}s at the same index.
1605     * It is assumed that list1 and list2 only contain EObjects.
1606     * @return whether <code>list1</code> and <code>list2</code> contain equal objects.
1607     * @since 2.1.0
1608     */

1609    public boolean equals(List JavaDoc list1, List JavaDoc list2)
1610    {
1611      int size = list1.size();
1612      if (size != list2.size())
1613      {
1614        return false;
1615      }
1616
1617      for (int i = 0; i < size; i++)
1618      {
1619        EObject eObject1 = (EObject)list1.get(i);
1620        EObject eObject2 = (EObject)list2.get(i);
1621        if (!equals(eObject1, eObject2))
1622        {
1623          return false;
1624        }
1625      }
1626
1627      return true;
1628    }
1629
1630    /**
1631     * Returns whether the two objects have {@link EqualityHelper equal} {@link EObject#eGet(EStructuralFeature) value}s for the reference.
1632     * @return whether the two objects have equal values for the reference.
1633     * @since 2.1.0
1634     * @see #equals(EObject, EObject)
1635     * @see #equals(List, List)
1636     */

1637    protected boolean haveEqualReference(EObject eObject1, EObject eObject2, EReference reference)
1638    {
1639      Object JavaDoc value1 = eObject1.eGet(reference);
1640      Object JavaDoc value2 = eObject2.eGet(reference);
1641
1642      return
1643        reference.isMany() ?
1644          equals((List JavaDoc)value1, (List JavaDoc)value2) :
1645          equals((EObject)value1, (EObject)value2);
1646    }
1647
1648
1649    /**
1650     * Returns whether the two objects have {@link EqualityHelper equal} {@link EObject#eGet(EStructuralFeature) value}s for the attribute.
1651     * @return whether the two objects have equal values for the attribute.
1652     * @since 2.1.0
1653     * @see #equalFeatureMaps(FeatureMap, FeatureMap)
1654     */

1655    protected boolean haveEqualAttribute(EObject eObject1, EObject eObject2, EAttribute attribute)
1656    {
1657      Object JavaDoc value1 = eObject1.eGet(attribute);
1658      Object JavaDoc value2 = eObject2.eGet(attribute);
1659
1660      // If the first value is null, the second value must be null.
1661
//
1662
if (value1 == null)
1663      {
1664        return value2 == null;
1665      }
1666      
1667      // Since the first value isn't null, if the second one is, they aren't equal.
1668
//
1669
if (value2 == null)
1670      {
1671        return false;
1672      }
1673
1674      // If this is a feature map...
1675
//
1676
if (FeatureMapUtil.isFeatureMap(attribute))
1677      {
1678        // The feature maps must be equal.
1679
//
1680
FeatureMap featureMap1 = (FeatureMap)value1;
1681        FeatureMap featureMap2 = (FeatureMap)value2;
1682        return equalFeatureMaps(featureMap1, featureMap2);
1683      }
1684      else
1685      {
1686        // The values must be Java equal.
1687
//
1688
return value1.equals(value2);
1689      }
1690    }
1691
1692    /**
1693     * Returns whether the two feature maps are {@link EqualityHelper equal}.
1694     * @return whether the two feature maps are equal.
1695     * @since 2.1.0
1696     */

1697    protected boolean equalFeatureMaps(FeatureMap featureMap1, FeatureMap featureMap2)
1698    {
1699      // If they don't have the same size, the feature maps aren't equal.
1700
//
1701
int size = featureMap1.size();
1702      if (size != featureMap2.size())
1703      {
1704        return false;
1705      }
1706
1707      // Compare entries in order.
1708
//
1709
for (int i = 0; i < size; i++)
1710      {
1711        // If entries don't have the same feature, the feature maps aren't equal.
1712
//
1713
EStructuralFeature feature = featureMap1.getEStructuralFeature(i);
1714        if (feature != featureMap2.getEStructuralFeature(i))
1715        {
1716          return false;
1717        }
1718
1719        Object JavaDoc value1 = featureMap1.getValue(i);
1720        Object JavaDoc value2 = featureMap2.getValue(i);
1721
1722        if (feature instanceof EReference)
1723        {
1724          // If the referenced EObjects aren't equal, the feature maps aren't equal.
1725
//
1726
if (!equals((EObject)value1, (EObject)value2))
1727          {
1728            return false;
1729          }
1730        }
1731        // If the values aren't Java equal, the feature maps aren't equal.
1732
//
1733
else if (value1 == null ? value2 != null : !value1.equals(value2))
1734        {
1735          return false;
1736        }
1737      }
1738
1739      // There is no reason they aren't equals.
1740
//
1741
return true;
1742    }
1743  } // EqualityHelper
1744

1745  /**
1746   * A cross referencer that finds each usage of an EObject or collection of EObjects.
1747   */

1748  public static class UsageCrossReferencer extends CrossReferencer
1749  {
1750    /**
1751     * The collection of usage target objects.
1752     */

1753    protected Collection JavaDoc eObjectsOfInterest;
1754
1755    /**
1756     * Creates an instance for the given object.
1757     * @param eObject the object to cross reference.
1758     */

1759    protected UsageCrossReferencer(EObject eObject)
1760    {
1761      super(eObject);
1762    }
1763
1764    /**
1765     * Creates an instance for the given resource.
1766     * @param resource the resource to cross reference.
1767     */

1768    protected UsageCrossReferencer(Resource resource)
1769    {
1770      super(resource);
1771    }
1772
1773    /**
1774     * Creates an instance for the given resource set.
1775     * @param resourceSet the resource set to cross reference.
1776     */

1777    protected UsageCrossReferencer(ResourceSet resourceSet)
1778    {
1779      super(resourceSet);
1780    }
1781
1782    /**
1783     * Creates an instance for the given collection of objects.
1784     * @param emfObjects the collection of objects to cross reference.
1785     */

1786    protected UsageCrossReferencer(Collection JavaDoc emfObjects)
1787    {
1788      super(emfObjects);
1789    }
1790
1791    /**
1792     * Return true if the specified eReference from eObject to crossReferencedEObject should be
1793     * considiered a cross reference by this cross referencer.
1794     * @param eObject an object in the cross referencer's content tree.
1795     * @param eReference a reference from the object.
1796     * @param crossReferencedEObject the target of the specified reference.
1797     * @return if the cross referencer should consider the specified reference a cross reference.
1798     */

1799    protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject)
1800    {
1801      return eObjectsOfInterest.contains(crossReferencedEObject);
1802    }
1803
1804    /**
1805     * Returns the collection of usage references to the specified object.
1806     * @param eObject the usage target.
1807     * @return a collection of cross references.
1808     */

1809    protected Collection JavaDoc findUsage(EObject eObject)
1810    {
1811      eObjectsOfInterest = Collections.singleton(eObject);
1812      crossReference();
1813      this.eObjectsOfInterest = null;
1814      done();
1815      return getCollection(eObject);
1816    }
1817
1818    /**
1819     * Returns the map of usage references to objects in the specified collection.
1820     * @param eObjectsOfInterest a collection of usage targets.
1821     * @return a map of cross references.
1822     */

1823    protected Map JavaDoc findAllUsage(Collection JavaDoc eObjectsOfInterest)
1824    {
1825      this.eObjectsOfInterest = eObjectsOfInterest;
1826      crossReference();
1827      this.eObjectsOfInterest = null;
1828      done();
1829      return this;
1830    }
1831
1832    /**
1833     * Returns a collection of usage references from the specified content tree.
1834     * @param eObjectOfInterest the usage target.
1835     * @param eObject an object whose content trees should be considered.
1836     * @return a collection of cross references.
1837     */

1838    public static Collection JavaDoc find(EObject eObjectOfInterest, EObject eObject)
1839    {
1840      return new UsageCrossReferencer(eObject).findUsage(eObjectOfInterest);
1841    }
1842
1843    /**
1844     * Returns a collection of usage references from the specified content tree.
1845     * @param eObjectOfInterest the usage target.
1846     * @param resource a resource whose content tree should be considered.
1847     * @return a collection of cross references.
1848     */

1849    public static Collection JavaDoc find(EObject eObjectOfInterest, Resource resource)
1850    {
1851      return new UsageCrossReferencer(resource).findUsage(eObjectOfInterest);
1852    }
1853
1854    /**
1855     * Returns a collection of usage references from the specified content tree.
1856     * @param eObjectOfInterest the usage target.
1857     * @param resourceSet a resource set whose content tree should be considered.
1858     * @return a collection of cross references.
1859     */

1860    public static Collection JavaDoc find(EObject eObjectOfInterest, ResourceSet resourceSet)
1861    {
1862      return new UsageCrossReferencer(resourceSet).findUsage(eObjectOfInterest);
1863    }
1864
1865    /**
1866     * Returns a collection of usage references from the combined content trees of the specified collection of objects.
1867     * @param eObjectOfInterest the usage target.
1868     * @param emfObjectsToSearch a collection of objects whose combined content trees should be considered.
1869     * @return a collection of cross references.
1870     */

1871    public static Collection JavaDoc find(EObject eObjectOfInterest, Collection JavaDoc emfObjectsToSearch)
1872    {
1873      return new UsageCrossReferencer(emfObjectsToSearch).findUsage(eObjectOfInterest);
1874    }
1875
1876    /**
1877     * Returns a map of usage references from the specified content tree.
1878     * @param eObjectsOfInterest a collection of usage targets.
1879     * @param eObject an object whose content trees should be considered.
1880     * @return a map of cross references.
1881     */

1882    public static Map JavaDoc findAll(Collection JavaDoc eObjectsOfInterest, EObject eObject)
1883    {
1884      return new UsageCrossReferencer(eObject).findAllUsage(eObjectsOfInterest);
1885    }
1886
1887    /**
1888     * Returns a map of usage references from the specified content tree.
1889     * @param eObjectsOfInterest a collection of usage targets.
1890     * @param resource a resource whose content tree should be considered.
1891     * @return a map of cross references.
1892     */

1893    public static Map JavaDoc findAll(Collection JavaDoc eObjectsOfInterest, Resource resource)
1894    {
1895      return new UsageCrossReferencer(resource).findAllUsage(eObjectsOfInterest);
1896    }
1897
1898    /**
1899     * Returns a map of usage references from the specified content tree.
1900     * @param eObjectsOfInterest a collection of usage targets.
1901     * @param resourceSet a resource set whose content tree should be considered.
1902     * @return a map of cross references.
1903     */

1904    public static Map JavaDoc findAll(Collection JavaDoc eObjectsOfInterest, ResourceSet resourceSet)
1905    {
1906      return new UsageCrossReferencer(resourceSet).findAllUsage(eObjectsOfInterest);
1907    }
1908
1909    /**
1910     * Returns a map of usage references from the combined content trees of the specified collection of objects.
1911     * @param eObjectsOfInterest a collection of usage targets.
1912     * @param emfObjectsToSearch a collection of objects whose combined content trees should be considered.
1913     * @return a map of cross references.
1914     */

1915    public static Map JavaDoc findAll(Collection JavaDoc eObjectsOfInterest, Collection JavaDoc emfObjectsToSearch)
1916    {
1917      return new UsageCrossReferencer(emfObjectsToSearch).findAllUsage(eObjectsOfInterest);
1918    }
1919  }
1920
1921  /**
1922   * A cross referencer that finds proxies; the cross referencer will not cause proxies to be resolved.
1923   */

1924  public static class ProxyCrossReferencer extends CrossReferencer
1925  {
1926    /**
1927     * Creates an instance for the given object.
1928     * @param eObject the object to cross reference.
1929     */

1930    protected ProxyCrossReferencer(EObject eObject)
1931    {
1932      super(eObject);
1933    }
1934
1935    /**
1936     * Creates an instance for the given resource.
1937     * @param resource the resource to cross reference.
1938     */

1939    protected ProxyCrossReferencer(Resource resource)
1940    {
1941      super(Collections.singleton(resource));
1942    }
1943
1944    /**
1945     * Creates an instance for the given resource set.
1946     * @param resourceSet the resource set to cross reference.
1947     */

1948    protected ProxyCrossReferencer(ResourceSet resourceSet)
1949    {
1950      super(Collections.singleton(resourceSet));
1951    }
1952
1953    /**
1954     * Creates an instance for the given collection of objects.
1955     * @param emfObjects the collection of objects to cross reference.
1956     */

1957    protected ProxyCrossReferencer(Collection JavaDoc emfObjects)
1958    {
1959      super(emfObjects);
1960    }
1961
1962    /**
1963     * Return true if potential cross references that are proxies should be resolved.
1964     * @return if the cross referencer should resolve proxies.
1965     */

1966    protected boolean resolve()
1967    {
1968      return false;
1969    }
1970
1971    /**
1972     * Return true if the specified eReference from eObject to crossReferencedEObject should be
1973     * considiered a cross reference by this cross referencer.
1974     * @param eObject an object in the cross referencer's content tree.
1975     * @param eReference a reference from the object.
1976     * @param crossReferencedEObject the target of the specified reference.
1977     * @return if the cross referencer should consider the specified reference a cross reference.
1978     */

1979    protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject)
1980    {
1981      return crossReferencedEObject.eIsProxy();
1982    }
1983
1984    /**
1985     * Returns the map of proxy references for this cross referencer.
1986     * @return a map of cross references.
1987     */

1988    protected Map JavaDoc findProxyCrossReferences()
1989    {
1990      crossReference();
1991      done();
1992      return this;
1993    }
1994
1995    /**
1996     * Returns a map of all proxy references from the specified content tree.
1997     * @param eObject an object whose content trees should be considered.
1998     * @return a map of cross references.
1999     */

2000    public static Map JavaDoc find(EObject eObject)
2001    {
2002      return new ProxyCrossReferencer(eObject).findProxyCrossReferences();
2003    }
2004
2005    /**
2006     * Returns a map of all proxy references from the specified content tree.
2007     * @param resource a resource whose content tree should be considered.
2008     * @return a map of cross references.
2009     */

2010    public static Map JavaDoc find(Resource resource)
2011    {
2012      return new ProxyCrossReferencer(resource).findProxyCrossReferences();
2013    }
2014
2015    /**
2016     * Returns a map of all proxy references from the specified content tree.
2017     * @param resourceSet a resourceSet whose content tree should be considered.
2018     * @return a map of cross references.
2019     */

2020    public static Map JavaDoc find(ResourceSet resourceSet)
2021    {
2022      return new ProxyCrossReferencer(resourceSet).findProxyCrossReferences();
2023    }
2024
2025    /**
2026     * Returns a map of all proxy references from the specified content tree.
2027     * @param emfObjects a collection of objects whose combined content trees should be considered.
2028     * @return a map of cross references.
2029     */

2030    public static Map JavaDoc find(Collection JavaDoc emfObjects)
2031    {
2032      return new ProxyCrossReferencer(emfObjects).findProxyCrossReferences();
2033    }
2034  }
2035
2036  /**
2037   * A cross referencer that finds proxies that cannot be resolved.
2038   */

2039  public static class UnresolvedProxyCrossReferencer extends CrossReferencer
2040  {
2041    /**
2042     * Creates an instance for the given object.
2043     * @param eObject the object to cross reference.
2044     */

2045    protected UnresolvedProxyCrossReferencer(EObject eObject)
2046    {
2047      super(eObject);
2048    }
2049
2050    /**
2051     * Creates an instance for the given resource.
2052     * @param resource the resource to cross reference.
2053     */

2054    protected UnresolvedProxyCrossReferencer(Resource resource)
2055    {
2056      super(Collections.singleton(resource));
2057    }
2058
2059    /**
2060     * Creates an instance for the given resource set.
2061     * @param resourceSet the resource set to cross reference.
2062     */

2063    protected UnresolvedProxyCrossReferencer(ResourceSet resourceSet)
2064    {
2065      super(Collections.singleton(resourceSet));
2066    }
2067
2068    /**
2069     * Creates an instance for the given collection of objects.
2070     * @param emfObjects the collection of objects to cross reference.
2071     */

2072    protected UnresolvedProxyCrossReferencer(Collection JavaDoc emfObjects)
2073    {
2074      super(emfObjects);
2075    }
2076
2077    /**
2078     * Return true if the specified eReference from eObject to crossReferencedEObject should be
2079     * considiered a cross reference by this cross referencer.
2080     * @param eObject an object in the cross referencer's content tree.
2081     * @param eReference a reference from the object.
2082     * @param crossReferencedEObject the target of the specified reference.
2083     * @return if the cross referencer should consider the specified reference a cross reference.
2084     */

2085    protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject)
2086    {
2087      return crossReferencedEObject.eIsProxy();
2088    }
2089
2090    /**
2091     * Returns the map of unresolvable proxies for this cross referencer.
2092     * @return a map of cross references.
2093     */

2094    protected Map JavaDoc findUnresolvedProxyCrossReferences()
2095    {
2096      crossReference();
2097      done();
2098      return this;
2099    }
2100
2101    /**
2102     * Returns a map of all unresolvable proxies from the specified content tree.
2103     * @param eObject an object whose content trees should be considered.
2104     * @return a map of cross references.
2105     */

2106    public static Map JavaDoc find(EObject eObject)
2107    {
2108      return new UnresolvedProxyCrossReferencer(eObject).findUnresolvedProxyCrossReferences();
2109    }
2110
2111    /**
2112     * Returns a map of all unresolvable proxies from the specified content tree.
2113     * @param resource a resource whose content tree should be considered.
2114     * @return a map of cross references.
2115     */

2116    public static Map JavaDoc find(Resource resource)
2117    {
2118      return new UnresolvedProxyCrossReferencer(resource).findUnresolvedProxyCrossReferences();
2119    }
2120
2121    /**
2122     * Returns a map of all unresolvable proxies from the specified content tree.
2123     * @param resourceSet a resourceSet whose content tree should be considered.
2124     * @return a map of cross references.
2125     */

2126    public static Map JavaDoc find(ResourceSet resourceSet)
2127    {
2128      return new UnresolvedProxyCrossReferencer(resourceSet).findUnresolvedProxyCrossReferences();
2129    }
2130
2131    /**
2132     * Returns a map of all unresolvable proxies from the specified content tree.
2133     * @param emfObjects a collection of objects whose combined content trees should be considered.
2134     * @return a map of cross references.
2135     */

2136    public static Map JavaDoc find(Collection JavaDoc emfObjects)
2137    {
2138      return new UnresolvedProxyCrossReferencer(emfObjects).findUnresolvedProxyCrossReferences();
2139    }
2140  }
2141
2142  /**
2143   * Returns a unique string identification of the eObject;
2144   * it is structured as follows:
2145   *<pre>
2146   * &lt;java-class-name>[/&lt;dynamic-eclass-name>]@&lt;java-hex-hash-code>{&lt;uri-of-eobject>}
2147   *</pre>
2148   * @param eObject the object for which to get an identification.
2149   * @return the identification string for the object.
2150   */

2151  public static String JavaDoc getIdentification(EObject eObject)
2152  {
2153    StringBuffer JavaDoc result = new StringBuffer JavaDoc(eObject.getClass().getName());
2154    EClass eClass = eObject.eClass();
2155    if (eClass.getInstanceClassName() == null)
2156    {
2157      result.append('/');
2158      result.append(eClass.getEPackage().getNsURI());
2159      result.append('#');
2160      result.append(eClass.getName());
2161    }
2162    result.append('@');
2163    result.append(Integer.toHexString(eObject.hashCode()));
2164
2165    result.append('{');
2166    result.append(getURI(eObject));
2167    result.append('}');
2168
2169    return result.toString();
2170  }
2171
2172  /**
2173   * Returns a URI for the eObject,
2174   * i.e., either
2175   * the eProxyURI,
2176   * the URI of the eResource with the fragment produced by the eResource,
2177   * or the URI consisting of just the fragment that would be produced by a default Resource
2178   * with the eObject as its only contents.
2179   * @param eObject the object for which to get the URI.
2180   * @return the URI for the object.
2181   */

2182  public static URI getURI(EObject eObject)
2183  {
2184    // If it's a proxy, use that.
2185
//
2186
URI proxyURI = ((InternalEObject)eObject).eProxyURI();
2187    if (proxyURI != null)
2188    {
2189      return proxyURI;
2190    }
2191    else
2192    {
2193      // If it is in a resource, form the URI relative to that resource.
2194
//
2195
EObject eRootContainer = EcoreUtil.getRootContainer(eObject);
2196      Resource resource = eRootContainer.eResource();
2197      if (resource != null)
2198      {
2199        return resource.getURI().appendFragment(resource.getURIFragment(eObject));
2200      }
2201      else
2202      {
2203        // Implement the default encoding algorithm.
2204
//
2205
StringBuffer JavaDoc result = new StringBuffer JavaDoc("#//");
2206        List JavaDoc uriFragmentPath = new ArrayList JavaDoc();
2207        for (EObject container = eObject.eContainer(); container != null; container = eObject.eContainer())
2208        {
2209          uriFragmentPath.add(((InternalEObject)container).eURIFragmentSegment(eObject.eContainmentFeature(), eObject));
2210          eObject = container;
2211        }
2212
2213        int size = uriFragmentPath.size();
2214        if (size > 0)
2215        {
2216          for (int i = size - 1;; --i)
2217          {
2218            result.append((String JavaDoc)uriFragmentPath.get(i));
2219            if (i == 0)
2220            {
2221              break;
2222            }
2223            else
2224            {
2225              result.append('/');
2226            }
2227          }
2228        }
2229
2230        return URI.createURI(result.toString());
2231      }
2232    }
2233  }
2234
2235  /**
2236   * Searches for the first occurence of the given argument in list starting from
2237   * a specified index. The equality is tested using the operator <tt>==<tt> and
2238   * the <tt>equals</tt> method.
2239   * @param list
2240   * @param o an object (can be null)
2241   * @param fromIndex
2242   * @return the index of the first occurrence of the argument in this
2243   * list (where index>=fromIndex); returns <tt>-1</tt> if the
2244   * object is not found.
2245   * @deprecated replaced by {@link ECollections#indexOf(List, Object, int)} in 2.1.0
2246   */

2247  public static int indexOf(List JavaDoc list, Object JavaDoc o, int fromIndex)
2248  {
2249    return ECollections.indexOf(list, o, fromIndex);
2250  }
2251
2252  /**
2253   * Sets the <code>eList</code>'s contents and order to be exactly that of the <code>prototype</code> collection.
2254   * This implementation mimimizes the number of notifications the operation will produce.
2255   * Objects already in the list will be moved, missing objects will be added, and extra objects will be removed.
2256   * If <code>eList</code>'s contents and order are already exactly that of the <code>prototype</code> collection,
2257   * no change will be made.
2258   * @param eList the list to set.
2259   * @param prototypeCollection the collection representing the desired content and order.
2260   * @deprecated replaced by {@link ECollections#setEList(EList, List)} in 2.1.0
2261   */

2262  public static void setEList(EList eList, Collection JavaDoc prototypeCollection)
2263  {
2264    ECollections.setEList(eList, new ArrayList JavaDoc(prototypeCollection));
2265  }
2266
2267  /**
2268   * Sets the <code>eList</code>'s contents and order to be exactly that of the <code>prototype</code> list.
2269   * This implementation mimimizes the number of notifications the operation will produce.
2270   * Objects already in the list will be moved, missing objects will be added, and extra objects will be removed.
2271   * If <code>eList</code>'s contents and order are already exactly that of the <code>prototype</code> list,
2272   * no change will be made.
2273   * @param eList the list to set.
2274   * @param prototypeList the list representing the desired content and order.
2275   * @deprecated replaced by {@link ECollections#setEList(EList, List)} in 2.1.0
2276   */

2277  public static void setEList(EList eList, List JavaDoc prototypeList)
2278  {
2279    ECollections.setEList(eList, prototypeList);
2280  }
2281
2282  /**
2283   * Removes the value from the setting.
2284   * @param setting the setting holding the value.
2285   * @param value the value to remove.
2286   */

2287  public static void remove(EStructuralFeature.Setting setting, Object JavaDoc value)
2288  {
2289    if (setting.getEStructuralFeature().isMany())
2290    {
2291      ((List JavaDoc)setting.get(false)).remove(value);
2292    }
2293    else
2294    {
2295      setting.unset();
2296    }
2297  }
2298
2299  /**
2300   * Replaces the old value in the setting with the new value.
2301   * @param setting the setting holding the values.
2302   * @param oldValue the value to replace.
2303   * @param newValue the replacement value.
2304   */

2305  public static void replace(EStructuralFeature.Setting setting, Object JavaDoc oldValue, Object JavaDoc newValue)
2306  {
2307    if (setting.getEStructuralFeature().isMany())
2308    {
2309      List JavaDoc list = (List JavaDoc)setting.get(false);
2310      list.set(list.indexOf(oldValue), newValue);
2311    }
2312    else
2313    {
2314      setting.set(newValue);
2315    }
2316  }
2317
2318  /**
2319   * Removes the value from the feature of the object.
2320   * @param eObject the object holding the value.
2321   * @param eStructuralFeature the feature of the object holding the value.
2322   * @param value the value to remove.
2323   */

2324  public static void remove(EObject eObject, EStructuralFeature eStructuralFeature, Object JavaDoc value)
2325  {
2326    if (eStructuralFeature.isMany())
2327    {
2328      ((List JavaDoc)eObject.eGet(eStructuralFeature)).remove(value);
2329    }
2330    else
2331    {
2332      eObject.eUnset(eStructuralFeature);
2333    }
2334  }
2335
2336  /**
2337   * Replaces the old value in the object's feature with the new value.
2338   * @param eObject the object holding the values.
2339   * @param eStructuralFeature the feature of the object holding the values.
2340   * @param oldValue the value to replace.
2341   * @param newValue the replacement value.
2342   */

2343  public static void replace(EObject eObject, EStructuralFeature eStructuralFeature, Object JavaDoc oldValue, Object JavaDoc newValue)
2344  {
2345    if (eStructuralFeature.isMany())
2346    {
2347      List JavaDoc list = (List JavaDoc)eObject.eGet(eStructuralFeature);
2348      list.set(list.indexOf(oldValue), newValue);
2349    }
2350    else
2351    {
2352      eObject.eSet(eStructuralFeature, newValue);
2353    }
2354  }
2355
2356  /**
2357   * Removes the object from its {@link EObject#eResource containing} resource
2358   * or its {@link EObject#eContainer containing} object.
2359   * @param eObject the object to remove.
2360   */

2361  public static void remove(EObject eObject)
2362  {
2363    EObject container = eObject.eContainer();
2364    if (container != null)
2365    {
2366      EReference feature = eObject.eContainmentFeature();
2367      if (feature.isMany())
2368      {
2369        ((EList)container.eGet(feature)).remove(eObject);
2370      }
2371      else
2372      {
2373        container.eUnset(feature);
2374      }
2375    }
2376    else
2377    {
2378      Resource resource = eObject.eResource();
2379      if (resource != null)
2380      {
2381        resource.getContents().remove(eObject);
2382      }
2383    }
2384  }
2385
2386  /**
2387   * Replace the object in its {@link EObject#eResource containing} resource
2388   * or its {@link EObject#eContainer containing} object,
2389   * with the replacement object.
2390   * @param eObject the object to replace.
2391   * @param replacementEObject the replacement object.
2392   */

2393  public static void replace(EObject eObject, EObject replacementEObject)
2394  {
2395    EObject container = eObject.eContainer();
2396    if (container != null)
2397    {
2398      EReference feature = eObject.eContainmentFeature();
2399      if (feature.isMany())
2400      {
2401        List JavaDoc list = (List JavaDoc)container.eGet(feature);
2402        list.set(list.indexOf(eObject), replacementEObject);
2403      }
2404      else
2405      {
2406        container.eSet(feature, replacementEObject);
2407      }
2408    }
2409    else
2410    {
2411      Resource resource = eObject.eResource();
2412      if (resource != null)
2413      {
2414        List JavaDoc list = resource.getContents();
2415        list.set(list.indexOf(eObject), replacementEObject);
2416      }
2417    }
2418  }
2419
2420  /**
2421   * Creates an instance of the class.
2422   * @param eClass the class to instantiate.
2423   * @return an instance of the class.
2424   */

2425  public static EObject create(EClass eClass)
2426  {
2427    return eClass.getEPackage().getEFactoryInstance().create(eClass);
2428  }
2429
2430  /**
2431   * Creates an instance of the datatype.
2432   * @param eDataType the datatype to instantiate.
2433   * @param literal the string value of the datatype.
2434   * @return an instance of the datatype.
2435   * @see #convertToString(EDataType, Object)
2436   */

2437  public static Object JavaDoc createFromString(EDataType eDataType, String JavaDoc literal)
2438  {
2439    return eDataType.getEPackage().getEFactoryInstance().createFromString(eDataType, literal);
2440  }
2441
2442  /**
2443   * Converts an instance of the datatype to a string literal representation.
2444   * @param eDataType the datatype to instantiate.
2445   * @param value a value of the datatype.
2446   * @return the string literal representation of the value.
2447   * @see #createFromString(EDataType, String)
2448   */

2449  public static String JavaDoc convertToString(EDataType eDataType, Object JavaDoc value)
2450  {
2451    return eDataType.getEPackage().getEFactoryInstance().convertToString(eDataType, value);
2452  }
2453
2454  /**
2455   * Returns the value of the object's ID attribute as a String.
2456   * If the object has no ID attribute or the ID attribute is not set, it returns <code>null</code>.
2457   * @param eObject the object in question.
2458   * @return the value of the object's ID attribute as a String.
2459   * @see org.eclipse.emf.ecore.EAttribute#isID
2460   * @see org.eclipse.emf.ecore.EClass#getEIDAttribute
2461   * @see #setID(EObject, String)
2462   */

2463  public static String JavaDoc getID(EObject eObject)
2464  {
2465    EClass eClass = eObject.eClass();
2466    EAttribute eIDAttribute = eClass.getEIDAttribute();
2467    return eIDAttribute == null || !eObject.eIsSet(eIDAttribute) ? null : convertToString(
2468      eIDAttribute.getEAttributeType(),
2469      eObject.eGet(eIDAttribute));
2470  }
2471
2472  /**
2473   * Sets the value of the object's ID attribute according to the value represented by the String.
2474   * A <code>null</code> ID will unset the attribute rather than setting it to <code>null</code>.
2475   * @param eObject the object in question.
2476   * @param id the String value of the new ID.
2477   * @return the value of the object's ID attribute as a String.
2478   * @throws IllegalArgumentException if the object has no ID attribute.
2479   * @see #getID(EObject)
2480   * @see org.eclipse.emf.ecore.EAttribute#isID
2481   * @see org.eclipse.emf.ecore.EClass#getEIDAttribute
2482   */

2483  public static void setID(EObject eObject, String JavaDoc id)
2484  {
2485    EClass eClass = eObject.eClass();
2486    EAttribute eIDAttribute = eClass.getEIDAttribute();
2487    if (eIDAttribute == null)
2488    {
2489      throw new IllegalArgumentException JavaDoc("The object doesn't have an ID feature.");
2490    }
2491    else if (id == null)
2492    {
2493      eObject.eUnset(eIDAttribute);
2494    }
2495    else
2496    {
2497      eObject.eSet(eIDAttribute, createFromString(eIDAttribute.getEAttributeType(), id));
2498    }
2499  }
2500
2501  /**
2502   * Returns the wrapper class for the primitive class, or the original class, if it's not a primitive class.
2503   * @param javaClass
2504   */

2505  public static Class JavaDoc wrapperClassFor(Class JavaDoc javaClass)
2506  {
2507    if (javaClass == null)
2508    {
2509      return null;
2510    }
2511    else if (javaClass.isPrimitive())
2512    {
2513      if (javaClass == Boolean.TYPE)
2514      {
2515        return Boolean JavaDoc.class;
2516      }
2517      else if (javaClass == Integer.TYPE)
2518      {
2519        return Integer JavaDoc.class;
2520      }
2521      else if (javaClass == Float.TYPE)
2522      {
2523        return Float JavaDoc.class;
2524      }
2525      else if (javaClass == Double.TYPE)
2526      {
2527        return Double JavaDoc.class;
2528      }
2529      else if (javaClass == Long.TYPE)
2530      {
2531        return Long JavaDoc.class;
2532      }
2533      else if (javaClass == Short.TYPE)
2534      {
2535        return Short JavaDoc.class;
2536      }
2537      else if (javaClass == Byte.TYPE)
2538      {
2539        return Byte JavaDoc.class;
2540      }
2541      else
2542      // if (javaClass == Character.TYPE)
2543
{
2544        return Character JavaDoc.class;
2545      }
2546    }
2547    else
2548    {
2549      return javaClass;
2550    }
2551  }
2552
2553  protected static final String JavaDoc GEN_MODEL_PACKAGE_NS_URI = "http://www.eclipse.org/emf/2002/GenModel";
2554
2555  public static String JavaDoc getDocumentation(EModelElement eModelElement)
2556  {
2557    EAnnotation eAnnotation = eModelElement.getEAnnotation(GEN_MODEL_PACKAGE_NS_URI);
2558    return eAnnotation == null ? null : (String JavaDoc)eAnnotation.getDetails().get("documentation");
2559  }
2560
2561  public static void setDocumentation(EModelElement eModelElement, String JavaDoc documentation)
2562  {
2563    EAnnotation eAnnotation = eModelElement.getEAnnotation(GEN_MODEL_PACKAGE_NS_URI);
2564    if (documentation == null)
2565    {
2566      if (eAnnotation != null)
2567      {
2568        eAnnotation.getDetails().remove("documentation");
2569      }
2570    }
2571    else
2572    {
2573      if (eAnnotation == null)
2574      {
2575        eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
2576        eAnnotation.setSource(GEN_MODEL_PACKAGE_NS_URI);
2577        eModelElement.getEAnnotations().add(eAnnotation);
2578      }
2579      eAnnotation.getDetails().put("documentation", documentation);
2580    }
2581  }
2582
2583  public static List JavaDoc getConstraints(EModelElement eModelElement)
2584  {
2585    EAnnotation eAnnotation = eModelElement.getEAnnotation(EcorePackage.eNS_URI);
2586    if (eAnnotation != null)
2587    {
2588      String JavaDoc constraints = (String JavaDoc)eAnnotation.getDetails().get("constraints");
2589      if (constraints != null)
2590      {
2591        List JavaDoc result = new ArrayList JavaDoc();
2592        for (StringTokenizer JavaDoc stringTokenizer = new StringTokenizer JavaDoc(constraints); stringTokenizer.hasMoreTokens();)
2593        {
2594          String JavaDoc constraint = stringTokenizer.nextToken();
2595          result.add(constraint);
2596        }
2597        return result;
2598      }
2599    }
2600    return Collections.EMPTY_LIST;
2601  }
2602
2603  public static void setConstraints(EModelElement eModelElement, List JavaDoc constraints)
2604  {
2605    EAnnotation eAnnotation = eModelElement.getEAnnotation(EcorePackage.eNS_URI);
2606    if (constraints == null || constraints.isEmpty())
2607    {
2608      if (eAnnotation != null)
2609      {
2610        eAnnotation.getDetails().remove("constraints");
2611      }
2612    }
2613    else
2614    {
2615      if (eAnnotation == null)
2616      {
2617        eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
2618        eAnnotation.setSource(EcorePackage.eNS_URI);
2619        eModelElement.getEAnnotations().add(eAnnotation);
2620      }
2621      StringBuffer JavaDoc value = new StringBuffer JavaDoc();
2622      for (Iterator JavaDoc i = constraints.iterator(); i.hasNext();)
2623      {
2624        value.append(i.next());
2625        if (i.hasNext())
2626        {
2627          value.append(' ');
2628        }
2629      }
2630      eAnnotation.getDetails().put("constraints", value.toString());
2631    }
2632  }
2633
2634  public static String JavaDoc getAnnotation(EModelElement eModelElement, String JavaDoc sourceURI, String JavaDoc key)
2635  {
2636    EAnnotation eAnnotation = eModelElement.getEAnnotation(sourceURI);
2637    return eAnnotation == null ? null : (String JavaDoc)eAnnotation.getDetails().get(key);
2638  }
2639
2640  public static void setAnnotation(EModelElement eModelElement, String JavaDoc sourceURI, String JavaDoc key, String JavaDoc value)
2641  {
2642    EAnnotation eAnnotation = eModelElement.getEAnnotation(sourceURI);
2643    if (eAnnotation == null)
2644    {
2645      eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
2646      eAnnotation.setSource(sourceURI);
2647      eModelElement.getEAnnotations().add(eAnnotation);
2648    }
2649    eAnnotation.getDetails().put(key, value);
2650  }
2651
2652  /**
2653   * Identifier for the get accessor.
2654   * @see #isSuppressedVisibility
2655   * @see #setSuppressedVisibility
2656   * @since 2.1
2657   */

2658  public static final int GET = 0;
2659
2660  /**
2661   * Identifier for the set accessor.
2662   * @see #isSuppressedVisibility
2663   * @see #setSuppressedVisibility
2664   * @since 2.1
2665   */

2666  public static final int SET = 1;
2667
2668  /**
2669   * Identifier for the isSet accessor.
2670   * @see #isSuppressedVisibility
2671   * @see #setSuppressedVisibility
2672   * @since 2.1
2673   */

2674  public static final int IS_SET = 2;
2675
2676  /**
2677   * Identifier for the unset accessor.
2678   * @see #isSuppressedVisibility
2679   * @see #setSuppressedVisibility
2680   * @since 2.1
2681   */

2682  public static final int UNSET = 3;
2683
2684  // Keys that will be used to record visibility for the accessors.
2685
//
2686
static final String JavaDoc[] ACCESSOR_KEYS =
2687  {
2688    "suppressedGetVisibility",
2689    "suppressedSetVisibility",
2690    "suppressedIsSetVisibility",
2691    "suppressedUnsetVisibility"
2692  };
2693
2694  // Value used to suppress visibility.
2695
//
2696
static final String JavaDoc TRUE = "true";
2697
2698  /**
2699   * Tests whether the given structural feature has been annotated to prevent generation of accessor methods in its
2700   * interface.
2701   * @param eStructuralFeature the structural feature
2702   * @param accessor the type of accessor method, one of {@link #GET}, {@link #SET}, {@link #IS_SET}, or {@link #UNSET}
2703   * @return whether the specified accessor's visibility is suppressed
2704   * @since 2.1
2705   */

2706  public static boolean isSuppressedVisibility(EStructuralFeature eStructuralFeature, int accessor)
2707  {
2708    if (accessor < GET || accessor > UNSET) throw new IllegalArgumentException JavaDoc("Invalid accessor identifier: " + accessor);
2709
2710    EAnnotation eAnnotation = eStructuralFeature.getEAnnotation(GEN_MODEL_PACKAGE_NS_URI);
2711    return eAnnotation == null ? false : TRUE.equalsIgnoreCase((String JavaDoc)eAnnotation.getDetails().get(ACCESSOR_KEYS[accessor]));
2712  }
2713
2714  /**
2715   * Sets or removes annotations on the given structural feature to prevent generation of accessor methods in its interface.
2716   * @param eStructuralFeature the structural feature
2717   * @param accessor the type of accessor method, one of {@link #GET}, {@link #SET}, {@link #IS_SET}, or {@link #UNSET}
2718   * @param suppress whether the specified accessor's visibility should be suppressed
2719   * @since 2.1
2720   */

2721  public static void setSuppressedVisibility(EStructuralFeature eStructuralFeature, int accessor, boolean suppress)
2722  {
2723    if (accessor < GET || accessor > UNSET) throw new IllegalArgumentException JavaDoc("Invalid accessor identifier: " + accessor);
2724
2725    EAnnotation eAnnotation = eStructuralFeature.getEAnnotation(GEN_MODEL_PACKAGE_NS_URI);
2726    if (!suppress)
2727    {
2728      if (eAnnotation != null)
2729      {
2730        eAnnotation.getDetails().removeKey(ACCESSOR_KEYS[accessor]);
2731      }
2732    }
2733    else
2734    {
2735      if (eAnnotation == null)
2736      {
2737        eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
2738        eAnnotation.setSource(GEN_MODEL_PACKAGE_NS_URI);
2739        eStructuralFeature.getEAnnotations().add(eAnnotation);
2740      }
2741      eAnnotation.getDetails().put(ACCESSOR_KEYS[accessor], TRUE);
2742    }
2743  }
2744
2745  /**
2746   * Generates a universally unique identifier,
2747   * i.e., a <a HREF="ftp://ietf.org/internet-drafts/draft-mealling-uuid-urn-02.txt">UUID</a>.
2748   * It encodes the 128 bit UUID in <a HREF="http://www.ietf.org/rfc/rfc2045.txt">base 64</a>,
2749   * but rather than padding the encoding with two "=" characters,
2750   * it prefixes the encoding with a single "_" character,
2751   * to ensure that the result is a valid <a HREF="http://www.w3.org/TR/xmlschema-2/#ID">ID</a>,
2752   * i.e., an <a HREF="http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName">NCName</a>
2753   * @return a universally unique identifier.
2754   */

2755  public static String JavaDoc generateUUID()
2756  {
2757    return UUID.generate();
2758  }
2759
2760  private static final class UUID
2761  {
2762    public synchronized static String JavaDoc generate()
2763    {
2764      updateCurrentTime();
2765
2766      // Do a base 64 conversion by turning every 3 bytes into 4 base 64 characters
2767
//
2768
for (int i = 0; i < 5; ++i)
2769      {
2770        buffer[4 * i + 1] = BASE64_DIGITS[(uuid[i * 3] >> 2) & 0x3F];
2771        buffer[4 * i + 2] = BASE64_DIGITS[((uuid[i * 3] << 4) & 0x30) | ((uuid[i * 3 + 1] >> 4) & 0xF)];
2772        buffer[4 * i + 3] = BASE64_DIGITS[((uuid[i * 3 + 1] << 2) & 0x3C) | ((uuid[i * 3 + 2] >> 6) & 0x3)];
2773        buffer[4 * i + 4] = BASE64_DIGITS[uuid[i * 3 + 2] & 0x3F];
2774      }
2775
2776      // Handle the last byte at the end.
2777
//
2778
buffer[21] = BASE64_DIGITS[(uuid[15] >> 2) & 0x3F];
2779      buffer[22] = BASE64_DIGITS[(uuid[15] << 4) & 0x30];
2780
2781      return new String JavaDoc(buffer);
2782    }
2783
2784    private UUID()
2785    {
2786    }
2787
2788    private static final char[] BASE64_DIGITS = {
2789      'A',
2790      'B',
2791      'C',
2792      'D',
2793      'E',
2794      'F',
2795      'G',
2796      'H',
2797      'I',
2798      'J',
2799      'K',
2800      'L',
2801      'M',
2802      'N',
2803      'O',
2804      'P',
2805      'Q',
2806      'R',
2807      'S',
2808      'T',
2809      'U',
2810      'V',
2811      'W',
2812      'X',
2813      'Y',
2814      'Z',
2815      'a',
2816      'b',
2817      'c',
2818      'd',
2819      'e',
2820      'f',
2821      'g',
2822      'h',
2823      'i',
2824      'j',
2825      'k',
2826      'l',
2827      'm',
2828      'n',
2829      'o',
2830      'p',
2831      'q',
2832      'r',
2833      's',
2834      't',
2835      'u',
2836      'v',
2837      'w',
2838      'x',
2839      'y',
2840      'z',
2841      '0',
2842      '1',
2843      '2',
2844      '3',
2845      '4',
2846      '5',
2847      '6',
2848      '7',
2849      '8',
2850      '9',
2851      '-',
2852      '_' };
2853
2854    /**
2855     * An adjustment to convert the Java epoch of Jan 1, 1970 00:00:00 to
2856     * the epoch required by the IETF specification, Oct 15, 1582 00:00:00.
2857     */

2858    private static final long EPOCH_ADJUSTMENT = new GregorianCalendar JavaDoc(1970, 0, 1, 0, 0, 0).getTime().getTime()
2859      - new GregorianCalendar JavaDoc(1582, 9, 15, 0, 0, 0).getTime().getTime();
2860
2861    private static long lastTime = System.currentTimeMillis() + EPOCH_ADJUSTMENT;
2862
2863    private static short clockSequence;
2864
2865    private static short timeAdjustment;
2866    
2867    private static int sleepTime = 1;
2868
2869    /**
2870     * A cached array of bytes representing the UUID. The second 8 bytes
2871     * will be kept the same unless the clock sequence has changed.
2872     */

2873    private static final byte[] uuid = new byte [16];
2874
2875    private static final char[] buffer = new char [23];
2876
2877    static
2878    {
2879      SecureRandom JavaDoc random = new SecureRandom JavaDoc();
2880
2881      clockSequence = (short)random.nextInt(16384);
2882      updateClockSequence();
2883
2884      // Generate a 48 bit node identifier;
2885
// This is an alternative to the IEEE 802 host address, which is not available in Java.
2886
//
2887
byte[] nodeAddress = new byte [6];
2888
2889      random.nextBytes(nodeAddress);
2890
2891      // Set the most significant bit of the first octet to 1 so as to distinguish it from IEEE node addresses
2892
//
2893
nodeAddress[0] |= (byte)0x80;
2894
2895      // The node identifier is already in network byte order,
2896
// so there is no need to do any byte order reversing.
2897
//
2898
for (int i = 0; i < 6; ++i)
2899      {
2900        uuid[i + 10] = nodeAddress[i];
2901      }
2902
2903      buffer[0] = '_';
2904    }
2905
2906    /**
2907     * Updates the clock sequence portion of the UUID. The clock sequence
2908     * portion may seem odd, but in the specification, the high order byte
2909     * comes before the low order byte. The variant is multiplexed into the
2910     * high order octet of clockseq_hi.
2911     */

2912    private static void updateClockSequence()
2913    {
2914      // clockseq_hi
2915
uuid[8] = (byte)(((clockSequence >> 8) & 0x3F) | 0x80);
2916      // clockseq_low
2917
uuid[9] = (byte)(clockSequence & 0xFF);
2918    }
2919
2920    /**
2921     * Updates the UUID with the current time, compensating for the fact
2922     * that the clock resolution may be less than 100 ns. The byte array
2923     * will have its first eight bytes populated with the time in the
2924     * correct sequence of bytes, as per the specification.
2925     */

2926    private static void updateCurrentTime()
2927    {
2928      // Get the current time in milliseconds since the epoch
2929
// and adjust it to match the epoch required by the specification.
2930
//
2931
long currentTime = System.currentTimeMillis() + EPOCH_ADJUSTMENT;
2932
2933      if (lastTime > currentTime)
2934      {
2935        // The system clock has been rewound so the clock sequence must be incremented
2936
// to ensure that a duplicate UUID is not generated.
2937
//
2938
++clockSequence;
2939
2940        if (16384 == clockSequence)
2941        {
2942          clockSequence = 0;
2943        }
2944
2945        updateClockSequence();
2946      }
2947      else if (lastTime == currentTime)
2948      {
2949        // The system time hasn't changed so add some increment of 100s of nanoseconds to guarantee uniqueness.
2950
//
2951
++timeAdjustment;
2952
2953        if (timeAdjustment > 9999)
2954        {
2955          // Wait so that the clock can catch up and the time adjustment won't overflow.
2956
try
2957          {
2958            Thread.sleep(sleepTime);
2959          }
2960          catch (InterruptedException JavaDoc exception)
2961          {
2962          }
2963
2964          timeAdjustment = 0;
2965          currentTime = System.currentTimeMillis() + EPOCH_ADJUSTMENT;
2966
2967          while (lastTime == currentTime)
2968          {
2969            try
2970            {
2971              ++sleepTime;
2972              Thread.sleep(1);
2973            }
2974            catch (InterruptedException JavaDoc exception)
2975            {
2976            }
2977            currentTime = System.currentTimeMillis() + EPOCH_ADJUSTMENT;
2978          }
2979        }
2980      }
2981      else
2982      {
2983        timeAdjustment = 0;
2984      }
2985
2986      lastTime = currentTime;
2987
2988      // Since the granularity of time in Java is only milliseconds,
2989
// add an adjustment so that the time is represented in 100s of nanoseconds.
2990
// The version number (1) is multiplexed into the most significant hex digit.
2991
//
2992
currentTime *= 10000;
2993      currentTime += timeAdjustment;
2994      currentTime |= 0x1000000000000000L;
2995
2996      // Place the time into the byte array in network byte order.
2997
//
2998
for (int i = 0; i < 4; ++i)
2999      {
3000        // time_low
3001
//
3002
uuid[i] = (byte)((currentTime >> 8 * (3 - i)) & 0xFFL);
3003      }
3004
3005      for (int i = 0; i < 2; ++i)
3006      {
3007        // time_mid
3008
//
3009
uuid[i + 4] = (byte)((currentTime >> 8 * (1 - i) + 32) & 0xFFL);
3010      }
3011
3012      for (int i = 0; i < 2; ++i)
3013      {
3014        // time_hi
3015
//
3016
uuid[i + 6] = (byte)((currentTime >> 8 * (1 - i) + 48) & 0xFFL);
3017      }
3018    }
3019  }
3020
3021  /**
3022   * Marks the package to indicate that it and everything it contains or that its contents depend on can no longer be changed.
3023   * This helps to improve the performance of the model but has no other effect.
3024   */

3025  public static void freeze(EPackage ePackage)
3026  {
3027    try
3028    {
3029      ((EPackageImpl)ePackage).freeze();
3030    }
3031    catch (ClassCastException JavaDoc exception)
3032    {
3033    }
3034  }
3035
3036  /*
3037   static
3038   {
3039   System.err.println("UUID");
3040   for (int loop = 0; loop < 5; ++loop)
3041   {
3042   long before = System.currentTimeMillis();
3043   long count = 500000;
3044   for (int i = 0; i < count; ++i)
3045   {
3046   generateUUID();
3047   }
3048   long after = System.currentTimeMillis();
3049   System.err.println("Elapsed " + (after - before));
3050   System.err.println("Time " + 1000 * ((float)(after - before))/((float)count));
3051   }
3052
3053   final EPackage ecorePackage = EPackage.Registry.INSTANCE.getEPackage("ecore.xmi");
3054   final Resource ecorePackageResource = ecorePackage.eResource();
3055   final EPackage genModelPackage = EPackage.Registry.INSTANCE.getEPackage("genmodel.xmi");
3056   final Resource genModelPackageResource = genModelPackage.eResource();
3057
3058   // Proxy finder.
3059   //
3060   {
3061   // Create a proxy and stuff it into the eSuperTypes.
3062   // This is a really very nasty thing to do.
3063   //
3064   EClass eClass = org.eclipse.emf.ecore.EcoreFactory.eINSTANCE.createEClass();
3065   ((InternalEObject)eClass).eSetProxyURI(URI.createURI("Yes!"));
3066   ((EClass)genModelPackage.getEClassifier("GenClass")).getESuperTypes().add(eClass);
3067
3068   System.err.println("=========================================");
3069   System.err.println("All proxy references in the GenModel EPackage");
3070   Map proxyCrossReferences = ProxyCrossReferencer.find(genModelPackage);
3071   CrossReferencer.print(System.err, proxyCrossReferences);
3072
3073   // Clean up the prox.
3074   //
3075   ((EClass)genModelPackage.getEClassifier("GenClass")).getESuperTypes().remove(eClass);
3076   }
3077
3078   // External cross reference finder.
3079   //
3080   {
3081   System.err.println("=========================================");
3082   System.err.println("All cross document references in the GenModel EPackage");
3083   Map externalCrossReferences = ExternalCrossReferencer.find(genModelPackage);
3084   CrossReferencer.print(System.err, externalCrossReferences);
3085   }
3086
3087   {
3088   // Find uses for object of interest.
3089   //
3090   EObject objectOfInterest = ecorePackage.getEClassifier("EDataType");
3091   System.err.println("=========================================");
3092   System.err.println("Uses of: " + getIdentification(objectOfInterest));
3093
3094   // Put the models in a resource set temporarily.
3095   //
3096   ResourceSet resourceSet = new org.eclipse.emf.ecore.resource.impl.ResourceSetImpl();
3097   resourceSet.getResources().add(ecorePackageResource);
3098   resourceSet.getResources().add(genModelPackageResource);
3099
3100   // Search the whole resource set.
3101   //
3102   Collection result = new UsageCrossReferencer(resourceSet).findUsage(objectOfInterest);
3103   for (Iterator i = result.iterator(); i.hasNext(); )
3104   {
3105   // Show the settings that reference the objectOfInterest.
3106   //
3107   EStructuralFeature.Setting setting = (EStructuralFeature.Setting)i.next();
3108   EObject eObject = setting.getEObject();
3109   EStructuralFeature eStructuralFeature = (EStructuralFeature)setting.getEStructuralFeature();
3110   System.err.println
3111   ("> " + eStructuralFeature.getEContainingClass().getName() + "." + eStructuralFeature.getName() +
3112   " <- " + getIdentification(eObject));
3113   }
3114
3115   // Cleanup.
3116   //
3117   resourceSet.getResources().clear();
3118   }
3119
3120   List list = org.eclipse.emf.ecore.EcorePackage.eINSTANCE.getEReference().getEAllStructuralFeatures();
3121
3122   {
3123   Object object = org.eclipse.emf.ecore.EcorePackage.eINSTANCE.getEReference_EReferenceType();
3124   
3125   for (int i = 0; i < 100; ++i)
3126   {
3127   list.indexOf(object);
3128   }
3129   long before = System.currentTimeMillis();
3130   for (int i = 0; i < 500000; ++i)
3131   {
3132   list.indexOf(object);
3133   }
3134   long after = System.currentTimeMillis();
3135   System.err.println("Elapsed " + (after - before));
3136   }
3137
3138   {
3139   Object object = org.eclipse.emf.ecore.EcorePackage.eINSTANCE.getENamedElement_Name();
3140   
3141   for (int i = 0; i < 100; ++i)
3142   {
3143   list.indexOf(object);
3144   }
3145   long before = System.currentTimeMillis();
3146   for (int i = 0; i < 500000; ++i)
3147   {
3148   list.indexOf(object);
3149   }
3150   long after = System.currentTimeMillis();
3151   System.err.println("Elapsed " + (after - before));
3152   }
3153   }
3154   */

3155}
3156
3157
Popular Tags