// Path: src/main/java/org/nextrtc/signalingserver/domain/Conversation.java
// @Getter
// @Component
// @Scope("prototype")
// public abstract class Conversation implements NextRTCConversation {
//     protected static final ExecutorService parallel = Executors.newCachedThreadPool();
//     protected final String id;
// 
//     private LeftConversation leftConversation;
//     protected MessageSender messageSender;
// 
//     public Conversation(String id) {
//         this.id = id;
//     }
// 
//     public Conversation(String id,
//                         LeftConversation leftConversation,
//                         MessageSender messageSender) {
//         this.id = id;
//         this.leftConversation = leftConversation;
//         this.messageSender = messageSender;
//     }
// 
//     public abstract void join(Member sender);
// 
//     public synchronized void left(Member sender) {
//         if (remove(sender) && isWithoutMember()) {
//             leftConversation.destroy(this, sender);
//         }
//     }
// 
//     protected abstract boolean remove(Member leaving);
// 
//     protected void assignSenderToConversation(Member sender) {
//         sender.assign(this);
//     }
// 
//     public abstract boolean isWithoutMember();
// 
//     public abstract boolean has(Member from);
// 
//     public abstract void exchangeSignals(InternalMessage message);
// 
//     protected void sendJoinedToConversation(Member sender, String id) {
//         messageSender.send(InternalMessage.create()//
//                 .to(sender)//
//                 .content(id)//
//                 .signal(Signal.JOINED)//
//                 .build());
//     }
// 
//     protected void sendJoinedFrom(Member sender, Member member) {
//         messageSender.send(InternalMessage.create()//
//                 .from(sender)//
//                 .to(member)//
//                 .signal(Signal.NEW_JOINED)//
//                 .content(sender.getId())
//                 .build());
//     }
// 
//     protected void sendLeftMessage(Member leaving, Member recipient) {
//         messageSender.send(InternalMessage.create()//
//                 .from(leaving)//
//                 .to(recipient)//
//                 .signal(Signal.LEFT)//
//                 .build());
//     }
// 
//     public abstract void broadcast(Member from, InternalMessage message);
// 
//     @Inject
//     public void setLeftConversation(LeftConversation leftConversation) {
//         this.leftConversation = leftConversation;
//     }
// 
//     @Inject
//     public void setMessageSender(MessageSender messageSender) {
//         this.messageSender = messageSender;
//     }
// 
//     @Override
//     public String toString() {
//         return this.getClass().getSimpleName() + ": " + id;
//     }
// }
// 
// Path: src/main/java/org/nextrtc/signalingserver/domain/Member.java
// @Getter
// @Component
// @Scope("prototype")
// public class Member implements NextRTCMember {
// 
//     private String id;
//     private Connection connection;
//     private Conversation conversation;
// 
//     private NextRTCEventBus eventBus;
// 
//     private ScheduledFuture<?> ping;
// 
//     public Member(Connection connection, ScheduledFuture<?> ping) {
//         this.id = connection.getId();
//         this.connection = connection;
//         this.ping = ping;
//     }
// 
//     public Optional<Conversation> getConversation() {
//         return Optional.ofNullable(conversation);
//     }
// 
//     public void markLeft() {
//         ping.cancel(true);
//     }
// 
//     void assign(Conversation conversation) {
//         this.conversation = conversation;
//         eventBus.post(MEMBER_JOINED.basedOn(
//                 builder()
//                         .conversation(conversation)
//                         .from(this)));
//     }
// 
//     public void unassignConversation(Conversation conversation) {
//         eventBus.post(MEMBER_LEFT.basedOn(
//                 builder()
//                         .conversation(conversation)
//                         .from(this)));
//         this.conversation = null;
//     }
// 
//     public boolean hasSameConversation(Member to) {
//         return to != null && conversation.equals(to.conversation);
//     }
// 
//     @Inject
//     public void setEventBus(NextRTCEventBus eventBus) {
//         this.eventBus = eventBus;
//     }
// 
//     @Override
//     public String toString() {
//         return String.format("%s", id);
//     }
// 
//     public synchronized Connection getConnection() {
//         return connection;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (!(o instanceof Member)) {
//             return false;
//         }
//         Member m = (Member) o;
//         return new EqualsBuilder()//
//                 .append(m.id, id)//
//                 .isEquals();
//     }
// 
//     @Override
//     public int hashCode() {
//         return new HashCodeBuilder()//
//                 .append(id)//
//                 .build();
//     }
// }


import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.nextrtc.signalingserver.domain.Conversation;
import org.nextrtc.signalingserver.domain.Member;
import org.springframework.stereotype.Repository;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.nextrtc.signalingserver.exception.Exceptions.CONVERSATION_NAME_OCCUPIED;
package org.nextrtc.signalingserver.repository;




@Slf4j
@Repository
public class Conversations implements ConversationRepository {

    private Map<String, Conversation> conversations = Maps.newConcurrentMap();

    @Override
    public Optional<Conversation> findBy(String id) {
        if (isEmpty(id)) {
            return Optional.empty();
        }
        return Optional.ofNullable(conversations.get(id));
    }

    @Override
// Path: src/main/java/org/nextrtc/signalingserver/domain/Conversation.java
// @Getter
// @Component
// @Scope("prototype")
// public abstract class Conversation implements NextRTCConversation {
//     protected static final ExecutorService parallel = Executors.newCachedThreadPool();
//     protected final String id;
// 
//     private LeftConversation leftConversation;
//     protected MessageSender messageSender;
// 
//     public Conversation(String id) {
//         this.id = id;
//     }
// 
//     public Conversation(String id,
//                         LeftConversation leftConversation,
//                         MessageSender messageSender) {
//         this.id = id;
//         this.leftConversation = leftConversation;
//         this.messageSender = messageSender;
//     }
// 
//     public abstract void join(Member sender);
// 
//     public synchronized void left(Member sender) {
//         if (remove(sender) && isWithoutMember()) {
//             leftConversation.destroy(this, sender);
//         }
//     }
// 
//     protected abstract boolean remove(Member leaving);
// 
//     protected void assignSenderToConversation(Member sender) {
//         sender.assign(this);
//     }
// 
//     public abstract boolean isWithoutMember();
// 
//     public abstract boolean has(Member from);
// 
//     public abstract void exchangeSignals(InternalMessage message);
// 
//     protected void sendJoinedToConversation(Member sender, String id) {
//         messageSender.send(InternalMessage.create()//
//                 .to(sender)//
//                 .content(id)//
//                 .signal(Signal.JOINED)//
//                 .build());
//     }
// 
//     protected void sendJoinedFrom(Member sender, Member member) {
//         messageSender.send(InternalMessage.create()//
//                 .from(sender)//
//                 .to(member)//
//                 .signal(Signal.NEW_JOINED)//
//                 .content(sender.getId())
//                 .build());
//     }
// 
//     protected void sendLeftMessage(Member leaving, Member recipient) {
//         messageSender.send(InternalMessage.create()//
//                 .from(leaving)//
//                 .to(recipient)//
//                 .signal(Signal.LEFT)//
//                 .build());
//     }
// 
//     public abstract void broadcast(Member from, InternalMessage message);
// 
//     @Inject
//     public void setLeftConversation(LeftConversation leftConversation) {
//         this.leftConversation = leftConversation;
//     }
// 
//     @Inject
//     public void setMessageSender(MessageSender messageSender) {
//         this.messageSender = messageSender;
//     }
// 
//     @Override
//     public String toString() {
//         return this.getClass().getSimpleName() + ": " + id;
//     }
// }
// 
// Path: src/main/java/org/nextrtc/signalingserver/domain/Member.java
// @Getter
// @Component
// @Scope("prototype")
// public class Member implements NextRTCMember {
// 
//     private String id;
//     private Connection connection;
//     private Conversation conversation;
// 
//     private NextRTCEventBus eventBus;
// 
//     private ScheduledFuture<?> ping;
// 
//     public Member(Connection connection, ScheduledFuture<?> ping) {
//         this.id = connection.getId();
//         this.connection = connection;
//         this.ping = ping;
//     }
// 
//     public Optional<Conversation> getConversation() {
//         return Optional.ofNullable(conversation);
//     }
// 
//     public void markLeft() {
//         ping.cancel(true);
//     }
// 
//     void assign(Conversation conversation) {
//         this.conversation = conversation;
//         eventBus.post(MEMBER_JOINED.basedOn(
//                 builder()
//                         .conversation(conversation)
//                         .from(this)));
//     }
// 
//     public void unassignConversation(Conversation conversation) {
//         eventBus.post(MEMBER_LEFT.basedOn(
//                 builder()
//                         .conversation(conversation)
//                         .from(this)));
//         this.conversation = null;
//     }
// 
//     public boolean hasSameConversation(Member to) {
//         return to != null && conversation.equals(to.conversation);
//     }
// 
//     @Inject
//     public void setEventBus(NextRTCEventBus eventBus) {
//         this.eventBus = eventBus;
//     }
// 
//     @Override
//     public String toString() {
//         return String.format("%s", id);
//     }
// 
//     public synchronized Connection getConnection() {
//         return connection;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (!(o instanceof Member)) {
//             return false;
//         }
//         Member m = (Member) o;
//         return new EqualsBuilder()//
//                 .append(m.id, id)//
//                 .isEquals();
//     }
// 
//     @Override
//     public int hashCode() {
//         return new HashCodeBuilder()//
//                 .append(id)//
//                 .build();
//     }
// }


// Path: src/main/java/org/nextrtc/signalingserver/repository/Conversations.java
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.nextrtc.signalingserver.domain.Conversation;
import org.nextrtc.signalingserver.domain.Member;
import org.springframework.stereotype.Repository;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.nextrtc.signalingserver.exception.Exceptions.CONVERSATION_NAME_OCCUPIED;

package org.nextrtc.signalingserver.repository;




@Slf4j
@Repository
public class Conversations implements ConversationRepository {

    private Map<String, Conversation> conversations = Maps.newConcurrentMap();

    @Override
    public Optional<Conversation> findBy(String id) {
        if (isEmpty(id)) {
            return Optional.empty();
        }
        return Optional.ofNullable(conversations.get(id));
    }

    @Override
    public Optional<Conversation> findBy(Member from) {