OrderedEventController.java

package org.microcol.gui.event;

import java.util.ArrayList;
import java.util.List;

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

import com.google.common.base.Preconditions;

/**
 * Listener controller that support ordering of listeners. s *
 * 
 * @param <E>
 *            event object
 */
public class OrderedEventController<E> {

	private final Logger logger = LoggerFactory.getLogger(OrderedEventController.class);

	/**
	 * Value of priority when it's not specified.
	 */
	private final static int DEFAULT_PRIORITY = 10;

	/**
	 * Listeners
	 */
	private final List<ValueWithPriority<E>> listeners = new ArrayList<>();

	/**
	 * It add listener with default priority.
	 * 
	 * @param listener
	 *            required listener
	 */
	public void addListener(final Listener<E> listener) {
		addListener(listener, DEFAULT_PRIORITY);
	}

	/**
	 * Add listener with priority.
	 * 
	 * @param listener
	 *            required listener
	 * @param priority
	 *            priority lower values are executed first higher later
	 */
	public void addListener(final Listener<E> listener, final int priority) {
		Preconditions.checkNotNull(listener);
		listeners.add(new ValueWithPriority<>(listener, priority));
	}

	/**
	 * Synchronously invoke event on all listeners. Listeners are called in
	 * ordered way. listener with lover priority is called before listener with
	 * bigger priority.
	 * 
	 * @param event
	 *            required event object
	 */
	public void fireEvent(final E event) {
		Preconditions.checkNotNull(event);
		logger.debug("Event " + event + " was triggered.");
		listeners.stream().sorted((v1, v2) -> v1.getPriority() - v2.getPriority())
				.forEach(valueWithPriority -> valueWithPriority.getListener().onEvent(event));
	}

	/**
	 * Class helps to hold listener of specific type and it's priority.
	 * 
	 * @param <ET>
	 *            event type
	 */
	private class ValueWithPriority<ET> {

		private final Listener<ET> listener;

		private final int priority;

		public ValueWithPriority(final Listener<ET> listener, final int priority) {
			this.listener = listener;
			this.priority = priority;
		}

		public Listener<ET> getListener() {
			return listener;
		}

		public int getPriority() {
			return priority;
		}

	}

}