//=============================================================================	
//
// file :		attrdesc.h
//
// description :	Include file for the Attr classes hierarchy. 
//			Three classes are declared in this file :
//				The Attr class
//				The SpectrumAttr class
//				The ImageAttr class
//
// project :		TANGO
//
// author(s) :		A.Gotz + E.Taurel
//
// Copyright (C) :      2004,2005,2006,2007,2008,2009,2010,2011
//						European Synchrotron Radiation Facility
//                      BP 220, Grenoble 38043
//                      FRANCE
//
// This file is part of Tango.
//
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Tango 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 Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
// $Revision: 15556 $
//
// $Log$
// Revision 3.19  2010/09/09 13:44:46  taurel
// - Add year 2010 in Copyright notice
//
// Revision 3.18  2010/09/09 13:29:09  taurel
// - Commit after the last merge with the bugfixes branch
// - Fix some warning when compiled -W -Wall
//
// Revision 3.17  2010/08/25 11:41:27  taurel
// - Fix some bugs preventing dynamic attributes management (in some cases)
//
// Revision 3.16  2009/12/09 15:48:56  taurel
// - Add Attr and Attribute methods set_data_ready_event() and is_data_ready_event().
// - Admin device command EventSubcriptionChange fails is one of these methods has not been called
//
// Revision 3.15  2009/01/21 12:49:04  taurel
// - Change CopyRights for 2009
//
// Revision 3.14  2009/01/19 08:06:26  taurel
// - Fix warnings generated by Doxygen
//
// Revision 3.13  2008/10/06 15:00:36  taurel
// - Changed the licensing info from GPL to LGPL
//
// Revision 3.12  2008/10/03 06:51:36  taurel
// - Add some licensing info in each files
//
// Revision 3.11  2008/06/14 11:29:15  taurel
// - DevEncoded attribute data type implementation work going on
//
// Revision 3.10  2006/06/20 08:00:04  jensmeyer
// After changing the the init value of the attribute polling period to -1 insted of 0 I detected
// a campatibility problem with the old versions. I changed back the init value to 0 and
// solved the problem with new methods on the Attribute object.
//
// Revision 3.9  2006/06/14 11:21:35  jensmeyer
// Modifications to make the set_polling_period() for attributes work
// with a polling period set to 0.
//
// Revision 3.8  2006/04/27 13:44:51  taurel
// - Fix compatibility bug introduced in previous release by moving new
// class data members in their corresponding extension classes
//
// Revision 3.7  2006/04/13 14:49:37  jensmeyer
// Added methods to the Attr class to initialise the fire event configuration
// with pogo.
//
// Revision 3.6  2005/11/07 12:15:00  jensmeyer
// Corrected initialisation of memorised attributes. No longer exits when receiving an
// exception during initialisation. Also added an option to only initialise the attribute setpoint and not writing to the attribute.
// set_memorized_init(false) -> only applies setpoint.
// set_memorized_init(true) -> also writes setpoint value to the attribute.
//
// Revision 3.5  2005/01/13 08:27:32  taurel
// - Merge trunk with Release_5_0 from brach Release_5_branch
//
// Revision 3.4.2.2  2004/11/22 14:14:45  taurel
// - Added methods for the AttrDesc class for the new attribute config
//   parameters.
// - Some minor changes
//
// Revision 3.4.2.1  2004/10/22 11:24:59  taurel
// Added warning alarm
// Change attribute config. It now includes alarm and event parameters
// Array attribute property now supported
// subscribe_event throws exception for change event if they are not correctly configured
// Change in the polling thread: The event heartbeat has its own work in the work list
// Also add some event_unregister
// Fix order in which classes are destructed
// Fix bug in asynchronous mode (PUSH_CALLBACK). The callback thread ate all the CPU
// Change in the CORBA info call for the device type
//
// Revision 3.4  2004/07/07 08:39:56  taurel
//
// - Fisrt commit after merge between Trunk and release 4 branch
// - Add EventData copy ctor, asiignement operator and dtor
// - Add Database and DeviceProxy::get_alias() method
// - Add AttributeProxy ctor from "device_alias/attribute_name"
// - Exception thrown when subscribing two times for exactly yhe same event
//
// Revision 3.3  2003/09/02 13:08:14  taurel
// Add memorized attribute feature (only for SCALAR and WRITE/READ_WRITE attribute)
//
// Revision 3.2  2003/08/22 12:52:54  taurel
// - For device implementing release 3 of IDL (derivating from device_3impl), change
//   the way how attributes are read or written
// - Fix small bug in vector iterator usage in case of "erase()" method called in
//   a for loop
//
// Revision 3.1  2003/08/21 07:23:46  taurel
// - End of the implementation of the new way to transfer data for read and
//   write attributes (better use of exception)
// - Added Attribute::set_date() and Attribute::set_value_date_quality() methods
// - Added DeviceAttribute ctors from "const char *"
// - Enable writing of spectrum and image attributes
// - Many new DeviceAttribute ctors/inserters to enable easy image and spectrums
//   attribute writing
// - Attribute date automatically set in case of attribute quality factor set to INVALID
// - Change in the polling thread discarding element algo. to support case of polling
//   several cmd/atts at the same polling period with cmd/attr having a long response time
// - Take cmd/attr execution time into account in the "Data not updated since" polling
//   status string
// - Split "str().c_str()" code in two lines of code. It was the reason of some problem
//   on Windows device server
// - Add the possibility to set a cmd/attr polling as "externally triggered". Add method
//   to send trigger to the polling thread
//
// Revision 3.0.4.1  2003/09/30 11:49:56  taurel
// Add some changes foreseen for release 4.1 and already implemented on
// the trunck into this release 4.0 branch
//
// Revision 3.0  2003/03/25 16:41:50  taurel
// Many changes for Tango release 3.0 including
// - Added full logging features
// - Added asynchronous calls
// - Host name of clients now stored in black-box
// - Three serialization model in DS
// - Fix miscellaneous bugs
// - Ported to gcc 3.2
// - Added ApiUtil::cleanup() and destructor methods
// - Some internal cleanups
// - Change the way how TangoMonitor class is implemented. It's a recursive
//   mutex
//
//=============================================================================

#ifndef _ATTRDESC_H
#define _ATTRDESC_H

#include <tango.h>

namespace Tango
{

class AttrProperty;
class WAttribute;

class AttrExt
{
public:
	AttrExt():poll_period(0),cl_name("Attr") {disp_level = Tango::OPERATOR;}
	AttrExt(DispLevel level):poll_period(0),cl_name("Attr") {disp_level = level;}
	
	Tango::DispLevel	disp_level;			// Display  level
	long				poll_period;		// Polling period

	bool				fire_change_event;
	bool				fire_archive_event;	
	bool				check_change_event;
	bool				check_archive_event;
	bool				fire_dr_event;

	string				cl_name;
};

class UserDefaultAttrPropExt
{
};

/**
 * User class to set attribute default properties.
 *
 * This class is used to set attribute default properties. Three levels of 
 * attributes properties setting are implemented within Tango. The highest
 * property setting level is the database. Then the user default (set using
 * this UserDefaultAttrProp class) and finally a Tango library default
 * value
 *
 * $Author: taurel $
 * $Revision: 15556 $
 */
 
class UserDefaultAttrProp
{
public:

/**@name Constructor
 * Only one constructor is defined for this class */
//@{
/**
 * Constructs a newly allocated UserDefaultAttrProp object.
 */
	UserDefaultAttrProp() {ext = NULL;}
//@}
	
	~UserDefaultAttrProp() {delete ext;}

/**@name Set default property methods */
//@{
/**
 * Set default label property
 *
 * @param	def_label	The user default label property
 */
	void set_label(const char *def_label)
	{
		label = def_label;
	}
	
/**
 * Set default description property
 *
 * @param	def_desc	The user default description property
 */	
	void set_description(const char *def_desc)
	{
		description = def_desc;
	}
	
/**
 * Set default unit property
 *
 * @param	def_unit	The user default unit property
 */
	void set_unit(const char *def_unit)
	{
		unit = def_unit;
	}
	
/**
 * Set default standard unit property
 *
 * @param	def_std_unit	The user default standard unit property
 */
	void set_standard_unit(const char *def_std_unit)
	{
		standard_unit = def_std_unit;
	}
	
/**
 * Set default display unit property
 *
 * @param	def_disp_unit	The user default display unit property
 */
	void set_display_unit(const char *def_disp_unit)
	{
		display_unit = def_disp_unit;
	}
	
/**
 * Set default format property
 *
 * @param	def_format	The user default format property
 */
	void set_format(const char *def_format)
	{
		format = def_format;
	}
	
/**
 * Set default min_value property
 *
 * @param	def_min_value	The user default min_value property
 */
	void set_min_value(const char *def_min_value)
	{
		min_value = def_min_value;
	}
	
/**
 * Set default max_value property
 *
 * @param	def_max_value	The user default max_value property
 */
	void set_max_value(const char *def_max_value)
	{
		max_value = def_max_value;
	}
	
/**
 * Set default min_alarm property
 *
 * @param	def_min_alarm	The user default min_alarm property
 */
	void set_min_alarm(const char *def_min_alarm)
	{
		min_alarm = def_min_alarm;
	}
	
/**
 * Set default max_alarm property
 *
 * @param	def_max_alarm	The user default max_alarm property
 */
	void set_max_alarm(const char *def_max_alarm)
	{
		max_alarm = def_max_alarm;
	}
	
/**
 * Set default min_warning property
 *
 * @param	def_min_warning	The user default min_warning property
 */
	void set_min_warning(const char *def_min_warning)
	{
		min_warning = def_min_warning;
	}
	
/**
 * Set default max_warning property
 *
 * @param	def_max_warning	The user default max_warning property
 */
	void set_max_warning(const char *def_max_warning)
	{
		max_warning = def_max_warning;
	}
	
/**
 * Set default RDS alarm delta_t property
 *
 * @param	def_delta_t	The user default RDS alarm delta_t property
 */
	void set_delta_t(const char *def_delta_t)
	{
		delta_t = def_delta_t;
	}
	
/**
 * Set default RDS alarm delta_val property
 *
 * @param	def_delta_val	The user default RDS alarm delta_val property
 */
	void set_delta_val(const char *def_delta_val)
	{
		delta_val = def_delta_val;
	}
	
/**
 * Set default change event abs_change property
 *
 * @param	def_abs_change	The user default change event abs_change property
 */
	void set_abs_change(const char *def_abs_change)
	{
		abs_change = def_abs_change;
	}
	
/**
 * Set default change event rel_change property
 *
 * @param	def_rel_change	The user default change event rel_change property
 */
	void set_rel_change(const char *def_rel_change)
	{
		rel_change = def_rel_change;
	}
	
/**
 * Set default periodic event period property
 *
 * @param	def_period	The user default periodic event period property
 */
	void set_period(const char *def_period)
	{
		period = def_period;
	}
	
/**
 * Set default archive event abs_change property
 *
 * @param	def_archive_abs_change	The user default archive event abs_change property
 */
	void set_archive_abs_change(const char *def_archive_abs_change)
	{
		archive_abs_change = def_archive_abs_change;
	}
	
/**
 * Set default archive event rel_change property
 *
 * @param	def_archive_rel_change	The user default archive event rel_change property
 */
	void set_archive_rel_change(const char *def_archive_rel_change)
	{
		archive_rel_change = def_archive_rel_change;
	}
	
/**
 * Set default archive event period property
 *
 * @param	def_archive_period	The user default archive event period property
 */
	void set_archive_period(const char *def_archive_period)
	{
		archive_period = def_archive_period;
	}
//@}
					
	string 			label;
	string 			description;
	string 			unit;
	string 			standard_unit;
	string 			display_unit;
	string 			format;
	string 			min_value;
	string			max_value;
	string			min_alarm;
	string			max_alarm;
	string			min_warning;
	string			max_warning;
	string			delta_val;
	string			delta_t;
	string			abs_change;
	string			rel_change;
	string			period;
	string			archive_abs_change;
	string			archive_rel_change;
	string			archive_period;
	
	UserDefaultAttrPropExt	*ext;	
};

/**
 * User class to create a no dimension attribute object.
 *
 * Information from this class and information fetched out from the Tango
 * database allows the Tango core software to create the Attribute object
 * for the attribute created by the user.
 *
 * $Author: taurel $
 * $Revision: 15556 $
 */
 
class Attr
{
public:

/**@name Constructors
 * Two constructor are defined for this class */
//@{
/**
 * Constructs a newly allocated Attr object.
 * The attribute display level is set to OPERATOR.
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	w_type	The attribute type (read, write, read with write ...)
 * @param	assoc	Name of the associated writable attribute. This is used
 * only the read with write attribute
 *
 */
	Attr(const char *name,long data_type,
	     Tango::AttrWriteType w_type = Tango::READ,
	     const char *assoc = AssocWritNotSpec);

/**
 * Constructs a newly allocated Attr object.
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	disp	The attribute display level
 * @param	w_type	The attribute type (read, write, read with write ...)
 * @param	assoc	Name of the associated writable attribute. This is used
 * only the read with write attribute
 *
 */	     
	Attr(const char *name,long data_type,Tango::DispLevel disp,
	     Tango::AttrWriteType w_type = Tango::READ,
	     const char *assoc = AssocWritNotSpec);
//@}

/**@name Destructor
 * Only one desctructor is defined for this class */
//@{
/**
 * The object desctructor.
 */
	virtual ~Attr();
//@}

/**@name Miscellaneous methods*/
//@{
/**
 * Set default attribute properties
 *
 * @param	prop	The user default property class
 */
 	void set_default_properties(UserDefaultAttrProp &prop);
/**
 * Set the attribute display level
 *
 * @param	level	The attribute display level
 */
 	void set_disp_level(Tango::DispLevel level) {ext->disp_level = level;}
/**
 * Set the attribute polling update period
 *
 * @param	update	The attribute polling period (in mS)
 */
 	void set_polling_period(long update) {ext->poll_period = update;}
/**
 * Set the attribute as memorized in database (only for scalar and writable
 * attribute)
 * With no argument the setpoint will be written to the attribute during initialisation!
 */
 	void set_memorized();
/**
 * Set the initialisation flag for memorized attributes
 * 	true  = the setpoint value will be written to the attribute on initialisation
 *  false = only the attribute setpoint is initialised. No action is taken on the attribute
 * 
 * @param	write_on_init	If true the setpoint value will be written to the attribute on initialisation
 */
 	void set_memorized_init(bool write_on_init) {mem_init = write_on_init;}	
/**
 * Set a flag to indicate that the server fires change events manually without
 * the polling to be started for the attribute.
 * If the detect parameter is set to true, the criteria specified for the change 
 * event are verified and the event is only pushed if they are fullfilled.
 * If detect is set to false the event is fired without checking!
 *
 * @param implemented True when the server fires change events manually. 
 * @param detect Triggers the verification of the change event properties when set to true.
 */
	void set_change_event(bool implemented, bool detect) 
			{ ext->fire_change_event  = implemented;
			  ext->check_change_event = detect; }	
/**
 * Check if the change event is fired manually for this attribute.
 *
 * @return A boolean set to true if a manual fire change event is implemented.
 */			
	bool is_change_event() {return ext->fire_change_event;}
/**
 * Check if the change event criteria should be checked when firing
 * the event manually.
 *
 * @return A boolean set to true if a change event criteria will be checked.
 */			
	bool is_check_change_criteria() {return ext->check_change_event;}
/**
 * Set a flag to indicate that the server fires archive events manually without
 * the polling to be started for the attribute
 * If the detect parameter is set to true, the criteria specified for the archive 
 * event are verified and the event is only pushed if they are fullfilled.
 * If detect is set to false the event is fired without checking!
 *
 * @param implemented True when the server fires archive events manually.
 * @param detect Triggers the verification of the archive event properties when set to true.
 */
	void set_archive_event(bool implemented, bool detect) 
			{ext->fire_archive_event  = implemented;
			 ext->check_archive_event = detect;}	

/**
 * Check if the archive event is fired manually for this attribute.
 *
 * @return A boolean set to true if a manual fire archive event is implemented.
 */			
	bool is_archive_event() {return ext->fire_archive_event;}	
/**
 * Check if the archive event criteria should be checked when firing
 * the event manually.
 *
 * @return A boolean set to true if a archive event criteria will be checked.
 */			
	bool is_check_archive_criteria() {return ext->check_archive_event;}
	
/**
 * Set a flag to indicate that the server fires data ready events
 *
 * @param implemented True when the server fires data ready events
 */
	void set_data_ready_event(bool implemented) { ext->fire_dr_event  = implemented;}	
/**
 * Check if the data ready event is fired for this attribute.
 *
 * @return A boolean set to true if firing data ready event is implemented.
 */			
	bool is_data_ready_event() {return ext->fire_dr_event;}	
//@}

	string 			&get_name() {return name;}
	Tango::AttrDataFormat 	get_format() {return format;}
	Tango::AttrWriteType 	get_writable() {return writable;}
	long 			get_type() {return type;}
	Tango::DispLevel	get_disp_level() {return ext->disp_level;}
	long			get_polling_period() {return ext->poll_period;}
	bool			get_memorized() {return mem;}
	bool			get_memorized_init() {return mem_init;}
	string			&get_assoc() {return assoc_name;}
	const string	&get_cl_name() {return ext->cl_name;}
	void			set_cl_name(const string &cl) {ext->cl_name = cl;}
	bool			is_assoc()
				{
					if (assoc_name != AssocWritNotSpec)
						return true;
					else
						return false;
				}
	
	vector<AttrProperty>	&get_class_properties() {return class_properties;}
	vector<AttrProperty>	&get_user_default_properties() {return user_default_properties;}
	void 			set_class_properties(vector<AttrProperty> &in_prop)
				{
					class_properties = in_prop;
				}
	void			check_type();

	virtual void read(DeviceImpl *,Attribute &) {};
	virtual void write(DeviceImpl *,WAttribute &) {};
	virtual bool is_allowed(DeviceImpl *,AttReqType) {return true;}
	
	
#ifndef TANGO_HAS_LOG4TANGO
	friend ostream &operator<<(ostream &,const Attr &);
#endif
		
protected:
	string					name;
	Tango::AttrDataFormat	format;
	Tango::AttrWriteType	writable;
	long					type;
	string					assoc_name;
	bool					mem;
	bool					mem_init;		
	
	vector<AttrProperty>	class_properties;
	vector<AttrProperty>	user_default_properties;

private:	
	AttrExt					*ext;
};

class SpectrumAttrExt
{
};

/**
 * User class to create a one dimension attribute object.
 *
 * Information from this class and information fetched out from the Tango
 * database allows the Tango core software to create the Attribute object
 * for the attribute created by the user.
 *
 * $Author: taurel $
 * $Revision: 15556 $
 */
 
class SpectrumAttr: public Attr
{
public:

/**@name Constructors
 * Two constructors are defined for this class */
//@{
/**
 * Constructs a newly allocated SpectrumAttr object.
 * The attribute display level is set to OPERATOR.
 * The attribute write type is set to READ
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	max_x	The attribute maximum x dimension
 *
 */
	SpectrumAttr(const char *name,long data_type,long max_x);

/**
 * Constructs a newly allocated SpectrumAttr object.
 * The attribute display level is set to OPERATOR.
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	w_type  The attribute write type (READ, WRITE, READ_WRITE)
 * @param	max_x	The attribute maximum x dimension
 *
 */
	SpectrumAttr(const char *name,long data_type,Tango::AttrWriteType w_type,long max_x);
	
/**
 * Constructs a newly allocated SpectrumAttr object.
 * The attribute write type is set to READ
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	max_x	The attribute maximum x dimension
 * @param	level 	The attribute display type
 *
 */
	SpectrumAttr(const char *name,long data_type,long max_x,DispLevel level);

/**
 * Constructs a newly allocated SpectrumAttr object.
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	w_type  The attribute write type (READ, WRITE, READ_WRITE)
 * @param	max_x	The attribute maximum x dimension
 * @param	level 	The attribute display type
 *
 */
	SpectrumAttr(const char *name,long data_type,Tango::AttrWriteType w_type,long max_x,DispLevel level);

//@}

/**@name Destructor
 * Only one desctructor is defined for this class */
//@{
/**
 * The object desctructor.
 */
	~SpectrumAttr() {delete ext;}
//@}
	
	long 			get_max_x() {return max_x;}
	
protected:
	long			max_x;
	
private:
	SpectrumAttrExt		*ext;
};

class ImageAttrExt
{
};

/**
 * User class to create a two dimensions attribute object.
 *
 * Information from this class and information fetched out from the Tango
 * database allows the Tango core software to create the Attribute object
 * for the attribute created by the user.
 *
 * $Author: taurel $
 * $Revision: 15556 $
 */
 
class ImageAttr: public SpectrumAttr
{
public:

/**@name Constructors
 * Two constructors are defined for this class */
//@{
/**
 * Constructs a newly allocated ImageAttr object.
 * The attribute display level is set to OPERATOR.
 * The attribute write type is set to READ
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	max_x	The attribute maximum x dimension
 * @param	max_y	The attribute maximum y dimension
 *
 */
	ImageAttr(const char *name,long data_type,long max_x, long max_y);

/**
 * Constructs a newly allocated ImageAttr object.
 * The attribute display level is set to OPERATOR.
 * The attribute write type is set to READ
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	w_type  The attribute write type (READ, WRITE, READ_WRITE)
 * @param	max_x	The attribute maximum x dimension
 * @param	max_y	The attribute maximum y dimension
 *
 */
	ImageAttr(const char *name,long data_type,Tango::AttrWriteType w_type,long max_x, long max_y);
		
/**
 * Constructs a newly allocated ImageAttr object.
 * The attribute write type is set to READ
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	max_x	The attribute maximum x dimension
 * @param	max_y	The attribute maximum y dimension
 * @param	level	The attribute display type
 *
 */
	ImageAttr(const char *name,long data_type,long max_x,
		  long max_y, Tango::DispLevel level);
		  
/**
 * Constructs a newly allocated ImageAttr object.
 * The attribute write type is set to READ
 *
 * @param 	name	The attribute name
 * @param	data_type	The attribute data type
 * @param	w_type  The attribute write type (READ, WRITE, READ_WRITE)
 * @param	max_x	The attribute maximum x dimension
 * @param	max_y	The attribute maximum y dimension
 * @param	level	The attribute display type
 *
 */
	ImageAttr(const char *name,long data_type,Tango::AttrWriteType w_type,
		  long max_x, long max_y, Tango::DispLevel level);
		  
//@}

/**@name Destructor
 * Only one desctructor is defined for this class */
//@{
/**
 * The object desctructor.
 */
	~ImageAttr() {delete ext;}
//@}
	
	long 			get_max_y() {return max_y;}
	
protected:
	long			max_y;
	
private:
	ImageAttrExt		*ext;
};

} // End of Tango namespace

#endif /* _ATTRDESC_H */
