/******************************************************************************* * Copyright (c) 2002, 2007 Innoopract Informationssysteme GmbH. * 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: * Innoopract Informationssysteme GmbH - initial API and implementation ******************************************************************************/ package org.eclipse.rwt.internal; import java.util.*; import org.eclipse.rwt.AdapterFactory; import org.eclipse.rwt.SessionSingletonBase; /** * <p>Implementation of the <code>AdapterManager</code> protocol.</p> * <p>Implementation as Singleton.</p> */ public class AdapterManagerImpl extends SessionSingletonBase implements AdapterManager { /** <p>the internal datastructure of <code>AdapterManagerImpl</code></p>*/ private final Map registry; private final Map factoryCache; private final AdapterFactory nullFactory; private static class NullFactory implements AdapterFactory { private static final Class[] EMPTY = new Class[ 0 ]; public Object getAdapter( final Object adaptable, final Class adapter ) { return null; } public Class[] getAdapterList() { return EMPTY; } } /** <p>creates the singleton instance of <code>AdapterManagerImpl</code></p>*/ private AdapterManagerImpl() { registry = new HashMap(); factoryCache = new HashMap(); nullFactory = new NullFactory(); } /** <p>returns the singleton instance of this * <code>AdapterManager</code> implementation.</p> */ public static AdapterManager getInstance() { return ( AdapterManager )getInstance( AdapterManagerImpl.class ); } //////////////////////////// // interface implementations public Object getAdapter( final Object adaptable, final Class adapter ) { // Note [fappel]: Since this code is performance critical, don't change // anything without checking it against a profiler. Object result = null; Object hash = calculateHash( adaptable, adapter ); AdapterFactory cachedFactory = ( AdapterFactory )factoryCache.get( hash ); if( cachedFactory != null ) { result = cachedFactory.getAdapter( adaptable, adapter ); } else { result = doGetAdapter( adaptable, adapter, hash ); } return result; } private Object calculateHash( final Object adaptable, final Class adapter ) { Class adaptableClass = adaptable.getClass(); int hash = 23273 + adaptableClass.hashCode() * 37 + adapter.hashCode(); return new Integer( hash ); } private Object doGetAdapter( final Object adaptable, final Class adapter, final Object hash ) { Object result = null; Class[] keys = new Class[ registry.size() ]; registry.keySet().toArray( keys ); for( int i = 0; result == null && i < keys.length; i++ ) { if( keys[ i ].isAssignableFrom( adaptable.getClass() ) ) { List factoryList = ( List )registry.get( keys[ i ] ); AdapterFactory[] factories = new AdapterFactory[ factoryList.size() ]; factoryList.toArray( factories ); for( int j = 0; result == null && j < factories.length; j++ ) { Class[] adapters = factories[ j ].getAdapterList(); for( int k = 0; result == null && k < adapters.length; k++ ) { if( adapter.isAssignableFrom( adapters[ k ] ) ) { result = factories[ j ].getAdapter( adaptable, adapter ); factoryCache.put( hash, factories[ j ] ); } } } } } if( result == null ) { factoryCache.put( hash, nullFactory ); } return result; } public void registerAdapters( final AdapterFactory factory, final Class adaptable ) { if( registry.containsKey( adaptable ) ) { List factories = ( List )registry.get( adaptable ); if( !factories.contains( factory ) ) { factories.add( factory ); } } else { List factories = new ArrayList(); factories.add( factory ); registry.put( adaptable, factories ); } factoryCache.clear(); } public void deregisterAdapters( final AdapterFactory factory, final Class adaptable ) { if( registry.containsKey( adaptable ) ) { List factories = ( List )registry.get( adaptable ); if( factories.contains( factory ) ) { factories.remove( factory ); } } factoryCache.clear(); } }