/*
 * SPDX-FileCopyrightText: 2004 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#include <tango/server/Command.h>

#include <tango/server/TemplCommand.h>
#include <tango/server/TemplCommandIn.h>
#include <tango/server/TemplCommandInOut.h>

#include <new>

namespace Tango
{

//+-------------------------------------------------------------------------
//
// method :         Command::Command
//
// description :     constructors for abstract class Command
//
//--------------------------------------------------------------------------

Command::Command(const std::string &s, Tango::CmdArgType in, Tango::CmdArgType out, Tango::DispLevel level) :
    name(s),
    in_type(in),
    out_type(out),
    ext(new CommandExt),
    poll_period(0)
{
    cmd_disp_level = level;
    lower_name = name;
    std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
}

Command::Command(const std::string &s,
                 Tango::CmdArgType in,
                 Tango::CmdArgType out,
                 const std::string &in_desc,
                 const std::string &out_desc,
                 Tango::DispLevel level) :
    name(s),
    in_type(in),
    out_type(out),
    in_type_desc(in_desc),
    out_type_desc(out_desc),
    ext(new CommandExt),
    poll_period(0)
{
    cmd_disp_level = level;
    lower_name = name;
    std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
}

//+----------------------------------------------------------------------------
//
// method :         Command::extract()
//
// description :     Command extract methods. These are very simple methods
//            but overloaded many times for all Tango types.
//
//-----------------------------------------------------------------------------

void Command::throw_bad_type(const char *type)
{
    TangoSys_OMemStream o;

    o << "Incompatible command argument type, expected type is : Tango::" << type << std::ends;
    TANGO_THROW_EXCEPTION(API_IncompatibleCmdArgumentType, o.str());
}

void Command::extract(const CORBA::Any &in, Tango::DevBoolean &data)
{
    if(!(in >>= CORBA::Any::to_boolean(data)))
    {
        throw_bad_type("DevBoolean");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevShort &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevShort");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevLong &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevLong");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevLong64 &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevLong64");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevFloat &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevFloat");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevDouble &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevDouble");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevUShort &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevUShort");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevULong &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevULong");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevULong64 &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevULong64");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevString &data)
{
    if(!(in >>= const_cast<const char *&>(data)))
    {
        throw_bad_type("DevString");
    }
}

void Command::extract(const CORBA::Any &in, const char *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("ConstDevString");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarCharArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarCharArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarShortArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarShortArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarLongArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarLongArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarLong64Array *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarLong64Array");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarFloatArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarFloatArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarDoubleArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarDoubleArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarUShortArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarUShortArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarULongArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarULongArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarULong64Array *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarULong64Array");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarStringArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarStringArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarBooleanArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarBooleanArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarLongStringArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarLongStringArray");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevVarDoubleStringArray *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevVarDoubleStringArray");
    }
}

void Command::extract(const CORBA::Any &in, Tango::DevState &data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevState");
    }
}

void Command::extract(const CORBA::Any &in, const Tango::DevEncoded *&data)
{
    if(!(in >>= data))
    {
        throw_bad_type("DevEncoded");
    }
}

//+----------------------------------------------------------------------------
//
// method :         Command::insert()
//
// description :     Command insert methods. These are very simple methods
//            but overloaded many times for all Tango types.
//
//-----------------------------------------------------------------------------

void Command::alloc_any(CORBA::Any *&any_ptr)
{
    try
    {
        any_ptr = new CORBA::Any();
    }
    catch(std::bad_alloc &)
    {
        TANGO_THROW_EXCEPTION(API_MemoryAllocation, "Can't allocate memory in server");
    }
}

CORBA::Any *Command::insert()
{
    CORBA::Any *out_any;
    alloc_any(out_any);
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevBoolean data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);
    CORBA::Any::from_boolean tmp(data);

    (*out_any) <<= tmp;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevShort data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevLong data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevLong64 data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevFloat data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevDouble data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevUShort data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevULong data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevULong64 data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevString data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    delete[] data;

    return out_any;
}

CORBA::Any *Command::insert(const char *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarCharArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarCharArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarShortArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarShortArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarLongArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarLongArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarLong64Array &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarLong64Array *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarFloatArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarFloatArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarDoubleArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarDoubleArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarUShortArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarUShortArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarULongArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarULongArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarULong64Array &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarULong64Array *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarStringArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(DevVarBooleanArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= *data;
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(DevVarBooleanArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarStringArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarLongStringArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarLongStringArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarDoubleStringArray *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

CORBA::Any *Command::insert(Tango::DevVarDoubleStringArray &data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevState data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= data;
    return out_any;
}

CORBA::Any *Command::insert(Tango::DevEncoded *data)
{
    CORBA::Any *out_any;
    alloc_any(out_any);

    (*out_any) <<= (*data);
    delete data;

    return out_any;
}

} // namespace Tango
