// Path: jpost/src/main/java/com/mindorks/jpost/core/ChannelPost.java
// public class ChannelPost<T, V> implements Post<T, V> {
// 
//     private T message;
//     private V sender;
//     private Integer channelId;
//     private Integer priority;
//     private Object[] receivers;
//     private boolean isSerialised;
//     private String className;
// 
//     public ChannelPost(T message, Integer channelId, Integer priority) {
//         this.message = message;
//         this.channelId = channelId;
//         this.priority = priority;
//     }
// 
//     public ChannelPost(T message, Integer channelId, Integer priority, boolean isSerialised, String className) {
//         this.message = message;
//         this.channelId = channelId;
//         this.priority = priority;
//         this.isSerialised = isSerialised;
//         this.className = className;
//     }
// 
//     @Override
//     public void setMessage(T message){
//         this.message = message;
//     }
// 
//     @Override
//     public T getMessage() {
//         return message;
//     }
// 
//     @Override
//     public void setPriority(Integer priority){
//         this.priority = priority;
//     }
// 
//     @Override
//     public Integer getPriority() {
//         return priority;
//     }
// 
//     @Override
//     public V getSender() throws NullObjectException {
//         return sender;
//     }
// 
//     @Override
//     public void setSender(V sender) {
//         this.sender = sender;
//     }
// 
//     @Override
//     public void setReceivers(Object... receivers){
//         this.receivers = receivers;
//     }
// 
//     @Override
//     public Object[] getReceiversList() {
//         return receivers;
//     }
// 
//     @Override
//     public void setIsSerialised(boolean isSerialised) {
//         this.isSerialised = isSerialised;
//     }
// 
//     @Override
//     public boolean isSerialised() {
//         return isSerialised;
//     }
// 
//     @Override
//     public void setSerialisedClassName(String className){
//         this.className = className;
//     }
// 
//     @Override
//     public String getSerialisedClassName() {
//         return className;
//     }
// 
//     public Integer getChannelId() {
//         return channelId;
//     }
// 
//     public void setChannelId(Integer channelId){
//         this.channelId = channelId;
//     }
// }
// 
// Path: jpost/src/main/java/com/mindorks/jpost/exceptions/IllegalChannelStateException.java
// public class IllegalChannelStateException extends Exception{
// 
//     public IllegalChannelStateException(String message) {
//         super(message);
//     }
// 
//     public String toString() {
//         return "IllegalChannelStateException[" + super.getMessage() + "]";
//     }
// }
// 
// Path: jpost/src/main/java/com/mindorks/jpost/exceptions/NullObjectException.java
// public class NullObjectException extends Exception{
// 
//     public NullObjectException(String message) {
//         super(message);
//     }
// 
//     public String toString() {
//         return "NullObjectException[" + super.getMessage() + "]";
//     }
// }


import com.mindorks.jpost.core.OnMessage;
import com.mindorks.jpost.core.*;
import com.mindorks.jpost.core.ChannelPost;
import com.mindorks.jpost.exceptions.IllegalChannelStateException;
import com.mindorks.jpost.exceptions.NullObjectException;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;
    public void startChannel() {
        super.setChannelState(ChannelState.OPEN);
    }

    @Override
    public void stopChannel() {
        super.setChannelState(ChannelState.STOPPED);
    }

    @Override
    public <T> void broadcast(T msg, Integer... subscriberIds) throws NullObjectException, IllegalChannelStateException {
        if(super.getChannelState() != ChannelState.OPEN){
            throw new IllegalChannelStateException("Channel with id " + super.getChannelId() + " is closed");
        }
        if(msg == null){
            throw new NullObjectException("message is null");
        }
        ChannelPost post = new ChannelPost<>(msg, getChannelId(), Post.PRIORITY_MEDIUM);
        getPostQueue().put(new WeakReference<>(post));

        while (!getPostQueue().isEmpty()) {
            WeakReference<ChannelPost> msgRef = getPostQueue().poll();
            if(msgRef != null) {
                ChannelPost mspPost = msgRef.get();
                if (mspPost != null && mspPost.getChannelId() != null) {
                    if (mspPost.getChannelId().equals(getChannelId())) {
                        for (Integer subscriberId : subscriberIds) {
                            if (getSubscriberMap().containsKey(subscriberId)) {
                                WeakReference<Object> subscriberRef = getSubscriberMap().get(subscriberId);
                                if(subscriberRef != null) {
// Path: jpost/src/main/java/com/mindorks/jpost/core/ChannelPost.java
// public class ChannelPost<T, V> implements Post<T, V> {
// 
//     private T message;
//     private V sender;
//     private Integer channelId;
//     private Integer priority;
//     private Object[] receivers;
//     private boolean isSerialised;
//     private String className;
// 
//     public ChannelPost(T message, Integer channelId, Integer priority) {
//         this.message = message;
//         this.channelId = channelId;
//         this.priority = priority;
//     }
// 
//     public ChannelPost(T message, Integer channelId, Integer priority, boolean isSerialised, String className) {
//         this.message = message;
//         this.channelId = channelId;
//         this.priority = priority;
//         this.isSerialised = isSerialised;
//         this.className = className;
//     }
// 
//     @Override
//     public void setMessage(T message){
//         this.message = message;
//     }
// 
//     @Override
//     public T getMessage() {
//         return message;
//     }
// 
//     @Override
//     public void setPriority(Integer priority){
//         this.priority = priority;
//     }
// 
//     @Override
//     public Integer getPriority() {
//         return priority;
//     }
// 
//     @Override
//     public V getSender() throws NullObjectException {
//         return sender;
//     }
// 
//     @Override
//     public void setSender(V sender) {
//         this.sender = sender;
//     }
// 
//     @Override
//     public void setReceivers(Object... receivers){
//         this.receivers = receivers;
//     }
// 
//     @Override
//     public Object[] getReceiversList() {
//         return receivers;
//     }
// 
//     @Override
//     public void setIsSerialised(boolean isSerialised) {
//         this.isSerialised = isSerialised;
//     }
// 
//     @Override
//     public boolean isSerialised() {
//         return isSerialised;
//     }
// 
//     @Override
//     public void setSerialisedClassName(String className){
//         this.className = className;
//     }
// 
//     @Override
//     public String getSerialisedClassName() {
//         return className;
//     }
// 
//     public Integer getChannelId() {
//         return channelId;
//     }
// 
//     public void setChannelId(Integer channelId){
//         this.channelId = channelId;
//     }
// }
// 
// Path: jpost/src/main/java/com/mindorks/jpost/exceptions/IllegalChannelStateException.java
// public class IllegalChannelStateException extends Exception{
// 
//     public IllegalChannelStateException(String message) {
//         super(message);
//     }
// 
//     public String toString() {
//         return "IllegalChannelStateException[" + super.getMessage() + "]";
//     }
// }
// 
// Path: jpost/src/main/java/com/mindorks/jpost/exceptions/NullObjectException.java
// public class NullObjectException extends Exception{
// 
//     public NullObjectException(String message) {
//         super(message);
//     }
// 
//     public String toString() {
//         return "NullObjectException[" + super.getMessage() + "]";
//     }
// }


// Path: jpost/src/main/java/com/mindorks/jpost/core/PublicChannel.java
import com.mindorks.jpost.core.OnMessage;
import com.mindorks.jpost.core.*;
import com.mindorks.jpost.core.ChannelPost;
import com.mindorks.jpost.exceptions.IllegalChannelStateException;
import com.mindorks.jpost.exceptions.NullObjectException;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;

    public void startChannel() {
        super.setChannelState(ChannelState.OPEN);
    }

    @Override
    public void stopChannel() {
        super.setChannelState(ChannelState.STOPPED);
    }

    @Override
    public <T> void broadcast(T msg, Integer... subscriberIds) throws NullObjectException, IllegalChannelStateException {
        if(super.getChannelState() != ChannelState.OPEN){
            throw new IllegalChannelStateException("Channel with id " + super.getChannelId() + " is closed");
        }
        if(msg == null){
            throw new NullObjectException("message is null");
        }
        ChannelPost post = new ChannelPost<>(msg, getChannelId(), Post.PRIORITY_MEDIUM);
        getPostQueue().put(new WeakReference<>(post));

        while (!getPostQueue().isEmpty()) {
            WeakReference<ChannelPost> msgRef = getPostQueue().poll();
            if(msgRef != null) {
                ChannelPost mspPost = msgRef.get();
                if (mspPost != null && mspPost.getChannelId() != null) {
                    if (mspPost.getChannelId().equals(getChannelId())) {
                        for (Integer subscriberId : subscriberIds) {
                            if (getSubscriberMap().containsKey(subscriberId)) {
                                WeakReference<Object> subscriberRef = getSubscriberMap().get(subscriberId);
                                if(subscriberRef != null) {
                                    Object subscriberObj = subscriberRef.get();