/*!
  @file           PIn_SpecialParts.cpp
  @author         Bernd Vorsprach - bernd.vorsprach@sap.com
  @brief          Sub classes to represent common part types

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2003-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end



\endif
*/

/*
  -----------------------------------------------------------------------------
  includes
  -----------------------------------------------------------------------------
 */
#include "SAPDBCommon/ErrorsAndMessages/SAPDBErr_MessageEventConverter.hpp"
#include "SAPDB/PacketInterface/PIn_SpecialParts.h"
#include "SAPDB/Interfaces/Runtime/Util/IFRUtil_VDNNumber.h"
#include "hsp40.h"
#include "hsp77.h"

/*! @brief constructor */
PIn_SpecialPart::PIn_SpecialPart 
  ( PIn_Part & oPart, tsp1_part_kind_Param partKind  )
  : PIn_Part( oPart )
{
  if (this->GetPartKind() != partKind) {
    this->Invalidate();
  } // end if
  
} // end PIn_SpecialPart::PIn_SpecialPart

/* ======================================================== */

/*! @brief constructor */
PIn_MessageListPart::PIn_MessageListPart 
  ( PIn_Part & oPart )
  : PIn_SpecialPart(oPart, sp1pk_message_list)
{
} // end PIn_MessageListPart::PIn_MessageListPart

/*! @brief destructor */
PIn_MessageListPart::~PIn_MessageListPart 
  ( )
{
} // end PIn_MessageListPart::~PIn_MessageListPart

/*! @brief public member */
SAPDBErr_MessageList const & PIn_MessageListPart::MessageList
  ( )
{
  teo200_EventList oEventList;
  teo200_EventList oEventListError;

  oEventList.eo200_ClearEventList();
  oEventListError.eo200_ClearEventList();
  this->oMessageList.ClearMessageList();

  oEventList.eo200_LoadEventList  (  (void *) this->GetReadData(), this->Length(), &oEventListError );

  SAPDBErr_ConvertEventToMessageList(this->oMessageList, oEventList);

  return this->oMessageList;
} // end PIn_MessageListPart::MessageList

/* ======================================================== */

/*! @brief constructor */
PIn_ErrorTextPart::PIn_ErrorTextPart 
  ( PIn_Part & oPart )
  : PIn_SpecialPart(oPart, sp1pk_errortext)
{
} // end PIn_ErrorTextPart::PIn_ErrorTextPart

/*! @brief destructor */
PIn_ErrorTextPart::~PIn_ErrorTextPart 
  ( )
{
} // end PIn_ErrorTextPart::~PIn_ErrorTextPart

/* ======================================================== */

/*! @brief constructor */
PIn_SessionInfoPart::PIn_SessionInfoPart 
  ( PIn_Part & oPart )
  : PIn_SpecialPart(oPart, sp1pk_session_info_returned)
{
} // end PIn_SessionInfoPart::PIn_SessionInfoPart

/*! @brief destructor */
PIn_SessionInfoPart::~PIn_SessionInfoPart 
  ( )
{
} // end PIn_SessionInfoPart::~PIn_SessionInfoPart

/*! @brief public member */
int PIn_SessionInfoPart::IsUnicode 
  ( )
{
  if (this->IsValid()) {
    return this->GetReadData()[0];
  } // end if

  return -1;
} // end PIn_SessionInfoPart::IsUnicode

/* ======================================================== */

/*! @brief constructor */
PIn_DataPart::PIn_DataPart 
  ( PIn_Part & oPart )
  : PIn_SpecialPart(oPart, sp1pk_data)
{
} // end PIn_DataPart::PIn_DataPart

/*! @brief destructor */
PIn_DataPart::~PIn_DataPart 
  ( )
{
} // end PIn_DataPart::~PIn_DataPart

/*! @brief public member */
const tsp00_Byte * PIn_DataPart::GetValueAdress
  ( tsp1_param_info * pInfo )
{
  const tsp00_Byte      * pValue = NULL;
  tsp00_LongDescriptor    aDescriptor;

  switch (pInfo->sp1i_data_type) {
    case dstra:
    case dstre:
    case dstrb:
    case dstrdb:
      // long data type found
      pValue = (const tsp00_Byte *) this->GetReadData() + pInfo->sp1i_bufpos - 1;
      pValue = (*pValue == csp_undef_byte) ? NULL : pValue + 1;

      if (pValue != NULL) {
        memcpy(&aDescriptor, (pValue + 1), sizeof(tsp00_LongDescriptor));
        pValue = (const tsp00_Byte *) this->GetReadData() + aDescriptor.ld_valpos () - 1;
        pInfo->sp1i_length = aDescriptor.ld_vallen();
      } // end if
      break;
    default:
      // other data type
      pValue = (const tsp00_Byte *) this->GetReadData() + pInfo->sp1i_bufpos - 1;
      pValue = (*pValue == csp_undef_byte) ? NULL : pValue + 1;
      break;
  } // end switch

  return pValue;
} // end PIn_DataPart::GetValueAdress

/*! @brief public member */
bool PIn_DataPart::IsNull
  ( tsp1_param_info * pInfo )
{
  return (this->GetValueAdress(pInfo) == NULL);
} // end PIn_DataPart::IsNull

/*! @brief public member */
bool PIn_DataPart::GetValueAsInt
  ( tsp1_param_info * pInfo,
    tsp00_Int4      & nValue )
{
  const tsp00_Byte * pAddr    = this->GetValueAdress(pInfo);
  bool               bReturn  = true;
  tsp00_NumError     nError;

  nError.becomes(num_ok);

  if (pAddr != NULL) {
    switch (pInfo->sp1i_data_type) {
      case dfixed:
      case dfloat:
      case dvfloat:
      case dsmallint:
      case dinteger:
//        s40glint ((tsp00_Number*)pAddr, 1, pInfo->sp1i_in_out_len,  nValue, nError);
        s40glint ((tsp00_Number*)pAddr, 1, pInfo->sp1i_length,  nValue, nError);
        bReturn = (nError == num_ok);
        break;
      case dboolean:
        nValue  = (*pAddr == 0) ? 0 : 1;
        break;
      default:
        bReturn = false;
        break;
    } // end switch
  } else {
    bReturn = false;
  } // end if

  return bReturn;
} // end PIn_DataPart::GetValueAsInt

/*! @brief public member */
bool PIn_DataPart::GetValueAsChar
  ( tsp1_param_info *  pInfo,
    const char      *& pValue,
    tsp00_Int4       & nLength,
    ConversionNeeded & oConversion )
{
  const tsp00_Byte * pAddr    = this->GetValueAdress(pInfo);
  bool               bReturn  = true;
  tsp00_NumError     nError;
  static char        szValue[1000];
  const char       * pChars = "0123456789ABCDEF";      

  nError.becomes(num_ok);
  oConversion = ConvertUnknown;

  if (pAddr != NULL) {
    switch (pInfo->sp1i_data_type) {
      case dfixed:
      case dsmallint:
      case dinteger:
      case dfloat:
      case dvfloat:
        if (IFRUtil_VDNNumber::numberToString((tsp00_Byte *) pAddr,
                                              &szValue[0], 
                                              sizeof(szValue),
                                              IFR_StringEncodingAscii,
                                              (pInfo->sp1i_data_type != dvfloat) && (pInfo->sp1i_data_type != dfloat),
                                              pInfo->sp1i_length,
                                              pInfo->sp1i_frac) != IFR_OK) {
          bReturn = false;
        } else {
          nLength = (tsp00_Int4) strlen(szValue);
          pValue  = &szValue[0];
          oConversion = ConvertNever;
        } // end if
        break;

      case dboolean:
        if (*pAddr == 0) {
          strcpy(szValue, "false");
          nLength = (tsp00_Int4) strlen(szValue);
          pValue  = &szValue[0];
        } else {
          strcpy(szValue, "true");
          nLength = (tsp00_Int4) strlen(szValue);
          pValue  = &szValue[0];
        } // end if
        oConversion = ConvertNever;
        break;
      case dchb:
      case dvarcharb:
      case dstrb:
        nLength = 0;
        szValue[0] = 'x';
        szValue[1] = '\'';
        for (nLength = 0; nLength < pInfo->sp1i_length; ++nLength) {
          if (2*nLength > 996) {
            break;
          } // end if
          szValue[2*nLength + 2] = pChars[pAddr[nLength]>>4];
          szValue[2*nLength + 3] = pChars[(pAddr[nLength] & 0x0F)];
        } // end for
        szValue[2*nLength + 2] = '\'';
        nLength = 2*nLength + 3;
        pValue  = &szValue[0];
        oConversion = ConvertNever;
        break;
      case dstrdb:
        bReturn = false;
        break;
      case dche:
      case dvarchare:
      case dstre:
        bReturn = false;
        break;
      case dcha:
      case dvarchara:
      case ddate:
      case dtime:
      case dtimestamp:
      case dstra:
        nLength = pInfo->sp1i_length;
        pValue  = (const char *) pAddr;
        oConversion = ConvertSometimes;
        break;
      case dunicode:
      case dvarcharuni:
        nLength = pInfo->sp1i_length;
        pValue  = (const char *) pAddr;
        oConversion = ConvertAlways;
        break;
      default:
        bReturn = false;
        break;
    } // end switch
  } else {
    strcpy(szValue, "(null)");
    nLength = (tsp00_Int4) strlen(szValue);
    pValue  = &szValue[0];
    oConversion = ConvertNever;
  } // end if

  return bReturn;
} // end PIn_DataPart::GetValueAsChar
