///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoField.cc
// ------------
// Cego database table field 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: CegoField
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

// cego includes
#include "CegoField.h"
#include "CegoXMLdef.h"
#include "CegoTypeConverter.h"

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

CegoField::CegoField()
{
}

CegoField::CegoField(const CegoField& f)
{
    _tableName = f._tableName;
    _tableAlias = f._tableAlias;
    _attrName = f._attrName;
    _type = f._type;
    _len = f._len;
    _id = f._id;
    _fv = (CegoFieldValue)f._fv;
}

CegoField::CegoField(const Chain& tableName, const Chain& attrName)
{
    _tableName = tableName;
    _attrName = attrName;
    _id = 0;
}

CegoField::CegoField(const Chain& tableName, const Chain& tableAlias, const Chain& attrName, CegoDataType type, int len, const CegoFieldValue& defVal, bool isNullable, int id)
{
    _tableName = tableName;
    _tableAlias = tableAlias;
    _attrName = attrName;
    _type = type;
    _len = len;
    _isNullable = isNullable;
    _id = id;
    _fv = defVal;
}

CegoField::CegoField(const CegoFieldValue& fv)
{ 
    _fv = fv;
}

CegoField::~CegoField()
{  
}

void CegoField::setNullable(bool isNullable)
{
    _isNullable = isNullable;
}

bool CegoField::isNullable() const
{
    return _isNullable;
}

void CegoField::setTableName(const Chain& tableName)
{
    _tableName = tableName;
}

void CegoField::setTableAlias(const Chain& tableAlias)
{
    _tableAlias = tableAlias;
}

const Chain& CegoField::getTableName() const
{
    return _tableName;
}

const Chain& CegoField::getTableAlias() const
{
    return _tableAlias;
}

void CegoField::setId(int id)
{
    _id = id;
}

int CegoField::getId() const
{
    return _id;
}

void CegoField::setAttrName(const Chain& attrName)
{
    _attrName = attrName;
}

const Chain& CegoField::getAttrName() const
{
    return _attrName;
}


void CegoField::setType(const CegoDataType t)
{
    _type = t;
}

const CegoDataType CegoField::getType() const
{
    return _type;
}

void CegoField::setLength(int len)
{
    _len = len;
}

int CegoField::getLength() const
{
    return _len;
}

CegoFieldValue& CegoField::getValue()
{
    return _fv;
}

void CegoField::setValue(const CegoFieldValue& fv)
{
    _fv = (CegoFieldValue)fv;
}

CegoField& CegoField::operator = ( const CegoField& f)
{
    _tableName = f._tableName;
    _tableAlias = f._tableAlias;
    _attrName = f._attrName;
    _isNullable = f._isNullable;
    _id = f._id;
    _len = f._len;
    _type = f._type;
    _fv = (CegoFieldValue)f._fv;

    return (*this);
}

bool CegoField::operator == ( const CegoField& f)
{
    if ( ( ( (Chain)_tableName == (Chain)f._tableName 
	     && (Chain)_tableAlias == (Chain)f._tableAlias )
	   || (Chain)_tableName == (Chain)f._tableAlias
	   || (Chain)_tableAlias == (Chain)f._tableName
	   || (Chain)f._tableName == Chain()
	   || (Chain)_tableName == Chain() )
	 && (Chain)_attrName == (Chain)f._attrName)
	return true;
    return false;
}

Chain CegoField::typeToChain() const
{

    Chain s;

    switch ( _type )
    {
    case NULL_TYPE:
    {
	s = Chain("null");
	break;
    }
    case VARCHAR_TYPE:
    case FIXED_TYPE:
    case BIGINT_TYPE:
    case DECIMAL_TYPE:
    {
	s = CEGO_TYPE_MAP[_type] + Chain("(") + Chain(_len) + Chain(")");
	break;
    }
    default:
    {
	s = CEGO_TYPE_MAP[_type];
	break;
    }
    }

    return s;

}    


Element* CegoField::toElement() const
{
    Element* pFieldElement = new Element(XML_FIELD_ELEMENT);
    
    pFieldElement->setAttribute( XML_TABLENAME_ATTR, _tableName );
    pFieldElement->setAttribute( XML_TABLEALIAS_ATTR, _tableAlias );
    pFieldElement->setAttribute( XML_ATTRNAME_ATTR, _attrName );

    if ( _isNullable )
	pFieldElement->setAttribute( XML_COLNULLABLE_ATTR, XML_TRUE_VALUE);
    else
	pFieldElement->setAttribute( XML_COLNULLABLE_ATTR, XML_FALSE_VALUE);

    CegoTypeConverter tc;
    pFieldElement->setAttribute( XML_COLTYPE_ATTR, tc.getTypeString(_type ));
    pFieldElement->setAttribute( XML_COLSIZE_ATTR, Chain(_len) );	
    return pFieldElement;
}

void CegoField::fromElement(Element *pFieldElement)
{
    
    _tableName = pFieldElement->getAttributeValue( XML_TABLENAME_ATTR );
    _tableAlias = pFieldElement->getAttributeValue( XML_TABLEALIAS_ATTR );
    _attrName = pFieldElement->getAttributeValue( XML_ATTRNAME_ATTR );

    Chain nullableString = pFieldElement->getAttributeValue( XML_COLNULLABLE_ATTR );
    
    if ( nullableString == Chain(XML_TRUE_VALUE) )
    {
	_isNullable = true;
    }
    else
    {
	_isNullable = false;
    }

    CegoTypeConverter tc;

    _fv.setType( tc.getTypeId(pFieldElement->getAttributeValue( XML_COLTYPE_ATTR )) );
    _fv.setLength( pFieldElement->getAttributeValue( XML_COLSIZE_ATTR ).asInteger() );
    
    
}
