blob: e76c30e8fdadb3606a0b53e5ca87509355e3a62c [file] [log] [blame]
/*******************************************************************************
* 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);
}
}