All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 );
    }

}