//+==================================================================================================================
//
// file :               attribute_spec_templ.h
//
// description :        C++ source code for the Attribute class template methods when they are specialized
//
// project :            TANGO
//
// author(s) :          E.Taurel
//
// Copyright (C) :      2013,2014,2015
//                        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/>.
//
//
//-=================================================================================================================

#ifndef _ATTRIBUTE_SPEC_TPP
#define _ATTRIBUTE_SPEC_TPP

//
// These methods are in a sepearte files because I did not find a way to explicitely instantiate specialized
// templates. Therefore, for template management we have three files:
// 1 - A file with explicit template instanciation (templ_inst.cpp)
// 2 - A file with template method definition (attribute_templ.h for Attribute class)
// 3 - A file with template specialization defnition (attribute_spec_templ.h (this file))
//
// We did this in order to have explicit instanciation of templates method except for specialized templates
// for which we have instanciation following the inclusion model
// See C++ template book chapter 6
//

namespace Tango
{

//+-------------------------------------------------------------------------------------------------------------------
//
// method :
//        Attribute::set_min_alarm()
//        Template specialization for data type DevEncoded and string
//
// description :
//        Sets minimum alarm attribute property. Throws exception in case the data type of provided property does not
//        match the attribute data type
//
// args :
//         in :
//            - new_min_alarm : The minimum alarm property to be set
//
//-------------------------------------------------------------------------------------------------------------------

template <>
inline void Attribute::set_min_alarm(const Tango::DevEncoded &)
{
    std::string err_msg = "Attribute properties cannot be set with Tango::DevEncoded data type";
    TANGO_THROW_EXCEPTION(API_MethodArgument, err_msg.c_str());
}

template <>
inline void Attribute::set_min_alarm(const std::string &new_min_alarm_str)
{
    if((data_type == Tango::DEV_STRING) || (data_type == Tango::DEV_BOOLEAN) || (data_type == Tango::DEV_STATE))
    {
        throw_err_data_type("min_alarm", d_name, "Attribute::set_min_alarm()");
    }

    std::string min_alarm_str_tmp = new_min_alarm_str;
    std::string dev_name = d_name;

    Tango::DeviceClass *dev_class = get_att_device_class(d_name);
    Tango::MultiClassAttribute *mca = dev_class->get_class_attr();
    Tango::Attr &att = mca->get_attr(name);
    std::vector<AttrProperty> &def_user_prop = att.get_user_default_properties();
    std::vector<AttrProperty> &def_class_prop = att.get_class_properties();

    size_t nb_class = def_class_prop.size();
    size_t nb_user = def_user_prop.size();

    std::string usr_def_val;
    std::string class_def_val;
    bool user_defaults = false;
    bool class_defaults = false;

    user_defaults = prop_in_list("min_alarm", usr_def_val, nb_user, def_user_prop);

    class_defaults = prop_in_list("min_alarm", class_def_val, nb_class, def_class_prop);

    bool set_value = true;

    if(class_defaults)
    {
        if(TG_strcasecmp(new_min_alarm_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("min_alarm", dev_name);
            avns_in_att(MIN_ALARM);
        }
        else if((TG_strcasecmp(new_min_alarm_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_min_alarm_str.c_str(), class_def_val.c_str()) == 0))
        {
            min_alarm_str_tmp = class_def_val;
        }
        else if(strlen(new_min_alarm_str.c_str()) == 0)
        {
            if(user_defaults)
            {
                min_alarm_str_tmp = usr_def_val;
            }
            else
            {
                set_value = false;

                avns_in_db("min_alarm", dev_name);
                avns_in_att(MIN_ALARM);
            }
        }
    }
    else if(user_defaults)
    {
        if(TG_strcasecmp(new_min_alarm_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("min_alarm", dev_name);
            avns_in_att(MIN_ALARM);
        }
        else if((TG_strcasecmp(new_min_alarm_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_min_alarm_str.c_str(), usr_def_val.c_str()) == 0) ||
                (strlen(new_min_alarm_str.c_str()) == 0))
        {
            min_alarm_str_tmp = usr_def_val;
        }
    }
    else
    {
        if((TG_strcasecmp(new_min_alarm_str.c_str(), AlrmValueNotSpec) == 0) ||
           (TG_strcasecmp(new_min_alarm_str.c_str(), NotANumber) == 0) || (strlen(new_min_alarm_str.c_str()) == 0))
        {
            set_value = false;

            avns_in_db("min_alarm", dev_name);
            avns_in_att(MIN_ALARM);
        }
    }

    if(set_value)
    {
        if((data_type != Tango::DEV_STRING) && (data_type != Tango::DEV_BOOLEAN) && (data_type != Tango::DEV_STATE) &&
           (data_type != Tango::DEV_ENUM))
        {
            double db;
            float fl;

            TangoSys_MemStream str;
            str.precision(TANGO_FLOAT_PRECISION);
            str << min_alarm_str_tmp;
            switch(data_type)
            {
            case Tango::DEV_SHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                set_min_alarm((DevShort) db);
                break;

            case Tango::DEV_LONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                set_min_alarm((DevLong) db);
                break;

            case Tango::DEV_LONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                set_min_alarm((DevLong64) db);
                break;

            case Tango::DEV_DOUBLE:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                set_min_alarm(db);
                break;

            case Tango::DEV_FLOAT:
                if(!(str >> fl && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                set_min_alarm(fl);
                break;

            case Tango::DEV_USHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                (db < 0.0) ? set_min_alarm((DevUShort) (-db)) : set_min_alarm((DevUShort) db);
                break;

            case Tango::DEV_UCHAR:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                (db < 0.0) ? set_min_alarm((DevUChar) (-db)) : set_min_alarm((DevUChar) db);
                break;

            case Tango::DEV_ULONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                (db < 0.0) ? set_min_alarm((DevULong) (-db)) : set_min_alarm((DevULong) db);
                break;

            case Tango::DEV_ULONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                (db < 0.0) ? set_min_alarm((DevULong64) (-db)) : set_min_alarm((DevULong64) db);
                break;

            case Tango::DEV_ENCODED:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_alarm", dev_name, "Attribute::set_min_alarm()");
                }
                (db < 0.0) ? set_min_alarm((DevUChar) (-db)) : set_min_alarm((DevUChar) db);
                break;
            }
        }
        else
        {
            throw_err_data_type("min_alarm", dev_name, "Attribute::set_min_alarm()");
        }
    }
}

//+-------------------------------------------------------------------------------------------------------------------
//
// method :
//        Attribute::set_max_alarm()
//        Template specialization for data type DevEncoded and string
//
// description :
//        Sets maximum alarm attribute property. Throws exception in case the data type of provided property does not
//        match the attribute data type
//
// args :
//         in :
//            - new_min_alarm : The minimum alarm property to be set
//
//-------------------------------------------------------------------------------------------------------------------

template <>
inline void Attribute::set_max_alarm(const Tango::DevEncoded &)
{
    std::string err_msg = "Attribute properties cannot be set with Tango::DevEncoded data type";
    TANGO_THROW_EXCEPTION(API_MethodArgument, err_msg.c_str());
}

template <>
inline void Attribute::set_max_alarm(const std::string &new_max_alarm_str)
{
    if((data_type == Tango::DEV_STRING) || (data_type == Tango::DEV_BOOLEAN) || (data_type == Tango::DEV_STATE))
    {
        throw_err_data_type("max_alarm", d_name, "Attribute::set_max_alarm()");
    }

    std::string max_alarm_str_tmp = new_max_alarm_str;
    std::string dev_name = d_name;

    Tango::DeviceClass *dev_class = get_att_device_class(d_name);
    Tango::MultiClassAttribute *mca = dev_class->get_class_attr();
    Tango::Attr &att = mca->get_attr(name);
    std::vector<AttrProperty> &def_user_prop = att.get_user_default_properties();
    std::vector<AttrProperty> &def_class_prop = att.get_class_properties();

    size_t nb_class = def_class_prop.size();
    size_t nb_user = def_user_prop.size();

    std::string usr_def_val;
    std::string class_def_val;
    bool user_defaults = false;
    bool class_defaults = false;

    user_defaults = prop_in_list("max_alarm", usr_def_val, nb_user, def_user_prop);

    class_defaults = prop_in_list("max_alarm", class_def_val, nb_class, def_class_prop);

    bool set_value = true;

    if(class_defaults)
    {
        if(TG_strcasecmp(new_max_alarm_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("max_alarm", dev_name);
            avns_in_att(MAX_ALARM);
        }
        else if((TG_strcasecmp(new_max_alarm_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_max_alarm_str.c_str(), class_def_val.c_str()) == 0))
        {
            max_alarm_str_tmp = class_def_val;
        }
        else if(strlen(new_max_alarm_str.c_str()) == 0)
        {
            if(user_defaults)
            {
                max_alarm_str_tmp = usr_def_val;
            }
            else
            {
                set_value = false;

                avns_in_db("max_alarm", dev_name);
                avns_in_att(MAX_ALARM);
            }
        }
    }
    else if(user_defaults)
    {
        if(TG_strcasecmp(new_max_alarm_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("max_alarm", dev_name);
            avns_in_att(MAX_ALARM);
        }
        else if((TG_strcasecmp(new_max_alarm_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_max_alarm_str.c_str(), usr_def_val.c_str()) == 0) ||
                (strlen(new_max_alarm_str.c_str()) == 0))
        {
            max_alarm_str_tmp = usr_def_val;
        }
    }
    else
    {
        if((TG_strcasecmp(new_max_alarm_str.c_str(), AlrmValueNotSpec) == 0) ||
           (TG_strcasecmp(new_max_alarm_str.c_str(), NotANumber) == 0) || (strlen(new_max_alarm_str.c_str()) == 0))
        {
            set_value = false;

            avns_in_db("max_alarm", dev_name);
            avns_in_att(MAX_ALARM);
        }
    }

    if(set_value)
    {
        if((data_type != Tango::DEV_STRING) && (data_type != Tango::DEV_BOOLEAN) && (data_type != Tango::DEV_STATE) &&
           (data_type != Tango::DEV_ENUM))
        {
            double db;
            float fl;

            TangoSys_MemStream str;
            str.precision(TANGO_FLOAT_PRECISION);
            str << max_alarm_str_tmp;
            switch(data_type)
            {
            case Tango::DEV_SHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                set_max_alarm((DevShort) db);
                break;

            case Tango::DEV_LONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                set_max_alarm((DevLong) db);
                break;

            case Tango::DEV_LONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                set_max_alarm((DevLong64) db);
                break;

            case Tango::DEV_DOUBLE:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                set_max_alarm(db);
                break;

            case Tango::DEV_FLOAT:
                if(!(str >> fl && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                set_max_alarm(fl);
                break;

            case Tango::DEV_USHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                (db < 0.0) ? set_max_alarm((DevUShort) (-db)) : set_max_alarm((DevUShort) db);
                break;

            case Tango::DEV_UCHAR:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                (db < 0.0) ? set_max_alarm((DevUChar) (-db)) : set_max_alarm((DevUChar) db);
                break;

            case Tango::DEV_ULONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                (db < 0.0) ? set_max_alarm((DevULong) (-db)) : set_max_alarm((DevULong) db);
                break;

            case Tango::DEV_ULONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                (db < 0.0) ? set_max_alarm((DevULong64) (-db)) : set_max_alarm((DevULong64) db);
                break;

            case Tango::DEV_ENCODED:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_alarm", dev_name, "Attribute::set_max_alarm()");
                }
                (db < 0.0) ? set_max_alarm((DevUChar) (-db)) : set_max_alarm((DevUChar) db);
                break;
            }
        }
        else
        {
            throw_err_data_type("max_alarm", dev_name, "Attribute::set_max_alarm()");
        }
    }
}

//+-------------------------------------------------------------------------------------------------------------------
//
// method :
//        Attribute::set_min_warning()
//        Template specialization for data type DevEncoded and string
//
// description :
//        Sets minimum warning attribute property. Throws exception in case the data type of provided property does not
//        match the attribute data type
//
// args :
//         in :
//            - new_min_alarm : The minimum alarm property to be set
//
//-------------------------------------------------------------------------------------------------------------------

template <>
inline void Attribute::set_min_warning(const Tango::DevEncoded &)
{
    std::string err_msg = "Attribute properties cannot be set with Tango::DevEncoded data type";
    TANGO_THROW_EXCEPTION(API_MethodArgument, err_msg.c_str());
}

template <>
inline void Attribute::set_min_warning(const std::string &new_min_warning_str)
{
    if((data_type == Tango::DEV_STRING) || (data_type == Tango::DEV_BOOLEAN) || (data_type == Tango::DEV_STATE))
    {
        throw_err_data_type("min_warning", d_name, "Attribute::set_min_warning()");
    }

    std::string min_warning_str_tmp = new_min_warning_str;
    std::string dev_name = d_name;

    Tango::DeviceClass *dev_class = get_att_device_class(d_name);
    Tango::MultiClassAttribute *mca = dev_class->get_class_attr();
    Tango::Attr &att = mca->get_attr(name);
    std::vector<AttrProperty> &def_user_prop = att.get_user_default_properties();
    std::vector<AttrProperty> &def_class_prop = att.get_class_properties();

    size_t nb_class = def_class_prop.size();
    size_t nb_user = def_user_prop.size();

    std::string usr_def_val;
    std::string class_def_val;
    bool user_defaults = false;
    bool class_defaults = false;

    user_defaults = prop_in_list("min_warning", usr_def_val, nb_user, def_user_prop);

    class_defaults = prop_in_list("min_warning", class_def_val, nb_class, def_class_prop);

    bool set_value = true;

    if(class_defaults)
    {
        if(TG_strcasecmp(new_min_warning_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("min_warning", dev_name);
            avns_in_att(MIN_WARNING);
        }
        else if((TG_strcasecmp(new_min_warning_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_min_warning_str.c_str(), class_def_val.c_str()) == 0))
        {
            min_warning_str_tmp = class_def_val;
        }
        else if(strlen(new_min_warning_str.c_str()) == 0)
        {
            if(user_defaults)
            {
                min_warning_str_tmp = usr_def_val;
            }
            else
            {
                set_value = false;

                avns_in_db("min_warning", dev_name);
                avns_in_att(MIN_WARNING);
            }
        }
    }
    else if(user_defaults)
    {
        if(TG_strcasecmp(new_min_warning_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("min_warning", dev_name);
            avns_in_att(MIN_WARNING);
        }
        else if((TG_strcasecmp(new_min_warning_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_min_warning_str.c_str(), usr_def_val.c_str()) == 0) ||
                (strlen(new_min_warning_str.c_str()) == 0))
        {
            min_warning_str_tmp = usr_def_val;
        }
    }
    else
    {
        if((TG_strcasecmp(new_min_warning_str.c_str(), AlrmValueNotSpec) == 0) ||
           (TG_strcasecmp(new_min_warning_str.c_str(), NotANumber) == 0) || (strlen(new_min_warning_str.c_str()) == 0))
        {
            set_value = false;

            avns_in_db("min_warning", dev_name);
            avns_in_att(MIN_WARNING);
        }
    }

    if(set_value)
    {
        if((data_type != Tango::DEV_STRING) && (data_type != Tango::DEV_BOOLEAN) && (data_type != Tango::DEV_STATE) &&
           (data_type != Tango::DEV_ENUM))
        {
            double db;
            float fl;

            TangoSys_MemStream str;
            str.precision(TANGO_FLOAT_PRECISION);
            str << min_warning_str_tmp;
            switch(data_type)
            {
            case Tango::DEV_SHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                set_min_warning((DevShort) db);
                break;

            case Tango::DEV_LONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                set_min_warning((DevLong) db);
                break;

            case Tango::DEV_LONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                set_min_warning((DevLong64) db);
                break;

            case Tango::DEV_DOUBLE:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                set_min_warning(db);
                break;

            case Tango::DEV_FLOAT:
                if(!(str >> fl && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                set_min_warning(fl);
                break;

            case Tango::DEV_USHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                (db < 0.0) ? set_min_warning((DevUShort) (-db)) : set_min_warning((DevUShort) db);
                break;

            case Tango::DEV_UCHAR:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                (db < 0.0) ? set_min_warning((DevUChar) (-db)) : set_min_warning((DevUChar) db);
                break;

            case Tango::DEV_ULONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                (db < 0.0) ? set_min_warning((DevULong) (-db)) : set_min_warning((DevULong) db);
                break;

            case Tango::DEV_ULONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                (db < 0.0) ? set_min_warning((DevULong64) (-db)) : set_min_warning((DevULong64) db);
                break;

            case Tango::DEV_ENCODED:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("min_warning", dev_name, "Attribute::set_min_warning()");
                }
                (db < 0.0) ? set_min_warning((DevUChar) (-db)) : set_min_warning((DevUChar) db);
                break;
            }
        }
        else
        {
            throw_err_data_type("min_warning", dev_name, "Attribute::set_min_warning()");
        }
    }
}

//+-------------------------------------------------------------------------------------------------------------------
//
// method :
//        Attribute::set_max_warning()
//        Template specialization for data type DevEncoded and string
//
// description :
//        Sets maximum warning attribute property. Throws exception in case the data type of provided property does not
//        match the attribute data type
//
// args :
//         in :
//            - new_min_alarm : The minimum alarm property to be set
//
//-------------------------------------------------------------------------------------------------------------------

template <>
inline void Attribute::set_max_warning(const Tango::DevEncoded &)
{
    std::string err_msg = "Attribute properties cannot be set with Tango::DevEncoded data type";
    TANGO_THROW_EXCEPTION(API_MethodArgument, err_msg.c_str());
}

template <>
inline void Attribute::set_max_warning(const std::string &new_max_warning_str)
{
    if((data_type == Tango::DEV_STRING) || (data_type == Tango::DEV_BOOLEAN) || (data_type == Tango::DEV_STATE))
    {
        throw_err_data_type("max_warning", d_name, "Attribute::set_max_warning()");
    }

    std::string max_warning_str_tmp = new_max_warning_str;
    std::string dev_name = d_name;

    Tango::DeviceClass *dev_class = get_att_device_class(d_name);
    Tango::MultiClassAttribute *mca = dev_class->get_class_attr();
    Tango::Attr &att = mca->get_attr(name);
    std::vector<AttrProperty> &def_user_prop = att.get_user_default_properties();
    std::vector<AttrProperty> &def_class_prop = att.get_class_properties();

    size_t nb_class = def_class_prop.size();
    size_t nb_user = def_user_prop.size();

    std::string usr_def_val;
    std::string class_def_val;
    bool user_defaults = false;
    bool class_defaults = false;

    user_defaults = prop_in_list("max_warning", usr_def_val, nb_user, def_user_prop);

    class_defaults = prop_in_list("max_warning", class_def_val, nb_class, def_class_prop);

    bool set_value = true;

    if(class_defaults)
    {
        if(TG_strcasecmp(new_max_warning_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("max_warning", dev_name);
            avns_in_att(MAX_WARNING);
        }
        else if((TG_strcasecmp(new_max_warning_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_max_warning_str.c_str(), class_def_val.c_str()) == 0))
        {
            max_warning_str_tmp = class_def_val;
        }
        else if(strlen(new_max_warning_str.c_str()) == 0)
        {
            if(user_defaults)
            {
                max_warning_str_tmp = usr_def_val;
            }
            else
            {
                set_value = false;

                avns_in_db("max_warning", dev_name);
                avns_in_att(MAX_WARNING);
            }
        }
    }
    else if(user_defaults)
    {
        if(TG_strcasecmp(new_max_warning_str.c_str(), AlrmValueNotSpec) == 0)
        {
            set_value = false;

            avns_in_db("max_warning", dev_name);
            avns_in_att(MAX_WARNING);
        }
        else if((TG_strcasecmp(new_max_warning_str.c_str(), NotANumber) == 0) ||
                (TG_strcasecmp(new_max_warning_str.c_str(), usr_def_val.c_str()) == 0) ||
                (strlen(new_max_warning_str.c_str()) == 0))
        {
            max_warning_str_tmp = usr_def_val;
        }
    }
    else
    {
        if((TG_strcasecmp(new_max_warning_str.c_str(), AlrmValueNotSpec) == 0) ||
           (TG_strcasecmp(new_max_warning_str.c_str(), NotANumber) == 0) || (strlen(new_max_warning_str.c_str()) == 0))
        {
            set_value = false;

            avns_in_db("max_warning", dev_name);
            avns_in_att(MAX_WARNING);
        }
    }

    if(set_value)
    {
        if((data_type != Tango::DEV_STRING) && (data_type != Tango::DEV_BOOLEAN) && (data_type != Tango::DEV_STATE) &&
           (data_type != Tango::DEV_ENUM))
        {
            double db;
            float fl;

            TangoSys_MemStream str;
            str.precision(TANGO_FLOAT_PRECISION);
            str << max_warning_str_tmp;
            switch(data_type)
            {
            case Tango::DEV_SHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                set_max_warning((DevShort) db);
                break;

            case Tango::DEV_LONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                set_max_warning((DevLong) db);
                break;

            case Tango::DEV_LONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                set_max_warning((DevLong64) db);
                break;

            case Tango::DEV_DOUBLE:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                set_max_warning(db);
                break;

            case Tango::DEV_FLOAT:
                if(!(str >> fl && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                set_max_warning(fl);
                break;

            case Tango::DEV_USHORT:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                (db < 0.0) ? set_max_warning((DevUShort) (-db)) : set_max_warning((DevUShort) db);
                break;

            case Tango::DEV_UCHAR:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                (db < 0.0) ? set_max_warning((DevUChar) (-db)) : set_max_warning((DevUChar) db);
                break;

            case Tango::DEV_ULONG:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                (db < 0.0) ? set_max_warning((DevULong) (-db)) : set_max_warning((DevULong) db);
                break;

            case Tango::DEV_ULONG64:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                (db < 0.0) ? set_max_warning((DevULong64) (-db)) : set_max_warning((DevULong64) db);
                break;

            case Tango::DEV_ENCODED:
                if(!(str >> db && str.eof()))
                {
                    throw_err_format("max_warning", dev_name, "Attribute::set_max_warning()");
                }
                (db < 0.0) ? set_max_warning((DevUChar) (-db)) : set_max_warning((DevUChar) db);
                break;
            }
        }
        else
        {
            throw_err_data_type("max_warning", dev_name, "Attribute::set_max_warning()");
        }
    }
}

template <>
inline Tango::DevVarULong64Array **Attribute::get_value_storage()
{
    return &value.ulg64_seq;
}

template <>
inline Tango::DevVarShortArray **Attribute::get_value_storage()
{
    return &value.sh_seq;
}

template <>
inline Tango::DevVarDoubleArray **Attribute::get_value_storage()
{
    return &value.db_seq;
}

template <>
inline Tango::DevVarStringArray **Attribute::get_value_storage()
{
    return &value.str_seq;
}

template <>
inline Tango::DevVarFloatArray **Attribute::get_value_storage()
{
    return &value.fl_seq;
}

template <>
inline Tango::DevVarBooleanArray **Attribute::get_value_storage()
{
    return &value.boo_seq;
}

template <>
inline Tango::DevVarUShortArray **Attribute::get_value_storage()
{
    return &value.ush_seq;
}

template <>
inline Tango::DevVarCharArray **Attribute::get_value_storage()
{
    return &value.cha_seq;
}

template <>
inline Tango::DevVarLong64Array **Attribute::get_value_storage()
{
    return &value.lg64_seq;
}

template <>
inline Tango::DevVarLongArray **Attribute::get_value_storage()
{
    return &value.lg_seq;
}

template <>
inline Tango::DevVarULongArray **Attribute::get_value_storage()
{
    return &value.ulg_seq;
}

template <>
inline Tango::DevVarStateArray **Attribute::get_value_storage()
{
    return &value.state_seq;
}

template <>
inline Tango::DevVarEncodedArray **Attribute::get_value_storage()
{
    return &value.enc_seq;
}

} // namespace Tango
#endif // _ATTRIBUTE_SPEC_TPP
