///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoContentObject.cc 
// --------------------
// Cego content object class implementation
//     
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2025 Bjoern Lemke
//
// 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: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// CEGO INCLUDES
#include "CegoContentObject.h"
#include "CegoTypeConverter.h"

// POSIX INCLUDES
#include <string.h>
#include <stdlib.h>

CegoContentObject::CegoContentObject()
{
}

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

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

CegoContentObject::CegoContentObject(unsigned tabSetId,
				     CegoObject::ObjectType type,
				     const Chain& contentName,
				     const Chain& tabName,
				     const ListT<CegoField>& schema) : CegoDecodableObject(type, contentName, tabSetId)
{
    _schema = schema;
    _tabName = tabName;
    _tabAlias = 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;
}

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

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

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

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

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

	// field dim
	schemaSize += sizeof(unsigned);

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

    return schemaSize;
}

unsigned CegoContentObject::getBaseContentSize() const
{
    unsigned baseContentSize = CegoObject::getBaseSize();

    // object tabname size
    baseContentSize += 1; 
    baseContentSize += _tabName.length();

    // object tabalias size
    baseContentSize += 1; 
    baseContentSize += _tabAlias.length();

    // schema size
    baseContentSize += sizeof(unsigned);
    baseContentSize += getSchemaSize();

    return baseContentSize;
}

void CegoContentObject::encodeBaseContent(char *buf, unsigned size) const
{
    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();

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

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

    CegoField* pF = _schema.First();
    while (pF)
    {
	
	unsigned id = pF->getId();
	memcpy (bufPtr, &id , sizeof(unsigned));
	bufPtr += sizeof(unsigned);
	
	CegoDataType dt = pF->getType();
	memcpy (bufPtr, &dt , sizeof(CegoDataType));
	bufPtr += sizeof(CegoDataType);
	
	unsigned l;
	l = pF->getLength();
	memcpy (bufPtr, &l , sizeof(unsigned));
	bufPtr = bufPtr + sizeof(unsigned);

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

	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, unsigned& size)
{
    char* bufPtr = buf;

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

    // skip tablename length information
    bufPtr++;
    _tabName = Chain(bufPtr);    
    bufPtr=bufPtr + _tabName.length();

    // skip tablealias length information
    bufPtr++;
    _tabAlias = Chain(bufPtr);    
    bufPtr=bufPtr + _tabAlias.length();
    
    unsigned schemaSize;

    memcpy (&schemaSize, bufPtr, sizeof(unsigned));
    bufPtr += sizeof(unsigned);
    
    char* schemaBase = bufPtr;
    _schema.Empty();
    while ((bufPtr - schemaBase) < schemaSize)
    {
	// bool isPrimary;
	bool isNullable;
	char c;
	CegoDataType type;
	unsigned id;
	Chain attrName, tableName, tableAlias;
	
	memcpy (&id, bufPtr, sizeof(unsigned));
	bufPtr += sizeof(unsigned);
	
	memcpy (&type, bufPtr, sizeof(CegoDataType));
	bufPtr += sizeof(CegoDataType);

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

	unsigned dim;
	memcpy (&dim, bufPtr, sizeof(unsigned));
	bufPtr += sizeof(unsigned);
	
	unsigned deflen;
	memcpy (&deflen, bufPtr, sizeof(unsigned));
	bufPtr += sizeof(unsigned);

	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, _tabAlias, attrName, type, len, dim, defValue, isNullable, id));
    }
}

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

    return (*this);
}

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