///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoContentObject.cc 
// ------------------
// Cego content object class 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: CegoContentObject
// 
// Description: This is a super class for all content classes like CegoTableObject, CegoIndexObject, and others which are used
//              to describe data content objects.
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

#include "CegoContentObject.h"
#include "CegoTypeConverter.h"

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

CegoContentObject::CegoContentObject()
{
}

CegoContentObject::CegoContentObject(const CegoContentObject& co) : CegoDecodableObject(co)
{
    _schema = co._schema;
    _tabName = co._tabName;
}

CegoContentObject::CegoContentObject(int tabSetId, CegoObject::ObjectType type, const Chain& contentName) : CegoDecodableObject(type, contentName, tabSetId)
{
    _tabName = contentName;
}

CegoContentObject::CegoContentObject(int tabSetId, CegoObject::ObjectType type, const Chain& contentName, const Chain& tabName, const ListT<CegoField>& schema) : CegoDecodableObject(type, contentName, tabSetId)
{
    _schema = schema;
    _tabName = tabName;
}

CegoContentObject::~CegoContentObject()
{
}

void CegoContentObject::setTabName(const Chain& tabName)
{
    _tabName = tabName;
}

const Chain& CegoContentObject::getTabName() const
{
    return _tabName;
}

void CegoContentObject::setTabAlias(const Chain& tabAlias)
{
    _tabAlias = tabAlias;
    
    CegoField* pF = _schema.First();
    while (pF)
    {
	pF->setTableAlias(tabAlias);
	pF = _schema.Next();
    }
}

const Chain& CegoContentObject::getTabAlias() const
{
    return _tabAlias;
}


ListT<CegoContentObject*>& CegoContentObject::getSubCOList()
{
    return _subCOList;
}

ListT<CegoField>& CegoContentObject::getSchema()
{
    return _schema;
}

int CegoContentObject::getSchemaSize() const
{
    int schemaSize=0;

    CegoField* pF = _schema.First();
    while (pF)
    {
	// key information
	schemaSize += sizeof(char);

	// field id information
	schemaSize += sizeof(int);

       	// data type information
	schemaSize += sizeof(CegoDataType);
	
        // field size
	schemaSize += sizeof(int);

	// default value size
	schemaSize += sizeof(int) + pF->getValue().getLength();
	
        // allowed null information
	schemaSize += sizeof(char);
	
	// attribute len
	schemaSize += sizeof(char);
	
	schemaSize += pF->getAttrName().length();
	
	pF = _schema.Next();
    }

    return schemaSize;
}

int CegoContentObject::getBaseContentSize() const
{

    int baseContentSize = CegoObject::getBaseSize();

    // object tabname size
    baseContentSize += 1; 
    baseContentSize += _tabName.length();
    
    // schema size
    baseContentSize += sizeof(int);
    baseContentSize += getSchemaSize();

    return baseContentSize;
}

void CegoContentObject::encodeBaseContent(char *buf, int size)
{
    char* bufPtr = buf;

    CegoObject::encodeBase(bufPtr, size);
    bufPtr += CegoObject::getBaseSize();

    char c;

    c = (char)_tabName.length();
    memcpy (bufPtr, &c , 1);
    bufPtr++;
    
    memcpy(bufPtr, (char*)_tabName, _tabName.length());
    bufPtr=bufPtr + _tabName.length();


    int schemaSize = getSchemaSize();
    memcpy (bufPtr, &schemaSize, sizeof(int));
    bufPtr += sizeof(int);

    CegoField* pF = _schema.First();
    while (pF)
    {
	char c;
	c = true; // pF->isPrimary();
	memcpy (bufPtr, &c , 1);
	bufPtr++;
	
	int id = pF->getId();
	memcpy (bufPtr, &id , sizeof(int));
	bufPtr += sizeof(int);
	
	CegoDataType dt = pF->getType();
	memcpy (bufPtr, &dt , sizeof(CegoDataType));
	bufPtr += sizeof(CegoDataType);
	
	int l;
	l = pF->getLength();
	memcpy (bufPtr, &l , sizeof(int));
	bufPtr = bufPtr + sizeof(int);

	int deflen;
	deflen = pF->getValue().getLength();
	memcpy (bufPtr, &deflen , sizeof(int));
	bufPtr = bufPtr + sizeof(int);

	if ( deflen > 0 )
	{	    
	    memcpy (bufPtr, pF->getValue().getValue() , deflen);
	    bufPtr = bufPtr + deflen;
	}
	
	if ( pF->isNullable() )
	    c = true;
	else
	    c = false;
	memcpy (bufPtr, &c , 1);
	bufPtr++;
	
	
	// encode attribute
	c = pF->getAttrName().length();
	memcpy (bufPtr, &c , 1);
	bufPtr++;
	
	memcpy (bufPtr, (char*)pF->getAttrName(), pF->getAttrName().length());
	bufPtr=bufPtr + pF->getAttrName().length();
		
	pF = _schema.Next();
    }    
}

void CegoContentObject::decodeBaseContent(char *buf, int& size)
{

    char* bufPtr = buf;

    CegoObject::decodeBase(bufPtr, size);
    bufPtr += CegoObject::getBaseSize();

    bufPtr++;
    _tabName = Chain(bufPtr);    
    bufPtr=bufPtr + _tabName.length();

    int schemaSize;

    memcpy (&schemaSize, bufPtr, sizeof(int));
    bufPtr += sizeof(int);

    char* schemaBase = bufPtr;
    _schema.Empty();
    while ((bufPtr - schemaBase) < schemaSize)
    {	

	bool isPrimary;
	bool isNullable;
	char c;
	CegoDataType type;
	int id;
	Chain attrName, tableName, tableAlias;
	
	memcpy (&c, bufPtr , 1);
	isPrimary=c;
	bufPtr++;
	
	memcpy (&id, bufPtr, sizeof(int));
	bufPtr += sizeof(int);
	
	memcpy (&type, bufPtr, sizeof(CegoDataType));
	bufPtr += sizeof(CegoDataType);

	int len;
	memcpy (&len, bufPtr, sizeof(int));
	bufPtr += sizeof(int);

	int deflen;
	memcpy (&deflen, bufPtr, sizeof(int));
	bufPtr += sizeof(int);

	CegoFieldValue defValue;
	if ( deflen > 0 )
	{
	    void* defBuf = malloc(deflen);
	    memcpy(defBuf, bufPtr, deflen);
	    defValue = CegoFieldValue(type, defBuf, deflen, true);
	    bufPtr += deflen;
	}

	///////////////////
	memcpy (&c, bufPtr , 1);
	isNullable=c;
	bufPtr++;
	
	bufPtr++;		
	attrName = Chain(bufPtr);
	
	bufPtr=bufPtr + attrName.length();

	_schema.Insert( CegoField( _tabName, _tabName, attrName, type, len, defValue, isNullable, id));

    }
}

CegoContentObject& CegoContentObject::operator = ( const CegoContentObject& co)
{
    CegoDecodableObject::operator=(co);
    _tabName = co._tabName;
    _schema = co._schema;
    return (*this);
}

bool CegoContentObject::operator == ( const CegoContentObject& co)
{
    return CegoDecodableObject::operator==(co);
}

