KickJava   Java API By Example, From Geeks To Geeks.

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


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

17 package org.eclipse.emf.edit.provider;
18
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27
28 import org.eclipse.emf.common.notify.Adapter;
29 import org.eclipse.emf.common.notify.AdapterFactory;
30 import org.eclipse.emf.common.notify.Notification;
31 import org.eclipse.emf.common.notify.Notifier;
32 import org.eclipse.emf.ecore.EClass;
33 import org.eclipse.emf.ecore.EObject;
34 import org.eclipse.emf.ecore.EPackage;
35 import org.eclipse.emf.edit.EMFEditPlugin;
36
37
38 /**
39  * This provides support for composing several factories for different models
40  * into a single factory serving the union of the model objects.
41  */

42 public class ComposedAdapterFactory
43   implements
44     AdapterFactory,
45     ComposeableAdapterFactory,
46     IChangeNotifier,
47     IDisposable
48 {
49   /**
50    * A descriptor is can create an adapter factory.
51    * They are used as the values in a {@link Descritor.Registry registry}.
52    */

53   public interface Descriptor
54   {
55     /**
56      * Creates an adapter factory.
57      * @return a new adapter factory.
58      */

59     AdapterFactory createAdapterFactory();
60     
61     /**
62      * A registry is an index that takes a collection of keys,
63      * typically a pair consisting of an EPackage or java.lang.Package, and a java.lang.Class,
64      * and maps it to a {@link Descriptor descriptor}.
65      */

66     interface Registry
67     {
68       /**
69        * The global registry typically populated by plugin registration.
70        */

71       Registry INSTANCE = org.eclipse.emf.edit.EMFEditPlugin.getComposedAdapterFactoryDescriptorRegistry();
72       
73       /**
74        * Returns descriptor that can create a factory for the types.
75        * @param a collections of keys, typically a pair consisting of an EPackage or java.lang.Package, and a java.lang.Class.
76        * @return a descriptor that can create a factory for the types.
77        */

78       Descriptor getDescriptor(Collection JavaDoc types);
79       
80       /**
81        * A simple registry implementation that supports delegation.
82        */

83       class Impl extends HashMap JavaDoc implements Registry
84       {
85         /**
86          * The delegate registry should lookup fail locally.
87          */

88         protected Registry delegateRegistry;
89         
90         /**
91          * Creates an instance.
92          * @param delegateRegistry <code>null</code> or a registration that should act as the delegate.
93          */

94         public Impl(Registry delegateRegistry)
95         {
96           this.delegateRegistry = delegateRegistry;
97         }
98         
99         public Descriptor getDescriptor(Collection JavaDoc types)
100         {
101           Descriptor descriptor = (Descriptor)get(types);
102           return descriptor == null ? delegatedGetDescriptor(types) : descriptor;
103         }
104         
105         /**
106          * This is called when local lookup fails.
107          */

108         protected Descriptor delegatedGetDescriptor(Collection JavaDoc types)
109         {
110           if (delegateRegistry != null)
111           {
112             return delegateRegistry.getDescriptor(types);
113           }
114           
115           return null;
116         }
117       }
118     }
119   }
120   
121   /**
122    * This keeps track of all the {@link org.eclipse.emf.common.notify.AdapterFactory} delegates.
123    */

124   protected List JavaDoc adapterFactories = new ArrayList JavaDoc();
125
126   /**
127    * This is used to implement the {@link ComposeableAdapterFactory} interface.
128    */

129   protected ComposedAdapterFactory parentAdapterFactory;
130
131   /**
132    * This is used to implement {@link IChangeNotifier}
133    */

134   protected ChangeNotifier changeNotifier = new ChangeNotifier();
135
136   /**
137    * This is used to demand create adapter factories from a registry.
138    */

139   protected Descriptor.Registry adapterFactoryDescriptorRegistry;
140
141   public ComposedAdapterFactory()
142   {
143   }
144   
145   /**
146    */

147   public ComposedAdapterFactory(Descriptor.Registry adapterFactoryDescriptorRegistry)
148   {
149     this.adapterFactoryDescriptorRegistry = adapterFactoryDescriptorRegistry;
150   }
151   
152   /**
153    */

154   public ComposedAdapterFactory(AdapterFactory adapterFactory)
155   {
156     addAdapterFactory(adapterFactory);
157   }
158
159   public ComposedAdapterFactory(AdapterFactory [] adapterFactories)
160   {
161     for (int i = 0; i < adapterFactories.length; ++i)
162     {
163       addAdapterFactory(adapterFactories[i]);
164     }
165   }
166
167   public ComposedAdapterFactory(Collection JavaDoc adapterFactories)
168   {
169     for (Iterator JavaDoc factories = adapterFactories.iterator(); factories.hasNext(); )
170     {
171       addAdapterFactory((AdapterFactory)factories.next());
172     }
173   }
174
175   public boolean isFactoryForType(Object JavaDoc type)
176   {
177     for (Iterator JavaDoc factories = adapterFactories.iterator(); factories.hasNext(); )
178     {
179       AdapterFactory adapterFactory = (AdapterFactory)factories.next();
180       if (adapterFactory.isFactoryForType(type))
181       {
182         return true;
183       }
184     }
185
186     return false;
187   }
188
189   public AdapterFactory getFactoryForType(Object JavaDoc type)
190   {
191     return getFactoryForTypes(Collections.singleton(type));
192   }
193
194   public AdapterFactory getFactoryForTypes(Collection JavaDoc types)
195   {
196     FactoryLoop : for (Iterator JavaDoc factories = adapterFactories.iterator(); factories.hasNext(); )
197     {
198       AdapterFactory factory = (AdapterFactory)factories.next();
199       if (factory instanceof ComposedAdapterFactory)
200       {
201         factory = ((ComposedAdapterFactory)factory).getFactoryForTypes(types);
202         if (factory != null)
203         {
204           return factory;
205         }
206       }
207       else
208       {
209         for (Iterator JavaDoc i = types.iterator(); i.hasNext(); )
210         {
211           if (!factory.isFactoryForType(i.next()))
212           {
213             continue FactoryLoop;
214           }
215         }
216         return factory;
217       }
218     }
219     
220     if (adapterFactoryDescriptorRegistry != null)
221     {
222       Descriptor descriptor = adapterFactoryDescriptorRegistry.getDescriptor(types);
223       if (descriptor != null)
224       {
225         AdapterFactory result = descriptor.createAdapterFactory();
226         addAdapterFactory(result);
227         return result;
228       }
229     }
230     
231     return delegatedGetFactoryForTypes(types);
232   }
233   
234   protected AdapterFactory delegatedGetFactoryForTypes(Collection JavaDoc types)
235   {
236     return null;
237   }
238
239   public Object JavaDoc adapt(Object JavaDoc target, Object JavaDoc type)
240   {
241     Object JavaDoc adapter = target;
242     if (target instanceof Notifier)
243     {
244       adapter = adapt((Notifier)target, type);
245     }
246
247     if (!(type instanceof Class JavaDoc) || (((Class JavaDoc)type).isInstance(adapter)))
248     {
249       return adapter;
250     }
251
252     return null;
253   }
254
255   public Adapter adapt(Notifier target, Object JavaDoc type)
256   {
257     Adapter result = null;
258
259     if (target instanceof EObject)
260     {
261       EObject eObject = (EObject)target;
262       EClass eClass = eObject.eClass();
263       if (eClass != null)
264       {
265         EPackage ePackage = eClass.getEPackage();
266         Collection JavaDoc types = new ArrayList JavaDoc();
267         types.add(ePackage);
268         if (type != null)
269         {
270           types.add(type);
271         }
272         AdapterFactory delegateAdapterFactory = getFactoryForTypes(types);
273         if (delegateAdapterFactory != null)
274         {
275           result = delegateAdapterFactory.adapt(target, type);
276         }
277
278         if (result == null)
279         {
280           Collection JavaDoc failedPackageSet = new HashSet JavaDoc();
281           failedPackageSet.add(ePackage);
282           for (Iterator JavaDoc supertypes = eClass.getEAllSuperTypes().iterator(); supertypes.hasNext(); )
283           {
284             EClass eSuperType = (EClass)supertypes.next();
285             EPackage eSupertypePackage = eSuperType.getEPackage();
286             if (failedPackageSet.add(eSupertypePackage))
287             {
288               Collection JavaDoc superTypes = new ArrayList JavaDoc();
289               superTypes.add(ePackage);
290               if (type != null)
291               {
292                 superTypes.add(type);
293               }
294               delegateAdapterFactory = getFactoryForTypes(superTypes);
295               if (delegateAdapterFactory != null)
296               {
297                 result = delegateAdapterFactory.adapt(target, type);
298                 if (result != null)
299                 {
300                   break;
301                 }
302               }
303             }
304           }
305         }
306       }
307     }
308     else
309     {
310       result = adapt(target, type, new HashSet JavaDoc(), target.getClass());
311     }
312
313     return result;
314   }
315
316   protected Adapter adapt(Notifier target, Object JavaDoc type, Collection JavaDoc failedPackages, Class JavaDoc javaClass)
317   {
318     Adapter result = null;
319
320
321     Package JavaDoc javaPackage = javaClass.getPackage();
322     if (failedPackages.add(javaPackage))
323     {
324       Collection JavaDoc types = new ArrayList JavaDoc();
325       types.add(javaPackage);
326       if (type != null)
327       {
328         types.add(type);
329       }
330       AdapterFactory delegateAdapterFactory = getFactoryForTypes(types);
331       if (delegateAdapterFactory != null)
332       {
333         result = delegateAdapterFactory.adapt(target, type);
334       }
335     }
336
337     if (result == null)
338     {
339       Class JavaDoc superclass = javaClass.getSuperclass();
340       if (superclass != null)
341       {
342         result = adapt(target, type, failedPackages, javaClass.getSuperclass());
343       }
344       if (result == null)
345       {
346         Class JavaDoc [] interfaces = javaClass.getInterfaces();
347         for (int i = 0; i < interfaces.length; ++i)
348         {
349           result = adapt(target, type, failedPackages, interfaces[i]);
350           if (result != null)
351           {
352             break;
353           }
354         }
355       }
356     }
357
358     return result;
359   }
360
361   /**
362    * This method isn't implemented and will throw and exception.
363    */

364   public Adapter adaptNew(Notifier target, Object JavaDoc type)
365   {
366     throw
367       new RuntimeException JavaDoc
368         (EMFEditPlugin.INSTANCE.getString
369           ("_EXC_Method_not_implemented", new Object JavaDoc [] { this.getClass() + "adaptNew(Notifier target, Object type)" }));
370   }
371
372   public void adaptAllNew(Notifier target)
373   {
374     for (Iterator JavaDoc factories = adapterFactories.iterator(); factories.hasNext(); )
375     {
376       AdapterFactory adapterFactory = (AdapterFactory)factories.next();
377       if (adapterFactory.isFactoryForType(target))
378       {
379         adapterFactory.adaptAllNew(target);
380       }
381     }
382   }
383
384   public void insertAdapterFactory(AdapterFactory adapterFactory)
385   {
386     if (!adapterFactories.contains(adapterFactory))
387     {
388       adapterFactories.add(0, adapterFactory);
389       if (adapterFactory instanceof ComposeableAdapterFactory)
390       {
391         ((ComposeableAdapterFactory)adapterFactory).setParentAdapterFactory(this);
392       }
393     }
394   }
395
396   public void addAdapterFactory(AdapterFactory adapterFactory)
397   {
398     if (!adapterFactories.contains(adapterFactory))
399     {
400       adapterFactories.add(adapterFactory);
401       if (adapterFactory instanceof ComposeableAdapterFactory)
402       {
403         ((ComposeableAdapterFactory)adapterFactory).setParentAdapterFactory(this);
404       }
405     }
406   }
407
408   public void removeAdapterFactory(AdapterFactory adapterFactory)
409   {
410     if (adapterFactories.contains(adapterFactory))
411     {
412       adapterFactories.remove(adapterFactory);
413       if (adapterFactory instanceof ComposeableAdapterFactory)
414       {
415         ((ComposeableAdapterFactory)adapterFactory).setParentAdapterFactory(null);
416       }
417     }
418   }
419
420   /**
421    * This returns the root adapter factory that delegates to this factory.
422    */

423   public ComposeableAdapterFactory getRootAdapterFactory()
424   {
425     return parentAdapterFactory == null ? this : parentAdapterFactory.getRootAdapterFactory();
426   }
427
428   /**
429    * This sets the direct parent adapter factory into which this factory is composed.
430    */

431   public void setParentAdapterFactory(ComposedAdapterFactory parentAdapterFactory)
432   {
433     this.parentAdapterFactory = parentAdapterFactory;
434   }
435
436   public void addListener(INotifyChangedListener notifyChangedListener)
437   {
438     changeNotifier.add(notifyChangedListener);
439   }
440
441   public void removeListener(INotifyChangedListener notifyChangedListener)
442   {
443     changeNotifier.remove(notifyChangedListener);
444   }
445
446   public void fireNotifyChanged(Notification notification)
447   {
448     changeNotifier.fireNotifyChanged(notification);
449
450     if (parentAdapterFactory != null)
451     {
452       parentAdapterFactory.fireNotifyChanged(notification);
453     }
454   }
455
456   public void dispose()
457   {
458     for (Iterator JavaDoc factories = adapterFactories.iterator(); factories.hasNext(); )
459     {
460       Object JavaDoc factory = factories.next();
461       if (factory instanceof IDisposable)
462       {
463         ((IDisposable)factory).dispose();
464       }
465     }
466   }
467 }
468
Popular Tags