blob: e4208d287541f78f2cc291c8cf58b30ee700339c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 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.space;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Provider;
import org.eclipse.sisu.Mediator;
import org.eclipse.sisu.inject.BeanLocator;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
* {@link InjectionListener} that listens for mediated watchers and registers them with the {@link BeanLocator}.
*/
final class MediationListener
extends AbstractMatcher<TypeLiteral<?>>
implements TypeListener, InjectionListener<Object>
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private final List<Mediation<?, ?, ?>> mediation;
private final Provider<BeanLocator> locator;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
public MediationListener( final Binder binder )
{
mediation = new ArrayList<Mediation<?, ?, ?>>();
locator = binder.getProvider( BeanLocator.class );
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
/**
* Adds a {@link Mediation} record containing the necessary details about a mediated watcher.
*
* @param key The watched key
* @param mediator The bean mediator
* @param watcherType The watcher type
*/
@SuppressWarnings( { "unchecked", "rawtypes" } )
public void mediate( final Key key, final Mediator mediator, final Class watcherType )
{
mediation.add( new Mediation( key, mediator, watcherType ) );
}
public boolean matches( final TypeLiteral<?> type )
{
for ( final Mediation<?, ?, ?> m : mediation )
{
if ( m.watcherType.isAssignableFrom( type.getRawType() ) )
{
return true;
}
}
return false;
}
public <T> void hear( final TypeLiteral<T> type, final TypeEncounter<T> encounter )
{
encounter.register( this ); // look out for watcher instances
}
@SuppressWarnings( { "unchecked", "rawtypes" } )
public void afterInjection( final Object watcher )
{
for ( final Mediation m : mediation )
{
if ( m.watcherType.isInstance( watcher ) )
{
locator.get().watch( m.watchedKey, m.mediator, watcher );
}
}
}
// ----------------------------------------------------------------------
// Implementation types
// ----------------------------------------------------------------------
/**
* Record containing all the necessary details about a mediated watcher.
*/
private static final class Mediation<Q extends Annotation, T, W>
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
final Key<T> watchedKey;
final Mediator<Q, T, W> mediator;
final Class<W> watcherType;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
Mediation( final Key<T> watchedKey, final Mediator<Q, T, W> mediator, final Class<W> watcherType )
{
this.watchedKey = watchedKey;
this.mediator = mediator;
this.watcherType = watcherType;
}
}
}