/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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 of the License, or
    (at your option) any later version.

***************************************************************************/


#ifndef DDDATAOBJECT_H
#define DDDATAOBJECT_H

#include <ddstringrow.h>
#include <ddbaseobject.h>

/// dddataobject : Neufassung von dddbobject.
/**
	Diesmal eher KISS: Ein dddataobject ist eine ddstringrow, die als Zeile einer
	Tabelle dient und von dieser einen Pointer auf den Feldindex erhält, um den
	'acces by key' zu gewährleisten.
	
	@see ddstring
	@see ddstringrow
	@see ddwebview
	
	Änderung: _index zeigt _nicht_ auf die Eltern-table sondern auf deren 
	feldindex -> Abkürzung.
*/

// syntactic sugar
class dddatastaterow : public ddstringstaterow
{
	
public:
	
	enum dd_dataflags
	{
	  data_is_public = 1,
		data_is_removed = 2,
		data_is_alerted = 4,
		data_is_subscribed = 8,
		data_is_solved = 16,
   	data_is_closed = 32,
		data_is_draft = 64,
		data_is_private = 128
		//...
  };
  
  inline bool is_public() const 
	{
   	return ( _flags & dddatastaterow::data_is_public );
	}
	
	inline bool is_removed() const 
	{
		return ( _flags & dddatastaterow::data_is_removed );
	}
	
	inline bool is_alerted() const 
	{
		return ( _flags & dddatastaterow::data_is_alerted );
	}
	
	inline bool is_subscribed() const 
	{
		return ( _flags & dddatastaterow::data_is_subscribed );
	}
	
	inline bool is_solved() const 
	{
		return ( _flags & dddatastaterow::data_is_solved );
	}
  
  inline bool is_closed() const 
	{
   	return ( _flags & dddatastaterow::data_is_closed );
	}

};


template<class T>
class dddataobject : public dddatastaterow
{

public: 
	
	dddataobject()
	:	_parent( 0 )
	{
	}
	
	dddataobject( T* parent )
	:	_parent( parent )
	{
	}

	
	dddataobject( const dddataobject& src  )
	{
		*this = src;
	}
	
	dddataobject& operator=( const dddataobject& src  )
	{
		_flags = src._flags;
		_parent = src._parent;
		ddstringrow::operator=( src );
		return *this;
	}

	
	
	/**
		Elternobject setzen
	*/

  inline void set_parent( T* parent )
	{
		_parent = parent;
	}
  
	
	/**
		Gibt das Elternobject zurürck
	*/

	inline T& get_parent()
	{
		return *_parent;
	}
  
	
	/**
		Gibt den index für ein Feld oder -1 im Fehlerfall zurück.
	*/

	int index_of( const ddstring& key ) const
	{
		return _parent->get_field_index().index_of( key );	
	}
    		
  
  /**
		Ist 'true' wenn der Eintrag 'key' existiert. 
	*/

	bool contains_key( const ddstring& key ) const
	{
		return _parent->get_field_index().contains_key( key );
	}


	/**
		Access by key.
	*/
	
	ddstring& operator[]( const ddstring& key )
	{
		int idx = _parent->get_field_index().index_of( key );
		if( idx>-1 )
			return ddstringrow::operator[](idx);
		throw out_of_range( "dddataobject::operator[key]: key not found:" + key );
	}
	
	
	/**
		Access by key, const Version.
	*/
	
	const ddstring& operator[]( const ddstring& key ) const
	{
		int idx = _parent->get_field_index().index_of( key );
		if( idx>-1 )
			return ddstringrow::operator[](idx);
		throw out_of_range( "dddataobject::operator[key]: key not found:" + key );
	}
		
		
	/**
		Access by index: Der schweinecompiler rafts nicht, das das 
		schon definiert ist.
	*/
	
	ddstring& operator[]( int idx )
	{
		if( idx>-1 )
			return at(idx);
		throw out_of_range( "dddataobject::operator[idx]: -1" );			
	}
	
	
	/**
		Access by index, const Version. Der schweinecompiler rafts nicht, das das 
		schon definiert ist.
	*/
	
	const ddstring& operator[]( int idx ) const
	{
		if( idx>-1 )
			return at(idx);
		throw out_of_range( "dddataobject::operator[idx]: -1" );			
	}
		
		
protected: 

	T* _parent;
	
};


#endif
