// $Id: JGObjectManager.cpp,v 1.12 2003/03/16 14:51:01 fukasawa Exp $

//=============================================================================
/**
 *  @file    JGObjectManager.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.
 */
//=============================================================================

#define BEE_BUILD_DLL

#include "JGObjectManager.h"
#include "JGSpecification.h"
#include "JGClass.h"
#include "JGObject.h"
#include "JGErrorList.h"
#include "JGAttrData.h"
#include "JGAttribute.h"
#include "JGObserver.h"
#include "JGService.h"
#include "JGVariable.h"
#include "BS2Message.h"
#include "BS2ListItem.h"
#include "BS2DeclAtoms.h"

static ObjManager * singleton_;

//-----------------------------------------------------------------------------
// Constructor/Destructor
//-----------------------------------------------------------------------------
JGObjectManager::JGObjectManager() : JGManager(CATEGORY_OBJECT)
{
    TRACE_FUNCTION(TRL_CONSTRUCT, "JGObjectManager::JGObjectManager");

}

//-----------------------------------------------------------------------------
JGObjectManager::~JGObjectManager()
{
    TRACE_FUNCTION(TRL_CONSTRUCT, "JGObjectManager::~JGObjectManager");

}

//-----------------------------------------------------------------------------
// Initialize
//-----------------------------------------------------------------------------
int JGObjectManager::init(void * parm)
{
    TRACE_FUNCTION(TRL_MIDDLE, "JGObjectManager::init");
    ACE_UNUSED_ARG(singleton_);
    ACE_UNUSED_ARG(parm);

    // initial equipment variables
    m_env = (JGSpecification *)ObjSpec::instance();

    return 0;
}

//-----------------------------------------------------------------------------
// Accept trigger from the variable.
//-----------------------------------------------------------------------------
int JGObjectManager::notify(const string& category, JGVariable * var,
                            void * arg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::notify");
    ACE_UNUSED_ARG(var);
    ACE_UNUSED_ARG(arg);

    // TRACE_ERROR((_TX("%s : %s = %s\n"), category.c_str(), var->charName(),
    //                                     var->getv().toString().c_str()));

    {
        TRACE_ERROR((_TX("Not implement: %s\n"), category.c_str()));
        return BEE_ERROR;
    }
    return BEE_SUCCESS;
}


//-----------------------------------------------------------------------------
// Find class by name(ObjType)
//-----------------------------------------------------------------------------
JGClass * JGObjectManager::find(const string& name) const
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::find");

    JGClass * result = (JGClass *)m_env->find(name);
    return result;
}

//-----------------------------------------------------------------------------
JGClass * JGObjectManager::findByUser(const string& name) const
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::findByUser");

    JGClass * result = (JGClass *)m_env->findByUserName(name);
    return result;
}

//-----------------------------------------------------------------------------
JGObject * JGObjectManager::findObject(const string& name) const
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::findObject");

    JGObject * result = m_env->findObject(name);
    return result;
}

//-----------------------------------------------------------------------------
// Add new class
//-----------------------------------------------------------------------------
int JGObjectManager::add(JGClass * cls)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::add");

    m_env->add(cls);

    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Entry new object
//-----------------------------------------------------------------------------
int JGObjectManager::addObject(JGObject * obj)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::addObject");

    m_env->addObject(obj);

    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Remove object
//-----------------------------------------------------------------------------
int JGObjectManager::remove(JGObject * obj)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::remove");

    m_env->remove(obj);

    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Get objects
//-----------------------------------------------------------------------------
int JGObjectManager::getAllClasses(vector<JGClass *>& clazzes)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::getAllClasses");

    return m_env->getAllClasses(clazzes);
}

//-----------------------------------------------------------------------------
int JGObjectManager::getAllObjects(vector<JGObject *>& objs)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::getAllObjects");

    return m_env->getAllObjects(objs);
}

//-----------------------------------------------------------------------------
// Parse request attributes of objects
//-----------------------------------------------------------------------------
class GetAttrParam : public BS2Traverser
{
public:
    GetAttrParam(JGSpecification * spec, int sf) : BS2Traverser(),
                                                    m_env(spec), m_sf(sf) {}
    virtual ~GetAttrParam() {}

    JGSpecification * m_env;
    int    m_sf;
    string m_objspec;
    string m_objtype;
    JGClass * m_clazz;
    vector<JGid> m_objids;
    vector<JGAttrFilter> m_filter;          // query id in S14F1
    vector<JGid> m_attrids;                 // request id in S14F1
    JGErrorList  m_errlist;

    virtual int parseItem(BS2Item * item) {
        TRACE_FUNCTION(TRL_LOW, "JGObjectManager::GetAttrParam::parseItem");
        BS2Atom * atom = item->atom();
        if (item->name() == _TX("ATTRID"))
        {
            if (this->nest() == 3)        // objects qualifiers to match
            {
                JGAttrFilter filter;
                atom->get(filter.m_attrid);
                m_filter.push_back(filter);
            }
            else
            {                             // attributes request
                JGid attrid;
                atom->get(attrid);
                m_attrids.push_back(attrid);
            }
        }
        else if (item->name() == _TX("ATTRDATA"))
        {
            m_filter.back().m_attrdata = *atom;
        }
        else if (item->name() == _TX("OBJSPEC"))
        {
            if (! atom->isAscii())
            {
                TRACE_ERROR(("Unexpect OBJSPEC format\n"));
                m_objspec = atom->getValue().toString();
                m_errlist.append(ERRCODE_INVALID_PARAMETER, m_objspec);
                return -1;
            }
            m_objspec = ((BS2Ascii *)atom)->value();
            if (m_objspec.size() > 0 && m_env->name() != m_objspec)
            {
                TRACE_ERROR((_TX("Unexpect OBJSPEC(%s / %s)\n"),
                             m_objspec.c_str(), m_env->name().c_str()));
                m_errlist.append(ERRCODE_INVALID_PARAMETER, m_objspec);
                return -1;
            }
        }
        else if (item->name() == _TX("OBJTYPE"))
        {
            if (! atom->isAscii())
            {
                TRACE_ERROR(("Unexpect OBJTYPE format\n"));
                m_errlist.append(ERRCODE_INVALID_PARAMETER, m_objtype);
                return -1;
            }
            m_objtype = ((BS2Ascii *)atom)->value();
            m_clazz = m_env->find(m_objtype);
            if (m_clazz == NULL)
            {
                m_env->dump();

                TRACE_ERROR((_TX("Unknown OBJTYPE(%s)\n"), m_objtype.c_str()));
                m_errlist.append(ERRCODE_UNKNOWN_OBJECT, m_objtype);
                return BEE_ERROR;
            }
        }
        else if (item->name() == _TX("OBJID"))
        {
            JGid objid;
            atom->get(objid);
            m_objids.push_back(objid);
        }

        if (item->name() == _TX("ATTRRELN"))
        {
            if (! atom->isUInt1())
            {
                TRACE_ERROR(("Unexpect ATTRRELN format\n"));
                m_errlist.append(ERRCODE_INVALID_PARAMETER);
                return -1;
            }
            int reln = ((BS2UInt1 *)atom)->value();
            m_filter.back().m_attrreln = reln;
        }
        // * For same item name, in this case is decided by nest position
        // else if (item->name() == _TX("ATTRID_REQ"))
        // {
        //     JGid attrid(*atom);
        //     m_attrids.push_back(attrid);
        // }
        return 0;
    }

    //-----------------------------------------------------------------------------
    int getObjects(JGSpecification * objspec, vector<JGObject *>& objects)
    {
        TRACE_FUNCTION(TRL_LOW, "JGObjectManager::GetAttrParam::getObjects");
        ACE_UNUSED_ARG(objspec);
        size_t i;

        // Check ATTRID of responce
        if (m_sf == SFCODE(14,3))
        {   // pickup attribute identifier for responce
            for (i = 0; i < m_filter.size(); i++)
            {
                m_attrids.push_back(m_filter[i].m_attrid);
            }
        }

        for (i = 0; i < m_attrids.size(); i++)
        {
            string attrid;
            m_attrids[i].get(attrid);
            if (m_clazz->find(attrid) == NULL)
            {
                m_errlist.append(ERRCODE_UNKNOWN_ATTRIBUTE, attrid);
            }
        }

        // Search Object Identifiers
        JGObject * obj;
        for (i = 0; i < m_objids.size(); i++)
        {
            string objid;
            m_objids[i].get(objid);
            obj = m_env->findObject(objid);
            if (obj == NULL)
            {
                m_errlist.append(ERRCODE_UNKNOWN_OBJECT_INSTANCE, objid);
            }
            else
            {
                objects.push_back(obj);
            }
        }
        if (m_objids.size() > 0 && objects.size() == 0)
        {   // request object is nothing
            m_errlist.append(ERRCODE_UNKNOWN_OBJECT_INSTANCE);
            return BEE_ERROR;
        }
        else if (m_objids.size() == 0)
        {
            if (m_clazz->getAllObjects(objects) == 0)
            {       // Instance is nothing
                m_errlist.append(ERRCODE_UNKNOWN_OBJECT_INSTANCE);
                return BEE_ERROR;
            }
        }
        return BEE_SUCCESS;
    }
};


//-----------------------------------------------------------------------------
// Parse message : GetAttr Request (S14F1)
//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::reqGetAttr(BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::reqGetAttr");

    int    result;
    size_t i;
    BS2ListItem * objlist = new BS2ListItem;
    BS2ListItem * rootlist = new BS2ListItem;
    JGObject * obj;
    vector<JGObject *> objects;
    vector<JGObject *> find_objects;
    BS2Message * replymsg = BS2Message::response(msg);
    replymsg->add(rootlist);
    rootlist->add(objlist);

    GetAttrParam gap(m_env, SFCODE(14,1));
    gap.m_errlist.set(_TX("OBJACK"), ATOM_UINT1);

    // Parse S14F1
    result = msg->traverse(&gap);
    if ((result < 0) && (gap.m_errlist.count() > 0))
    {
        rootlist->add(gap.m_errlist.makeItem());
        return replymsg;
    }

    result = gap.getObjects(m_env, objects);
    if (result < 0)
    {
        rootlist->add(gap.m_errlist.makeItem());
        return replymsg;
    }

    // Retrieve Objects with Filter
    for (i = 0; i < objects.size(); i++)
    {
        obj = objects[i];
        // check attribute value
        int ret = obj->relation(gap.m_filter, gap.m_errlist);
        if (ret == 0)
        {
            find_objects.push_back(obj);
        }
        else if (ret < 0)
        {
            rootlist->add(gap.m_errlist.makeItem());
            return replymsg;
        }
        else /* if (ret > 0) */
        {
            ;  // ignore this object
        }
    }

    if (find_objects.size() == 0)
    {   // Request object is not found
        gap.m_errlist.append(ERRCODE_UNKNOWN_OBJECT_INSTANCE);
        rootlist->add(gap.m_errlist.makeItem());
        return replymsg;
    }

    // Create reply attributes of object
    for (i = 0; i < find_objects.size(); i++)
    {
        obj = find_objects[i];
        BS2Item * objdata = obj->makeIDandAttrList(gap.m_attrids);
        objlist->add(objdata);
    }

    rootlist->add(gap.m_errlist.makeItem());
    return replymsg;
}


//-----------------------------------------------------------------------------
// Parse message : SetAttr Request (S14F3)
//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::reqSetAttr(BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::reqSetAttr");

    int result;
    size_t i;
    BS2ListItem * objlist = new BS2ListItem;
    BS2ListItem * rootlist = new BS2ListItem;
    JGObject * obj;
    vector<JGObject *> objects;
    BS2Message * reply = BS2Message::response(msg);
    reply->add(rootlist);
    rootlist->add(objlist);

    GetAttrParam gap(m_env, SFCODE(14,3));
    gap.m_errlist.set(_TX("OBJACK"), ATOM_UINT1);

    // Parse S14F3
    result = msg->traverse(&gap);
    if ((result < 0) && (gap.m_errlist.count() > 0))
    {
        rootlist->add(gap.m_errlist.makeItem());
        return reply;
    }

    result = gap.getObjects(m_env, objects);
    if (result < 0)
    {
        rootlist->add(gap.m_errlist.makeItem());
        return reply;
    }

    // Set Attributes in Objects
    for (i = 0; i < objects.size(); i++)
    {
        obj = objects[i];
        // update attribute value
        int ret = obj->set(gap.m_filter, gap.m_errlist);
        if (ret < 0)
        {
            rootlist->add(gap.m_errlist.makeItem());
            return reply;
        }
    }

    // Make responce attributes of objects
    for (i = 0; i < objects.size(); i++)
    {
        obj = objects[i];
        // make message item of the object
        BS2Item * objdata = obj->makeIDandAttrList(gap.m_attrids);
        objlist->add(objdata);
    }

    rootlist->add(gap.m_errlist.makeItem());
    return reply;
}

//-----------------------------------------------------------------------------
// Parse message : GetType Request (S14F5)
//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::reqGetType(BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::reqGetType");

    BS2ListItem * rootlist = new BS2ListItem;
    BS2ListItem * objlist = new BS2ListItem;
    JGErrorList errlist(_TX("OBJACK"), ATOM_UINT1);
    vector<JGObject *> objects;
    BS2Message * reply = BS2Message::response(msg);
    reply->add(rootlist);
    rootlist->add(objlist);

    BS2Atom * atom = msg->getAtom(_TX("OBJSPEC"));
    if (atom == NULL)
    {
        errlist.append(ERRCODE_UNKNOWN_OBJECT);
        rootlist->add(errlist.makeItem());
        return reply;
    }

    // Get object type name in class
    m_env->getObjTypes(objlist);

    rootlist->add(errlist.makeItem());
    return reply;
}

//-----------------------------------------------------------------------------
// Parse message : GetAttrName Request (S14F7)
//-----------------------------------------------------------------------------
class GetAttrNameParam : public BS2Traverser
{
public:
    GetAttrNameParam() : BS2Traverser() {}
    virtual ~GetAttrNameParam() {}

    string m_objspec;
    string m_objtype;
    vector<string> m_objtypes;

    virtual int parseItem(BS2Item * item) {
        TRACE_FUNCTION(TRL_LOW, "JGObjectManager::GetAttrNameParam::parseItem");
        BS2Atom * atom = item->atom();
        if (item->name() == _TX("OBJTYPE"))
        {
            if (! atom->isAscii())
            {
                TRACE_ERROR((_TX("Unexpect OBJTYPE format\n")));
                return -1;
            }
            m_objtypes.push_back(((BS2Ascii *)atom)->value());
        }
        else if (item->name() == _TX("OBJSPEC"))
        {
            if (! atom->isAscii())
            {
                TRACE_ERROR((_TX("Unexpect OBJSPEC format\n")));
                return -1;
            }
            m_objspec = ((BS2Ascii *)atom)->value();
        }
        return 0;
    }
};


//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::reqGetAttrName(BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::reqGetAttrName");
    size_t i;
    BS2ListItem * typelist = new BS2ListItem;
    BS2ListItem * rootlist = new BS2ListItem;
    JGErrorList errlist(_TX("OBJACK"), ATOM_UINT1);
    vector<JGClass *> classes;
    BS2Message * reply = BS2Message::response(msg);
    reply->add(rootlist);
    rootlist->add(typelist);

    GetAttrNameParam ganp;
    int result = msg->traverse(&ganp);
    if (result < 0)
    {
        errlist.append(ERRCODE_UNKNOWN_OBJECT);
        rootlist->add(errlist.makeItem());
        return reply;
    }

    // Get class by objtype
    JGClass * cur_class;
    if (ganp.m_objtypes.size() == 0)
    {
        m_env->getAllClasses(classes);
    }
    else
    {
        for (i = 0; i < ganp.m_objtypes.size() ; i++)
        {
            string objtype = ganp.m_objtypes[i];
            cur_class = m_env->find(objtype);
            if (cur_class != NULL)
            {
                classes.push_back(cur_class);
            }
            else
            {
                errlist.append(ERRCODE_UNKNOWN_OBJTYPE, objtype);
            }
        }
    }

    // Get object type name in class
    for (i = 0; i < classes.size(); i++)
    {
        BS2Item * item = classes[i]->getAttrName();
        typelist->add(item);
    }

    rootlist->add(errlist.makeItem());
    return reply;
}

//-----------------------------------------------------------------------------
// Parse message : Create Object Request (S14F9)
//-----------------------------------------------------------------------------
class ObjectParam : public BS2Traverser
{
public:
    ObjectParam(JGSpecification * spec) : BS2Traverser(), m_env(spec) {}
    virtual ~ObjectParam() {}

    JGSpecification * m_env;
    string m_objspec;
    string m_objtype;
    JGClass * m_clazz;
    vector<JGAttrFilter> m_filter;    // attrid & attrdata
    JGErrorList  m_errlist;

    virtual int parseItem(BS2Item * item) {
        TRACE_FUNCTION(TRL_LOW, "JGObjectManager::CreateObjectParam::parseItem");
        BS2Atom * atom = item->atom();
        if (item->name() == _TX("ATTRID"))
        {
            JGAttrFilter filter;
            atom->get(filter.m_attrid);
            m_filter.push_back(filter);
        }
        else if (item->name() == _TX("ATTRDATA"))
        {
             atom->get(m_filter.back().m_attrdata);
        }
        else if (item->name() == _TX("OBJSPEC"))
        {
            if (! atom->isAscii())
            {
                TRACE_ERROR((_TX("Unexpect OBJSPEC format\n")));
                m_objspec = atom->getValue().toString();
                m_errlist.append(ERRCODE_INVALID_PARAMETER, m_objspec);
                return -1;
            }
            m_objspec = ((BS2Ascii *)atom)->value();
        }
        else if (item->name() == _TX("OBJTYPE"))
        {
            if (! atom->isAscii())
            {
                TRACE_ERROR((_TX("Unexpect OBJTYPE format\n")));
                return -1;
            }
            m_objtype = ((BS2Ascii *)atom)->value();
            m_clazz = m_env->find(m_objtype);
            if (m_clazz == NULL)
            {
                TRACE_ERROR(("Unknown OBJTYPE\n"));
                m_errlist.append(ERRCODE_UNKNOWN_OBJECT, m_objtype);
                return BEE_ERROR;
            }
        }
        return 0;
    }
};

//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::reqCreateObj(BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::reqCreateObj");

    int result;
    BS2ListItem * rootlist = new BS2ListItem;
    BS2Message * reply = BS2Message::response(msg);
    reply->add(rootlist);

    ObjectParam op(m_env);
    op.m_errlist.set(_TX("OBJACK"), ATOM_UINT1);
    result = msg->traverse(&op);
    if (result < 0)
    {
        rootlist->add(BS2Item::factory(_TX("OBJSPEC"),
                                       new BS2Ascii(op.m_objspec)));
        rootlist->add(new BS2ListItem());
        rootlist->add(op.m_errlist.makeItem());
        return reply;
    }

    // Set Attributes in Object
    JGObject * obj = reinterpret_cast<JGObject *>(op.m_clazz->instance(op.m_objspec));
    int ret = obj->set(op.m_filter, op.m_errlist);
    if (ret < 0)
    {
        rootlist->add(BS2Item::factory(_TX("OBJSPEC"),
                                       new BS2Ascii(op.m_objspec)));
        rootlist->add(new BS2ListItem());
        rootlist->add(op.m_errlist.makeItem());
        return reply;
    }

    // Make responce attributes of object (All Attributes)
    BS2Item * objspec = obj->makeObjSpec();
    rootlist->add(objspec);
    vector<JGid> attrids;
    for (size_t i = 0; i < op.m_filter.size(); i++)
    {
        attrids.push_back(op.m_filter[i].m_attrid);
    }
    BS2Item * objdata = obj->makeAttrList(attrids);
    rootlist->add(objdata);

    rootlist->add(op.m_errlist.makeItem());
    return reply;
}

//-----------------------------------------------------------------------------
// Parse message : Delete Object Request (S14F11)
//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::reqDeleteObj(BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGObjectManager::reqDeleteObj");

    int result;
    BS2ListItem * rootlist = new BS2ListItem;
    JGClass *  objtype;
    BS2Message * reply = BS2Message::response(msg);
    reply->add(rootlist);

    ObjectParam op(m_env);
    op.m_errlist.set(_TX("OBJACK"), ATOM_UINT1);
    result = msg->traverse(&op);
    if (result < 0)
    {
        rootlist->add(new BS2ListItem());
        rootlist->add(op.m_errlist.makeItem());
        return reply;
    }

    // Find Object
    JGObject * obj = m_env->findObject(op.m_objspec);
    if (obj == NULL)
    {
        rootlist->add(new BS2ListItem);
        op.m_errlist.append(ERRCODE_UNKNOWN_OBJECT_INSTANCE, op.m_objspec);
        rootlist->add(op.m_errlist.makeItem());
        return reply;
    }
    objtype = obj->getObjType();

    if (op.m_filter.size() > 0)
    {
        int ret = obj->relation(op.m_filter, op.m_errlist);
        if (ret != 0)
        {
            rootlist->add(new BS2ListItem);
            op.m_errlist.append(ERRCODE_INVALID_VALUE, op.m_objspec);
            rootlist->add(op.m_errlist.makeItem());
            return reply;
        }
    }

    // Make responce attributes of object (All Attributes)
    vector<JGid> attrids;
    for (size_t i = 0; i < op.m_filter.size(); i++)
    {
        attrids.push_back(op.m_filter[i].m_attrid);
    }
    BS2Item * objdata = obj->makeAttrList(attrids);
    rootlist->add(objdata);

    delete obj;           // Delete object (remove from class)

    //
    // Notify changed contents
    //
    JGService * ost = new JGService(_TX("Delete"));
    JGvalue specval(op.m_objspec);
    ost->add(_TX("ObjSpec"), specval);
    m_observer->notify(ost);
    //

    rootlist->add(op.m_errlist.makeItem());
    return reply;
}

//-----------------------------------------------------------------------------
// Thread of received trigger event.
//-----------------------------------------------------------------------------
BS2Message * JGObjectManager::msg_svc(JGMessageTrigger * trigger,
                                      BS2Message * msg)
{
    ACE_UNUSED_ARG(trigger);
    BS2Message * replymsg = NULL;

    if (msg->sf() == SFCODE(14,1))
    {
        replymsg = this->reqGetAttr(msg);
    }
    else if (msg->sf() == SFCODE(14,3))
    {
        replymsg = this->reqSetAttr(msg);
    }
    else if (msg->sf() == SFCODE(14,5))
    {
        replymsg = this->reqGetType(msg);
    }
    else if (msg->sf() == SFCODE(14,7))
    {
        replymsg = this->reqGetAttrName(msg);
    }
    else if (msg->sf() == SFCODE(14,9))
    {
        replymsg = this->reqCreateObj(msg);
    }
    else if (msg->sf() == SFCODE(14,11))
    {
        replymsg = this->reqDeleteObj(msg);
    }
    else
    {   // Unexpected message
        replymsg = this->unrecognized(msg);
    }
    return replymsg;
}


