/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* This file is part of CATS.
*
* CATS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CATS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CATS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.comcast.cats.event.impl;
import static com.comcast.cats.event.CatsEventType.ALL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.comcast.cats.event.CatsEvent;
import com.comcast.cats.event.CatsEventDispatcher;
import com.comcast.cats.event.CatsEventHandler;
import com.comcast.cats.event.CatsEventType;
/**
* Basic CatsEventDispatcher implementation class for sending CatsEvents.
*
* @author cfrede001
*
*/
public class CatsEventDispatcherImpl implements CatsEventDispatcher
{
protected static Logger logger = LoggerFactory
.getLogger( CatsEventDispatcherImpl.class );
Map< CatsEventHandler, List< CatsEventType >> listeners = new HashMap< CatsEventHandler, List< CatsEventType >>();
Map< CatsEventHandler, Object > listenerSources = new HashMap< CatsEventHandler, Object >();
/**
* Zero arg constructor is perfectly acceptable for this dispatcher, since
* no external information is needed.
*/
public CatsEventDispatcherImpl()
{
logger.trace( "CatsEventDispatcherImpl Constructor" );
}
/**
* Synchronized method that add listener.
*
* @param handler
* {@linkplain CatsEventHandler}
* @param type
* - {@linkplain CatsEventType}
*/
@Override
public synchronized void addListener( CatsEventHandler handler, CatsEventType type )
{
if ( logger.isDebugEnabled() )
{
logger.debug( "addListener to handler for single CatsEventType" );
}
List< CatsEventType > types = new ArrayList< CatsEventType >();
types.add( type );
listeners.put( handler, types );
}
/**
* Method that add listener.
*
* @param handler
* {@linkplain CatsEventHandler}
* @param type
* - {@linkplain CatsEventType}
* @param source
* - Object
*/
@Override
public void addListener( CatsEventHandler handler, CatsEventType type, Object source )
{
addListener( handler, type );
listenerSources.put( handler, source );
}
/**
* Synchronized method that add listener.
*
* @param handler
* {@linkplain CatsEventHandler}
* @param types
* - List of {@linkplain CatsEventType}
*/
@Override
public synchronized void addListener( CatsEventHandler handler, List< CatsEventType > types )
{
if ( logger.isDebugEnabled() )
{
logger.debug( "addListener for CatsEventHandler[" + handler + "] for CatsEventType(s):" );
for ( CatsEventType type : types )
{
logger.debug( "\t" + type );
}
}
listeners.put( handler, types );
}
/**
* Synchronized method that remove all listeners.
*
* @param handler
* {@linkplain CatsEventHandler}
*/
@Override
public synchronized void removeListener( CatsEventHandler handler )
{
if ( listeners.containsKey( handler ) )
{
listeners.remove( handler );
}
if ( listenerSources.containsKey( handler ) )
{
listenerSources.remove( handler );
}
}
/**
* Is this handler listening to events coming from event.getSource(). If no
* source is found, assume it is listening to all sources.
*
* @param evt
* {@linkplain CatsEvent}
* @param handler
* {@linkplain CatsEventHandler}
* @return Boolean
*/
protected boolean isHandlerValidSource( CatsEvent evt, CatsEventHandler handler )
{
Object source = null;
if ( listenerSources.containsKey( handler ) )
{
source = listenerSources.get( handler );
}
else
{
/**
* By default if you aren't listening to a specific source you're
* listening to everything.
*/
return true;
}
if ( source != null && evt.getSource() == source )
{
return true;
}
return false;
}
/**
* Synchronized method that sends events to all listeners.
*
* @param evt
* {@linkplain CatsEvent}
* @throws IllegalArgumentException
*/
@Override
public synchronized void sendCatsEvent( CatsEvent evt ) throws IllegalArgumentException
{
if ( evt == null )
{
logger.warn( "CatsEvent is null throwing exception" );
throw new IllegalArgumentException( "CatsEvent can't be null" );
}
if ( logger.isTraceEnabled() )
{
logger.trace( "sendCatsEvent " + evt.toString() );
}
CatsEventType type = evt.getType();
for ( CatsEventHandler handler : listeners.keySet() )
{
if ( !isHandlerValidSource( evt, handler ) )
{
// If we're not listening to this source then just continue.
continue;
}
List< CatsEventType > types = listeners.get( handler );
if ( logger.isDebugEnabled() )
{
logger.debug( "handler [" + handler + "] is listening to types:" );
for ( CatsEventType t : types )
{
logger.debug( "\t" + t );
}
}
if ( handlerListensToEvent( types, type ) )
{
if ( logger.isDebugEnabled() )
{
logger.debug( "handler.catsEventPerformed(" + evt + ")" );
}
handler.catsEventPerformed( evt );
}
}
}
private boolean handlerListensToEvent( List< CatsEventType > types, CatsEventType type )
{
if ( types.contains( ALL ) )
{
return true;
}
else if ( types.contains( type ) )
{
return true;
}
return false;
}
}