/**
 * Copyright (c) 2015-2016 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see <http://www.gnu.org/licenses/>
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.bc.gateway.inbound;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.ow2.petals.bc.gateway.jbidescriptor.generated.JbiConsumerDomain;
import org.ow2.petals.bc.gateway.messages.ServiceKey;
import org.ow2.petals.bc.gateway.messages.TransportedToConsumerDomainAddedConsumes;
import org.ow2.petals.component.framework.jbidescriptor.generated.Consumes;

import io.netty.channel.ChannelHandlerContext;

/**
 * There is one instance of this class per consumer domain in an SU configuration (jbi.xml).
 * 
 * It is responsible of notifying the channels (to consumer partner) of existing Consumes propagated to them.
 * 
 * The main idea is that a given consumer partner can contact us (a provider partner) with multiple connections (for
 * example in case of HA) and each of these needs to know what are the consumes propagated to them.
 * 
 * TODO how do we close this consumer domain?
 * 
 * @author vnoel
 *
 */
public class ConsumerDomain {

    /**
     * This lock is here to prevent concurrent modifications of {@link #services} and {@link #channels}.
     * 
     * It ensures that any ordering of adding channels and listeners will be valid.
     */
    private final Lock lock = new ReentrantLock();

    /**
     * The keys of the {@link Consumes} propagated to this consumer domain.
     */
    private final Map<ServiceKey, Consumes> services = new HashMap<>();

    /**
     * The channels from this consumer domain (there can be more than one in case of HA or stuffs like that for example)
     */
    private final Set<ChannelHandlerContext> channels = new HashSet<>();

    public final JbiConsumerDomain jcd;

    public ConsumerDomain(final JbiConsumerDomain jcd, final Collection<Consumes> consumes) {
        this.jcd = jcd;
        for (final Consumes c : consumes) {
            assert c != null;
            services.put(new ServiceKey(c), c);
        }
    }

    public void registerChannel(final ChannelHandlerContext ctx) {
        lock.lock();
        try {
            channels.add(ctx);
            for (final ServiceKey key : services.keySet()) {
                assert key != null;
                ctx.write(new TransportedToConsumerDomainAddedConsumes(key));
            }
            ctx.flush();
        } finally {
            lock.unlock();
        }
    }

    public void deregisterChannel(ChannelHandlerContext ctx) {
        lock.lock();
        try {
            channels.remove(ctx);
        } finally {
            lock.unlock();
        }
    }

    /**
     * Ensure the transport is accepted for this consumer domain
     * 
     * TODO support many transports?
     */
    public boolean accept(final String transportId) {
        return jcd.getTransport().equals(transportId);
    }

    public void exceptionReceived(final Exception msg) {
        // TODO just print it: receiving an exception here means that there is nothing to do, it is just
        // information for us.
    }
}

@@ -881,23 +881,27 @@
 va.util.
-HashMap
+Collections
 ;%0Aimport
@@ -915,19 +915,19 @@
 til.Hash
-Set
+Map
 ;%0Aimport
@@ -996,67 +996,25 @@
 ent.
-locks.Lock;%0Aimport java.util.concurrent.locks.ReentrantLock
+ConcurrentHashMap
 ;%0A%0Ai
@@ -1896,273 +1896,8 @@
  %7B%0A%0A
-    /**%0A     * This lock is here to prevent concurrent modifications of %7B@link #services%7D and %7B@link #channels%7D.%0A     * %0A     * It ensures that any ordering of adding channels and listeners will be valid.%0A     */%0A    private final Lock lock = new ReentrantLock();%0A%0A
     
@@ -2186,32 +2186,62 @@
 xample)%0A     */%0A
+    @SuppressWarnings(%22null%22)%0A
     private fina
@@ -2284,23 +2284,103 @@
 s = 
-new HashSet%3C
+Collections%0A            .newSetFromMap(new ConcurrentHashMap%3CChannelHandlerContext, Boolean
 %3E()
+)
 ;%0A%0A 
@@ -2747,47 +2747,8 @@
 ) %7B%0A
-        lock.lock();%0A        try %7B%0A    
     
@@ -2774,28 +2774,24 @@
 x);%0A        
-   
- 
 for (final S
@@ -2835,28 +2835,24 @@
             
-    
 assert key !
@@ -2867,28 +2867,24 @@
             
-  
-  
 ctx.write(ne
@@ -2933,20 +2933,16 @@
 (key));%0A
-    
         
@@ -2947,28 +2947,24 @@
   %7D%0A        
-    
 ctx.flush();
@@ -2968,65 +2968,8 @@
 ();%0A
-        %7D finally %7B%0A            lock.unlock();%0A        %7D%0A
     
@@ -3005,16 +3005,22 @@
 Channel(
+final 
 ChannelH
@@ -3052,125 +3052,29 @@
     
-lock.lock();%0A        try %7B%0A            channels.remove(ctx);%0A        %7D finally %7B%0A            lock.unlock();%0A        %7D
+channels.remove(ctx);
 %0A   

Remove useless lock