// Path: utils/src/main/java/co/flyver/utils/CapacityQueue.java
// public class CapacityQueue<E> extends LinkedBlockingQueue<E> {
//         private int limit;
// 
//         public CapacityQueue(int limit) {
//             this.limit = limit;
//         }
// 
//         @Override
//         public boolean add(E e) {
//             boolean added = super.add(e);
//             while(added && size() > limit) {
//                 super.remove();
//             }
//             return added;
//         }
//     }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/exceptions/NoSuchTopicException.java
// public class NoSuchTopicException extends Exception {
//     public NoSuchTopicException(String detailMessage) {
//         super(detailMessage);
//     }
// }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/exceptions/ProducerAlreadyRegisteredException.java
// public class ProducerAlreadyRegisteredException extends Exception {
//     public ProducerAlreadyRegisteredException(String detailMessage) {
//         super(detailMessage);
//     }
// }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/interfaces/FlyverMQCallback.java
// public interface FlyverMQCallback {
//     /**
//      * Called every time a producer is registered to the message queue
//      * Used to notify components for new producers that they might be interested in
//      * @param topic String, the topic of the messages sent by the producer
//      */
//     public void producerRegistered(String topic);
// 
//     /**
//      * Called every time a producer is unregistered or replaced from the system
//      * Used to notify components that a producer has disappeared, so they should unregister
//      * for it's messages
//      * @param topic String, the topic of the messages of the unregistered producer
//      */
//     public void producerUnregistered(String topic);
// }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/interfaces/FlyverMQConsumer.java
// public interface FlyverMQConsumer {
//     /**
//      * Data recieved callback for the consumer.
//      * Called when a message with the associated topic
//      * for the consumer is received in the message queue
//      * @param message SimpleMQMessage data container
//      */
//     public void dataReceived(FlyverMQMessage message);
// 
//     /**
//      * Consumer unregister hook
//      * Called when the consumer is removed from the message queue
//      */
//     public void unregistered();
// 
//     //TODO: clarify if consumers need onPause/onResume functionallity
//     public void paused();
//     public void resumed();
// }


import android.util.Log;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import co.flyver.utils.CapacityQueue;
import co.flyver.utils.flyverMQ.exceptions.NoSuchTopicException;
import co.flyver.utils.flyverMQ.exceptions.ProducerAlreadyRegisteredException;
import co.flyver.utils.flyverMQ.interfaces.FlyverMQCallback;
import co.flyver.utils.flyverMQ.interfaces.FlyverMQConsumer;
package co.flyver.utils.flyverMQ;




/**
 * Created by Petar Petrov on 12/9/14.
 */
public class FlyverMQ {


    /**
     * Helper class
     * Used to easily associate producers with an internal queue for their events
     * Constructor can be passed only producer, and the queue will be dynamic LinkedList,
     * or producer and size, and the queue will be CapacityQueue, which automatically removes
     * the oldest objects, when it's capacity is reached
     */
    private class SimpleMQProducerWrapper {
        private FlyverMQProducer producer;

        public FlyverMQProducer getProducer() {
            return producer;
        }

        public BlockingQueue<FlyverMQMessage> getQueue() {
            return queue;
        }

        private BlockingQueue<FlyverMQMessage> queue;

        SimpleMQProducerWrapper(FlyverMQProducer producer) {
            this.producer = producer;
            queue = new LinkedBlockingQueue<>();
        }

        SimpleMQProducerWrapper(FlyverMQProducer producer, int size) {
            this.producer = producer;
// Path: utils/src/main/java/co/flyver/utils/CapacityQueue.java
// public class CapacityQueue<E> extends LinkedBlockingQueue<E> {
//         private int limit;
// 
//         public CapacityQueue(int limit) {
//             this.limit = limit;
//         }
// 
//         @Override
//         public boolean add(E e) {
//             boolean added = super.add(e);
//             while(added && size() > limit) {
//                 super.remove();
//             }
//             return added;
//         }
//     }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/exceptions/NoSuchTopicException.java
// public class NoSuchTopicException extends Exception {
//     public NoSuchTopicException(String detailMessage) {
//         super(detailMessage);
//     }
// }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/exceptions/ProducerAlreadyRegisteredException.java
// public class ProducerAlreadyRegisteredException extends Exception {
//     public ProducerAlreadyRegisteredException(String detailMessage) {
//         super(detailMessage);
//     }
// }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/interfaces/FlyverMQCallback.java
// public interface FlyverMQCallback {
//     /**
//      * Called every time a producer is registered to the message queue
//      * Used to notify components for new producers that they might be interested in
//      * @param topic String, the topic of the messages sent by the producer
//      */
//     public void producerRegistered(String topic);
// 
//     /**
//      * Called every time a producer is unregistered or replaced from the system
//      * Used to notify components that a producer has disappeared, so they should unregister
//      * for it's messages
//      * @param topic String, the topic of the messages of the unregistered producer
//      */
//     public void producerUnregistered(String topic);
// }
// 
// Path: utils/src/main/java/co/flyver/utils/flyverMQ/interfaces/FlyverMQConsumer.java
// public interface FlyverMQConsumer {
//     /**
//      * Data recieved callback for the consumer.
//      * Called when a message with the associated topic
//      * for the consumer is received in the message queue
//      * @param message SimpleMQMessage data container
//      */
//     public void dataReceived(FlyverMQMessage message);
// 
//     /**
//      * Consumer unregister hook
//      * Called when the consumer is removed from the message queue
//      */
//     public void unregistered();
// 
//     //TODO: clarify if consumers need onPause/onResume functionallity
//     public void paused();
//     public void resumed();
// }


// Path: utils/src/main/java/co/flyver/utils/flyverMQ/FlyverMQ.java
import android.util.Log;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import co.flyver.utils.CapacityQueue;
import co.flyver.utils.flyverMQ.exceptions.NoSuchTopicException;
import co.flyver.utils.flyverMQ.exceptions.ProducerAlreadyRegisteredException;
import co.flyver.utils.flyverMQ.interfaces.FlyverMQCallback;
import co.flyver.utils.flyverMQ.interfaces.FlyverMQConsumer;

package co.flyver.utils.flyverMQ;




/**
 * Created by Petar Petrov on 12/9/14.
 */
public class FlyverMQ {


    /**
     * Helper class
     * Used to easily associate producers with an internal queue for their events
     * Constructor can be passed only producer, and the queue will be dynamic LinkedList,
     * or producer and size, and the queue will be CapacityQueue, which automatically removes
     * the oldest objects, when it's capacity is reached
     */
    private class SimpleMQProducerWrapper {
        private FlyverMQProducer producer;

        public FlyverMQProducer getProducer() {
            return producer;
        }

        public BlockingQueue<FlyverMQMessage> getQueue() {
            return queue;
        }

        private BlockingQueue<FlyverMQMessage> queue;

        SimpleMQProducerWrapper(FlyverMQProducer producer) {
            this.producer = producer;
            queue = new LinkedBlockingQueue<>();
        }

        SimpleMQProducerWrapper(FlyverMQProducer producer, int size) {
            this.producer = producer;
            queue = new CapacityQueue<>(size);