blob: 95cc369400d2538b6781e003b9e995b6fd010c23 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2013 Sonatype, Inc.
* 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:
* Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
*******************************************************************************/
package org.eclipse.sisu.wire;
import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.sisu.BeanEntry;
import org.eclipse.sisu.inject.BeanLocator;
import org.eclipse.sisu.inject.TypeArguments;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
/**
* Supplies various bean {@link Provider}s backed by dynamic bean lookups.
*/
final class BeanProviders
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
final Provider<BeanLocator> locator;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
BeanProviders( final Binder binder )
{
locator = binder.getProvider( BeanLocator.class );
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
/**
* Provides {@link Iterable} sequences of raw {@link BeanEntry}s.
*/
public <K extends Annotation, V> Provider<Iterable<? extends BeanEntry<K, V>>> beanEntriesOf( final Key<V> key )
{
return new Provider<Iterable<? extends BeanEntry<K, V>>>()
{
public Iterable<? extends BeanEntry<K, V>> get()
{
return locator.get().locate( key );
}
};
}
/**
* Provides {@link Iterable} sequences of bean/provider mappings
*/
@SuppressWarnings( { "rawtypes", "unchecked" } )
public <K extends Annotation, V> Provider<Iterable<Entry<K, V>>> entriesOf( final Key key )
{
final TypeLiteral<V> type = key.getTypeLiteral();
final Class<?> clazz = type.getRawType();
if ( javax.inject.Provider.class != clazz && com.google.inject.Provider.class != clazz )
{
return beanEntriesOf( key );
}
final Provider<Iterable<BeanEntry>> beanEntries = beanEntriesOf( key.ofType( TypeArguments.get( type, 0 ) ) );
return new Provider<Iterable<Entry<K, V>>>()
{
public Iterable<Entry<K, V>> get()
{
return new ProviderIterableAdapter( beanEntries.get() );
}
};
}
/**
* Provides {@link List}s of qualified beans/providers.
*/
public <K extends Annotation, V> Provider<List<V>> listOf( final Key<V> key )
{
final Provider<Iterable<Entry<K, V>>> entries = entriesOf( key );
return new Provider<List<V>>()
{
public List<V> get()
{
return new EntryListAdapter<K, V>( entries.get() );
}
};
}
/**
* Provides {@link Set}s of qualified beans/providers.
*/
public <K extends Annotation, V> Provider<Set<V>> setOf( final Key<V> key )
{
final Provider<Iterable<Entry<K, V>>> entries = entriesOf( key );
return new Provider<Set<V>>()
{
public Set<V> get()
{
return new EntrySetAdapter<K, V>( entries.get() );
}
};
}
/**
* Provides {@link Map}s of qualified beans/providers.
*/
public <K extends Annotation, V> Provider<Map<K, V>> mapOf( final Key<V> key )
{
final Provider<Iterable<Entry<K, V>>> entries = entriesOf( key );
return new Provider<Map<K, V>>()
{
public Map<K, V> get()
{
return new EntryMapAdapter<K, V>( entries.get() );
}
};
}
/**
* Provides string {@link Map}s of named beans/providers.
*/
public <V> Provider<Map<String, V>> stringMapOf( final TypeLiteral<V> type )
{
final Provider<Iterable<Entry<Named, V>>> entries = entriesOf( Key.get( type, Named.class ) );
return new Provider<Map<String, V>>()
{
public Map<String, V> get()
{
return new EntryMapAdapter<String, V>( new NamedIterableAdapter<V>( entries.get() ) );
}
};
}
/**
* Provides single qualified beans/providers.
*/
<V> Provider<V> firstOf( final Key<V> key )
{
final Provider<Iterable<? extends BeanEntry<Annotation, V>>> beanEntries = beanEntriesOf( key );
return new Provider<V>()
{
public V get()
{
return firstOf( beanEntries.get() );
}
};
}
/**
* Provides placeholder beans/providers.
*/
public <V> Provider<V> placeholderOf( final Key<V> key )
{
return new PlaceholderBeanProvider<V>( locator, key );
}
/**
* Selects first bean from the sequence; or null if none is available.
*/
public static <V> V firstOf( final Iterable<? extends Entry<?, V>> entries )
{
final Iterator<? extends Entry<?, V>> itr = entries.iterator();
return itr.hasNext() ? itr.next().getValue() : null; // TODO: dynamic proxy??
}
}