//______________________________________________________________________________
//   |       |
//   | knipp |           Knipp Medien und Kommunikation GmbH
//    -------
//
//
//     Knipp RRI Toolkit
//
//
//     Copyright (C) 2005 by Knipp Medien und Kommunikation GmbH
//
//     This 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 any later version.
// 
//     This 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 library; if not, write to the 
//     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
//     Boston, MA 02111-1307 USA 
//
//
//     initial author:    Klaus Malorny
//
//     version:           1.3 (15112), 2011/05/27 16:00:14
//                        $Revision: 14936 $ 
//                        $Date: 2010-11-05 15:57:40 +0100 (Fri, 05 Nov 2010) $
//                        $Author: Klaus.Malorny $
//

package de.knipp.rritoolkit.test;

import java.io.IOException;

import de.knipp.rritoolkit.ChannelFactory;
import de.knipp.rritoolkit.RegistryChannel;

/**
 *  This is a helper class for debugging/logging purposes. It is a wrapper
 *  to a factory. The channels returned by this wrapper are also wrapped
 *  into a class which prints the communication with the registry to the 
 *  console.
 *
 *  @version  $Revision: 14936 $
 *  @author   Klaus Malorny
 */

public class DebugChannelFactory implements ChannelFactory
{
  /** the actual factory */
  
  private ChannelFactory factory;
  
  
  /** a counter to allow the identification of the created channels */
  
  private int counter;
  
  
  /**
   *  constructor
   *
   *  @param theFactory                the actual factory
   */
  
  public DebugChannelFactory (ChannelFactory theFactory)
  {
    factory = theFactory;
    counter = 0;
  }
  
  
  //--- implementation of ChannelFactory ---------------------------------------
  
  /**
   *  create a new channel. If a implementation or configuration specific
   *  limit of number of channels exists and this limit has been reached,
   *  {@code null} is returned. If a channel could not be created for
   *  a different reason, an {@code IOException} is thrown. Channels that
   *  are no longer used by the caller should be closed
   *
   *  @return                    the channel or {@code null} if no more
   *                             channels are available
   *  @throws IOException        if the channel could not be created
   */

  @Override
  public RegistryChannel createChannel ()
    throws IOException
  {
    try
    {
      RegistryChannel channel = factory.createChannel ();
      return new DebugChannel (channel, ++counter);
      
    } catch (IOException e)
    {
      System.err.println ("failed to create a new channel");
      e.printStackTrace (System.err);
      
      throw e;
    }
  }
  
  
  
  /**
   *  wrapper class for a connection. Prints messages sent and received
   *  to the console.
   *
   *  @version  $Revision: 14936 $
   *  @author   Klaus Malorny
   */
  
  private static class DebugChannel implements RegistryChannel
  {
    /** the actual channel */
    
    private RegistryChannel channel;
    
    
    /** the ID of the channel */
    
    private int id;
    
    
    /**
     *  constructor
     *
     *  @param theChannel                the actual channel
     *  @param theID                     the assigned ID
     */
    
    public DebugChannel (RegistryChannel theChannel, int theID)
    {
      channel = theChannel;
      id = theID;
      
      System.err.println ("channel " + id + " created.");
    }
    
    
    //--- implementation of RegistryChannel ------------------------------------
    
    /**
     *  send the given message to the registry. As the transport mechanism
     *  may need to know whether the data represents the XML or key-value form
     *  of the request, it must be specified. If the channel is already closed,
     *  an exception is thrown.
     *
     *  @param data                    the data representing the message
     *  @param isXml                   {@code true} if the message uses the
     *                                 XML encoding, {@code false} if the
     *                                 message uses key-value pairs.
     *  @throws IOException            if the transmission failed
     */

    @Override
    public void send (byte[] data, boolean isXml)
      throws IOException
    {
      try
      {
        System.err.println ("channel " + id +
          ": >>>>>> sending to registry >>>>>>");
        
        System.err.println (new String (data, "UTF-8")); // we know it's UTF-8
        System.err.println ();
        
        channel.send (data, isXml);
        
      } catch (IOException e)
      {
        System.err.println ("channel " + id + ": send failed:");
        e.printStackTrace (System.err);
        
        throw e;
      }
    }



    /**
     *  wait for a response from the registry.
     *
     *  @return                         the message that has been received
     *  @throws IOException             if the connection has been closed either
     *                                  before or during the call.
     */

    @Override
    public byte[] receive ()
      throws IOException
    {
      try
      {
        System.err.println ("channel " + id + ": waiting for the response");
        byte[] data = channel.receive ();
        
        System.err.println ("channel " + id + 
          ": <<<<<< received from registry <<<<<<");

        System.err.println (new String (data, "UTF-8")); // we know it's UTF-8
        System.err.println ();
        
        return data;

      } catch (IOException e)
      {
        System.err.println ("channel " + id + ": receive failed:");
        e.printStackTrace (System.err);
        
        throw e;
      }
    }



    /**
     *  return whether the channel has been closed
     *
     *  @return                     {@code true} if closed
     */

    @Override
    public boolean isClosed ()
    {
      return channel.isClosed ();
    }



    /**
     *  close the channel. Closing an already closed channel should be
     *  ignored
     */

    @Override
    public void close ()
    {
      channel.close ();
      System.err.println ("channel " + id + ": close called");
    }
  }
}





