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

com.addc.commons.queue.BoundedNotifyingQueue Maven / Gradle / Ivy

Go to download

The addc-queues library supplies support for internal persistent queues using an optional DERBY database for storage.

The newest version!
package com.addc.commons.queue;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The BoundedNotifyingQueue receives elements and adds them
 * to a queue. When the queue is full or a trigger is received from a timer, the
 * queue contents are sent to any listeners and the queue is cleared.
 * 
 * This class is thread-safe.
 * 
 * @see BoundedNotifyingQueueListener
 * @see BoundedNotifyingQueueTimer
 * 
 */
public class BoundedNotifyingQueue {

    private static final Logger LOGGER= LoggerFactory.getLogger(BoundedNotifyingQueue.class);
    private final int maxQueueLength;
    protected final List> listeners;
    protected List queue;
    private boolean isShutDown;
    private EnqueueProcessor enqueueProcessor;
    
    /**
     * Constructor
     * 
     * @param maxQueuelength the maximum number of elements allowed in the internal queue
     * @param enqueueProcessor Object that will process the elements just before they are put in the queue can be null
     */
    public BoundedNotifyingQueue(int maxQueuelength, EnqueueProcessor enqueueProcessor) {
        this.maxQueueLength= maxQueuelength;
        this.listeners= Collections.synchronizedList(new LinkedList>());
        this.queue= new ArrayList<>(getMaxQueueLength());
        this.isShutDown= false;
        this.enqueueProcessor= enqueueProcessor;
        LOGGER.info("Created BoundedNotifyingQueue for {} elements", maxQueuelength);
    }

    
    /**
     * Adds a new {@link BoundedNotifyingQueueListener} to this queue
     * 
     * @param newListener The listener to add
     */
    public void addListener(BoundedNotifyingQueueListener newListener) {
        listeners.add(newListener);
        LOGGER.debug("Added a new queue listener");
    }

    /**
     * @return the EnqueueProcessor being used
     */
    public EnqueueProcessor getEnqueueProcessor() {
        return enqueueProcessor;
    }


    /**
     * Set the EnqueueProcessor to use.
     * @param enqueueProcessor the EnqueueProcessor to set
     */
    public void setEnqueueProcessor(EnqueueProcessor enqueueProcessor) {
        this.enqueueProcessor= enqueueProcessor;
    }


    /**
     * Terminates the queue and notifies the listeners with any elements are 
     * available. After the queue is terminated any elements added are dropped.
     * 
     */
    public void shutdown() {
        synchronized (queue) {
            isShutDown= true;
            empty();
        }
        LOGGER.debug("Event queue is shut down. New events are discarded.");
    }

    /**
     * Before actually placing the element in the buffer any EnqueueProcessor
     * attached to the queue is invoked. If the element is null or the result of
     * pre-processing the element is null it is simply ignored-
     * 
     * @param element the Element to be added to the buffer
     */
    public void put(E element) {
        synchronized (queue) {
            if (!isShutDown) {
                if (enqueueProcessor == null) {
                    if (element != null) {
                        queue.add(element);
                    }
                } else {
                    E ppel= enqueueProcessor.preProcess(element);
                    if (ppel != null) {
                        queue.add(ppel);
                    }
                }
                if (queue.size() == getMaxQueueLength()) {
                    LOGGER.debug("Event queue is full");
                    empty();
                }
            }
        }
    }

    /**
     * Query whether the queue is empty
     * @return true if the queue is empty
     */
    public boolean isEmpty() {        
        return queue.isEmpty();
    }

    /**
     * Get the maximum length of the queue
     * @return the maximum length of the queue
     */
    public int getMaxQueueLength() {
        return maxQueueLength;
    }
    
    /**
     * Empties the queue. If the queue was not empty already, it notifies
     * listeners. Listeners get the contents of the queue before itis cleared
     */
    public void empty() {
        synchronized (queue) {
            if (!isEmpty()) {
                notifyQueueEmptied();
                queue.clear();
            }
        }
    }
    
    /**
     * Iterates over the listeners: in every iteration the content of the
     * internal queue is passed to the actual {@link BoundedNotifyingQueueListener}.
     * 
     */
    private void notifyQueueEmptied() {
        ArrayList eventsToPost= new ArrayList<>(queue);
        
        synchronized (listeners) {
            for (BoundedNotifyingQueueListener listener : listeners) {
                listener.onEmpty(eventsToPost);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy