/******************************************************************************* * Copyright (c) 2010-present 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.inject; import java.util.Iterator; import java.util.NoSuchElementException; import org.eclipse.sisu.Hidden; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.ImplementedBy; import com.google.inject.Injector; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; import junit.framework.TestCase; public class RankedBindingsTest extends TestCase { @ImplementedBy( BeanImpl2.class ) static interface Bean { } static abstract class AbstractBean implements Bean { } static class BeanImpl extends AbstractBean { } static class BeanImpl2 extends AbstractBean { } @Hidden static class InternalBeanImpl extends AbstractBean { } static Injector injector0 = Guice.createInjector(); static Injector injector1 = Guice.createInjector( new AbstractModule() { @Override protected void configure() { bind( Bean.class ).annotatedWith( Names.named( "1" ) ).to( BeanImpl.class ); } } ); static Injector injector2 = Guice.createInjector( new AbstractModule() { @Override protected void configure() { bind( Bean.class ).annotatedWith( Names.named( "2" ) ).to( BeanImpl.class ); bind( Bean.class ).to( BeanImpl.class ); } } ); static Injector injector3 = Guice.createInjector( new AbstractModule() { @Override protected void configure() { bind( Bean.class ).annotatedWith( Names.named( "3" ) ).to( BeanImpl.class ); } } ); public void testExistingPublishers() { final RankedSequence<BindingPublisher> publishers = new RankedSequence<BindingPublisher>(); RankingFunction function; try { new DefaultRankingFunction( -1 ); fail( "Expected IllegalArgumentException" ); } catch ( final IllegalArgumentException e ) { // expected } function = new DefaultRankingFunction( 0 ); publishers.insert( new InjectorBindings( injector0, function ), function.maxRank() ); function = new DefaultRankingFunction( 1 ); publishers.insert( new InjectorBindings( injector1, function ), function.maxRank() ); function = new DefaultRankingFunction( 3 ); publishers.insert( new InjectorBindings( injector3, function ), function.maxRank() ); function = new DefaultRankingFunction( 2 ); publishers.insert( new InjectorBindings( injector2, function ), function.maxRank() ); final RankedBindings<Bean> bindings = new RankedBindings<Bean>( TypeLiteral.get( Bean.class ), publishers ); final Iterator<Binding<Bean>> itr = bindings.iterator(); assertEquals( 0, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 4, bindings.bindings.size() ); final Binding<Bean> explicitBinding = itr.next(); assertNull( explicitBinding.getKey().getAnnotation() ); assertEquals( BeanImpl.class, Implementations.find( explicitBinding ) ); assertEquals( 4, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 4, bindings.bindings.size() ); assertEquals( Names.named( "3" ), itr.next().getKey().getAnnotation() ); assertTrue( itr.hasNext() ); assertEquals( Names.named( "2" ), itr.next().getKey().getAnnotation() ); assertTrue( itr.hasNext() ); assertEquals( Names.named( "1" ), itr.next().getKey().getAnnotation() ); assertFalse( itr.hasNext() ); } public void testPendingPublishers() { final RankedBindings<Bean> bindings = new RankedBindings<Bean>( TypeLiteral.get( Bean.class ), null ); Iterator<Binding<Bean>> itr = bindings.iterator(); assertFalse( itr.hasNext() ); try { itr.next(); fail( "Expected NoSuchElementException" ); } catch ( final NoSuchElementException e ) { // expected } try { itr.remove(); fail( "Expected UnsupportedOperationException" ); } catch ( final UnsupportedOperationException e ) { // expected } RankingFunction function; assertEquals( 0, bindings.bindings.size() ); function = new DefaultRankingFunction( 2 ); bindings.add( new InjectorBindings( injector2, function ), function.maxRank() ); assertEquals( 0, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 2, bindings.bindings.size() ); Binding<Bean> explicitBinding = itr.next(); assertNull( explicitBinding.getKey().getAnnotation() ); assertEquals( BeanImpl.class, Implementations.find( explicitBinding ) ); assertEquals( 2, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 2, bindings.bindings.size() ); function = new DefaultRankingFunction( 0 ); bindings.add( new InjectorBindings( injector0, function ), function.maxRank() ); assertEquals( 2, bindings.bindings.size() ); function = new DefaultRankingFunction( 3 ); bindings.add( new InjectorBindings( injector3, function ), function.maxRank() ); assertEquals( 2, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 3, bindings.bindings.size() ); assertEquals( 3, bindings.bindings.size() ); function = new DefaultRankingFunction( 1 ); bindings.add( new InjectorBindings( injector1, function ), function.maxRank() ); assertEquals( 3, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 4, bindings.bindings.size() ); assertEquals( Names.named( "2" ), itr.next().getKey().getAnnotation() ); assertEquals( 4, bindings.bindings.size() ); assertTrue( itr.hasNext() ); assertEquals( 4, bindings.bindings.size() ); itr = bindings.iterator(); explicitBinding = itr.next(); assertNull( explicitBinding.getKey().getAnnotation() ); assertEquals( BeanImpl.class, Implementations.find( explicitBinding ) ); assertEquals( Names.named( "3" ), itr.next().getKey().getAnnotation() ); assertEquals( Names.named( "2" ), itr.next().getKey().getAnnotation() ); assertEquals( Names.named( "1" ), itr.next().getKey().getAnnotation() ); assertFalse( itr.hasNext() ); } public void testPublisherRemoval() { final BindingPublisher publisher0 = new InjectorBindings( injector0, new DefaultRankingFunction( 0 ) ); final BindingPublisher publisher1 = new InjectorBindings( injector1, new DefaultRankingFunction( 1 ) ); final BindingPublisher publisher2 = new InjectorBindings( injector2, new DefaultRankingFunction( 2 ) ); final BindingPublisher publisher3 = new InjectorBindings( injector3, new DefaultRankingFunction( 3 ) ); final RankedBindings<Bean> bindings = new RankedBindings<Bean>( TypeLiteral.get( Bean.class ), null ); bindings.add( publisher0, 0 ); bindings.add( publisher1, 1 ); bindings.add( publisher2, 2 ); bindings.add( publisher3, 3 ); Iterator<Binding<Bean>> itr = bindings.iterator(); bindings.remove( publisher1 ); assertTrue( itr.hasNext() ); Binding<Bean> explicitBinding = itr.next(); assertNull( explicitBinding.getKey().getAnnotation() ); assertEquals( BeanImpl.class, Implementations.find( explicitBinding ) ); bindings.remove( injector3.findBindingsByType( TypeLiteral.get( Bean.class ) ).get( 0 ) ); bindings.remove( publisher2 ); bindings.remove( injector1.findBindingsByType( TypeLiteral.get( Bean.class ) ).get( 0 ) ); assertFalse( itr.hasNext() ); itr = bindings.iterator(); bindings.bindings.clear(); bindings.add( publisher3, 0 ); bindings.add( publisher1, 0 ); bindings.add( publisher0, 0 ); bindings.add( publisher2, 0 ); assertTrue( itr.hasNext() ); explicitBinding = itr.next(); assertNull( explicitBinding.getKey().getAnnotation() ); assertEquals( BeanImpl.class, Implementations.find( explicitBinding ) ); assertTrue( itr.hasNext() ); assertEquals( Names.named( "3" ), itr.next().getKey().getAnnotation() ); assertTrue( itr.hasNext() ); assertEquals( Names.named( "2" ), itr.next().getKey().getAnnotation() ); assertTrue( itr.hasNext() ); assertEquals( Names.named( "1" ), itr.next().getKey().getAnnotation() ); assertFalse( itr.hasNext() ); assertFalse( itr.hasNext() ); } }