//______________________________________________________________________________
//   |       |
//   | 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.request;

import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.DOMException;

import de.knipp.rritoolkit.KVList;
import de.knipp.rritoolkit.Port;
import de.knipp.rritoolkit.XmlBuilder;
import de.knipp.rritoolkit.EncodeException;

import de.knipp.rritoolkit.response.Response;

import static de.knipp.rritoolkit.DenicConstants.NS_GLOBAL;
import static de.knipp.rritoolkit.DenicConstants.PREFIX_GLOBAL;
import static de.knipp.rritoolkit.DenicConstants.RRI_VERSION;

/**
 *  base class for all DENIC requests
 *
 *  @version  $Revision: 14936 $
 *  @author   Klaus Malorny
 */

public abstract class Request
{
  /** the client transaction ID */
  
  private String clientTxnID;
  

  
  /**
   *  execute the this request on the given port. Subclasses should
   *  override this method if subclasses of {@code Response} are
   *  returned.
   *
   *  @param port                 the port on which this request shall
   *                              be executed
   *  @return                     the response
   *  @throws IOException         if the execution failed
   */
  
  public Response execute (Port port)
    throws IOException
  {
    return port.execute (this);
  }
  
  
    
  //--- XML conversion ---------------------------------------------------------
  
  /**
   *  convert the request into an XML document
   *
   *  @param doc                  the empty document which shall be filled
   *  @throws DOMException        on DOM exceptions
   *  @throws EncodeException     if the encoding fails for some reason
   */
  
  public final void toXml (Document doc)
    throws DOMException, EncodeException
  {
    XmlBuilder xb = new XmlBuilder (doc);
    xb.es (NS_GLOBAL, PREFIX_GLOBAL, "registry-request");
    Node current = xb.getCurrent ();
    xb.ee ();
    
    doc.appendChild (xb.getBase ());
    
    requestToXml (current);
    
    if (clientTxnID != null)
    {
      xb = new XmlBuilder (current);
      xb.elt (NS_GLOBAL, PREFIX_GLOBAL, "ctid", clientTxnID);
    }
  }
  
  
  /**
   *  method that needs to be implemented by subclasses for the XML conversion
   *
   *  @param node                 the node where the request shall be added to
   *  @throws DOMException        on DOM exceptions
   *  @throws EncodeException     if the encoding fails for some reason
   */
  
  protected abstract void requestToXml (Node node)
    throws DOMException, EncodeException;
  
  
  
  //--- KV conversion ----------------------------------------------------------
  
  
  /**
   *  convert the request to a key-value list
   *
   *  @param list                 an empty list which whould be filled
   *  @throws EncodeException     if the encoding fails for some reason
   */
  
  public final void toList (KVList list)
    throws EncodeException
  {
    list.add ("action", getActionCode ());
    list.add ("version", getProtocolVersion ());
    if (clientTxnID != null) list.add ("ctid", clientTxnID);
    requestToKVList (list);
  }

  
  
 
  
  
  /**
   *  return the version number of the protocol. The default implementation
   *  returns the {@code DenicConstants.RRI_VERSION}
   *
   *  @return                     the version string
   */
  
  protected String getProtocolVersion ()
  {
    return RRI_VERSION;
  }

  
  
  
  /**
   *  return the action string for this request
   *
   *  @return                     the action string
   */
  
  protected abstract String getActionCode ();
  

  
  /**
   *  method that needs to be implemented by subclasses for the 
   *  key-value list conversion
   *
   *  @param list                   the list that has to be filled
   *  @throws EncodeException     if the encoding fails for some reason
   */
  
  protected abstract void requestToKVList (KVList list)
    throws EncodeException;
  
  
  //--- other ------------------------------------------------------------------
  
  /**
   *  return a string representation for debugging purposes
   *
   *  @return                      the string representation
   */
  
  @Override
  public String toString ()
  {
    StringBuilder sb = new StringBuilder ();
    sb.append (super.toString ());
    
    if (clientTxnID != null)
    {
      sb.append ("\n  client txn ID: ");
      sb.append (clientTxnID);
    }
    
    sb.append ("\n");
    return sb.toString ();
  }
  

  
  
  //--- access methods ---------------------------------------------------------
  
  /**
   *  return the client transaction ID
   *
   *  @return                     the ID or {@code null} if not set
   */
  
  public String getClientTxnID ()
  {
    return clientTxnID;
  }
  
  
  
  /**
   *  set the client transaction ID
   *
   *  @param txnID             the new transaction ID, may be {@code null}
   */
  
  public void setClientTxnID (String txnID)
  {
    clientTxnID = txnID;
  }
  
  
}

