///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoCheckObject.cc 
// ------------------
// Cego check object entry 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: CegoCheckObject
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

#include "CegoCheckObject.h"
#include "CegoXMLdef.h"
#include "CegoXMLHelper.h"

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

CegoCheckObject::CegoCheckObject()
{
    _pPredDesc = 0;
}

CegoCheckObject::CegoCheckObject(const CegoCheckObject& co) : CegoDecodableObject(co)
{
    _tabName = co._tabName;
    _pPredDesc = co._pPredDesc->clone();

}

CegoCheckObject::CegoCheckObject(ObjectType type, const Chain& objName, int tabSetId) : CegoDecodableObject(type, objName, tabSetId)
{
    _pPredDesc = 0;
}

CegoCheckObject::CegoCheckObject(int tabSetId, const Chain& checkName, const Chain& tabName, CegoPredDesc *pPredDesc) : CegoDecodableObject(CegoObject::CHECK, checkName, tabSetId)
{
    _pPredDesc = pPredDesc;
    _tabName = tabName;
}

CegoCheckObject::~CegoCheckObject()
{
    if ( _pPredDesc )
    {
	delete _pPredDesc;
    }
}

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

const Chain& CegoCheckObject::getTabName() const
{
    return _tabName;
}
  
void  CegoCheckObject::setPredDesc(CegoPredDesc *pPredDesc)
{
    _pPredDesc = pPredDesc;
}

CegoPredDesc* CegoCheckObject::getPredDesc()
{
    return _pPredDesc;
}

int CegoCheckObject::getEntrySize() const
{

    int entrySize = CegoObject::getBaseSize();

    entrySize += 1; // object tabname size
    entrySize += _tabName.length();
    entrySize += _pPredDesc->getEncodingLength();

    return entrySize;
}

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

    int entrySize = getEntrySize();

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

    char c;

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

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

    _pPredDesc->encode(bufPtr);
    
    
}

void CegoCheckObject::decode(char *buf)
{

    char* bufPtr = buf;

    int size;

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

    bufPtr++;
    _tabName =  Chain(bufPtr);    
    bufPtr=bufPtr + _tabName.length();
    
    _pPredDesc = new CegoPredDesc(bufPtr, 0);

}


CegoCheckObject& CegoCheckObject::operator = ( const CegoCheckObject& co)
{
    CegoObject::operator=(co);

    _tabName = co._tabName;
    _pPredDesc = co._pPredDesc->clone();

    return (*this);
}

bool CegoCheckObject::operator == ( const CegoCheckObject& co)
{
    return CegoObject::operator==(co);
}

Chain CegoCheckObject::toChain() const
{
    Chain s;
    s = CegoObject::toChain();

    s += Chain("TabName: ") + _tabName + Chain("\n");
    s += Chain("PredDesc: ") + _pPredDesc->toChain();
    
    return s;
}

Element* CegoCheckObject::getElement() const
{

    Element* pRoot = new Element(XML_OBJ_ELEMENT);

    pRoot->setAttribute(XML_TSID_ATTR, Chain(getTabSetId()));
    pRoot->setAttribute(XML_OBJTYPE_ATTR, XML_CHECKOBJ_VALUE);
    pRoot->setAttribute(XML_OBJNAME_ATTR, getName());

    pRoot->setAttribute(XML_TABLENAME_ATTR, _tabName);


    Element *pPDElement = _pPredDesc->toElement();

    pRoot->addContent(pPDElement);

    return pRoot;
}

void CegoCheckObject::putElement(Element* pElement)
{
    Element *pRoot = pElement;
    

    if ( pRoot )
    {
	
	Chain objName = pRoot->getAttributeValue(XML_OBJNAME_ATTR); 
	setName(objName);

	int tabSetId = pRoot->getAttributeValue(XML_TSID_ATTR).asInteger();
	setTabSetId(tabSetId);	

	_tabName = pRoot->getAttributeValue(XML_TABLENAME_ATTR); 

	Chain objType = pRoot->getAttributeValue(XML_OBJTYPE_ATTR);
	setType(CegoObject::CHECK);

	ListT<Element*> predList = pRoot->getChildren(XML_PRED_ELEMENT);
	Element **pPredElement = predList.First();
	if ( pPredElement )
	{
	    if ( _pPredDesc )
		delete _pPredDesc;

	    _pPredDesc = new CegoPredDesc(*pPredElement, 0);
	}
    }
}


Chain CegoCheckObject::getFormatted() const
{
    Chain s;

    int maxAttrLen = 12;
    int maxAttrLen1 = 12;
    int maxAttrLen2 = 12;
    
    s += "+" + fill("-", maxAttrLen + 1) + "+" + "\n";
    s += "| ObjectName : ";
    s += getName();
    s += fill(" ", maxAttrLen - 12 - getName().length()) + "|\n";
	
    s += "| ObjectType : check " +  fill(" ", maxAttrLen - 18) + "|\n";


    s += "| Table      : " + _tabName;
    s += fill(" ", maxAttrLen - 12 - _tabName.length()) + "|" + "\n";
	
    s += "+---------" + fill("-", maxAttrLen1-9)  + "----------" +  fill("-", maxAttrLen2-9) + "+\n";
    s += "| Check   " +  fill(" ", maxAttrLen1-9) + "          " +  fill(" ", maxAttrLen2-9) + "|\n";
    s += "+---------" + fill("-", maxAttrLen1-9) + "+---------" +  fill("-", maxAttrLen2-9) + "+\n";
	
    s += _pPredDesc->toChain();

    s +="+" + fill("-", maxAttrLen1) + "+" + fill("-", maxAttrLen2) + "+\n";

    
    return s;
}


Chain CegoCheckObject::fill(const Chain& s, int num) const
{
    
    Chain fs = Chain("");
    while (num > 0)
    {
	fs = fs + s;
	num--;
    }

    return fs;
}
