//Editor-Info: -*- C++ -*-
//
//Subject: GSMP
//
//File: gsmpstatisticsmessage.cpp
//
//Version: $Revision: 1.5 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/16 16:57:24 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Harri Sunila
//
//Description:
//      See corresponding header file
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//      
//Licence:
//     
//
//History:
//

#include <string.h>
#include "pf/types.h"
#include "gsmpstatisticsmessages.h"
#include "gsmpstate.h"
#include "gsmpexceptions.h"
#include "pf/error.h"

//
//Function: gsmpVCActivityRecord
//
//Description:
//    Default constructor
//

gsmpVCActivityRecord :: gsmpVCActivityRecord(void)
    : _inputPort(0),
      _flags(0),
      _inputVPI(0),
      _inputVCI(0),
      _VCTrafficCount()
{
    return;
}

//
//Function: gsmpVCActivityRecord
//
//Description:
//    Constructor
//

gsmpVCActivityRecord :: gsmpVCActivityRecord(pfUlong inputPort_,
                                             pfUlong flags_,
                                             pfUlong inputVPI_,
                                             pfUlong inputVCI_,
                                             string &VCTrafficCount_)
    : _inputPort(inputPort_),
      _flags(flags_),
      _inputVPI(inputVPI_),
      _inputVCI(inputVCI_),
      _VCTrafficCount(VCTrafficCount_)
{
    return;
}

//
//Function: gsmpVCActivityRecord
//
//Description:
//

gsmpVCActivityRecord::gsmpVCActivityRecord(const gsmpVCActivityRecord &other_)
    : _inputPort(other_._inputPort),
      _flags(other_._flags),
      _inputVPI(other_._inputVPI),
      _inputVCI(other_._inputVCI),
      _VCTrafficCount(other_._VCTrafficCount)
{
    return;
}

//
//Function: ~gsmpVCActivityRecord
//
//Description:
//

gsmpVCActivityRecord :: ~gsmpVCActivityRecord(void)
{
    return;
}

//
// Function: operator= 
//
// Description:  
//

gsmpVCActivityRecord &gsmpVCActivityRecord :: operator=(
    const gsmpVCActivityRecord &other_)
{
    if (this != &other_)
    {
        _inputPort = other_._inputPort;
        _flags = other_._flags;
        _inputVPI = other_._inputVPI;
        _inputVCI = other_._inputVCI;
        _VCTrafficCount = other_._VCTrafficCount;
    }
    return *this;
}

//
//Functions: Gets
//
//Description:
//

pfUlong gsmpVCActivityRecord :: getInputPort(void) const
{
    return _inputPort;
}

pfUlong gsmpVCActivityRecord :: getFlags(void) const
{
    return _flags;
}

pfUlong gsmpVCActivityRecord :: getInputVPI(void) const
{
    return _inputVPI;
}

pfUlong gsmpVCActivityRecord :: getInputVCI(void) const
{
    return _inputVCI;
}

string gsmpVCActivityRecord :: getVCTrafficCount(void) const
{
    return _VCTrafficCount;
}

//
//Function: gsmpVCActivityMessage
//
//Description:
//    Default constructor
//

gsmpVCActivityMessage :: gsmpVCActivityMessage(void)
    : gsmpMessage(),
      _numberOfRecords(0),
      _activityRecords()
{
    _activityRecords.reserve(gsmpMessage::MAXIMUM_ACTIVITY_RECORD_NUMBER);
    return;
}

//
//Function: gsmpVCActivityMessage
//
//Description:
//    Copy constructor
//

gsmpVCActivityMessage :: gsmpVCActivityMessage(
    const gsmpVCActivityMessage &other_)
    : gsmpMessage(other_),
      _numberOfRecords(other_._numberOfRecords),
      _activityRecords(other_._activityRecords)
{
    return;
}

//
//Function: ~gsmpVCActivityMessage
//
//Description:
//    Destructor
//

gsmpVCActivityMessage :: ~gsmpVCActivityMessage(void)
{
    return;
}

//
// Function: getNumberOfRecords
//
// Description:
//     Return the _numberOfRecords
//

pfUlong gsmpVCActivityMessage :: getNumberOfRecords(void) const
{
    return _numberOfRecords;
}

//
// Function: getActivityRecord
//
// Description:
//     Return _activityRecords.
//

gsmpVCactivityRecordVector gsmpVCActivityMessage :: getActivityRecord(void)
    const
{
    return _activityRecords;
}

//
//Function: decodeFrame
//
//Description:
//

void gsmpVCActivityMessage :: decodeFrame(pfFrame &frame_)
{
    _frame = frame_;
    _version = frame_.getFirst();
    _messageType = frame_.getFirst();
    _result = frame_.getFirst();
    _code = frame_.getFirst();
    _transactionIdentifier = frame_.getFirst32bit();
    _numberOfRecords = frame_.getFirst16bit();
    frame_.getFirst16bit(); // for the reserved 

    gsmpVCActivityRecord *record;
    pfUlong i, j;
    pfUlong inputPort;
    pfUlong inputVPI;
    pfUlong inputVCI;
    pfUlong flags;
    pfUlong VPIFlags;
    string VCTrafficCount;

    for (i = 0 ; i < _numberOfRecords ; i++)
    {
        inputPort = frame_.getFirst32bit();
        VPIFlags = frame_.getFirst16bit();
        inputVPI = VPIFlags & gsmpMessage::GSMP_VPI_MASK;
        flags = VPIFlags >> 12;
        inputVCI = frame_.getFirst16bit();
        
        for (j = 0; j < gsmpMessage::GSMP_COUNTER_LENGTH; j++)
        {
            VCTrafficCount[j] = frame_.getFirst();
        }
            
        record = new gsmpVCActivityRecord(inputPort,
                                          flags,
                                          inputVPI,
                                          inputVCI,
                                          VCTrafficCount);
        _activityRecords.push_back(*record);
    }
    if (frame_.length() != 0)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    return;
}

//
//Function: encodeFrame
//
//Description:
//

pfFrame gsmpVCActivityMessage :: encodeFrame(void)
{
    _frame.clear();
    _frame.putLast(_version);
    _frame.putLast(_messageType);
    _frame.putLast(_result);
    _frame.putLast(_code);
    _frame.putLast32bit(_transactionIdentifier);
    _frame.putLast16bit(_numberOfRecords);
    _frame.putLast16bit(0);

    pfUlong i, j;
    string VCTrafficCount;
    pfUlong inputPort, inputVPI, inputVCI, flags;

    for (i = 0; i < _numberOfRecords; i++)
    {
        inputPort = _activityRecords[i].getInputPort();
        _frame.putLast32bit(inputPort);
        flags = _activityRecords[i].getFlags();
        inputVPI = _activityRecords[i].getInputVPI();
        _frame.putLast16bit(((flags << 12) | inputVPI));
        inputVCI = _activityRecords[i].getInputVCI();
        _frame.putLast16bit(inputVCI);

        VCTrafficCount = _activityRecords[i].getVCTrafficCount();
        if (VCTrafficCount.length() != gsmpMessage::GSMP_COUNTER_LENGTH)
        {
            throw gsmpInvalidLengthException(PF_EX_INFO);
        }
        for (j = 0; j < gsmpMessage::GSMP_COUNTER_LENGTH; j++)
        {
            _frame.putLast(VCTrafficCount[j]);
        }
    }
    return _frame;
}

//
//Function: gsmpVCActivityRequestMessage
//
//Description:
//    Default constructor
//

gsmpVCActivityRequestMessage :: gsmpVCActivityRequestMessage(void)
    : gsmpVCActivityMessage()
{
    _messageType = gsmpMessage::VC_ACTIVITY;
    return;
}

//
//Function: gsmpVCActivityRequestMessage
//
//Description:
//    Constructor
//

gsmpVCActivityRequestMessage :: gsmpVCActivityRequestMessage(
    pfUlong transactionIdentifier_,
    gsmpVCactivityRecordVector &activityRecords_)
    : gsmpVCActivityMessage()
{
    _messageType = gsmpMessage::VC_ACTIVITY;
    _result = GSMP_ACK_ALL;
    _transactionIdentifier = transactionIdentifier_;
    _numberOfRecords = activityRecords_.size();
    _activityRecords = activityRecords_;
    return;
}

//
//Function: gsmpVCActivityRequestMessage
//
//Description:
//    Copy constructor
//

gsmpVCActivityRequestMessage :: gsmpVCActivityRequestMessage(
    const gsmpVCActivityRequestMessage &other_)
    : gsmpVCActivityMessage(other_)
{
    return;
}

//
//Function: ~gsmpVCActivityRequestMessage
//
//Description:
//    Destructor
//

gsmpVCActivityRequestMessage :: ~gsmpVCActivityRequestMessage()
{
    gsmpVCactivityRecordIterator begin, end;
    begin = _activityRecords.begin();
    end = _activityRecords.end();
    _activityRecords.erase(begin, end);
    return;
}

//
//Function: addActivityRecord
//
//Description:
//    Add a new activity record in the _activityRecords vector.
//

void gsmpVCActivityRequestMessage :: addActivityRecord(pfUlong inputPort_,
                                                       pfUlong inputVPI_,
                                                       pfUlong inputVCI_)
{
    string VCTrafficCount;
    pfUlong i;

    if (_numberOfRecords == gsmpMessage::MAXIMUM_ACTIVITY_RECORD_NUMBER)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    for (i = 0; i < gsmpMessage::GSMP_COUNTER_LENGTH; i++)
    {
        VCTrafficCount[i] = B0000_0000;
    }
    
    gsmpVCActivityRecord *record = new gsmpVCActivityRecord(inputPort_,
                                                            0,
                                                            inputVPI_,
                                                            inputVCI_,
                                                            VCTrafficCount);
    _numberOfRecords++;
    _activityRecords.push_back(*record);
    return;
}

//
//Function: clone
//
//Description:
//

gsmpVCActivityRequestMessage *gsmpVCActivityRequestMessage :: clone(void)
{
    gsmpVCActivityRequestMessage *message =
        new gsmpVCActivityRequestMessage(*this);
    return message;
}

//
//Function: apply
//
//Description:
//

void gsmpVCActivityRequestMessage :: apply(pfState *state_,
                                           pfProtocol *protocol_)
{
    gsmpState *state = dynamic_cast<gsmpState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpVCActivityRequestMessageAct(this, protocol_);
    return;
}

//
//Function: gsmpVCActivityResponseMessage
//
//Description:
//    Default constructor
//

gsmpVCActivityResponseMessage :: gsmpVCActivityResponseMessage(void)
    : gsmpVCActivityMessage()
{
    _messageType = gsmpMessage::VC_ACTIVITY;
    return;
}

//
//Function: gsmpVCActivityResponseMessage
//
//Description:
//    Constructor
//

gsmpVCActivityResponseMessage :: gsmpVCActivityResponseMessage(
    pfUlong transactionIdentifier_)
    : gsmpVCActivityMessage()
{
    _messageType = gsmpMessage::VC_ACTIVITY;
    _transactionIdentifier = transactionIdentifier_;
    return;
}

//
//Function: gsmpVCActivityResponseMessage
//
//Description:
//    Copy constructor
//

gsmpVCActivityResponseMessage :: gsmpVCActivityResponseMessage(
    const gsmpVCActivityResponseMessage &other_)
    : gsmpVCActivityMessage(other_)
{
    return;
}

//
//Function: ~gsmpVCActivityResponseMessage
//
//Description:
//    Destructor
//

gsmpVCActivityResponseMessage :: ~gsmpVCActivityResponseMessage()
{
    gsmpVCactivityRecordIterator begin, end;
    begin = _activityRecords.begin();
    end = _activityRecords.end();
    _activityRecords.erase(begin, end);
    return;
}

//
//Function: addActivityRecord
//
//Description:
//    Add a new activity record
//

void gsmpVCActivityResponseMessage :: addActivityRecord(pfUlong inputPort_,
                                                        pfUlong flags_,
                                                        pfUlong inputVPI_,
                                                        pfUlong inputVCI_,
                                                        string VCTrafficCount_)
{
    if (VCTrafficCount_.length() != gsmpMessage::GSMP_COUNTER_LENGTH);
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    if (_numberOfRecords == gsmpMessage::MAXIMUM_ACTIVITY_RECORD_NUMBER)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    gsmpVCActivityRecord *record = new gsmpVCActivityRecord(inputPort_,
                                                            flags_,
                                                            inputVPI_,
                                                            inputVCI_,
                                                            VCTrafficCount_);
    _numberOfRecords++;
    _activityRecords.push_back(*record);
    return;
}

//
//Function: clone
//
//Description:
//

gsmpVCActivityResponseMessage *gsmpVCActivityResponseMessage :: clone(void)
{
    gsmpVCActivityResponseMessage *message =
        new gsmpVCActivityResponseMessage(*this);
    return message;
}

//
//Function: apply
//
//Description:
//

void gsmpVCActivityResponseMessage :: apply(pfState *state_,
                                            pfProtocol *protocol_)
{
    gsmpState *state = dynamic_cast<gsmpState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpVCActivityResponseMessageAct(this, protocol_);
    return;
}

//
//Function: gsmpStatisticsRequestMessage
//
//Description:
//    Default constructor
//

gsmpStatisticsRequestMessage :: gsmpStatisticsRequestMessage(void)
    : gsmpMessage(),
      _port(0),
      _VPI(0),
      _VCI(0)
{
    return;
}

//
//Function: gsmpStatisticsRequestMessage
//
//Description:
//    Copy constructor
//

gsmpStatisticsRequestMessage :: gsmpStatisticsRequestMessage(
    const gsmpStatisticsRequestMessage &other_)
    : gsmpMessage(other_),
      _port(other_._port),
      _VPI(other_._VPI),
      _VCI(other_._VCI)
{
    return;
}

//
//Function: ~gmspStatisticsRequestMessage
//
//Description:
//    Destructor
//

gsmpStatisticsRequestMessage :: ~gsmpStatisticsRequestMessage(void)
{
    return;
}

//
//Function: decodeFrame
//
//Description:
//    Common method to decode a frame to either a GSMP Port or VC Statistics
//    request message.
//

void gsmpStatisticsRequestMessage :: decodeFrame(pfFrame &frame_)
{
    _frame = frame_;
    _version = frame_.getFirst();
    _messageType = frame_.getFirst();
    _result = frame_.getFirst();
    _code = frame_.getFirst();
    _transactionIdentifier = frame_.getFirst32bit();
    _port = frame_.getFirst32bit();
    _VPI = frame_.getFirst16bit() & gsmpMessage::GSMP_VPI_MASK;
    _VCI = frame_.getFirst16bit();
    if (frame_.length() != 0)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    return;
}

//
//Function: encodeFrame
//
//Description:
//    Common method to encode either a GSMP Port or VC Statistics request
//    message.
//

pfFrame gsmpStatisticsRequestMessage :: encodeFrame(void)
{
    _frame.clear();
    _frame.putLast(_version);
    _frame.putLast(_messageType);
    _frame.putLast(_result);
    _frame.putLast(_code);
    _frame.putLast32bit(_transactionIdentifier);
    _frame.putLast32bit(_port);
    _frame.putLast16bit(_VPI & gsmpMessage::GSMP_VPI_MASK);
    _frame.putLast16bit(_VCI);
    return _frame;
}    

//
//Functions: Gets
//
//Description:
//    These methods return the message data
//

pfUlong gsmpStatisticsRequestMessage :: getPort(void) const
{
    return _port;
}

pfUlong gsmpStatisticsRequestMessage :: getVPI(void) const
{
    return _VPI;
}

pfUlong gsmpStatisticsRequestMessage :: getVCI(void) const
{
    return _VCI;
}

//
//Function: gsmpVCStatisticsRequestMessage
//
//Description:
//    Default constructor
//

gsmpVCStatisticsRequestMessage :: gsmpVCStatisticsRequestMessage(void)
    : gsmpStatisticsRequestMessage()
{
    _messageType = gsmpMessage::VC_STATISTICS;
    return;
}

//
//Function: gsmpVCStatisticsRequestMessage
//
//Description:
//    Constructor
//

gsmpVCStatisticsRequestMessage :: gsmpVCStatisticsRequestMessage(
    pfUlong transactionIdentifier_,
    pfUlong port_,
    pfUlong VPI_,
    pfUlong VCI_)
    : gsmpStatisticsRequestMessage()
{
    _transactionIdentifier = transactionIdentifier_;
    _messageType = gsmpMessage::VC_STATISTICS;
    _result = GSMP_ACK_ALL;
    _port = port_;
    _VPI = VPI_;
    _VCI = VCI_;
    return;
}

//
//Function: gsmpVCStatisticsRequestMessage
//
//Description:
//    Copy constructor
//

gsmpVCStatisticsRequestMessage :: gsmpVCStatisticsRequestMessage(
    const gsmpVCStatisticsRequestMessage &other_)
    : gsmpStatisticsRequestMessage(other_)
{
    return;
}

//
//Function: ~gsmpVCStatisticsRequestMessage
//
//Description:
//    Destructor
//

gsmpVCStatisticsRequestMessage :: ~gsmpVCStatisticsRequestMessage(void)
{
    return;
}

//
//Function: clone
//
//Description:
//

gsmpVCStatisticsRequestMessage *gsmpVCStatisticsRequestMessage :: clone(void)
{
    gsmpVCStatisticsRequestMessage *message =
        new gsmpVCStatisticsRequestMessage(*this);
    return message;
}

//
//Function: apply
//
//Description:
//

void gsmpVCStatisticsRequestMessage :: apply(pfState *state_,
                                             pfProtocol *protocol_)
{
    gsmpState *state = dynamic_cast<gsmpState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpVCStatisticsRequestMessageAct(this, protocol_);
    return;
}

//
//Function: gsmpPortStatisticsRequestMessage
//
//Description:
//    Default constructor
//

gsmpPortStatisticsRequestMessage :: gsmpPortStatisticsRequestMessage(void)
    : gsmpStatisticsRequestMessage()
{
    _messageType = gsmpMessage::PORT_STATISTICS;
    return;
}

//
//Function: gsmpPortStatisticsRequestMessage
//
//Description:
//    Constructor
//

gsmpPortStatisticsRequestMessage :: gsmpPortStatisticsRequestMessage(
    pfUlong transactionIdentifier_,
    pfUlong port_)
    : gsmpStatisticsRequestMessage()
{
    _messageType = gsmpMessage::PORT_STATISTICS;
    _result = GSMP_ACK_ALL;
    _transactionIdentifier = transactionIdentifier_;
    _port = port_;
    return;
}

//
//Function: gsmpPortStatisticsRequestMessage
//
//Description:
//    Copy constructor
//

gsmpPortStatisticsRequestMessage :: gsmpPortStatisticsRequestMessage(
    const gsmpPortStatisticsRequestMessage &other_)
    : gsmpStatisticsRequestMessage(other_)
{
    return;
}

//
//Function: ~gsmpPortStatisticsRequestMessage
//
//Description:
//    Destructor
//

gsmpPortStatisticsRequestMessage :: ~gsmpPortStatisticsRequestMessage(void)
{
    return;
}

//
//Function: clone
//
//Description:
//

gsmpPortStatisticsRequestMessage *gsmpPortStatisticsRequestMessage::clone(void)
{
    gsmpPortStatisticsRequestMessage *message =
        new gsmpPortStatisticsRequestMessage(*this);
    return message;
}

//
//Function: apply
//
//Description:
//

void gsmpPortStatisticsRequestMessage :: apply(pfState *state_,
                                               pfProtocol *protocol_)
{
    gsmpState *state = dynamic_cast<gsmpState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpPortStatisticsRequestMessageAct(this, protocol_);
    return;
}

//
// Function: gsmpStatisticsResponseMessage
//
// Description: 
//     Default constructor 
//

gsmpStatisticsResponseMessage :: gsmpStatisticsResponseMessage(void)
    : gsmpMessage(),
      _port(0),
      _VPI(0),
      _VCI(0),
      _inputCellCount(),
      _inputFrameCount(),
      _inputCellDiscardCount(),
      _inputFrameDiscardCount(),
      _inputHecErrorCount(),
      _inputInvalidVPIVCICount(),
      _outputCellCount(),
      _outputFrameCount(),
      _outputCellDiscardCount(),
      _outputFrameDiscardCount()
{
    return;
}

//
// Function: gsmpStatisticsResponseMessage
//
// Description:
//     Copy constructor
//

gsmpStatisticsResponseMessage :: gsmpStatisticsResponseMessage(
    const gsmpStatisticsResponseMessage &other_)
    : gsmpMessage(other_),
      _port(other_._port),
      _VPI(other_._VPI),
      _VCI(other_._VCI),
      _inputCellCount(other_._inputCellCount),
      _inputFrameCount(other_._inputFrameCount),
      _inputCellDiscardCount(other_._inputCellDiscardCount),
      _inputFrameDiscardCount(other_._inputFrameDiscardCount),
      _inputHecErrorCount(other_._inputHecErrorCount),
      _inputInvalidVPIVCICount(other_._inputInvalidVPIVCICount),
      _outputCellCount(other_._outputCellCount),
      _outputFrameCount(other_._outputFrameCount),
      _outputCellDiscardCount(other_._outputCellDiscardCount),
      _outputFrameDiscardCount(other_._outputFrameDiscardCount)
{
    return;
}

//
//Function: ~gsmpStatisticsResponseMessage
//
//Description:
//    Destructor
//

gsmpStatisticsResponseMessage :: ~gsmpStatisticsResponseMessage(void)
{
    return;
}

//
//Function: decodeFrame
//
//Description:
//    Common method to decode either a GSMP Port or VC Statistics response
//    message
//

void gsmpStatisticsResponseMessage :: decodeFrame(pfFrame &frame_)
{
    _frame = frame_;
    _version = frame_.getFirst();
    _messageType = frame_.getFirst();
    _result = frame_.getFirst();
    _code = frame_.getFirst();
    _transactionIdentifier = frame_.getFirst32bit();
    _port = frame_.getFirst32bit();
    _VPI = (frame_.getFirst16bit() & gsmpMessage::GSMP_VPI_MASK);
    _VCI = frame_.getFirst16bit();
    
    decodeCounter(frame_, _inputCellCount);
    decodeCounter(frame_, _inputFrameCount);
    decodeCounter(frame_, _inputCellDiscardCount);
    decodeCounter(frame_, _inputFrameDiscardCount);
    decodeCounter(frame_, _inputHecErrorCount);
    decodeCounter(frame_, _inputInvalidVPIVCICount);
    decodeCounter(frame_, _outputCellCount);
    decodeCounter(frame_, _outputFrameCount);
    decodeCounter(frame_, _outputCellDiscardCount);
    decodeCounter(frame_, _outputFrameDiscardCount);
    
    if (frame_.length() != 0)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    return;
}

//
//Function: encodeFrame
//
//Description:
//    Common method to encode either a GSMP Port or VC Statistics response
//    message
//

pfFrame gsmpStatisticsResponseMessage :: encodeFrame(void)
{
    _frame.clear();
    _frame.putLast(_version);
    _frame.putLast(_messageType);
    _frame.putLast(_result);
    _frame.putLast(_code);
    _frame.putLast32bit(_transactionIdentifier);
    _frame.putLast32bit(_port);
    _frame.putLast16bit(_VPI & gsmpMessage::GSMP_VPI_MASK);
    _frame.putLast16bit(_VCI);

    try
    {
        encodeCounter(_frame, _inputCellCount);
        encodeCounter(_frame, _inputFrameCount);
        encodeCounter(_frame, _inputCellDiscardCount);
        encodeCounter(_frame, _inputFrameDiscardCount);
        encodeCounter(_frame, _inputHecErrorCount);
        encodeCounter(_frame, _inputInvalidVPIVCICount);
        encodeCounter(_frame, _outputCellCount);
        encodeCounter(_frame, _outputFrameCount);
        encodeCounter(_frame, _outputCellDiscardCount);
        encodeCounter(_frame, _outputFrameDiscardCount);
    }
    catch (...)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    return _frame;
}    

//
//Function: decodeCounter
//
//Description:
//    Method to decode a GSMP count from a frame
//

void gsmpStatisticsResponseMessage :: decodeCounter(pfFrame &frame_,
                                                    string &counter_)
{
    pfUlong i;
    for (i = 0; i < gsmpMessage::GSMP_COUNTER_LENGTH; i++)
    {
        counter_[i] = frame_.getFirst();
    }
    return;
}

//
//Function: encodeCounter
//
//Description:
//    Method to encode a GSMP count to a frame
//

void gsmpStatisticsResponseMessage :: encodeCounter(pfFrame &frame_,
                                                    string &counter_)
{
    pfUlong i;
    if (counter_.length() != gsmpMessage::GSMP_COUNTER_LENGTH)
    {
        throw gsmpInvalidLengthException(PF_EX_INFO);
    }
    for (i = 0; i < gsmpMessage::GSMP_COUNTER_LENGTH; i++)
    {
        frame_.putLast(counter_[i]);
    }
    return;
}

//
// Function: gsmpPortStatisticsResponseMessage
//
// Description:
//     Default constructor
//

gsmpPortStatisticsResponseMessage :: gsmpPortStatisticsResponseMessage(void)
    : gsmpStatisticsResponseMessage()
{
    _messageType = gsmpMessage::PORT_STATISTICS;
    return;
}

//
// Function: gsmpPortStatisticsResponseMessage
//
// Description:
//     Constructor
//

gsmpPortStatisticsResponseMessage :: gsmpPortStatisticsResponseMessage(
    pfUlong transactionIdentifier_,
    pfUlong port_,
    string inputCellCount_,
    string inputFrameCount_,
    string inputCellDiscardCount_,
    string inputFrameDiscardCount_,
    string inputHecErrorCount_,
    string inputInvalidVPIVCICount_,
    string outputCellCount_,
    string outputFrameCount_,
    string outputCellDiscardCount_,
    string outputFrameDiscardCount_)
    : gsmpStatisticsResponseMessage()
{
    _messageType = gsmpMessage::PORT_STATISTICS;
    _transactionIdentifier = transactionIdentifier_;
    _port = port_;
    _inputCellCount = inputCellCount_;
    _inputFrameCount = inputFrameCount_;
    _inputCellDiscardCount = inputCellDiscardCount_;
    _inputFrameDiscardCount = inputFrameDiscardCount_;
    _inputHecErrorCount = inputHecErrorCount_;
    _inputInvalidVPIVCICount = inputInvalidVPIVCICount_;
    _outputCellCount = outputCellCount_;
    _outputFrameCount = outputFrameCount_;
    _outputCellDiscardCount = outputCellDiscardCount_;
    _outputFrameDiscardCount = outputFrameDiscardCount_;
    return;
}

//
// Function: gsmpPortStatisticsResponseMessage
//
// Description:
//     Copy constructor
//

gsmpPortStatisticsResponseMessage :: gsmpPortStatisticsResponseMessage(
    const gsmpPortStatisticsResponseMessage &other_)
    : gsmpStatisticsResponseMessage(other_)
{
    return;
}

//
//Function: ~gsmpPortStatisticsResponseMessage
//
//Description:
//    Destructor
//

gsmpPortStatisticsResponseMessage :: ~gsmpPortStatisticsResponseMessage(void)
{
    return;
}

//
//Function: clone
//
//Description:
//

gsmpPortStatisticsResponseMessage *gsmpPortStatisticsResponseMessage :: clone(
    void)
{
    gsmpPortStatisticsResponseMessage *message =
        new gsmpPortStatisticsResponseMessage(*this);
    return message;
}

//
//Function: apply
//
//Description:
//

void gsmpPortStatisticsResponseMessage :: apply(pfState *state_,
                                                pfProtocol *protocol_)
{
    gsmpState *state = dynamic_cast<gsmpState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpPortStatisticsResponseMessageAct(this, protocol_);
    return;
}
 
//
//Function: gsmpVCStatisticsResponseMessage
//
//Description:
//    Default constructor
//

gsmpVCStatisticsResponseMessage :: gsmpVCStatisticsResponseMessage(void)
    : gsmpStatisticsResponseMessage()
{
    _messageType = gsmpMessage::VC_STATISTICS;
    return;
}
 
//
//Function: gsmpVCStatisticsResponseMessage
//
//Description:
//    Constructor
//

gsmpVCStatisticsResponseMessage :: gsmpVCStatisticsResponseMessage(
    pfUlong transactionIdentifier_,
    pfUlong port_,
    pfUlong VPI_,
    pfUlong VCI_,
    string inputCellCount_,
    string inputFrameCount_,
    string inputCellDiscardCount_,
    string inputFrameDiscardCount_,
    string inputHecErrorCount_,
    string inputInvalidVPIVCICount_,
    string outputCellCount_,
    string outputFrameCount_,
    string outputCellDiscardCount_,
    string outputFrameDiscardCount_)
    : gsmpStatisticsResponseMessage()
{
    _messageType = gsmpMessage::VC_STATISTICS;
    _transactionIdentifier = transactionIdentifier_;
    _port = port_;
    _VPI = VPI_;
    _VCI = VCI_;
    _inputCellCount = inputCellCount_;
    _inputFrameCount = inputFrameCount_;
    _inputCellDiscardCount = inputCellDiscardCount_;
    _inputFrameDiscardCount = inputFrameDiscardCount_;
    _inputHecErrorCount = inputHecErrorCount_;
    _inputInvalidVPIVCICount = inputInvalidVPIVCICount_;
    _outputCellCount = outputCellCount_;
    _outputFrameCount = outputFrameCount_;
    _outputCellDiscardCount = outputCellDiscardCount_;
    _outputFrameDiscardCount = outputFrameDiscardCount_;
    return;
}
 
//
//Function: gsmpVCStatisticsResponseMessage
//
//Description:
//    Copy constructor
//

gsmpVCStatisticsResponseMessage :: gsmpVCStatisticsResponseMessage(
    const gsmpVCStatisticsResponseMessage &other_)
    : gsmpStatisticsResponseMessage(other_)
{
    return;
}

//
//Function: ~gsmpVCStatisticsResponseMessage
//
//Description:
//    Destructor
//

gsmpVCStatisticsResponseMessage :: ~gsmpVCStatisticsResponseMessage(void)
{
    return;
}
 
//
//Function: clone
//
//Description:
//

gsmpVCStatisticsResponseMessage *gsmpVCStatisticsResponseMessage :: clone(void)
{
    gsmpVCStatisticsResponseMessage *message =
        new gsmpVCStatisticsResponseMessage(*this);
    return message;
}

//
//Function: apply
//
//Description:
//

void gsmpVCStatisticsResponseMessage :: apply(pfState *state_,
                                              pfProtocol *protocol_)
{
    gsmpState *state = dynamic_cast<gsmpState*>(state_);
    THROW_IF_DYNAMIC_CAST_FAILED(state);
    state->gsmpVCStatisticsResponseMessageAct(this, protocol_);
    return;
}
