///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoAliasObject.cc 
// ------------------
// Cego alias object entry implementation
//     
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2025 Bjoern Lemke
//
// IMPLEMENTATION MODULE
//
// Class: CegoCheckObject
//
// Description: Derived class from CegoDecodable to use as a container class for alias objects
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// CEGO INCLUDES
#include "CegoAliasObject.h"
#include "CegoXMLdef.h"

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

CegoAliasObject::CegoAliasObject()
{
    _subCOList.Insert(this);
}

CegoAliasObject::CegoAliasObject(const CegoAliasObject& ao) : CegoContentObject(ao)
{
    _aliasList = ao._aliasList;
    _subCOList.Insert(this);
}

CegoAliasObject::CegoAliasObject(unsigned tabSetId, const Chain& aliasName) : CegoContentObject(tabSetId, CegoObject::ALIAS, aliasName)
{
    _subCOList.Insert(this);
}

// alias schema information is just retrieved at runtime
CegoAliasObject::CegoAliasObject(unsigned tabSetId, const Chain& aliasName, const Chain& tabName, const ListT<CegoAttrAlias>& aliasList) : CegoContentObject(tabSetId, CegoObject::ALIAS, aliasName, tabName, ListT<CegoField>())
{
    _aliasList = aliasList;
    _subCOList.Insert(this);
}

CegoAliasObject::~CegoAliasObject()
{
}

void  CegoAliasObject::setAliasList(const ListT<CegoAttrAlias>& aliasList)
{
    _aliasList = aliasList;
}

const ListT<CegoAttrAlias>& CegoAliasObject::getAliasList()
{
    return _aliasList;
}

unsigned CegoAliasObject::getEntrySize() const
{
    unsigned entrySize = CegoContentObject::getBaseContentSize();
    
    // alias list size
    entrySize += sizeof(unsigned);
    CegoAttrAlias *pAlias = _aliasList.First();
    while ( pAlias )
    {
	entrySize += pAlias->getEncodingLength();
	pAlias = _aliasList.Next();
    }

    return entrySize;
}

void CegoAliasObject::encode(char *buf) const
{
    char* bufPtr = buf;

    unsigned entrySize = getEntrySize();

    CegoContentObject::encodeBaseContent(bufPtr, entrySize);
    bufPtr += CegoContentObject::getBaseContentSize();

    unsigned numAlias = _aliasList.Size();
    memcpy (bufPtr, &numAlias, sizeof(unsigned));
    bufPtr += sizeof(unsigned);
    
    CegoAttrAlias *pAlias = _aliasList.First();
    while ( pAlias )
    {
	pAlias->encode(bufPtr);
	bufPtr = bufPtr + pAlias->getEncodingLength();
	pAlias = _aliasList.Next();
    }
}

void CegoAliasObject::decode(char *buf)
{
    char* bufPtr = buf;

    unsigned size;

    CegoContentObject::decodeBaseContent(bufPtr, size);
    bufPtr += CegoContentObject::getBaseContentSize();

    unsigned numAlias;

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

    _aliasList.Empty();
    while ( numAlias > 0 )
    {
	CegoAttrAlias attrAlias;
	attrAlias.decode(bufPtr);
	bufPtr += attrAlias.getEncodingLength();
	_aliasList.Insert(attrAlias);
	numAlias--;
    }
}

void CegoAliasObject::setSchema(const ListT<CegoField>& schema)
{
    _schema = schema;
}

void CegoAliasObject::mapSchema()
{
    CegoAttrAlias *pA = _aliasList.First();
    while ( pA )
    {
	CegoField *pF = _schema.Find( CegoField( getTabName(), pA->getAttrName() ) );
	if ( pF )
	{
	    pF->setTableName( getName() );
	    pF->setTableAlias( getTabAlias() );
	    pF->setAttrName( pA->getAliasName() );	    
	}
	else
	{
	    throw Exception(EXLOC, Chain("Cannot find alias attribute ") + pA->getAttrName() + Chain(" in table ") + getTabName());
	}
	pA = _aliasList.Next();	
    }

    // remove non used field from schema
    CegoField *pF = _schema.First();
    while ( pF )
    {
	if ( pF->getTableName() == getTabName() )
	{	    
	    _schema.Remove(*pF);
	    pF = _schema.First();
	}
	else
	{
	    pF = _schema.Next();
	}
    }   
}

CegoAliasObject& CegoAliasObject::operator = ( const CegoAliasObject& ao)
{
    CegoContentObject::operator=(ao);
    _aliasList = ao._aliasList;
    return (*this);
}

bool CegoAliasObject::operator == ( const CegoAliasObject& ao)
{
    return CegoContentObject::operator==(ao);
}

Chain CegoAliasObject::getId(CegoProcBlock *pBlock) const
{
    return getTabName() + Chain("@") + getTableSet() + Chain("@") + getName();
}

Chain CegoAliasObject::toChain(unsigned defTabSetId) const
{
    if ( ( defTabSetId == getTabSetId() && defTabSetId != 0 ) || defTabSetId == 0 )
	return getName() + Chain(" ") + getTabAlias();
    else
	return getName() + Chain("@") + getTableSet() + Chain(" ") + getTabAlias();
}

CegoContentObject* CegoAliasObject::clone(bool isAttrRef)
{
    CegoAliasObject *pClone = new CegoAliasObject(*this);
    return (pClone);    
}

Chain CegoAliasObject::getInfo() const
{
    Chain s;
    s += Chain("Table=") + getTabName();
    s += Chain("Alias=");
    CegoAttrAlias *pAlias = _aliasList.First();
    while ( pAlias )
    {
	s += pAlias->toChain();
	pAlias = _aliasList.Next();
	if ( pAlias )
	    s += Chain(",");
    }    
    return s;
}
