//______________________________________________________________________________
//   |       |
//   | 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.4 (15127), 2011/06/03 14:52:49
//                        $Revision: 14936 $ 
//                        $Date: 2010-11-05 15:57:40 +0100 (Fri, 05 Nov 2010) $
//                        $Author: Klaus.Malorny $
//

package de.knipp.rritoolkit;

import java.io.IOException;

import de.knipp.rritoolkit.request.Request;

import de.knipp.rritoolkit.response.Response;

/**
 *  implementation of the {@code Port} interface that operates on a
 *  single channel. The port may be used by multiple threads in parallel.
 *
 *  @version  $Revision: 14936 $
 *  @author   Klaus Malorny
 */

public class SinglePort implements Port
{
  /** the channel */
  
  private RegistryChannel channel;
  
  
  /** the codec */
  
  private Codec codec;
  
  
  
  /**
   *  constructor
   *
   *  @param factory           the factory for the channel
   *  @param theCodec          the codec to use. If {@code null}, a
   *                           default codec is used
   *  @throws IOException      if no channel could be created
   */
  
  public SinglePort (ChannelFactory factory, Codec theCodec)
    throws IOException
  {
    channel = factory.createChannel ();
    if (channel == null) throw new IOException ("no more channels!");
    codec = theCodec == null ? new Codec () : theCodec;
  }
  

  /**
   *  constructor
   *
   *  @param theChannel        an already allocated channel
   *  @param theCodec          the codec to use. If {@code null}, a
   *                           default codec is used
   */
  
  public SinglePort (RegistryChannel theChannel, Codec theCodec)
  {
    channel = theChannel;
    codec = theCodec == null ? new Codec () : theCodec;
  }
  
  
  /**
   *  constructor
   *
   *  @param factory           the factory for the channel
   *  @throws IOException      if no channel could be created
   */
  
  public SinglePort (ChannelFactory factory)
    throws IOException
  {
    this (factory, new Codec ());
  }
  
  
  
  /**
   *  "execute" a request, i.e. send it to the registry and wait for the
   *  response
   *
   *  @param request          the request
   *  @return                 the response received
   *  @throws IOException     if either the transmission or the reception failed
   */

  @Override
  public synchronized Response execute (Request request)
    throws IOException
  {
    try
    {
      byte[] data = codec.encodeRequest (request);
      
      channel.send (data, codec.xmlUsed ());
      data = channel.receive ();

      return codec.decodeResponse (data, request);
      
    } catch (EncodeException e)
    {
      throw new IOException ("failed to encode the request", e);
      
    } catch (ResponseParseException e)
    {
      throw new IOException ("failed to decode the response", e);
    }
  }
  
  
  
  /**
   *  return the channel that is used.
   *
   *  @return                       the channel
   */
  
  public RegistryChannel getChannel ()
  {
    return channel;
  }
}
