// $Id: SACXmlParser.cpp,v 1.4 2003/03/16 14:51:00 fukasawa Exp $

//=============================================================================
/**
 *  @file    SACXmlParser.cpp
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-2003 BEE Co.,Ltd. All rights reserved.
 *
 * 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.
 *
 * 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; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
//=============================================================================

//
//  <configuration>
//    <devices>
//      <iodevice name="" id="" address="" devtype="">
//        <valattr type="valueAttr"></valattr>
//      </iodevice>
//    </devices>
//  </configuration>
//
//
//  <complexType name="valueAttr">
//    <sequence>
//      <init/>
//      <min/>
//      <max/>
//      <unit/>
//    </sequence>
//    <attribute name="format" type=xs:string"/>
//  </complexType>
//
//

#define BEE_BUILD_DLL

#include "SACXmlParser.h"
#include "JGPLCManager.h"
#include "PLCDeviceManager.h"


//-----------------------------------------------------------------------------
// Parse Devices element
//-----------------------------------------------------------------------------
class SACDevicesParser : public SACElementParser
{
public:
    SACDevicesParser() : SACElementParser(_TX("devices")) {}
    virtual ~SACDevicesParser() {}

    virtual int parseAttribute(JGDomParser * dom, string& nameStr,
                               string& valStr)
    {
        TRACE_FUNCTION(TRL_LOW, "SACDevicesParser::parseAttribute");
        SACXmlParser * parser = (SACXmlParser *)dom;
        if (nameStr == "idType")
        {
            if (valStr == "number")
                parser->m_idtype = ATOM_UINT4;
            else if (valStr == "ascii")
                parser->m_idtype = ATOM_ASCII;
            else
            {
                TRACE_ERROR(("Identifier Type is defined invalid value(%s).\n",
                             valStr.c_str()));
            }
            return BEE_SUCCESS;
        }
        return BEE_ERROR;
    }
};

//-----------------------------------------------------------------------------
// Parse I/O device element
//-----------------------------------------------------------------------------
class SACIODeviceParser : public SACElementParser
{
public:
    SACIODeviceParser() : SACElementParser(_TX("iodevice")) {}
    virtual ~SACIODeviceParser() {}

    virtual int begin(JGDomParser * dom)
    {
        SACXmlParser * parser = (SACXmlParser *)dom;
        parser->m_sac = new JGPLCDevice();
        return 0;
    }

    virtual int end(JGDomParser * dom)
    {
        SACXmlParser * parser = (SACXmlParser *)dom;
        ACE_UNUSED_ARG(parser);
        //
        // Entry PLC: parser->m_sac;
        //
        return 0;
    }

    virtual int parseAttribute(JGDomParser * dom, string& nameStr,
                               string& valStr)
    {
        TRACE_FUNCTION(TRL_LOW, "SACIODeviceParser::parseAttribute");

        SACXmlParser * parser = (SACXmlParser *)dom;
        JGPLCDevice * sac = parser->m_sac;

        if (nameStr == "name")
        {
            sac->name(valStr);
        }
        else if (nameStr == "id")
        {
            JGid devid;
            devid.set(valStr, parser->m_idtype);
            sac->id(devid);
        }
        else if (nameStr == "address")
        {
            parser->m_sac_mngr->rawio()->parseAddress(valStr, const_cast<PLCAccess&>(sac->access()));
        }
        else if (nameStr == "devtype")
        {
            if (valStr == "SENSOR")
                sac->devtype(JGPLCDevice::SENSOR);
            else if (valStr == "ACTUATOR")
                sac->devtype(JGPLCDevice::ACTUATOR);
            else if (valStr == "CONTROL")
                sac->devtype(JGPLCDevice::CONTROL);
            else
            {
                TRACE_ERROR(("%s: Invalid device type(%s).\n",
                         nameStr.c_str(), valStr.c_str()));
                sac->devtype(JGPLCDevice::SENSOR);
            }
        }
        else
        {
            TRACE_ERROR(("I/O device is defined invalid name(%s).\n",
                         nameStr.c_str()));
            // return BEE_ERROR;
        }
        return BEE_SUCCESS;
    }
};

//-----------------------------------------------------------------------------
// Parse value attribute element
//-----------------------------------------------------------------------------
class SACValueAttrParser : public SACElementParser
{
public:
    SACValueAttrParser() : SACElementParser(_TX("valattr")) {}
    virtual ~SACValueAttrParser() {}

    virtual int parseAttribute(JGDomParser * dom, string& nameStr,
                               string& valStr)
    {
        TRACE_FUNCTION(TRL_LOW, "SACValueAttrParser::parseAttribute");

        SACXmlParser * parser = (SACXmlParser *)dom;
        JGPLCDevice * sac = parser->m_sac;

        if (nameStr == "format")
        {
            if (valStr == "ascii" || valStr == "ASCII")
                sac->format(ATOM_ASCII);
            else if (valStr == "int1" || valStr == "INT1")
                sac->format(ATOM_INT1);
            else if (valStr == "int2" || valStr == "INT2")
                sac->format(ATOM_INT2);
            else if (valStr == "int4" || valStr == "INT4")
                sac->format(ATOM_INT4);
            else if (valStr == "int8" || valStr == "INT8")
                sac->format(ATOM_INT8);
            else if (valStr == "uint1" || valStr == "UINT1")
                sac->format(ATOM_UINT1);
            else if (valStr == "uint2" || valStr == "UINT2")
                sac->format(ATOM_UINT2);
            else if (valStr == "uint4" || valStr == "UINT4")
                sac->format(ATOM_UINT4);
            else if (valStr == "uint8" || valStr == "UINT8")
                sac->format(ATOM_UINT8);
            else if (valStr == "float4" || valStr == "FLOAT4")
                sac->format(ATOM_FLOAT4);
            else if (valStr == "float8" || valStr == "FLOAT8")
                sac->format(ATOM_FLOAT8);
            else if (valStr == "boolean" || valStr == "BOOLEAN")
                sac->format(ATOM_BOOLEAN);
            else if (valStr == "binary" || valStr == "BINARY")
                sac->format(ATOM_BINARY);
            else
            {
                TRACE_ERROR(("I/O device(%s) is defined invalid name(%s).\n",
                             sac->charName(), valStr.c_str()));
                // return BEE_ERROR;
                sac->format(ATOM_UINT2);
            }
            return BEE_SUCCESS;
        }
        TRACE_ERROR(("I/O device is defined invalid name(%s).\n",
                     nameStr.c_str()));
        return BEE_ERROR;
    }
};

//-----------------------------------------------------------------------------
class SACInitElmParser : public SACElementParser
{
public:
    SACInitElmParser() : SACElementParser(_TX("init"), _TX("valattr")) {}
    virtual ~SACInitElmParser() {}

    virtual int parseText(JGDomParser * dom, string& valStr)
    {
        SACXmlParser * parser = (SACXmlParser *)dom;
        JGPLCDevice * sac = parser->m_sac;
        sac->initval().set(valStr, sac->format());
        return BEE_SUCCESS;
    }
};

//-----------------------------------------------------------------------------
class SACMinElmParser : public SACElementParser
{
public:
    SACMinElmParser() : SACElementParser(_TX("min"), _TX("valattr")) {}
    virtual ~SACMinElmParser() {}

    virtual int parseText(JGDomParser * dom, string& valStr)
    {
        SACXmlParser * parser = (SACXmlParser *)dom;
        JGPLCDevice * sac = parser->m_sac;
        sac->minval().set(valStr, sac->format());
        return BEE_SUCCESS;
    }
};

//-----------------------------------------------------------------------------
class SACMaxElmParser : public SACElementParser
{
public:
    SACMaxElmParser() : SACElementParser(_TX("max"), _TX("valattr")) {}
    virtual ~SACMaxElmParser() {}

    virtual int parseText(JGDomParser * dom, string& valStr)
    {
        SACXmlParser * parser = (SACXmlParser *)dom;
        JGPLCDevice * sac = parser->m_sac;
        sac->maxval().set(valStr, sac->format());
        return BEE_SUCCESS;
    }
};

//-----------------------------------------------------------------------------
class SACUnitElmParser : public SACElementParser
{
public:
    SACUnitElmParser() : SACElementParser(_TX("unit"), _TX("valattr")) {}
    virtual ~SACUnitElmParser() {}

    virtual int parseText(JGDomParser * dom, string& valStr)
    {
        SACXmlParser * parser = (SACXmlParser *)dom;
        JGPLCDevice * sac = parser->m_sac;
        sac->unit(valStr);
        return BEE_SUCCESS;
    }
};

///////////////////////////////////////////////////////////////////////////////
//
// SAC Parser
//
//-----------------------------------------------------------------------------
// Initial parser
//-----------------------------------------------------------------------------
int SACXmlParser::init()
{
    TRACE_FUNCTION(TRL_LOW, "SACXmlParser::init");
    int result = 0;

    this->insert(new SACDevicesParser());
    this->insert(new SACIODeviceParser());
    this->insert(new SACValueAttrParser());
    this->insert(new SACInitElmParser());
    this->insert(new SACMinElmParser());
    this->insert(new SACMaxElmParser());
    this->insert(new SACUnitElmParser());

    return result;
}
