/******************************************************************************* * Copyright (c) 2006 Oracle Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Oracle Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.model.adapters; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.core.runtime.IAdapterManager; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.NotificationImpl; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; /** * This is the one place where EMF object adapters can be registered. * * @author Michal Chmielewski (michal.chmielewski@oracle.com) * @date Jul 23, 2007 * */ public class AdapterRegistry { /** * The singleton instance of this registry. */ static final public AdapterRegistry INSTANCE = new AdapterRegistry(); /** For every type of EClass or EPackage, register an Adapter Factory * This means that a particular EClass or EPackage may have N * * Adapter Factories. */ HashMap<Object,List<AdapterFactory>> fKeyToAdapterFactory ; /** The current adapter manager */ IAdapterManager fAdapterManager; /** * Private constructor. */ AdapterRegistry () { fKeyToAdapterFactory = new HashMap<Object,List<AdapterFactory>>(); if (Platform.isRunning()) { fAdapterManager = Platform.getAdapterManager(); } else { fAdapterManager = org.eclipse.core.internal.runtime.AdapterManager.getDefault(); } } /** * Register adapter factory for the given EClass. * * @param key * @param factory */ public void registerAdapterFactory (EClass key, AdapterFactory factory) { registerFactory (key,factory); } /** * Register adapter factory for the given EPackage. * * @param key * @param factory */ public void registerAdapterFactory (EPackage key, AdapterFactory factory) { registerFactory (key,factory); } /** * Unregister adapter factory for the given object (EClass) * @param key * @param factory */ public void unregisterAdapterFactory (EClass key, AdapterFactory factory) { unregisterFactory (key,factory); } /** * Unregister adapter factory for the given object (EPackage) * @param key * @param factory */ public void unregisterAdapterFactory (EPackage key, AdapterFactory factory) { unregisterFactory (key,factory); } /** * Register the factory (internal method, synchronized). * @param key * @param factory */ synchronized void registerFactory ( Object key, AdapterFactory factory) { List<AdapterFactory> list = fKeyToAdapterFactory.get(key); if (list == null) { list = new ArrayList<AdapterFactory>( ); fKeyToAdapterFactory.put( key, list ); list.add (factory); } else { if (list.contains(factory) == false) { list.add (factory); } } } synchronized void unregisterFactory (Object key, AdapterFactory factory) { List<AdapterFactory> list = fKeyToAdapterFactory.get(key); if (list == null) { return ; } list.remove(factory); } Class<?> adapterInterface ( Object type ) { if (type instanceof Class) { return (Class<?>) type; } if (type instanceof String) { try { return Class.forName((String)type); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } throw new RuntimeException("Adapter type " + type + " is not understood."); //$NON-NLS-1$ //$NON-NLS-2$ } /** * @param <T> * @param target * @param clazz * @return the adapted interface or object */ public <T extends Object> T adapt ( Object target, Class<T> clazz) { return adapt (target,clazz,true); } /** * * @param <T> * @param target * @param clazz * @param checkWSAdapters Check the Workspace adapters as well. * * @return the adapted interface or object */ public <T extends Object> T adapt ( Object target, Class<T> clazz, boolean checkWSAdapters ) { if (target == null) { return null; } if (clazz.isInstance(target)) { return clazz.cast(target); } Object adapter = null; if (target instanceof EObject) { EObject eObj = (EObject) target; EClass effectiveClass = eObj.eClass(); List<AdapterFactory> list = fKeyToAdapterFactory.get( effectiveClass ); if (list != null) { for(AdapterFactory factory : list) { adapter = factory.adapt(target, clazz); if (adapter != null && clazz.isInstance(adapter)) { return clazz.cast(adapter); } } } list = fKeyToAdapterFactory.get( effectiveClass.getEPackage() ); if (list != null) { for(AdapterFactory factory : list ) { adapter = factory.adapt(target, clazz); if (adapter != null && clazz.isInstance(adapter)) { return clazz.cast(adapter); } } } } if ( checkWSAdapters && fAdapterManager != null ) { // otherwise, the object we are adapting is not an EObject, try any other adapters. adapter = fAdapterManager.getAdapter(target, clazz); if (adapter != null && clazz.isInstance(adapter)) { return clazz.cast(adapter); } } return null; } /** * This method tries the registered adapter factories one by one, returning * the first non-null result it gets. If none of the factories can adapt * the result, it returns null. * @param target target object * @param type type of the adapter to find * @return the adapter for the target. */ public Object adapt (Object target, Object type) { if (target == null) { return null; } return adapt ( target, adapterInterface(type) ); } /** * Create an adapter for the given target of the given type. * In addition, pass a context object to the adapter(s) of the target. * * The idea is that some adapters can be stateful and depend not only * on the objects that they wrap, but also on some other context that is needed * to completely and correctly implement the interface for which the adaptor is * needed. * * Adapters that are stateless, should ignore any notifications sent to them. * * @param target the target object * @param type the type it wants to adapt to * @param context the context object * * @return the adapter */ public Object adapt (Object target, Object type, Object context) { Object adapter = adapt (target,type); if (adapter == null) { return adapter; } if (target instanceof EObject) { EObject eObject = (EObject) target; Notification n = new NotificationImpl(AbstractAdapter.CONTEXT_UPDATE_EVENT_TYPE, null, context); eObject.eNotify(n); } return adapter; } public void registerAdapterFactory (IAdapterFactory factory) { registerAdapterFactory(factory, Object.class); } /** * @param factory * @param class1 */ public void registerAdapterFactory(IAdapterFactory factory, Class<?> clazz) { fAdapterManager.registerAdapters(factory, clazz); } }