///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoExpOutStream.cc 
// -------------------
// Cego export outstream implementation
//     
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2010 Bjoern Lemke
//
// 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, 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; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// IMPLEMENTATION MODULE
//
// Class: CegoExpOutStream
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

// base includes
#include <lfc/Base64Coder.h>

// cego includes
#include "CegoExpOutStream.h"
#include "CegoXMLdef.h"

#include <string.h>
#include <stdlib.h>

CegoExpOutStream::CegoExpOutStream(int tabSetId, const Chain& tableName, const ListT<CegoField>& schema, CegoDistManager* pGTM)
{
    _pGTM = pGTM;
    _pOC = pGTM->getObjectCursor(tabSetId, tableName, tableName, CegoObject::TABLE);
    _schema = schema;
    _tabSetId = tabSetId;    
}

CegoExpOutStream::~CegoExpOutStream()
{   
    delete _pOC;
}

Element* CegoExpOutStream::getFirst()
{
    CegoDataPointer dp;
    if ( _pGTM->getFirstTuple(_pOC, _schema, dp ) )
    {
	return getRowElement(_schema);
    }
    else
    {
	Element* pRowElement = new Element(XML_NOROWS_ELEMENT);
	return pRowElement;	
    }
}

Element* CegoExpOutStream::getNext()
{
    CegoDataPointer dp;
    if ( _pGTM->getNextTuple(_pOC, _schema, dp ) )
    {
	return getRowElement(_schema);
    }
    return 0;
}

Element* CegoExpOutStream::getRowElement(ListT<CegoField>& schema)
{

    Element* pRowElement = new Element(XML_ROW_ELEMENT);
    
    long nextBlobId=0;
    CegoField *pF = schema.First();
    while ( pF ) 
    {
	if ( ! pF->getValue().isNull() )
	{
	    if ( pF->getType() == BLOB_TYPE )
	    {
		Chain blobId = Chain(XML_BLOBPREFIX) + Chain(nextBlobId);
		nextBlobId++;
		pRowElement->setAttribute(pF->getAttrName(), blobId);
		
		int fileId;
		int pageId;
		memcpy(&fileId, pF->getValue().getValue(), sizeof(int));
		memcpy(&pageId, (void*)((long)pF->getValue().getValue() + sizeof(int)), sizeof(int));
		
		long blobSize;
		unsigned char* blobBuf = _pGTM->getBlobData(_tabSetId, fileId, pageId, blobSize);

		Base64Coder b64;
		pRowElement->addData(b64.encode(blobSize, blobBuf));
				
	    }
	    else
		pRowElement->setAttribute(pF->getAttrName(), pF->getValue().valAsChain());		
	}
	pF = _schema.Next();
    }
    return pRowElement;
}
