org.codeartisans.java.sos.messagebus.BaseMessageBus Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2009, Paul Merlin. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.codeartisans.java.sos.messagebus;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Base MessageBus implementation.
*
* Only the publish method is abstract, other ones are final.
*
* Safe but could be too slow or too fat for your usage. New implementations will be done/accepted
* with a convincing test case to keep MessageBus small.
*/
public abstract class BaseMessageBus
implements MessageBus
{
private final ConcurrentHashMap, CopyOnWriteArrayList>> subscribers = new ConcurrentHashMap, CopyOnWriteArrayList>>();
private final ConcurrentHashMap, CopyOnWriteArrayList>> vetos = new ConcurrentHashMap, CopyOnWriteArrayList>>();
@Override
public abstract void publish( Message msg );
@Override
public Subscribtion subscribe( MessageType type, S subscriber )
{
subscribers( type ).add( subscriber );
return new Subscribtion( this, type, subscriber );
}
@Override
public void unsubscribe( MessageType type, S subscriber )
{
CopyOnWriteArrayList l = subscribers( type );
boolean result = l.remove( subscriber );
if ( l.isEmpty() ) {
subscribers.remove( type );
}
assert result : "Tried to remove unknown subscriber: " + subscriber + " for " + type;
}
@Override
public VetoRegistration registerVeto( MessageType type, Veto veto )
{
vetos( type ).add( veto );
return new VetoRegistration( this, type, veto );
}
@Override
public void unregisterVeto( MessageType type, Veto veto )
{
CopyOnWriteArrayList l = vetos( type );
boolean result = l.remove( veto );
if ( l.isEmpty() ) {
vetos.remove( type );
}
assert result : "Tried to remove unknown veto: " + veto + " for " + type;
}
@Override
public S getSubscriber( MessageType type, int index )
{
return subscribers( type ).get( index );
}
@Override
public boolean hasSubscribers( MessageType type )
{
return subscribers.containsKey( type );
}
@Override
public int countSubscribers( MessageType type )
{
CopyOnWriteArrayList> l = subscribers.get( type );
return l == null ? 0 : l.size();
}
/**
* @param Subscriber mark type, for type safety
* @param message Message
* @return True if the Message is vetoed, false otherwise
*/
protected final boolean vetoed( Message message )
{
CopyOnWriteArrayList msgVetos = vetos( message.getMessageType() );
for ( Veto eachVeto : msgVetos ) {
if ( eachVeto.veto( message ) ) {
return true;
}
}
return false;
}
/**
* @param Subscriber mark type, for type safety
* @param type MessageType
* @return The Subscriber collection for a MessageType
*/
@SuppressWarnings( "unchecked" )
protected final CopyOnWriteArrayList subscribers( MessageType type )
{
subscribers.putIfAbsent( type, new CopyOnWriteArrayList() );
// This cast is safe because we control the puts.
return ( CopyOnWriteArrayList ) subscribers.get( type );
}
/**
* @param Subscriber mark type, for type safety
* @param type MessageType
* @return The Veto collection for a MessageType
*/
@SuppressWarnings( "unchecked" )
protected final CopyOnWriteArrayList vetos( MessageType type )
{
vetos.putIfAbsent( type, new CopyOnWriteArrayList() );
// This cast is safe because we control the puts.
return ( CopyOnWriteArrayList ) vetos.get( type );
}
}