///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoAttrComp.cc
// ---------------
// Cego database table attribute comparison description
//      
// Design and Implementation by Bjoern Lemke
//     
// (C)opyright 2000-2011 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: CegoAttrComp
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

#include "CegoAttrComp.h"

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


CegoAttrComp::CegoAttrComp()
{
    _compMode = UNDEF;
    _pMatcher = 0;
}

CegoAttrComp::CegoAttrComp(const Chain& attrName)
{
    _attrName = attrName;
    _compMode = UNDEF;
    _pMatcher = 0;
}

CegoAttrComp::CegoAttrComp(const Chain& attrName, CegoComparison comp, const CegoFieldValue& fv)
{
    _attrName = attrName;
    _comp = comp;
    _fv = fv;
    _compMode = VAL;
    _isSetup = false;
    _pMatcher = 0;
}

CegoAttrComp::CegoAttrComp(const Chain& attrName, CegoComparison comp, const CegoAttrDesc& attrDesc)
{
    _attrName = attrName;
    _comp = comp;
    _attrDesc = attrDesc;
    _compMode = ATTR;
    _pMatcher = 0;
}

CegoAttrComp::CegoAttrComp(const Chain& attrName, const CegoFieldValue& fv, const CegoFieldValue& fv2)
{
    _attrName = attrName;
    _fv = fv;
    _fv2 = fv2;
    _compMode = BTWN;
    _pMatcher = 0;
}

CegoAttrComp::CegoAttrComp(const Chain& attrName, const Chain& pattern, bool isNot)
{
    _attrName = attrName;
    _pattern = pattern;
    
    if ( isNot )
	_compMode = ISNOTLIKE;
    else
	_compMode = ISLIKE;
    _pMatcher = 0;
}

CegoAttrComp::~CegoAttrComp()
{
    if ( _pMatcher )
	delete _pMatcher;
}

CegoAttrComp::CompMode CegoAttrComp::getCompMode() const
{
    return _compMode;
}

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

CegoComparison CegoAttrComp::getComparison() const
{
    return _comp;
}

void CegoAttrComp::setComparison(CegoComparison comp)
{
    _comp = comp;
}

const CegoFieldValue& CegoAttrComp::getFieldValue() const
{
    return _fv;
}

const CegoFieldValue& CegoAttrComp::getFieldValue2() const
{
    return _fv2;
}

const CegoAttrDesc& CegoAttrComp::getAttrDesc() const
{
    return _attrDesc;
}

bool CegoAttrComp::isSetup()
{
    return _isSetup;
}

const Chain& CegoAttrComp::getPattern() const
{
    return _pattern;
}

Matcher* CegoAttrComp::getMatcher()
{
    if ( _pMatcher == 0)
    {	
	Chain sqlPattern = Chain("^") + _pattern + Chain("$");
	sqlPattern.replaceAll(Chain("%"), Chain(".*"), sqlPattern);
	sqlPattern.replaceAll(Chain("_"), Chain("."), sqlPattern);	
	_pMatcher = new Matcher(sqlPattern);
	_pMatcher->prepare();
	
    }
    return _pMatcher;
}
bool CegoAttrComp::setup(const ListT<CegoField>& fl)
{
    _isSetup=false;
    CegoField* pF = fl.First();
    while ( pF && _isSetup == false )
    {	
	if ( ( _attrDesc.getTableName() == pF->getTableName() || _attrDesc.getTableName()== pF->getTableAlias() )
	     && _attrDesc.getAttrName() == pF->getAttrName() )
	{
	    _isSetup=true;
	    _fv = pF->getValue();
	}
	pF = fl.Next();
    }
    return _isSetup;
}

bool CegoAttrComp::setup(ListT<CegoField>* joinBuf, int offset, int size)
{
    int i = offset;
    _isSetup = false;
    while ( i < size+offset && _isSetup == false )
    {
	CegoField* pF = joinBuf[i].First();
	while (pF && _isSetup == false)
	{	
	    // cout << "Checking T=" << pF->getTableName() << " A=" << pF->getAttrName() << "Alias=" << pF->getTableAlias() << endl;
	    if ( ( _attrDesc.getTableName() == pF->getTableName() || _attrDesc.getTableName()== pF->getTableAlias() )
		 && _attrDesc.getAttrName() == pF->getAttrName() )
	    {
		_isSetup = true;
				
		_fv = pF->getValue();
	    }
	    pF = joinBuf[i].Next();
	}
	i++;
    }
    return _isSetup;
}

CegoAttrComp& CegoAttrComp::operator = ( const CegoAttrComp& ac)
{
    _attrName = ac._attrName;
    _comp = ac._comp;
    _fv = ac._fv;
    _fv2 = ac._fv2;
    _attrDesc = ac._attrDesc;
    _compMode = ac._compMode;
    _isSetup = ac._isSetup;
    _pattern = ac._pattern;
    _pMatcher = 0;
    return (*this);
}
    
bool CegoAttrComp::operator == ( const CegoAttrComp& ac) const
{
    if ( _compMode != ac._compMode )
	return false;    
    if ( _compMode == ATTR )
	return (_attrName == ac._attrName && _comp == ac._comp );
    if ( _compMode == VAL )
	return (_attrName == ac._attrName && _comp == ac._comp && _fv == ac._fv );
    if ( _compMode == BTWN )
	return (_attrName == ac._attrName && _fv == ac._fv && _fv2 == ac._fv2 );
    if ( _compMode == ISLIKE || _compMode == ISNOTLIKE )
	return (_attrName == ac._attrName && _pattern == ac._pattern  );

    return false;
}

Chain CegoAttrComp::toChain() const
{
    Chain s;
    
    s = _attrName;
    
    if ( _compMode == BTWN )
    {
	s += Chain(" between ") + _fv.toChain() + Chain(" and ") + _fv2.toChain();
    }
    else if ( _compMode == ISLIKE )
    {
	s += Chain(" like '") + _pattern + Chain("'"); 
    }
    else if ( _compMode == ISNOTLIKE )
    {
	s += Chain(" not like '") + _pattern + Chain("'"); 
    }
    else
    {
	switch ( _comp )
	{
	case EQUAL:
	    s += Chain(" = ");
	    break;
	case NOT_EQUAL:
	    s += Chain(" != ");
	    break;
	case LESS_THAN:
	    s += Chain(" < ");
	    break;
	case MORE_THAN:
	    s += Chain(" > ");
	    break;
	case LESS_EQUAL_THAN:
	    s += Chain(" <= ");
	    break;
	case MORE_EQUAL_THAN:
	    s += Chain(" >= ");
	    break;
	}
	if ( _compMode == VAL )
	    s += _fv.toChain();
	else
	{
	    s += _attrDesc.toChain();
	    if ( _isSetup )
		s += Chain("(") + _fv.toChain() + Chain(")");
	    else
		s += Chain(" -> not setup ");
	}
    }
    return s;
    
}

ostream& operator << (ostream& s, const CegoAttrComp& ac)
{
    s << ac.toChain();
    return s;
}

