2010-05-06 00:08:41 +00:00
<?xml version="1.0"?>
< xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" >
< xsl:output method = "text" indent = "no" / >
<!-- Output : can be 'header', 'cpp' or 'php' -->
< xsl:param name = "output" select = "'header'" / >
< xsl:param name = "filename" / >
<!-- A special template applyer that is mode aware -->
< xsl:template name = "myApplyTemplate" > < xsl:choose > < xsl:when test = "$output = 'header'" > < xsl:apply-templates mode = "header" / > < / xsl:when > < xsl:when test = "$output = 'cpp'" > < xsl:apply-templates mode = "cpp" / > < / xsl:when > < xsl:when test = "$output = 'php'" > < xsl:apply-templates mode = "php" / > < / xsl:when > < / xsl:choose > < / xsl:template >
<!-- some stupide template to remove unwanted text from output -->
< xsl:template match = "text()" mode = "php" / >
< xsl:template match = "text()" mode = "cpp" / >
< xsl:template match = "text()" mode = "header" / >
<!-- ######################################################### -->
<!-- ##### Root template matcher ####### -->
<!-- ######################################################### -->
< xsl:template match = "generator" >
< xsl:if test = "$output != 'php'" >
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
< / xsl:if >
< xsl:if test = "$output = 'header'" >
#ifndef < xsl:value-of select = "@header_tag" / >
#define < xsl:value-of select = "@header_tag" / >
#include "nel/misc/types_nl.h"
2014-09-07 06:53:10 +00:00
#include < memory>
2010-05-06 00:08:41 +00:00
#include "nel/misc/hierarchical_timer.h"
#include "nel/misc/string_conversion.h"
#include "nel/net/message.h"
#include "nel/net/module.h"
#include "nel/net/module_builder_parts.h"
#include "nel/net/module_message.h"
#include "nel/net/module_gateway.h"
< xsl:if test = "//callback_interface" >
<!-- #include "nel/net/callback_server.h"
#include "nel/net/callback_client.h"-->
#include "game_share/callback_adaptor.h"
< / xsl:if >
< xsl:if test = "//class/database" >
#include "nel/misc/string_common.h"
2014-09-07 06:53:10 +00:00
#include "server_share/mysql_wrapper.h"
2010-05-06 00:08:41 +00:00
< / xsl:if >
< xsl:if test = "//class/message" >
#include "game_share/synchronised_message.h"
< / xsl:if >
< / xsl:if >
<!-- <xsl:if test="$output = 'cpp'">
< xsl:apply-templates select = "cpp-include" / >
#include "< xsl:value-of select = "$filename" / > .h"
< / xsl:if > -->
< xsl:call-template name = "myApplyTemplate" / >
< xsl:if test = "$output = 'header'" >
#endif
< / xsl:if >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Namespace specification ####### -->
<!-- ######################################################### -->
< xsl:template match = "namespace" mode = "header" >
<!-- #ifndef NLNET_INTERFACE_GET_MODULE
# define NLNET_INTERFACE_GET_MODULE NLNET::IModule *getModuleInstance() { return this; }
#endif
-->
namespace < xsl:value-of select = "@name" / >
{
<!-- forward declaration of class -->
< xsl:for-each select = "class" >
class < xsl:value-of select = "@name" / > ;
< xsl:if test = "database" >
class < xsl:value-of select = "@name" / > Ptr;< / xsl:if > < / xsl:for-each >
< xsl:text >
< / xsl:text >
<!-- declaration of smart ptr class -->
< xsl:for-each select = "class" >
< xsl:if test = "database" >
< xsl:call-template name = "makePersistentPtrHeader" >
< xsl:with-param name = "className" select = "@name" / >
< / xsl:call-template >
< xsl:text >
< / xsl:text >
< / xsl:if >
< / xsl:for-each >
< xsl:call-template name = "myApplyTemplate" / >
}
< / xsl:template >
<!-- _______________________________________ -->
< xsl:template match = "namespace" mode = "cpp" >
#include "< xsl:value-of select = "$filename" / > .h"
namespace < xsl:value-of select = "@name" / >
{
< xsl:call-template name = "myApplyTemplate" / >
}
< / xsl:template >
<!-- _______________________________________ -->
< xsl:template match = "namespace" mode = "php" > < xsl:apply-templates mode = "php" / > < / xsl:template >
<!-- ######################################################### -->
<!-- ##### Additionnal includes ####### -->
<!-- ######################################################### -->
< xsl:template match = "include" mode = "header" >
#include "< xsl:value-of select = "@file" / > "
< / xsl:template >
< xsl:template match = "sys-include" mode = "header" >
#include < < xsl:value-of select = "@file" / > >
< / xsl:template >
< xsl:template match = "cpp-include" mode = "cpp" >
#include "< xsl:value-of select = "@file" / > "
< / xsl:template >
< xsl:template match = "php-include" mode = "php" >
< xsl:text > < ?php
require_once('< / xsl:text > < xsl:value-of select = "@file" / > < xsl:text > ');
?>
< / xsl:text >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Verbatim code ####### -->
<!-- ######################################################### -->
< xsl:template match = "verbatim_header" mode = "header" >
< xsl:value-of select = "." / >
< / xsl:template >
<!-- ################################################################## -->
<!-- ##### Generate a module interface classes (Header Part)#### -->
<!-- ################################################################## -->
< xsl:template match = "module_interface" mode = "header" >
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
class < xsl:value-of select = "@name" / > Skel
{
public:
/// the interceptor type
typedef NLNET::CInterceptorForwarder < < xsl:value-of select = "@name" / > Skel> TInterceptor;
protected:
< xsl:value-of select = "@name" / > Skel()
{
// do early run time check for message table
getMessageHandlers();
}
virtual ~< xsl:value-of select = "@name" / > Skel()
{
}
void init(NLNET::IModule *module)
{
_Interceptor.init(this, module);
}
<!-- If the interface contains two - way invocation methods, we need a virtual to retreive the module instance -->
< xsl:if test = "method/return" >
public:
<!-- // Virtual to retreive the instance of the implementation module
// Use the macro NLNET_INTERFACE_GET_MODULE to simply declare the implementation in your module
virtual NLNET::IModule *getModuleInstance() =0;
-->
< / xsl:if >
// unused interceptors
std::string fwdBuildModuleManifest() const { return std::string(); }
2010-08-28 13:02:00 +00:00
void fwdOnModuleUp(NLNET::IModuleProxy *moduleProxy) {}
void fwdOnModuleDown(NLNET::IModuleProxy *moduleProxy) {}
void fwdOnModuleSecurityChange(NLNET::IModuleProxy *moduleProxy) {}
2010-05-06 00:08:41 +00:00
// process module message interceptor
bool fwdOnProcessModuleMessage(NLNET::IModuleProxy *sender, const NLNET::CMessage & message);
private:
typedef void (< xsl:value-of select = "@name" / > Skel::*TMessageHandler)(NLNET::IModuleProxy *sender, const NLNET::CMessage & message);
typedef std::map< std::string, TMessageHandler> TMessageHandlerMap;
const TMessageHandlerMap & getMessageHandlers() const;
< xsl:for-each select = "method" >
< xsl:choose >
< xsl:when test = "not(return)" >
void < xsl:value-of select = "@name" / > _skel(NLNET::IModuleProxy *sender, const NLNET::CMessage & __message);
< / xsl:when >
< xsl:when test = "return" >
void < xsl:value-of select = "@name" / > _skel(NLNET::IModuleProxy *sender, const NLNET::CMessage & __message);
< / xsl:when >
< / xsl:choose >
< / xsl:for-each >
< xsl:text >
< / xsl:text > // declare one interceptor member of the skeleton
TInterceptor _Interceptor;
// declare the interceptor forwarder as friend of this class
friend class NLNET::CInterceptorForwarder < < xsl:value-of select = "@name" / > Skel> ;
< xsl:text > public:
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
< / xsl:text >
< xsl:for-each select = "method" >
< xsl:choose >
< xsl:when test = "not(return)" >
< xsl:call-template name = "makeMethodDoc" / >
< xsl:text > < / xsl:text > virtual void < xsl:value-of select = "@name" / > (NLNET::IModuleProxy *sender< xsl:call-template name = "makeParamList" / > )< xsl:text > =0;
< / xsl:text >
< / xsl:when >
< xsl:when test = "return" >
< xsl:call-template name = "makeMethodDoc" / >
< xsl:text > < / xsl:text > virtual < xsl:value-of select = "return/@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > (NLNET::IModuleProxy *sender< xsl:call-template name = "makeParamList" / > )< xsl:text > =0;
< / xsl:text >
< / xsl:when >
< / xsl:choose >
< / xsl:for-each >
};
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
< xsl:text > < / xsl:text > class < xsl:value-of select = "@name" / > Proxy
{
/// Smart pointer on the module proxy
NLNET::TModuleProxyPtr _ModuleProxy;
// Pointer on the local module that implement the interface (if the proxy is for a local module)
NLNET::TModulePtr _LocalModule;
// Direct pointer on the server implementation interface for collocated module
< xsl:value-of select = "@name" / > Skel *_LocalModuleSkel;
public:
< xsl:value-of select = "@name" / > Proxy(NLNET::IModuleProxy *proxy)
{
< xsl:if test = "@module_class" > nlassert(proxy->getModuleClassName() == < xsl:value-of select = "@module_class" / > );< / xsl:if >
_ModuleProxy = proxy;
// initialize collocated servant interface
if (proxy->getModuleDistance() == 0)
{
_LocalModule = proxy->getLocalModule();
nlassert(_LocalModule != NULL);
< xsl:value-of select = "@name" / > Skel::TInterceptor *interceptor = NULL;
interceptor = static_cast < NLNET::CModuleBase* > (_LocalModule.getPtr())->getInterceptor(interceptor);
nlassert(interceptor != NULL);
_LocalModuleSkel = interceptor->getParent();
nlassert(_LocalModuleSkel != NULL);
}
else
_LocalModuleSkel = 0;
}
virtual ~< xsl:value-of select = "@name" / > Proxy()
{
}
NLNET::IModuleProxy *getModuleProxy()
{
return _ModuleProxy;
}
< xsl:for-each select = "method" >
< xsl:call-template name = "makeMethodDoc" / >
< xsl:choose >
< xsl:when test = "not(return)" >
< xsl:text > < / xsl:text > void < xsl:value-of select = "@name" / > (NLNET::IModule *sender< xsl:call-template name = "makeParamList" / > );
< / xsl:when >
< xsl:when test = "return" >
< xsl:text > < / xsl:text > < xsl:value-of select = "return/@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > (NLNET::IModule *sender< xsl:call-template name = "makeParamList" / > );
< / xsl:when >
< / xsl:choose >
< / xsl:for-each >
< xsl:for-each select = "method[@broadcast = 'true']" >
< xsl:call-template name = "makeMethodDoc" / >
< xsl:text >
// This is the broadcast version of the method.
template < class ProxyIterator >
< / xsl:text > static void broadcast_< xsl:value-of select = "@name" / > (ProxyIterator first, ProxyIterator last, NLNET::IModule *sender< xsl:call-template name = "makeParamList" / > )
{
NLNET::CMessage message;
// create the message to send to multiple dest
buildMessageFor_< xsl:value-of select = "@name" / > (message < xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
for (; first != last; ++first)
{
NLNET::IModuleProxy *proxy = *first;
proxy->sendModuleMessage(sender, message);
}
}< xsl:text >
< / xsl:text >
< / xsl:for-each >
< xsl:for-each select = "method" >
< xsl:text >
// Message serializer. Return the message received in reference for easier integration
static const NLNET::CMessage & buildMessageFor_< / xsl:text > < xsl:value-of select = "@name" / > (NLNET::CMessage & __message< xsl:call-template name = "makeParamList" / > );
< / xsl:for-each >
};< xsl:text >
< / xsl:text >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Generate module interface, cpp part ####### -->
<!-- ######################################################### -->
< xsl:template match = "module_interface" mode = "cpp" >
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
< xsl:variable name = "skelName" select = "concat(@name, 'Skel')" / >
< xsl:variable name = "proxyName" select = "concat(@name, 'Proxy')" / >
const < xsl:value-of select = "$skelName" / > ::TMessageHandlerMap & < xsl:value-of select = "$skelName" / > ::getMessageHandlers() const
{
static TMessageHandlerMap handlers;
static bool init = false;
if (!init)
{
std::pair < TMessageHandlerMap::iterator, bool > res;
< xsl:for-each select = "method" >
res = handlers.insert(std::make_pair(std::string("< xsl:value-of select = "@msg" / > "), & < xsl:value-of select = "$skelName" / > ::< xsl:value-of select = "@name" / > _skel));
// if this assert, you have a doubly message name in your interface definition !
nlassert(res.second);
< / xsl:for-each >
init = true;
}
return handlers;
}
bool < xsl:value-of select = "@name" / > Skel::fwdOnProcessModuleMessage(NLNET::IModuleProxy *sender, const NLNET::CMessage & message)
{
const TMessageHandlerMap & mh = getMessageHandlers();
TMessageHandlerMap::const_iterator it(mh.find(message.getName()));
if (it == mh.end())
{
return false;
}
TMessageHandler cmd = it->second;
(this->*cmd)(sender, message);
return true;
}
< xsl:for-each select = "method" >
< xsl:choose >
< xsl:when test = "not(return)" >
void < xsl:value-of select = "$skelName" / > ::< xsl:value-of select = "@name" / > _skel(NLNET::IModuleProxy *sender, const NLNET::CMessage & __message)
{
H_AUTO(< xsl:value-of select = "$skelName" / > _< xsl:value-of select = "@name" / > _< xsl:value-of select = "@msg" / > );
< xsl:for-each select = "param" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ;< xsl:text >
< / xsl:text >
< xsl:call-template name = "serialRead" > < xsl:with-param name = "message" select = "'__message'" / > < / xsl:call-template >
< / xsl:for-each >
< xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > (sender< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );< xsl:text >
< / xsl:text >
< xsl:text > }
< / xsl:text >
< / xsl:when >
< xsl:when test = "return" >
void < xsl:value-of select = "$skelName" / > ::< xsl:value-of select = "@name" / > _skel(NLNET::IModuleProxy *sender, const NLNET::CMessage & __message)
{
H_AUTO(< xsl:value-of select = "$skelName" / > _< xsl:value-of select = "@name" / > _< xsl:value-of select = "@msg" / > );
< xsl:for-each select = "param" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ;< xsl:text >
< / xsl:text >
< xsl:call-template name = "serialRead" > < xsl:with-param name = "message" select = "'__message'" / > < / xsl:call-template >
< / xsl:for-each >
< xsl:text > < / xsl:text > < xsl:value-of select = "return/@type" / > __ret = < xsl:value-of select = "@name" / > (sender< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
// encode the return message
NLNET::CMessage __retMsg;
__retMsg.setType("R_< xsl:value-of select = "@msg" / > ", NLNET::CMessage::Response);
nlWrite(__retMsg, serial< xsl:value-of select = "return/@serial" / > , __ret);
// and send back the response
sender->sendModuleMessage(static_cast< NLNET::IModule*> (_Interceptor.getRegistrar()), __retMsg);
< xsl:text >
< / xsl:text >
< xsl:text > }
< / xsl:text >
< / xsl:when >
< / xsl:choose >
< / xsl:for-each >
< xsl:for-each select = "method" >
< xsl:call-template name = "makeMethodDoc" / >
< xsl:choose >
< xsl:when test = "not(return)" >
< xsl:text > < / xsl:text > void < xsl:value-of select = "$proxyName" / > ::< xsl:value-of select = "@name" / > (NLNET::IModule *sender< xsl:call-template name = "makeParamList" / > )
{
if (_LocalModuleSkel & & _LocalModule->isImmediateDispatchingSupported())
{
// immediate local synchronous dispatching
_LocalModuleSkel->< xsl:value-of select = "@name" / > (_ModuleProxy->getModuleGateway()->getPluggedModuleProxy(sender)< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
}
else
{
// send the message for remote dispatching and execution or local queing
NLNET::CMessage __message;
buildMessageFor_< xsl:value-of select = "@name" / > (__message< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
_ModuleProxy->sendModuleMessage(sender, __message);
}
}< xsl:text >
< / xsl:text >
< / xsl:when >
< xsl:when test = "return" >
< xsl:text > < / xsl:text > < xsl:value-of select = "return/@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "$proxyName" / > ::< xsl:value-of select = "@name" / > (NLNET::IModule *sender< xsl:call-template name = "makeParamList" / > )
{
if (_LocalModuleSkel & & _LocalModule->isImmediateDispatchingSupported())
{
// immediate local synchronous dispatching
return _LocalModuleSkel->< xsl:value-of select = "@name" / > (_ModuleProxy->getModuleGateway()->getPluggedModuleProxy(sender)< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
}
else
{
// send the message for remote dispatching and execution
NLNET::CMessage __message;
buildMessageFor_< xsl:value-of select = "@name" / > (__message< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
NLNET::CMessage __retMsg;
sender->invokeModuleOperation(_ModuleProxy, __message, __retMsg);
// check the return message type
if (__retMsg.getName() != "R_< xsl:value-of select = "@msg" / > ")
throw NLNET::IModule::EInvokeBadReturn();
< xsl:value-of select = "return/@type" / > __ret;
nlRead(__retMsg, serial, __ret);
return __ret;
}
}< xsl:text >
< / xsl:text >
< / xsl:when >
< / xsl:choose >
< / xsl:for-each >
< xsl:for-each select = "method" >
< xsl:text >
// Message serializer. Return the message received in reference for easier integration
const NLNET::CMessage & < / xsl:text > < xsl:value-of select = "$proxyName" / > ::buildMessageFor_< xsl:value-of select = "@name" / > (NLNET::CMessage & __message< xsl:call-template name = "makeParamList" / > )
{
__message.setType("< xsl:value-of select = "@msg" / > "< xsl:if test = "return" > , NLNET::CMessage::Request< / xsl:if > );
< xsl:for-each select = "param" > < xsl:call-template name = "serialWrite" > < xsl:with-param name = "message" select = "'__message'" / > < / xsl:call-template >
< / xsl:for-each >
return __message;
}< xsl:text >
< / xsl:text >
< / xsl:for-each >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Generate documentation ####### -->
<!-- ######################################################### -->
< xsl:template name = "makeMethodDoc" >
< xsl:for-each select = "doc" >
< xsl:text > // < / xsl:text > < xsl:value-of select = "@line" / > < xsl:text >
< / xsl:text >
< / xsl:for-each >
< / xsl:template >
< xsl:template name = "makeMasterDoc" >
< xsl:for-each select = "doc" >
< xsl:text > // < / xsl:text > < xsl:value-of select = "@line" / > < xsl:text >
< / xsl:text >
< / xsl:for-each >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Generate parameter list ####### -->
<!-- ######################################################### -->
< xsl:template name = "makeParamList" >
< xsl:if test = "param" >
< xsl:text > , < / xsl:text > < xsl:call-template name = "makeParamListNoStartingComma" / >
< / xsl:if >
< / xsl:template >
< xsl:template name = "makeParamListNoStartingComma" >
< xsl:if test = "param" >
< xsl:for-each select = "param" >
< xsl:choose >
< xsl:when test = "@array = 'true'" >
<!-- generate vector for callback interface -->
< xsl:text > const std::vector< < / xsl:text > < xsl:value-of select = "@type" / > > & < xsl:value-of select = "@name" / > < xsl:if test = "position() != last()" > , < / xsl:if >
< / xsl:when >
< xsl:otherwise >
< xsl:if test = "@byref = 'true' or @enum='smart'" > const < / xsl:if > < xsl:value-of select = "@type" / > < xsl:text > < / xsl:text > < xsl:if test = "@byref = 'true' or @enum = 'smart'" > & < / xsl:if > < xsl:value-of select = "@name" / > < xsl:if test = "position() != last()" > , < / xsl:if >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< / xsl:if >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Write serialisation ####### -->
<!-- ######################################################### -->
< xsl:template name = "serialWrite" >
< xsl:param name = "message" select = "'message'" / >
< xsl:choose >
< xsl:when test = "@byref = 'true'" >
< xsl:text > < / xsl:text > nlWrite(< xsl:value-of select = "$message" / > , serial< xsl:value-of select = "@serial" / > , const_cast < < xsl:value-of select = "@type" / > & > (< xsl:value-of select = "@name" / > ));< xsl:text >
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
< xsl:if test = "not(@array)" >
< xsl:text > < / xsl:text > nlWrite(< xsl:value-of select = "$message" / > , serial< xsl:value-of select = "@serial" / > , < xsl:value-of select = "@name" / > );< xsl:text >
< / xsl:text >
< / xsl:if >
< xsl:if test = "@array = 'true'" >
< xsl:text > < / xsl:text > nlWrite(< xsl:value-of select = "$message" / > , serialCont, < xsl:value-of select = "@name" / > );< xsl:text >
< / xsl:text >
< / xsl:if >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Read serialisation ####### -->
<!-- ######################################################### -->
< xsl:template name = "serialRead" >
< xsl:param name = "message" select = "'message'" / >
< xsl:if test = "not(@array)" >
< xsl:text > < / xsl:text > nlRead(< xsl:value-of select = "$message" / > , serial< xsl:value-of select = "@serial" / > , < xsl:value-of select = "@name" / > );< xsl:text >
< / xsl:text >
< / xsl:if >
< xsl:if test = "@array = 'true'" >
< xsl:text > < / xsl:text > nlRead(< xsl:value-of select = "$message" / > , serialCont, < xsl:value-of select = "@name" / > );< xsl:text >
< / xsl:text >
< / xsl:if >
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Enum generation ####### -->
<!-- ######################################################### -->
< xsl:template match = "enum" mode = "php" >
< xsl:text > < ?php
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
$arrayCounter = 0;
< / xsl:text >
< xsl:for-each select = "item" >
< xsl:text > $< / xsl:text > < xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "../@name" / > _EnumValues[$arrayCounter++] = "< xsl:value-of select = "@name" / > < xsl:text > ";
< / xsl:text > < / xsl:for-each >
< xsl:text > $< / xsl:text > < xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues[$arrayCounter] = "invalid";
$< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _InvalidValue = $arrayCounter;
class < xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / >
{
var $Value;
function < xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > ()
{
global $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _InvalidValue;
$this->Value = $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _InvalidValue;
}
function toString()
{
global $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues;
return $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues[$this->Value];
}
function fromString($strValue)
{
global $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues;
foreach ($< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues as $k => $v)
{
if ($strValue === $v)
{
$this->Value = $k;
return;
}
}
$this->Value = $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _InvalidValue;
}
function toInt()
{
return $this->Value;
}
function fromInt($intValue)
{
global $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _InvalidValue;
global $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues;
if (array_key_exists($intValue, $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _EnumValues))
$this->Value = $intValue;
else
$this->Value = $< xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@name" / > _InvalidValue;
}
}
< xsl:text > ?>
< / xsl:text > < / xsl:template >
< xsl:template match = "enum" mode = "header" >
< xsl:call-template name = "makeMasterDoc" / >
< xsl:if test = "@bitset='true'" >
< xsl:call-template name = "enumGen" >
< xsl:with-param name = "enumName" select = "concat(@name, 'Enum')" / >
< / xsl:call-template >
typedef NLMISC::CEnumBitset < < xsl:value-of select = "@name" / > Enum, uint32, < xsl:value-of select = "@name" / > Enum::invalid_val, ',', NLMISC::TContainedEnum < < xsl:value-of select = "@name" / > Enum, uint32 > , < xsl:value-of select = "@name" / > Enum::TValues > < xsl:value-of select = "@name" / > ;
< / xsl:if >
< xsl:if test = "not(@bitset='true')" >
< xsl:call-template name = "enumGen" >
< xsl:with-param name = "enumName" select = "@name" / >
< / xsl:call-template >
< / xsl:if >
< / xsl:template >
< xsl:template name = "enumGen" >
< xsl:param name = "enumName" / >
<!-- check that we don't set a base value AND a value for the 1st enum item -->
< xsl:if test = "@base and item[1]/@value" >
< xsl:message terminate = "yes" >
ERROR : You can't set a base value AND a value for the first item on enum definition < xsl:value-of select = "$enumName" / >
< / xsl:message >
< / xsl:if >
struct < xsl:value-of select = "$enumName" / >
{
enum TValues
{
< xsl:for-each select = "item" >
< xsl:value-of select = "@name" / > < xsl:if test = "@value" > = < xsl:value-of select = "@value" / > < / xsl:if >
< xsl:if test = "position() = 1 and ../@base" > = < xsl:value-of select = "../@base" / > < / xsl:if > ,
< / xsl:for-each >
<!-- generate a value 'past the end' and 'last_enum_item' if no values are set other than on first item -->
< xsl:if test = "count(item/@value) = 0 or (count(item/@value) = 1 and item[1]/@value)" >
< xsl:text > /// the highest valid value in the enum
last_enum_item = < / xsl:text > < xsl:value-of select = "item[last()]/@name" / > ,
/// a value equal to the last enum item +1
end_of_enum,
< / xsl:if >
<!-- generate an invalid and undefined value -->
invalid_val,
<!-- generate a count of node -->
/// Number of enumerated values
nb_enum_items = < xsl:value-of select = "count(item)" / >
};
<!-- generate an index table if the enum is 'linear' -->
< xsl:if test = "count(item/@value) = 0 or (count(item/@value) = 1 and item[1]/@value)" >
/// Index table to convert enum value to linear index table
const std::map< TValues, uint32> & getIndexTable() const
{
static std::map< TValues, uint32> indexTable;
static bool init = false;
if (!init)
{
// fill the index table
< xsl:for-each select = "item" >
< xsl:text > indexTable.insert(std::make_pair(< / xsl:text > < xsl:value-of select = "@name" / > , < xsl:value-of select = "position()-1" / > ));
< / xsl:for-each >
init = true;
}
return indexTable;
}
< / xsl:if >
static const NLMISC::CStringConversion< TValues> & getConversionTable()
{
NL_BEGIN_STRING_CONVERSION_TABLE(TValues)
< xsl:for-each select = "item" > NL_STRING_CONVERSION_TABLE_ENTRY(< xsl:value-of select = "@name" / > )
< / xsl:for-each > NL_STRING_CONVERSION_TABLE_ENTRY(invalid_val)
};
static NLMISC::CStringConversion< TValues>
conversionTable(TValues_nl_string_conversion_table, sizeof(TValues_nl_string_conversion_table)
/ sizeof(TValues_nl_string_conversion_table[0]), invalid_val);
return conversionTable;
}
TValues _Value;
public:
< xsl:value-of select = "$enumName" / > ()
: _Value(invalid_val)
{
}
< xsl:value-of select = "$enumName" / > (TValues value)
: _Value(value)
{
}
< xsl:value-of select = "$enumName" / > (const std::string & str)
{
_Value = getConversionTable().fromString(str);
}
void serial(NLMISC::IStream & s)
{
s.serialEnum(_Value);
}
bool operator == (const < xsl:value-of select = "$enumName" / > & other) const
{
return _Value == other._Value;
}
bool operator != (const < xsl:value-of select = "$enumName" / > & other) const
{
return ! (_Value == other._Value);
}
bool operator < (const < xsl:value-of select = "$enumName" / > & other) const
{
return _Value < other._Value;
}
bool operator < = (const < xsl:value-of select = "$enumName" / > & other) const
{
return _Value < = other._Value;
}
bool operator > (const < xsl:value-of select = "$enumName" / > & other) const
{
return !(_Value < = other._Value);
}
bool operator > = (const < xsl:value-of select = "$enumName" / > & other) const
{
return !(_Value < other._Value);
}
const std::string & toString() const
{
return getConversionTable().toString(_Value);
}
static const std::string & toString(TValues value)
{
return getConversionTable().toString(value);
}
TValues getValue() const
{
return _Value;
}
// return true if the actual value of the enum is valid, otherwise false
bool isValid()
{
if (_Value == invalid_val)
return false;
// not invalid, check other enum value
return getConversionTable().isValid(_Value);
}
<!-- generate an index table if the enum is 'linear' -->
< xsl:if test = "count(item/@value) = 0 or (count(item/@value) = 1 and item[1]/@value)" >
uint32 asIndex()
{
std::map< TValues, uint32> ::const_iterator it(getIndexTable().find(_Value));
nlassert(it != getIndexTable().end());
return it->second;
}
< / xsl:if >
<!-- insert user code if any -->
< xsl:if test = "header_code" >
< xsl:value-of select = "header_code" / >
< / xsl:if >
};
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Class generation (db mapping, serial and message)### -->
<!-- ######################################################### -->
< xsl:template name = "makeProperty" >
< xsl:param name = "property" / >
< xsl:text > < / xsl:text > // < xsl:value-of select = "$property/@doc" / > < xsl:text >
< / xsl:text >
< xsl:text > < / xsl:text > < xsl:value-of select = "$property/@type" / > < xsl:text > _< / xsl:text > < xsl:value-of select = "$property/@name" / > < xsl:text > ;
< / xsl:text >
< / xsl:template >
<!-- ///////////////////////////////////////////////////////// -->
< xsl:template name = "makePropertyAccessor" >
< xsl:param name = "property" / >
< xsl:text > < / xsl:text > // < xsl:value-of select = "$property/@doc" / > < xsl:text >
< / xsl:text >
< xsl:choose >
< xsl:when test = "$property/@byref = 'true'" >
< xsl:text > < / xsl:text > const < xsl:value-of select = "$property/@type" / > & get< xsl:value-of select = "$property/@name" / > () const
{
return _< xsl:value-of select = "$property/@name" / > ;
}
< xsl:if test = "not(../database) and $property/@byref = 'true'" >
<!-- for non database 'by reference' property, generate a non const get accessor -->
< xsl:text > < / xsl:text > < xsl:value-of select = "$property/@type" / > & get< xsl:value-of select = "$property/@name" / > ()
{
return _< xsl:value-of select = "$property/@name" / > ;
}
< / xsl:if >
void set< xsl:value-of select = "$property/@name" / > (const < xsl:value-of select = "$property/@type" / > & value)
{
< xsl:if test = "../database" >
if (_< xsl:value-of select = "$property/@name" / > != value)
{
if (getPersistentState() != NOPE::os_transient)
setPersistentState(NOPE::os_dirty);
< / xsl:if >
< xsl:variable name = "relation" select = "parent[@db_col = $property/@db_col]" / >
< xsl:if test = "$relation" >
<!-- this property is a child/parent relation, update the parent -->
< xsl:value-of select = "$relation/@class" / > Ptr parent = < xsl:value-of select = "$relation/@class" / > ::loadFromCache(_< xsl:value-of select = "$property/@name" / > );
if (parent & & getPersistentState() != NOPE::os_transient )
parent->remove< xsl:value-of select = "$relation/@child_name" / > Child(this);
< / xsl:if >
_< xsl:value-of select = "$property/@name" / > = value;
< xsl:if test = "$relation" >
<!-- this property is a child/parent relation, update the parent -->
< xsl:value-of select = "$relation/@class" / > Ptr parent = < xsl:value-of select = "$relation/@class" / > ::loadFromCache(_< xsl:value-of select = "$property/@name" / > );
if (parent & & getPersistentState() != NOPE::os_transient)
parent->insert< xsl:value-of select = "$relation/@child_name" / > Child(this);
< / xsl:if >
< xsl:if test = "../database" >
}
< / xsl:if >
}
< / xsl:when >
< xsl:otherwise >
< xsl:text > < / xsl:text > < xsl:value-of select = "$property/@type" / > get< xsl:value-of select = "$property/@name" / > () const
{
return _< xsl:value-of select = "$property/@name" / > ;
}
void set< xsl:value-of select = "$property/@name" / > (< xsl:value-of select = "$property/@type" / > value)
{
< xsl:if test = "../database" >
if (_< xsl:value-of select = "$property/@name" / > != value)
{
if (getPersistentState() != NOPE::os_transient)
setPersistentState(NOPE::os_dirty);
< / xsl:if >
_< xsl:value-of select = "$property/@name" / > = value;
< xsl:if test = "../database" >
}
< / xsl:if >
}
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
<!-- ///////////////////////////////////////////////////////// -->
< xsl:template name = "makeChildAccessor" >
< xsl:param name = "childClass" / >
< xsl:if test = "@cont" >
< xsl:choose >
< xsl:when test = "@cont = 'vector'" >
/** Return a const reference to the vector of child.
* If you want to modify the element inside, you need to
* use on of the two following methods who return non const pointer
* on contained elements.
*/
const std::vector< < xsl:value-of select = "@type" / > Ptr> & get< xsl:value-of select = "@name" / > () const;
/** Return the ith element of the child vector
* index must be valid (ie less than size of the vector)
*/
< xsl:value-of select = "@type" / > Ptr & get< xsl:value-of select = "@name" / > ByIndex(uint32 index) const;
/** Return the identified element by looking in the vector
* If no element match the id, NULL pointer is returned
*/
< xsl:value-of select = "@type" / > Ptr & get< xsl:value-of select = "@name" / > ById(uint32 id) const;
< / xsl:when >
< xsl:when test = "@cont = 'map'" >
/** Return a const reference to the map of child.
* If you want to modify the element inside, you need to
* use on of the two following method who return non const pointer
* on contained elements.
*/
const std::map< uint32, < xsl:value-of select = "@type" / > Ptr> & get< xsl:value-of select = "@name" / > () const;
/** Return the identified element by looking in the map
* If no element match the id, NULL pointer is returned
*/
< xsl:value-of select = "@type" / > Ptr & get< xsl:value-of select = "@name" / > ById(uint32 id) const;
< / xsl:when >
< xsl:otherwise >
< xsl:message terminate = "yes" >
ERROR : Invalide container, child must be either map or vector for child < xsl:value-of select = "@name" / > in class < xsl:value-of select = "../@name" / >
< / xsl:message >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:if >
< xsl:if test = "not(@cont)" >
/** Return the one child object (or null if not) */
< xsl:value-of select = "@type" / > Ptr get< xsl:value-of select = "@name" / > ();
< / xsl:if >
< / xsl:template >
<!-- ///////////////////////////////////////////////////////// -->
< xsl:template name = "makeColumList" >
< xsl:param name = "uniqueId" / >
< xsl:choose >
< xsl:when test = "property[@name = $uniqueId and @db_col]/@autogen = 'true'" >
qs += "< xsl:for-each select = "property[@name != $uniqueId]" >
< xsl:value-of select = "@db_col" / >
< xsl:if test = "position() != last()" > < xsl:text > , < / xsl:text > < / xsl:if >
< / xsl:for-each > < xsl:text > ";< / xsl:text >
< / xsl:when >
< xsl:otherwise >
qs += "< xsl:for-each select = "property[@db_col]" >
< xsl:value-of select = "@db_col" / >
< xsl:if test = "position() != last()" > , < / xsl:if >
< / xsl:for-each > < xsl:text > ";< / xsl:text >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
< xsl:template name = "makeColumListWithId" >
qs += "< xsl:for-each select = "property[@db_col]" >
< xsl:value-of select = "@db_col" / >
< xsl:if test = "position() != last()" > , < / xsl:if >
< / xsl:for-each >
< xsl:text > ";
< / xsl:text >
< / xsl:template >
< xsl:template name = "makeValueList" >
< xsl:param name = "uniqueId" / >
< xsl:choose >
< xsl:when test = "property[@name = $uniqueId]/@autogen = 'true'" >
< xsl:for-each select = "property[@name != $uniqueId and @db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
qs += "'"+_< xsl:value-of select = "@name" / > < xsl:text > .toString()+"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@date='true'" >
qs += "'"+MSW::encodeDate(_< xsl:value-of select = "@name" / > )< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@md5='true'" >
qs += "'"+MSW::escapeString(_< xsl:value-of select = "@name" / > .toString(), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
qs += "'"+MSW::escapeString(NLMISC::toString(_< xsl:value-of select = "@name" / > ), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:otherwise >
< / xsl:choose >
< xsl:if test = "position() != last()" > < xsl:text > qs += ", ";< / xsl:text > < / xsl:if >
< / xsl:for-each >
< / xsl:when >
< xsl:otherwise >
< xsl:for-each select = "property[@db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
qs += "'"+_< xsl:value-of select = "@name" / > < xsl:text > .toString()+"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@date='true'" >
qs += "'"+MSW::encodeDate(_< xsl:value-of select = "@name" / > )< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@md5='true'" >
qs += "'"+MSW::escapeString(_< xsl:value-of select = "@name" / > .toString(), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
qs += "'"+MSW::escapeString(NLMISC::toString(_< xsl:value-of select = "@name" / > ), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:otherwise >
< / xsl:choose >
< xsl:if test = "position() != last()" > < xsl:text > qs += ", ";< / xsl:text > < / xsl:if >
< / xsl:for-each >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
< xsl:template name = "makeValueListWithId" >
< xsl:for-each select = "property[@db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
qs += "'"+_< xsl:value-of select = "@name" / > .toString()+"'";
< / xsl:when >
< xsl:when test = "@date='true'" >
qs += "'"+MSW::encodeDate(_< xsl:value-of select = "@name" / > )< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@md5='true'" >
qs += "'"+MSW::escapeString(_< xsl:value-of select = "@name" / > .toString(), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
qs += "'"+MSW::escapeString(NLMISC::toString(_< xsl:value-of select = "@name" / > ), connection)+"'";
< / xsl:otherwise >
< / xsl:choose >
< xsl:if test = "position() != last()" > qs += ", ";< / xsl:if >
< / xsl:for-each >
< / xsl:template >
< xsl:template name = "makeSetList" >
< xsl:param name = "uniqueId" / >
< xsl:choose >
< xsl:when test = "property[@name = $uniqueId and @db_col]/@autogen = 'true'" >
< xsl:for-each select = "property[@name != $uniqueId and @db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
qs += "< xsl:value-of select = "@db_col" / > = '"+_< xsl:value-of select = "@name" / > < xsl:text > .toString()+"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@date='true'" >
qs += "< xsl:value-of select = "@db_col" / > = '"+MSW::encodeDate(_< xsl:value-of select = "@name" / > )< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@md5='true'" >
qs += "< xsl:value-of select = "@db_col" / > = '"+MSW::escapeString(_< xsl:value-of select = "@name" / > .toString(), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
qs += "< xsl:value-of select = "@db_col" / > = '"+MSW::escapeString(NLMISC::toString(_< xsl:value-of select = "@name" / > ), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:otherwise >
< / xsl:choose >
< xsl:if test = "position() != last()" > < xsl:text > qs += ", ";< / xsl:text > < / xsl:if >
< / xsl:for-each >
< / xsl:when >
< xsl:otherwise >
< xsl:for-each select = "property[@db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
qs += "< xsl:value-of select = "@db_col" / > = '"+_< xsl:value-of select = "@name" / > < xsl:text > .toString()+"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@date='true'" >
qs += "< xsl:value-of select = "@db_col" / > = '"+MSW::encodeDate(_< xsl:value-of select = "@name" / > )< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:when test = "@md5='true'" >
qs += "< xsl:value-of select = "@db_col" / > = '"+MSW::escapeString(_< xsl:value-of select = "@name" / > .toString(), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
qs += "< xsl:value-of select = "@db_col" / > = '"+MSW::escapeString(NLMISC::toString(_< xsl:value-of select = "@name" / > ), connection)< xsl:text > +"'";
< / xsl:text >
< / xsl:otherwise >
< / xsl:choose >
< xsl:if test = "position() != last()" > < xsl:text > qs += ", ";< / xsl:text > < / xsl:if >
< / xsl:for-each >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
< xsl:template name = "makeWhereClause" >
< xsl:param name = "uniqueId" / >
qs += " WHERE < xsl:value-of select = "property[@name = $uniqueId]/@db_col" / > = '"+NLMISC::toString(_< xsl:value-of select = "property[@name = $uniqueId]/@name" / > )+"'";
< / xsl:template >
< xsl:template name = "makeWhereClauseWithId" >
< xsl:param name = "uniqueId" / >
< xsl:param name = "id" / >
qs += " WHERE < xsl:value-of select = "property[@name = $uniqueId]/@db_col" / > = '"+NLMISC::toString(< xsl:value-of select = "$id" / > )+"'";
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Class generation (db mapping, serial and message)### -->
<!-- ######################################################### -->
<!-- ##### Include file #### -->
< xsl:template match = "class" mode = "header" >
< xsl:if test = "count(property[@unique_id = 'true' and @db_col]) != 1 and datase" >
< xsl:message terminate = "yes" >
ERROR : You must have ONE and ONLY one unique_id property in class '_< xsl:value-of select = "@name" / > '
< / xsl:message >
< / xsl:if >
< xsl:choose >
< xsl:when test = "database" >
< xsl:call-template name = "makeClassHeader" >
< xsl:with-param name = "className" select = "@name" / >
< xsl:with-param name = "uniqueId" select = "property[@unique_id = 'true']/@name" / >
< / xsl:call-template >
< / xsl:when >
< xsl:otherwise >
< xsl:call-template name = "makeClassHeader" >
< xsl:with-param name = "className" select = "@name" / >
< xsl:with-param name = "uniqueId" select = "''" / >
< / xsl:call-template >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
< xsl:template name = "makeClassHeader" >
< xsl:param name = "className" / >
< xsl:param name = "uniqueId" / >
<!-- <xsl:if test="database">
< xsl:call-template name = "makePersistentPtrHeader" >
< xsl:with-param name = "className" select = "@name" / >
< / xsl:call-template >
< / xsl:if >
-->
< xsl:call-template name = "makeMasterDoc" / >
< xsl:text > /////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
class < / xsl:text > < xsl:value-of select = "$className" / >
{
< xsl:text > protected:
< / xsl:text > < xsl:for-each select = "property" >
< xsl:call-template name = "makeProperty" >
< xsl:with-param name = "property" select = "." / >
< / xsl:call-template >
< / xsl:for-each >
< xsl:for-each select = "child_class[@relation = 'one-to-many']" >
friend class < xsl:value-of select = "@type" / > ;
< xsl:choose >
< xsl:when test = "@cont = 'map'" >
std::map < uint32, < xsl:value-of select = "@type" / > Ptr > *_< xsl:value-of select = "@name" / > ;
< / xsl:when >
< xsl:when test = "@cont = 'vector'" >
std::vector < < xsl:value-of select = "@type" / > Ptr > *_< xsl:value-of select = "@name" / > ;
< / xsl:when >
< xsl:otherwise >
< xsl:message terminate = "yes" >
ERROR : You must define the cont="" property with either 'vector' or 'map' value in the child_class element for class '< xsl:value-of select = "../@name" / > ' , child '_< xsl:value-of select = "@name" / > '
< / xsl:message >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:for-each select = "child_class[@relation = 'one-to-one']" >
< xsl:text > friend class < / xsl:text > < xsl:value-of select = "@type" / > ;
bool _< xsl:value-of select = "@name" / > Loaded;
< xsl:value-of select = "@type" / > Ptr _< xsl:value-of select = "@name" / > ;
< / xsl:for-each >
< xsl:text > public:
< / xsl:text > < xsl:for-each select = "property[@name != $uniqueId]" >
< xsl:call-template name = "makePropertyAccessor" >
< xsl:with-param name = "property" select = "." / >
< / xsl:call-template >
< / xsl:for-each >
< xsl:for-each select = "child_class" >
< xsl:call-template name = "makeChildAccessor" >
< xsl:with-param name = "childClass" select = "." / >
< / xsl:call-template >
< / xsl:for-each >
bool operator == (const < xsl:value-of select = "@name" / > & other) const
{
return < xsl:for-each select = "property" > _< xsl:value-of select = "@name" / > == other._< xsl:value-of select = "@name" / > < xsl:if test = "position() != last()" >
& & < / xsl:if > < / xsl:for-each > ;
}
< xsl:if test = "not(database)" >
< xsl:text >
// constructor
< / xsl:text > < xsl:value-of select = "$className" / > ()
{
< xsl:if test = "property[@default]" > // Default initialisation
< / xsl:if >
< xsl:for-each select = "property[@default]" >
< xsl:text > < / xsl:text > _< xsl:value-of select = "@name" / > = < xsl:value-of select = "@default" / > ;
< / xsl:for-each >
}
< / xsl:if >
< xsl:if test = "message" >
<!-- generate a serialisable and sendable nel message -->
void send(const std::string & serviceName)
{
NLNET::CMessage msg("< xsl:value-of select = "@name" / > ");
serial(msg);
sendMessageViaMirror( serviceName, msg );
}
void send(NLNET::TServiceId serviceId)
{
NLNET::CMessage msg("< xsl:value-of select = "@name" / > ");
serial(msg);
sendMessageViaMirror( serviceId, msg );
}
< / xsl:if >
< xsl:if test = "database" >
< xsl:text >
private:
// private constructor, you must use 'createTransient' to get an instance
< / xsl:text > < xsl:value-of select = "$className" / > ()
: _PtrList(NULL),
_ObjectState(NOPE::os_transient),
_< xsl:value-of select = "$uniqueId" / > (NOPE::INVALID_OBJECT_ID)
{
< xsl:if test = "property[@default]" > // Default initialisation
< / xsl:if >
< xsl:for-each select = "property[@default]" >
< xsl:text > < / xsl:text > _< xsl:value-of select = "@name" / > = < xsl:value-of select = "@default" / > ;
< / xsl:for-each >
< xsl:for-each select = "child_class[@relation = 'one-to-many']" >
< xsl:text > _< / xsl:text > < xsl:value-of select = "@name" / > = NULL;
< / xsl:for-each >
< xsl:for-each select = "child_class[@relation = 'one-to-one']" >
< xsl:text > _< / xsl:text > < xsl:value-of select = "@name" / > Loaded = false;
< / xsl:for-each >
// register the cache for this class (if not already done)
registerUpdatable();
}
// Destructor, delete any children
~< xsl:value-of select = "@name" / > ();
/// utility func to remove this object from the released object container
void removeFromReleased();
public:
/// Create a new instance in the transient space
static < xsl:value-of select = "$className" / > Ptr createTransient(const char *filename, uint32 lineNum)
{
return < xsl:value-of select = "$className" / > Ptr(new < xsl:value-of select = "$className" / > (), filename, lineNum);
}
/** Create a new object in the database from the current object data.
* The object MUST be in transient state (i.e, it must be a new
* object created by user and not comming from the databse).
* If identifier is autogenerated, the generated id can be read after
* this call.
*/
bool create(MSW::CConnection & connection);
/** Update the database with the current object state.
* The object MUST be either in clean or dirty state.
* Return true if the object has been effectively stored
* in the database.
* After this call, the object is in 'clean' state.
*/
bool update(MSW::CConnection & connection);
/** Remove the current object from the persistent storage.
* The object must be in clean or dirty state.
* Return true if the object has been correctly
* updated in the database.
* After the call, the object is in 'clean' state.
*/
bool remove(MSW::CConnection & connection);
/** Remove an object from the persistent storage by specifying
* the id to remove.
* Return true if an entry as been effectively removed from
* the database.
* After the call, the object is in 'removed' state and should
* no more be used. A good pratice should be to delete
* the transient object just after the remove call.
*/
static bool removeById(MSW::CConnection & connection, uint32 id);
/** Load an instance from the database.
* This call allocate a new object and load the property value
* from the database.
* Return NULL if the object id is not found.
*/
static < xsl:value-of select = "$className" / > Ptr load(MSW::CConnection & connection, uint32 id, const char *filename, uint32 lineNum);
< xsl:for-each select = "parent[@relation = 'one-to-many']" >
/** Load all objects children of < xsl:value-of select = "@class" / > and
* return them by using the specified output iterator.
*/
< xsl:choose >
< xsl:when test = "@cont = 'vector'" >
static bool loadChildrenOf< xsl:value-of select = "@class" / > (MSW::CConnection & connection, uint32 parentId, std::vector < < xsl:value-of select = "$className" / > Ptr > & children, const char *filename, uint32 lineNum);
< / xsl:when >
< xsl:when test = "@cont = 'map'" >
static bool loadChildrenOf< xsl:value-of select = "@class" / > (MSW::CConnection & connection, uint32 parentId, std::map < uint32, < xsl:value-of select = "$className" / > Ptr > & children, const char *filename, uint32 lineNum);
< / xsl:when >
< xsl:otherwise >
< xsl:message terminate = "yes" >
ERROR : parent/child relation support only 'map' or 'vector' cont specification in < xsl:value-of select = "$className" / > definition
< / xsl:message >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:for-each select = "parent[@relation = 'one-to-one']" >
/** Load the object child of < xsl:value-of select = "@class" / > and
* return true if no error, false in case of error (in SQL maybe).
* If no such object is found, fill the child pointer with NULL.
*/
static bool loadChildOf< xsl:value-of select = "@class" / > (MSW::CConnection & connection, uint32 parentId, < xsl:value-of select = "../@name" / > Ptr & childPtr, const char *filename, uint32 lineNum);
< / xsl:for-each >
<!-- <child_class type="CKnownUser" name="KnownUsers" relation="one - to - many" cont="vector"/> -->
< xsl:for-each select = "child_class" >
/// Load < xsl:value-of select = "@name" / > child(ren) object(s).
bool load< xsl:value-of select = "@name" / > (MSW::CConnection & connection, const char *filename, uint32 lineNum);
< / xsl:for-each >
< / xsl:if >
<!-- generate serial -->
< xsl:if test = "serial or message" >
< xsl:text >
void serial(NLMISC::IStream & s)
{
< / xsl:text >
< xsl:for-each select = "property" >
< xsl:text > s.serial< / xsl:text > < xsl:value-of select = "@serial" / > (_< xsl:value-of select = "@name" / > )< xsl:text > ;
< / xsl:text >
< / xsl:for-each >
}
< / xsl:if >
private:
<!-- generate private child container modifier -->
< xsl:for-each select = "child_class[relation = 'one-to-many' and cont='vector']" >
/// add a child in the container
void insert< xsl:value-of select = "@name" / > Child(< xsl:value-of select = "@type" / > & child)
{
nlassert(std::find(_< xsl:value-of select = "@name" / > .begin(), _< xsl:value-of select = "@name" / > .end(), child) == _< xsl:value-of select = "@name" / > .end());
_< xsl:value-of select = "@name" / > .push_back(child);
}
// remove a child from the container
void removeXXChild()
{
}
< / xsl:for-each >
< xsl:if test = "database" >
private:
friend class CPersistentCache;
friend class < xsl:value-of select = "$className" / > Ptr;
typedef std::map< uint32, < xsl:value-of select = "$className" / > *> TObjectCache;
typedef std::set< < xsl:value-of select = "$className" / > *> TObjectSet;
typedef std::map< time_t, TObjectSet> TReleasedObject;
/// The complete set of object currently in memory (either active or released) excluding transient instance
static TObjectCache _ObjectCache;
/// The set of object in memory ut released (no pointer on them) and waiting for decommit
static TReleasedObject _ReleasedObject;
/// The current object state
NOPE::TObjectState _ObjectState;
/// For object in released state, this is the release date (used to trigger deletion of the object from memory)
time_t _ReleaseDate;
/// The linked list of pointer on this object
< xsl:value-of select = "$className" / > Ptr *_PtrList;
// Try to load the specified object from the memory cache, return NULL if the object is not in the cache
static < xsl:value-of select = "$className" / > *loadFromCache(uint32 objectId, bool unrelease);
// Receive and execute command from the cache manager.
static uint32 cacheCmd(NOPE::TCacheCmd cmd);
static void dump();
static void updateCache();
public:
static void clearCache();
private:
void registerUpdatable();
// set the pointer on the first pointer of the pointer list (set to null when there is no more pointer)
void setFirstPtr(< xsl:value-of select = "$className" / > Ptr *ptr);
// return the first pointer of the pointer list (can be null)
< xsl:value-of select = "$className" / > Ptr *getFirstPtr()
{
return _PtrList;
}
public:
/** Return the object identifier (witch is unique)
* You can only call this method on a persistent instance.
* (because transient instance can have invalid id)
*/
uint32 getObjectId() const
{
< xsl:if test = "property[@name = $uniqueId]/@autogen = 'true'" >
nlassert(getPersistentState() != NOPE::os_transient);< / xsl:if >
return _< xsl:value-of select = "$uniqueId" / > ;
}
/** Set the object unique ID.
* You can only set the object id on a transient object
* having a non autogenerated unique id.
* Furthermore, you MUST set the id before calling create()
* if the id is not autogenerated.
*/
void setObjectId(uint32 objectId)
{
// can only be set when in transient state
nlassert(getPersistentState() == NOPE::os_transient);
// can only be set once
nlassert(_< xsl:value-of select = "$uniqueId" / > == NOPE::INVALID_OBJECT_ID);
_< xsl:value-of select = "$uniqueId" / > = objectId;
}
/** Return the current persistent state of the object.*/
NOPE::TObjectState getPersistentState() const
{
return _ObjectState;
}
private:
// Set the persistent state of the object and do some house keeping
void setPersistentState(NOPE::TObjectState state);
< / xsl:if >
};
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### Class generation (db mapping, serial and message)### -->
<!-- ######################################################### -->
<!-- ##### cpp file #### -->
< xsl:template match = "class" mode = "cpp" >
< xsl:if test = "count(property[@unique_id = 'true' and @db_col]) != 1 and database" >
< xsl:message terminate = "yes" >
ERROR : You must have ONE and ONLY one unique_id property in class '_< xsl:value-of select = "@name" / > '
< / xsl:message >
< / xsl:if >
< xsl:choose >
< xsl:when test = "database" >
< xsl:call-template name = "makeClassCpp" >
< xsl:with-param name = "className" select = "@name" / >
< xsl:with-param name = "uniqueId" select = "property[@unique_id = 'true']/@name" / >
< / xsl:call-template >
< / xsl:when >
< xsl:otherwise >
< xsl:call-template name = "makeClassCpp" >
< xsl:with-param name = "className" select = "@name" / >
< xsl:with-param name = "uniqueId" select = "''" / >
< / xsl:call-template >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
< xsl:template name = "makeClassCpp" >
< xsl:param name = "className" / >
< xsl:param name = "uniqueId" / >
< xsl:if test = "database" >
< xsl:call-template name = "makePersistentPtrCpp" >
< xsl:with-param name = "className" select = "@name" / >
< / xsl:call-template >
< / xsl:if >
< xsl:if test = "database" >
< xsl:text >
< / xsl:text > < xsl:value-of select = "$className" / > ::TObjectCache < xsl:value-of select = "$className" / > ::_ObjectCache;
< xsl:value-of select = "$className" / > ::TReleasedObject < xsl:value-of select = "$className" / > ::_ReleasedObject;
< xsl:text >
// Destructor, delete any children
< / xsl:text > < xsl:value-of select = "$className" / > ::~< xsl:value-of select = "@name" / > ()
{
// release childs reference
< xsl:for-each select = "child_class[@relation = 'one-to-many']" >
< xsl:text > if (_< / xsl:text > < xsl:value-of select = "@name" / > != NULL)
delete _< xsl:value-of select = "@name" / > ;
< / xsl:for-each >
if (_PtrList != NULL)
{
nlwarning("ERROR : someone try to delete this object, but there are still ptr on it !");
< xsl:value-of select = "$className" / > Ptr *ptr = _PtrList;
do
{
nlwarning(" Pointer created from '%s', line %u", ptr->_FileName, ptr->_LineNum);
ptr = _PtrList->getNextPtr();
} while(ptr != _PtrList);
nlstop;
}
// remove object from cache map
if (_< xsl:value-of select = "$uniqueId" / > != NOPE::INVALID_OBJECT_ID
& & _ObjectState != NOPE::os_removed
& & _ObjectState != NOPE::os_transient)
{
nldebug("NOPE: clearing < xsl:value-of select = "$className" / > @%p from cache with id %u", this, static_cast< uint32> (_< xsl:value-of select = "$uniqueId" / > ));
nlverify(_ObjectCache.erase(_< xsl:value-of select = "$uniqueId" / > ) == 1);
}
else if (_ObjectState != NOPE::os_transient)
{
nlassert(_ObjectCache.find(_< xsl:value-of select = "$uniqueId" / > ) == _ObjectCache.end());
}
if (_ObjectState == NOPE::os_released)
{
removeFromReleased();
}
else
{
TReleasedObject::iterator it(_ReleasedObject.find(_ReleaseDate));
if (it != _ReleasedObject.end())
{
nlassert(it->second.find(this) == it->second.end());
}
}
}
void < xsl:value-of select = "$className" / > ::removeFromReleased()
{
TReleasedObject::iterator it(_ReleasedObject.find(_ReleaseDate));
nlassert(it != _ReleasedObject.end());
TObjectSet & os = it->second;
nlverify(os.erase(this) == 1);
// nb : _ReleasedObject time entry are removed by the cache update
}
bool < xsl:value-of select = "$className" / > ::create(MSW::CConnection & connection)
{
nlassert(getPersistentState() == NOPE::os_transient);
< xsl:if test = "not(property[@name = $uniqueId]/@autogen = 'true')" >
nlassert(_< xsl:value-of select = "property[@name = $uniqueId]/@name" / > != 0);< / xsl:if >
std::string qs;
qs = "INSERT INTO < xsl:value-of select = "database/@table" / > (";
< xsl:call-template name = "makeColumList" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< / xsl:call-template >
qs += ") VALUES (";
< xsl:call-template name = "makeValueList" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< / xsl:call-template >
qs += ")";
if (connection.query(qs))
{
< xsl:if test = "property[@name = $uniqueId]/@autogen = 'true'" >
< xsl:text > uint32 _id_ = connection.getLastGeneratedId();
setObjectId(_id_);
< / xsl:text > < / xsl:if >
setPersistentState(NOPE::os_clean);
// update the parent class instance in cache if any
< xsl:for-each select = "parent[@relation = 'one-to-many']" >
< xsl:variable name = "db_col" select = "@db_col" / >
< xsl:variable name = "parentId" select = "concat('_', ../property[@db_col = $db_col]/@name)" / >
if (< xsl:value-of select = "$parentId" / > != 0)
{
// need to update the parent class child list if it is in the cache
< xsl:value-of select = "@class" / > *parent = < xsl:value-of select = "@class" / > ::loadFromCache(< xsl:value-of select = "$parentId" / > , false);
if (parent & & parent->_< xsl:value-of select = "@child_name" / > != NULL)
{
< xsl:choose >
< xsl:when test = "@cont = 'map'" >
nlverify(parent->_< xsl:value-of select = "@child_name" / > ->insert(std::make_pair(getObjectId(), < xsl:value-of select = "$className" / > Ptr(this, __FILE__, __LINE__))).second);
< / xsl:when >
< xsl:when test = "@cont = 'vector'" >
nlassert(std::find(parent->_< xsl:value-of select = "@child_name" / > ->begin(), parent->_< xsl:value-of select = "@child_name" / > ->end(), < xsl:value-of select = "$className" / > Ptr(this, __FILE__, __LINE__)) == parent->_< xsl:value-of select = "@child_name" / > ->end());
parent->_< xsl:value-of select = "@child_name" / > ->push_back(< xsl:value-of select = "$className" / > Ptr(this, __FILE__, __LINE__));
< / xsl:when >
< / xsl:choose >
}
}
< / xsl:for-each >
< xsl:for-each select = "parent[@relation = 'one-to-one']" >
< xsl:variable name = "db_col" select = "@db_col" / >
< xsl:variable name = "parentId" select = "concat('_', ../property[@db_col = $db_col]/@name)" / >
if (< xsl:value-of select = "$parentId" / > != 0)
{
// need to update the parent class child if it is in the cache
< xsl:value-of select = "@class" / > *parent = < xsl:value-of select = "@class" / > ::loadFromCache(< xsl:value-of select = "$parentId" / > , false);
if (parent & & parent->_< xsl:value-of select = "@child_name" / > Loaded)
{
nlassert(parent->_< xsl:value-of select = "@child_name" / > == NULL);
parent->_< xsl:value-of select = "@child_name" / > = < xsl:value-of select = "$className" / > Ptr(this, __FILE__, __LINE__);
}
}
< / xsl:for-each >
return true;
}
return false;
}
bool < xsl:value-of select = "$className" / > ::update(MSW::CConnection & connection)
{
nlassert(getPersistentState() == NOPE::os_dirty || getPersistentState() == NOPE::os_clean);
if (getPersistentState() == NOPE::os_clean)
// the object is clean, just ignore the save
return true;
std::string qs;
qs = "UPDATE < xsl:value-of select = "database/@table" / > SET ";
< xsl:call-template name = "makeSetList" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< / xsl:call-template >
< xsl:call-template name = "makeWhereClause" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< / xsl:call-template >
if (connection.query(qs))
{
if (connection.getAffectedRows() == 1)
{
setPersistentState(NOPE::os_clean);
return true;
}
}
return false;
}
bool < xsl:value-of select = "$className" / > ::remove(MSW::CConnection & connection)
{
nlassert(getPersistentState() == NOPE::os_dirty || getPersistentState() == NOPE::os_clean);
std::string qs;
qs = "DELETE FROM < xsl:value-of select = "database/@table" / > ";
< xsl:call-template name = "makeWhereClause" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< / xsl:call-template >
if (connection.query(qs))
{
if (connection.getAffectedRows() == 1)
{
< xsl:for-each select = "child_class[@on-delete = 'cascade' and @cont='vector']" >
{
// cascading deletion for vector child < xsl:value-of select = "@name" / >
nlassert(load< xsl:value-of select = "@name" / > (connection, __FILE__, __LINE__));
const std::vector < < xsl:value-of select = "@type" / > Ptr > & childs = get< xsl:value-of select = "@name" / > ();
while (!childs.empty())
{
get< xsl:value-of select = "@name" / > ByIndex(childs.size()-1)->remove(connection);
}
}
< / xsl:for-each >
< xsl:for-each select = "child_class[@on-delete = 'cascade' and @cont='map']" >
{
// cascading deletion for map child < xsl:value-of select = "@name" / >
nlassert(load< xsl:value-of select = "@name" / > (connection, __FILE__, __LINE__));
const std::map < uint32, < xsl:value-of select = "@type" / > Ptr > & childs = get< xsl:value-of select = "@name" / > ();
while (!childs.empty())
{
get< xsl:value-of select = "@name" / > ById(childs.begin()->first)->remove(connection);
}
}
< / xsl:for-each >
< xsl:for-each select = "child_class[@on-delete = 'cascade' and @relation='one-to-one']" >
{
// cascading deletion for single child < xsl:value-of select = "@name" / >
nlassert(load< xsl:value-of select = "@name" / > (connection, __FILE__, __LINE__));
if (get< xsl:value-of select = "@name" / > () != NULL)
get< xsl:value-of select = "@name" / > ()->remove(connection);
}
< / xsl:for-each >
< xsl:for-each select = "child_class[@on-delete = 'update' and @cont='vector']" >
{
// unreference (and update) for vector child < xsl:value-of select = "@name" / >
nlassert(load< xsl:value-of select = "@name" / > (connection, __FILE__, __LINE__));
const std::vector < < xsl:value-of select = "@type" / > Ptr > & childs = get< xsl:value-of select = "@name" / > ();
for (uint i=0; i < childs.size(); ++i)
{
< xsl:variable name = "type" select = "@type" / >
< xsl:variable name = "child_name" select = "@name" / >
< xsl:variable name = "parent_prop" select = "//class[@name = $type]/property[@db_col = //class[@name = $type]/parent[@class = $className]/@db_col]/@name" / >
get< xsl:value-of select = "@name" / > ByIndex(i)->set< xsl:value-of select = "$parent_prop" / > (0);
get< xsl:value-of select = "@name" / > ByIndex(i)->update(connection);
}
}
< / xsl:for-each >
< xsl:for-each select = "child_class[@on-delete = 'update' and @cont='map']" >
{
// unreference (and update) for map child < xsl:value-of select = "@name" / >
nlassert(load< xsl:value-of select = "@name" / > (connection, __FILE__, __LINE__));
const std::map < uint32, < xsl:value-of select = "@type" / > Ptr > & childs = get< xsl:value-of select = "@name" / > ();
std::map< uint32, < xsl:value-of select = "@type" / > Ptr > ::const_iterator first(childs.begin()), last(childs.end());
for (; first != last; ++first)
{
< xsl:variable name = "type" select = "@type" / >
< xsl:variable name = "child_name" select = "@name" / >
< xsl:variable name = "parent_prop" select = "//class[@name = $type]/property[@db_col = //class[@name = $type]/parent[@class = $className]/@db_col]/@name" / >
get< xsl:value-of select = "@name" / > ById(it->first)->set< xsl:value-of select = "$parent_prop" / > (0);
get< xsl:value-of select = "@name" / > ById(it->first)->update(connection);
}
}
< / xsl:for-each >
< xsl:for-each select = "child_class[@on-delete = 'update' and @relation='one-to-one']" >
{
// unreference (and update) for single child < xsl:value-of select = "@name" / >
nlassert(load< xsl:value-of select = "@name" / > (connection, __FILE__, __LINE__));
< xsl:variable name = "type" select = "@type" / >
< xsl:variable name = "child_name" select = "@name" / >
< xsl:variable name = "parent_prop" select = "//class[@name = $type]/property[@db_col = //class[@name = $type]/parent[@class = $className]/@db_col]/@name" / >
if (get< xsl:value-of select = "@name" / > () != NULL)
{
get< xsl:value-of select = "@name" / > ()->set< xsl:value-of select = "parent_prop" / > (0);
get< xsl:value-of select = "@name" / > ()->update(connection);
}
}
< / xsl:for-each >
// change the persistant state to 'removed'.
setPersistentState(NOPE::os_removed);
// need to remove ref from parent class container (if any)
< xsl:for-each select = "parent[@relation = 'one-to-many']" >
{
< xsl:variable name = "db_col" select = "@db_col" / >
< xsl:if test = "count(../property[@db_col = $db_col]) = 0" >
< xsl:message terminate = "yes" >
ERROR : parent/child relation : can't find parent param with db_col '< xsl:value-of select = "$db_col" / > ' in < xsl:value-of select = "$className" / > definition
< / xsl:message >
< / xsl:if >
< xsl:value-of select = "@class" / > Ptr parent(< xsl:value-of select = "@class" / > ::loadFromCache(_< xsl:value-of select = "../property[@db_col = $db_col]/@name" / > , true), __FILE__, __LINE__);
if (parent != NULL & & parent->_< xsl:value-of select = "@child_name" / > != NULL)
{
< xsl:choose >
< xsl:when test = "@cont = 'map'" >
parent->_< xsl:value-of select = "@child_name" / > ->erase(getObjectId());
< / xsl:when >
< xsl:when test = "@cont = 'vector'" >
std::vector < < xsl:value-of select = "$className" / > Ptr > ::iterator it = std::find(parent->_< xsl:value-of select = "@child_name" / > ->begin(), parent->_< xsl:value-of select = "@child_name" / > ->end(), this);
if (it != parent->_< xsl:value-of select = "@child_name" / > ->end())
{
parent->_< xsl:value-of select = "@child_name" / > ->erase(it);
}
< / xsl:when >
< xsl:otherwise >
< xsl:message terminate = "yes" >
ERROR : parent/child relation support only 'map' or 'vector' cont specification in < xsl:value-of select = "$className" / > definition
< / xsl:message >
< / xsl:otherwise >
< / xsl:choose >
}
}
< / xsl:for-each >
// need to remove ref from parent (if any)
< xsl:for-each select = "parent[@relation = 'one-to-one']" >
{
< xsl:variable name = "db_col" select = "@db_col" / >
< xsl:value-of select = "@class" / > Ptr parent(< xsl:value-of select = "@class" / > ::loadFromCache(_< xsl:value-of select = "../property[@db_col = $db_col]/@name" / > , true), __FILE__, __LINE__);
if (parent != NULL & & parent->_< xsl:value-of select = "@child_name" / > Loaded)
{
// assign a new NULL pointer
parent->_< xsl:value-of select = "@child_name" / > .assign(< xsl:value-of select = "$className" / > Ptr(), __FILE__, __LINE__);
}
}
< / xsl:for-each >
return true;
}
}
return false;
}
bool < xsl:value-of select = "$className" / > ::removeById(MSW::CConnection & connection, uint32 id)
{
< xsl:value-of select = "$className" / > *object = loadFromCache(id, true);
if (object != NULL)
{
return object->remove(connection);
}
// not in cache, run a SQL query
std::string qs;
qs = "DELETE FROM < xsl:value-of select = "database/@table" / > ";
< xsl:call-template name = "makeWhereClauseWithId" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< xsl:with-param name = "id" select = "'id'" / >
< / xsl:call-template >
if (connection.query(qs))
{
if (connection.getAffectedRows() == 1)
{
// ok, the row is removed
return true;
}
}
return false;
}
// Try to load the specified object from the memory cache, return NULL if the object is not in the cache
< xsl:value-of select = "$className" / > *< xsl:value-of select = "$className" / > ::loadFromCache(uint32 objectId, bool unrelease)
{
// look in the cache
TObjectCache::iterator it(_ObjectCache.find(objectId));
if (it == _ObjectCache.end())
{
// not found, return null
return NULL;
}
else
{
< xsl:value-of select = "$className" / > *object = it->second;
if (object->_ObjectState == NOPE::os_released)
{
if (unrelease)
{
// we need to remove this object from the released object set.
object->removeFromReleased();
object->_ObjectState = NOPE::os_clean;
}
}
return it->second;
}
}
// Receive and execute command from the cache manager.
uint32 < xsl:value-of select = "$className" / > ::cacheCmd(NOPE::TCacheCmd cmd)
{
if (cmd == NOPE::cc_update)
{
updateCache();
}
else if (cmd == NOPE::cc_clear)
{
clearCache();
}
else if (cmd == NOPE::cc_dump)
{
dump();
}
else if (cmd == NOPE::cc_instance_count)
{
return _ObjectCache.size();
}
// default return value
return 0;
}
void < xsl:value-of select = "$className" / > ::dump()
{
nlinfo(" Cache info for class < xsl:value-of select = "$className" / > :");
nlinfo(" There are %u object instances in cache", _ObjectCache.size());
// count the number of object in the released object set
uint32 nbReleased = 0;
TReleasedObject::iterator first(_ReleasedObject.begin()), last(_ReleasedObject.end());
for (; first != last; ++first)
{
nbReleased += first->second.size();
}
nlinfo(" There are %u object instances in cache not referenced (waiting deletion or re-use))", nbReleased);
}
void < xsl:value-of select = "$className" / > ::updateCache()
{
if (_ReleasedObject.empty())
return;
// 30 s hold in cache
const time_t MAX_CACHE_OLD_TIME = 30;
time_t now = NLMISC::CTime::getSecondsSince1970();
// look for object set older than MAX_CACHE_OLD_TIME and delete them
while (!_ReleasedObject.empty() & & _ReleasedObject.begin()-> first < now-MAX_CACHE_OLD_TIME)
{
TObjectSet & delSet = _ReleasedObject.begin()->second;
// unload this objects
while (!delSet.empty())
{
< xsl:value-of select = "$className" / > *object = *delSet.begin();
delete object;
}
_ReleasedObject.erase(_ReleasedObject.begin());
}
}
void < xsl:value-of select = "$className" / > ::clearCache()
{
// remove any unreferenced object from the cache
while (!_ReleasedObject.empty())
{
TObjectSet & delSet = _ReleasedObject.begin()->second;
// unload this objects
while (!delSet.empty())
{
< xsl:value-of select = "$className" / > *object = *delSet.begin();
delete object;
}
_ReleasedObject.erase(_ReleasedObject.begin());
}
}
void < xsl:value-of select = "$className" / > ::registerUpdatable()
{
static bool registered = false;
if (!registered)
{
NOPE::CPersistentCache::getInstance().registerCache(& < xsl:value-of select = "$className" / > ::cacheCmd);
registered = true;
}
}
// set the pointer on the first pointer of the pointer list (set to null when there is no more pointer)
void < xsl:value-of select = "$className" / > ::setFirstPtr(< xsl:value-of select = "$className" / > Ptr *ptr)
{
_PtrList = ptr;
if (ptr == NULL)
{
// this is the last pointer !
if (_ObjectState == NOPE::os_transient
|| _ObjectState == NOPE::os_removed)
{
// not a persistent object, or removed object, just delet it
delete this;
}
else if (_ObjectState != NOPE::os_removed)
{
setPersistentState(NOPE::os_released);
}
}
}
// Set the persistent state of the object and do some house keeping
void < xsl:value-of select = "$className" / > ::setPersistentState(NOPE::TObjectState state)
{
nlassert(NOPE::AllowedTransition[_ObjectState][state] == true);
if(_ObjectState == NOPE::os_released & & state == NOPE::os_removed)
{
// a release object gets removed (e.g. by remove by id)
// delete the object
delete this;
// no more to do
return;
}
if (_ObjectState == NOPE::os_transient & & state != NOPE::os_transient)
{
nldebug("NOPE: inserting < xsl:value-of select = "$className" / > @%p in cache with id %u", this, static_cast< uint32> (_< xsl:value-of select = "$uniqueId" / > ));
nlverify(_ObjectCache.insert(std::make_pair(_< xsl:value-of select = "$uniqueId" / > , this)).second);
}
if (_ObjectState != NOPE::os_transient)
nlassert(_ObjectCache.find(_< xsl:value-of select = "$uniqueId" / > ) != _ObjectCache.end());
_ObjectState = state;
if (state == NOPE::os_released)
{
_ReleaseDate = NLMISC::CTime::getSecondsSince1970();
nlverify(_ReleasedObject[_ReleaseDate].insert(this).second);
}
else if (state == NOPE::os_removed)
{
nldebug("NOPE: erasing < xsl:value-of select = "$className" / > @%p in cache with id %u", this, static_cast< uint32> (_< xsl:value-of select = "$uniqueId" / > ));
nlverify(_ObjectCache.erase(_< xsl:value-of select = "$uniqueId" / > ) == 1);
}
}
< xsl:value-of select = "$className" / > Ptr < xsl:value-of select = "$className" / > ::load(MSW::CConnection & connection, uint32 id, const char *filename, uint32 lineNum)
{
< xsl:value-of select = "$className" / > *inCache = loadFromCache(id, true);
if (inCache != NULL)
{
return < xsl:value-of select = "$className" / > Ptr(inCache, filename, lineNum);
}
std::string qs;
qs = "SELECT ";
< xsl:call-template name = "makeColumListWithId" / >
qs += " FROM < xsl:value-of select = "database/@table" / > ";
< xsl:call-template name = "makeWhereClauseWithId" >
< xsl:with-param name = "uniqueId" select = "$uniqueId" / >
< xsl:with-param name = "id" select = "'id'" / >
< / xsl:call-template >
< xsl:value-of select = "$className" / > Ptr ret;
if (!connection.query(qs))
{
return ret;
}
MSW::CStoreResult *result = connection.storeResult().release();
nlassert(result->getNumRows() < = 1);
if (result->getNumRows() == 1)
{
ret.assign(new < xsl:value-of select = "$className" / > , filename, lineNum);
// ok, we have an object
result->fetchRow();< xsl:text >
< / xsl:text > < xsl:for-each select = "property[@db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
< xsl:text > {
std::string s;
result->getField(< / xsl:text > < xsl:value-of select = "position()-1" / > , s);
ret->_< xsl:value-of select = "@name" / > = < xsl:value-of select = "@type" / > < xsl:text > (s);
}
< / xsl:text >
< / xsl:when >
< xsl:when test = "@date='true'" >
< xsl:text > result->getDateField(< / xsl:text > < xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > )< xsl:text > ;
< / xsl:text >
< / xsl:when >
< xsl:when test = "@md5='true'" >
< xsl:text > result->getMD5Field(< / xsl:text > < xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > )< xsl:text > ;
< / xsl:text >
< / xsl:when >
< xsl:otherwise >
< xsl:text > result->getField(< / xsl:text > < xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > )< xsl:text > ;
< / xsl:text >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
ret->setPersistentState(NOPE::os_clean);
}
delete result;
return ret;
}
< xsl:for-each select = "parent[@relation = 'one-to-many']" >
< xsl:choose >
< xsl:when test = "@cont='map'" >
bool < xsl:value-of select = "$className" / > ::loadChildrenOf< xsl:value-of select = "@class" / > (MSW::CConnection & connection, uint32 parentId, std::map < uint32, < xsl:value-of select = "$className" / > Ptr > & container, const char *filename, uint32 lineNum)
< / xsl:when >
< xsl:when test = "@cont='vector'" >
bool < xsl:value-of select = "$className" / > ::loadChildrenOf< xsl:value-of select = "@class" / > (MSW::CConnection & connection, uint32 parentId, std::vector < < xsl:value-of select = "$className" / > Ptr > & container, const char *filename, uint32 lineNum)
< / xsl:when >
< xsl:otherwise >
< xsl:message terminate = "yes" >
ERROR : parent/child relation support only 'map' or 'vector' cont specification in < xsl:value-of select = "$className" / > , < xsl:value-of select = "@class" / > parent definition
< / xsl:message >
< / xsl:otherwise >
< / xsl:choose >
{
std::string qs;
qs = "SELECT ";
< xsl:for-each select = ".." >
< xsl:call-template name = "makeColumListWithId" / >
< / xsl:for-each >
qs += " FROM < xsl:value-of select = "../database/@table" / > ";
qs += " WHERE < xsl:value-of select = "@db_col" / > = '"+NLMISC::toString(parentId)+"'";
if (!connection.query(qs))
{
return false;
}
std::auto_ptr< MSW::CStoreResult> result = connection.storeResult();
for (uint i=0; i< result->getNumRows(); ++i)
{
< xsl:value-of select = "$className" / > *ret = new < xsl:value-of select = "$className" / > ();
// ok, we have an object
result->fetchRow();
< xsl:for-each select = "../property[@db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
{
std::string s;
result->getField(< xsl:value-of select = "position()-1" / > , s);
ret->_< xsl:value-of select = "@name" / > = < xsl:value-of select = "@type" / > (s);
}
< / xsl:when >
< xsl:when test = "@date='true'" >
result->getDateField(< xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > );
< / xsl:when >
< xsl:when test = "@md5='true'" >
result->getMD5Field(< xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > );
< / xsl:when >
< xsl:otherwise >
result->getField(< xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > );
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:value-of select = "$className" / > *inCache = loadFromCache(ret->_< xsl:value-of select = "$uniqueId" / > , true);
if (inCache != NULL)
{
< xsl:choose >
< xsl:when test = "@cont='map'" >
container.insert(std::make_pair(inCache->getObjectId(), < xsl:value-of select = "$className" / > Ptr(inCache, filename, lineNum)));
< / xsl:when >
< xsl:when test = "@cont='vector'" >
container.push_back(< xsl:value-of select = "$className" / > Ptr(inCache, filename, lineNum));
< / xsl:when >
< / xsl:choose >
// no more needed
delete ret;
}
else
{
ret->setPersistentState(NOPE::os_clean);
< xsl:choose >
< xsl:when test = "@cont='map'" >
container.insert(std::make_pair(ret->getObjectId(), < xsl:value-of select = "$className" / > Ptr(ret, filename, lineNum)));
< / xsl:when >
< xsl:when test = "@cont='vector'" >
container.push_back(< xsl:value-of select = "$className" / > Ptr(ret, filename, lineNum));
< / xsl:when >
< / xsl:choose >
}
}
return true;
}
< / xsl:for-each >
< xsl:for-each select = "parent[@relation = 'one-to-one']" >
< xsl:text > bool < / xsl:text > < xsl:value-of select = "$className" / > ::loadChildOf< xsl:value-of select = "@class" / > (MSW::CConnection & connection, uint32 parentId, < xsl:value-of select = "../@name" / > Ptr & childPtr, const char *filename, uint32 lineNum)
{
std::string qs;
qs = "SELECT ";
< xsl:for-each select = ".." >
< xsl:call-template name = "makeColumListWithId" / >
< / xsl:for-each >
qs += " FROM < xsl:value-of select = "../database/@table" / > ";
qs += " WHERE < xsl:value-of select = "@db_col" / > = '"+NLMISC::toString(parentId)+"'";
< xsl:value-of select = "$className" / > Ptr ret;
if (!connection.query(qs))
{
childPtr = < xsl:value-of select = "../@name" / > Ptr();
return false;
}
std::auto_ptr< MSW::CStoreResult> result = connection.storeResult();
// check that the data description is consistent with database content
nlassert(result->getNumRows() < = 1);
if (result->getNumRows() == 1)
{
< xsl:value-of select = "$className" / > *object = new < xsl:value-of select = "$className" / > ;
// ok, we have an object
result->fetchRow();
< xsl:for-each select = "../property[@db_col]" >
< xsl:choose >
< xsl:when test = "@enum='true' or @enum='smart'" >
{
std::string s;
result->getField(< xsl:value-of select = "position()-1" / > , s);
object->_< xsl:value-of select = "@name" / > = < xsl:value-of select = "@type" / > (s);
}
< / xsl:when >
< xsl:when test = "@date='true'" >
result->getDateField(< xsl:value-of select = "position()-1" / > , object->_< xsl:value-of select = "@name" / > );
< / xsl:when >
< xsl:when test = "@md5='true'" >
result->getMD5Field(< xsl:value-of select = "position()-1" / > , ret->_< xsl:value-of select = "@name" / > );
< / xsl:when >
< xsl:otherwise >
result->getField(< xsl:value-of select = "position()-1" / > , object->_< xsl:value-of select = "@name" / > );
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:value-of select = "$className" / > *inCache = loadFromCache(object->_< xsl:value-of select = "$uniqueId" / > , true);
if (inCache != NULL)
{
ret.assign(inCache, filename, lineNum);
// no more needed
delete object;
}
else
{
object->setPersistentState(NOPE::os_clean);
ret.assign(object, filename, lineNum);
}
childPtr = ret;
return true;
}
// no result, but no error
childPtr = < xsl:value-of select = "../@name" / > Ptr();
return true;
}
< / xsl:for-each >
< xsl:for-each select = "child_class[@relation = 'one-to-many']" >
bool < xsl:value-of select = "$className" / > ::load< xsl:value-of select = "@name" / > (MSW::CConnection & connection, const char *filename, uint32 lineNum)
{
bool ret = true;
if (_< xsl:value-of select = "@name" / > != NULL)
{
// the children are already loaded, just return true
return true;
}
// allocate the container
< xsl:choose >
< xsl:when test = "@cont = 'map'" > _< xsl:value-of select = "@name" / > = new std::map < uint32, < xsl:value-of select = "@type" / > Ptr > ;< / xsl:when >
< xsl:when test = "@cont = 'vector'" > _< xsl:value-of select = "@name" / > = new std::vector < < xsl:value-of select = "@type" / > Ptr > ;< / xsl:when >
< / xsl:choose >
// load the childs
ret & = < xsl:value-of select = "@type" / > ::loadChildrenOf< xsl:value-of select = "../@name" / > (connection, getObjectId(), *_< xsl:value-of select = "@name" / > , filename, lineNum);
return ret;
}
< xsl:choose >
< xsl:when test = "@cont = 'vector'" >
const std::vector< < xsl:value-of select = "@type" / > Ptr> & < xsl:value-of select = "$className" / > ::get< xsl:value-of select = "@name" / > () const
{
nlassert(_< xsl:value-of select = "@name" / > != NULL);
return *_< xsl:value-of select = "@name" / > ;
}
< xsl:value-of select = "@type" / > Ptr & < xsl:value-of select = "$className" / > ::get< xsl:value-of select = "@name" / > ByIndex(uint32 index) const
{
nlassert(_< xsl:value-of select = "@name" / > != NULL);
nlassert(index < _< xsl:value-of select = "@name" / > ->size());
return const_cast< < xsl:value-of select = "@type" / > Ptr & > (_< xsl:value-of select = "@name" / > ->operator[](index));
}
< xsl:value-of select = "@type" / > Ptr & < xsl:value-of select = "$className" / > ::get< xsl:value-of select = "@name" / > ById(uint32 id) const
{
nlassert(_< xsl:value-of select = "@name" / > != NULL);
std::vector< < xsl:value-of select = "@type" / > Ptr > ::const_iterator first(_< xsl:value-of select = "@name" / > ->begin()), last(_< xsl:value-of select = "@name" / > ->end());
for (; first != last; ++first)
{
const < xsl:value-of select = "@type" / > Ptr & child = *first;
if (child->getObjectId() == id)
{
return const_cast< < xsl:value-of select = "@type" / > Ptr & > (child);
}
}
// no object with this id, return a null pointer
static < xsl:value-of select = "@type" / > Ptr nil;
return nil;
}
< / xsl:when >
< xsl:when test = "@cont = 'map'" >
const std::map< uint32, < xsl:value-of select = "@type" / > Ptr> & < xsl:value-of select = "$className" / > ::get< xsl:value-of select = "@name" / > () const
{
nlassert(_< xsl:value-of select = "@name" / > != NULL);
return *_< xsl:value-of select = "@name" / > ;
}
< xsl:value-of select = "@type" / > Ptr & < xsl:value-of select = "$className" / > ::get< xsl:value-of select = "@name" / > ById(uint32 id) const
{
nlassert(_< xsl:value-of select = "@name" / > != NULL);
std::map< uint32, < xsl:value-of select = "@type" / > Ptr> ::const_iterator it(_< xsl:value-of select = "@name" / > ->find(id));
if (it == _< xsl:value-of select = "@name" / > ->end())
{
// no object with this id, return a null pointer
static < xsl:value-of select = "@type" / > Ptr nil;
return nil;
}
return const_cast< < xsl:value-of select = "@type" / > Ptr & > (it->second);
}
< / xsl:when >
< xsl:otherwise >
< xsl:message terminate = "yes" >
ERROR : Invalide container, child must be either map or vector for child < xsl:value-of select = "@name" / > in class < xsl:value-of select = "../@name" / > < xsl:text >
< / xsl:text >
< / xsl:message >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:for-each select = "child_class[@relation = 'one-to-one']" >
bool < xsl:value-of select = "$className" / > ::load< xsl:value-of select = "@name" / > (MSW::CConnection & connection, const char *filename, uint32 lineNum)
{
if (_< xsl:value-of select = "@name" / > Loaded)
{
// the child is already loaded, just return true
return true;
}
bool ret = < xsl:value-of select = "@type" / > ::loadChildOf< xsl:value-of select = "../@name" / > (connection, getObjectId(), _< xsl:value-of select = "@name" / > , filename, lineNum);
_< xsl:value-of select = "@name" / > Loaded = true;
return ret;
}
/** Return the one child object (or null if not) */
< xsl:value-of select = "@type" / > Ptr < xsl:value-of select = "$className" / > ::get< xsl:value-of select = "@name" / > ()
{
nlassert(_< xsl:value-of select = "@name" / > Loaded);
return _< xsl:value-of select = "@name" / > ;
}
< / xsl:for-each >
< / xsl:if >
< / xsl:template >
<!-- ################################################################# -->
<!-- ##### C++ Layer 3 interface generation (server mode) ### -->
<!-- ################################################################# -->
<!-- ##### header file #### -->
< xsl:template match = "callback_interface" mode = "header" >
< xsl:call-template name = "makeMasterDoc" / >
< xsl:choose >
< xsl:when test = "@extend" >
class < xsl:value-of select = "@name" / > Itf : public < xsl:value-of select = "@extend" / > Itf
< / xsl:when >
< xsl:otherwise >
class < xsl:value-of select = "@name" / > Itf <!-- : public NLNET::CCallbackServer -->
< / xsl:otherwise >
< / xsl:choose >
{
protected:
< xsl:if test = "not(@extend)" >
/// the callback server adaptor
std::auto_ptr< ICallbackServerAdaptor> _CallbackServer;
< / xsl:if >
void getCallbakArray(NLNET::TCallbackItem *& arrayPtr, uint32 & arraySize)
{
static NLNET::TCallbackItem callbackArray[] =
{
< xsl:for-each select = "invoke" > { "< xsl:value-of select = "@msg" / > ", < xsl:value-of select = "../@name" / > Itf::cb_< xsl:value-of select = "@name" / > },
< / xsl:for-each >
};
arrayPtr = callbackArray;
arraySize = sizeofarray(callbackArray);
}
static void _cbConnection(NLNET::TSockId from, void *arg)
{
H_AUTO(< xsl:value-of select = "@name" / > __cbConnection);
< xsl:value-of select = "@name" / > Itf *_this = reinterpret_cast< < xsl:value-of select = "@name" / > Itf *> (arg);
_this->on_< xsl:value-of select = "@name" / > _Connection(from);
}
static void _cbDisconnection(NLNET::TSockId from, void *arg)
{
H_AUTO(< xsl:value-of select = "@name" / > __cbDisconnection);
< xsl:value-of select = "@name" / > Itf *_this = reinterpret_cast< < xsl:value-of select = "@name" / > Itf *> (arg);
_this->on_< xsl:value-of select = "@name" / > _Disconnection(from);
}
public:
/** Constructor, if you specify a replacement adaptor, then the object
* become owner of the adaptor (and it will be released with the
* interface).
*/
< xsl:if test = "@extend" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > Itf(ICallbackServerAdaptor *replacementAdaptor = NULL)
: < xsl:value-of select = "@extend" / > Itf(replacementAdaptor)
{}
< / xsl:if >
< xsl:if test = "not(@extend)" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > Itf(ICallbackServerAdaptor *replacementAdaptor = NULL)
{
if (replacementAdaptor == NULL)
{
// use default callback server
_CallbackServer = std::auto_ptr< ICallbackServerAdaptor> (new CNelCallbackServerAdaptor(this));
}
else
{
// use the replacement one
_CallbackServer = std::auto_ptr< ICallbackServerAdaptor> (replacementAdaptor);
}
}
< / xsl:if >
virtual ~< xsl:value-of select = "@name" / > Itf()
{
}
/// Open the interface socket in the specified port
void openItf(uint16 port)
{
NLNET::TCallbackItem *arrayPtr;
uint32 arraySize;
< xsl:if test = "@extend" >
// add callback array of the base interface class
< xsl:value-of select = "@extend" / > Itf::getCallbakArray(arrayPtr, arraySize);
_CallbackServer->addCallbackArray(arrayPtr, arraySize);
< / xsl:if >
getCallbakArray(arrayPtr, arraySize);
_CallbackServer->addCallbackArray(arrayPtr, arraySize);
_CallbackServer->setConnectionCallback (_cbConnection, this);
_CallbackServer->setDisconnectionCallback (_cbDisconnection, this);
_CallbackServer->init(port);
}
/** Must be called evenly, update the network subclass to receive message
* and dispatch method invokation.
*/
void update()
{
H_AUTO(< xsl:value-of select = "@name" / > _update);
try
{
_CallbackServer->update();
}
catch (...)
{
nlwarning("< xsl:value-of select = "@name" / > : Exception launch in callback server update");
}
}
< xsl:for-each select = "return" >
< xsl:call-template name = "makeMethodDoc" / >
void < xsl:value-of select = "@name" / > (NLNET::TSockId dest< xsl:call-template name = "makeParamList" / > )
{
H_AUTO(< xsl:value-of select = "@name" / > _< xsl:value-of select = "@name" / > );
#ifdef NL_DEBUG
nldebug("< xsl:value-of select = "../@name" / > ::< xsl:value-of select = "@name" / > called");
#endif
NLNET::CMessage message("< xsl:value-of select = "@msg" / > ");
< xsl:for-each select = "param" >
< xsl:call-template name = "serialWrite" / >
< / xsl:for-each >
_CallbackServer->send(message, dest);
}
< / xsl:for-each >
< xsl:for-each select = "invoke" >
static void cb_< xsl:value-of select = "@name" / > (NLNET::CMessage & message, NLNET::TSockId from, NLNET::CCallbackNetBase & netbase)
{
H_AUTO(< xsl:value-of select = "@name" / > _on_< xsl:value-of select = "@name" / > );
#ifdef NL_DEBUG
nldebug("< xsl:value-of select = "../@name" / > ::cb_< xsl:value-of select = "@name" / > received from class '%s'", typeid(netbase).name());
#endif
ICallbackServerAdaptor *adaptor = static_cast< ICallbackServerAdaptor *> (netbase.getUserData());
< xsl:value-of select = "../@name" / > Itf *callback = (< xsl:value-of select = "../@name" / > Itf *)adaptor->getContainerClass();
if (callback == NULL)
return;
< xsl:for-each select = "param" >
< xsl:if test = "not(@array)" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ;< xsl:text >
< / xsl:text >
< / xsl:if >
< xsl:if test = "@array = 'true'" >
< xsl:text > < / xsl:text > std::vector< < xsl:value-of select = "@type" / > > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ;< xsl:text >
< / xsl:text >
< / xsl:if >
< / xsl:for-each >
< xsl:for-each select = "param" >
< xsl:call-template name = "serialRead" / >
< / xsl:for-each >
#ifdef NL_DEBUG
nldebug("< xsl:value-of select = "../@name" / > ::cb_< xsl:value-of select = "@name" / > : calling on_< xsl:value-of select = "@name" / > ");
#endif
< xsl:if test = "not(return)" >
callback->on_< xsl:value-of select = "@name" / > (from< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
< / xsl:if >
< xsl:if test = "return" >
< xsl:if test = "not(return/@array)" >
< xsl:text > < / xsl:text > < xsl:value-of select = "return/@type" / > retValue;
< / xsl:if >
< xsl:if test = "return/@array" >
< xsl:text > std::vector< < / xsl:text > < xsl:value-of select = "return/@type" / > > retValue;
< / xsl:if >
retValue = callback->on_< xsl:value-of select = "@name" / > (from< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
NLNET::CMessage retMsg("R_< xsl:value-of select = "@msg" / > ");
< xsl:if test = "not(return/@array)" >
nlWrite(retMsg, serial< xsl:value-of select = "return/@serial" / > , retValue);
< / xsl:if >
< xsl:if test = "return/@array" >
nlWrite(retMsg, serialCont, retValue);
< / xsl:if >
callback->_CallbackServer->send(retMsg, from);
< / xsl:if >
}
< / xsl:for-each >
/// Connection callback : a new interface client connect
virtual void on_< xsl:value-of select = "@name" / > _Connection(NLNET::TSockId from) =0;
/// Disconnection callback : one of the interface client disconnect
virtual void on_< xsl:value-of select = "@name" / > _Disconnection(NLNET::TSockId from) =0;
< xsl:for-each select = "invoke" > < xsl:text >
< / xsl:text > < xsl:call-template name = "makeMethodDoc" / >
< xsl:if test = "not(return)" >
< xsl:text > virtual void on_< / xsl:text > < xsl:value-of select = "@name" / > (NLNET::TSockId from< xsl:call-template name = "makeParamList" / > ) =0;
< / xsl:if >
< xsl:if test = "return" >
< xsl:if test = "not(return/@array)" >
< xsl:text > virtual < / xsl:text > < xsl:value-of select = "return/@type" / > on_< xsl:value-of select = "@name" / > (NLNET::TSockId from< xsl:call-template name = "makeParamList" / > ) =0;
< / xsl:if >
< xsl:if test = "return/@array" >
< xsl:text > virtual std::vector< < / xsl:text > < xsl:value-of select = "return/@type" / > > on_< xsl:value-of select = "@name" / > (NLNET::TSockId from< xsl:call-template name = "makeParamList" / > ) =0;
< / xsl:if >
< / xsl:if >
< / xsl:for-each >
};
<!-- Callback interface client class -->
< xsl:call-template name = "makeMasterDoc" / >
/** This is the client side of the interface
* Derive from this class to invoke method on the callback server
*/
< xsl:choose >
< xsl:when test = "@extend" >
class < xsl:value-of select = "@name" / > ClientItf : public < xsl:value-of select = "@extend" / > ClientItf
< / xsl:when >
< xsl:otherwise >
class < xsl:value-of select = "@name" / > ClientItf <!-- : public NLNET::CCallbackClient -->
< / xsl:otherwise >
< / xsl:choose >
{
protected:
< xsl:if test = "not(@extend)" >
/// the callback client adaptor
std::auto_ptr < ICallbackClientAdaptor > _CallbackClient;
< / xsl:if >
void getCallbakArray(NLNET::TCallbackItem *& arrayPtr, uint32 & arraySize)
{
< xsl:if test = "not(return)" >
arrayPtr = NULL;
arraySize = 0;
< / xsl:if >
< xsl:if test = "return" >
static NLNET::TCallbackItem callbackArray[] =
{
< xsl:for-each select = "return" > { "< xsl:value-of select = "@msg" / > ", < xsl:value-of select = "../@name" / > ClientItf::cb_< xsl:value-of select = "@name" / > },
< / xsl:for-each >
};
arrayPtr = callbackArray;
arraySize = sizeofarray(callbackArray);
< / xsl:if >
}
static void _cbDisconnection(NLNET::TSockId from, void *arg)
{
< xsl:value-of select = "@name" / > ClientItf *_this = reinterpret_cast< < xsl:value-of select = "@name" / > ClientItf *> (arg);
_this->on_< xsl:value-of select = "@name" / > Client_Disconnection(from);
}
public:
/// Retreive the message name for a given callback name
static const std::string & getMessageName(const std::string & methodName)
{
static std::map< std::string, std::string> messageNames;
static bool initialized = false;
if (!initialized)
{
< xsl:for-each select = "return" > messageNames.insert(std::make_pair(std::string("on_< xsl:value-of select = "@name" / > "), std::string("< xsl:value-of select = "@msg" / > ")));
< / xsl:for-each >
initialized = true;
}
std::map < std::string, std::string> ::const_iterator it(messageNames.find(methodName));
if (it != messageNames.end())
return it->second;
< xsl:if test = "@extend" >
// try with the base class
return < xsl:value-of select = "@extend" / > ClientItf::getMessageName(methodName);
< / xsl:if >
< xsl:if test = "not(@extend)" >
static std::string emptyString;
return emptyString;
< / xsl:if >
}
< xsl:if test = "@extend" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ClientItf(ICallbackClientAdaptor *adaptorReplacement = NULL)
: < xsl:value-of select = "@extend" / > ClientItf(adaptorReplacement)
{}
< / xsl:if >
< xsl:if test = "not(@extend)" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ClientItf(ICallbackClientAdaptor *adaptorReplacement = NULL)
{
if (adaptorReplacement == NULL)
{
// use the default Nel adaptor
_CallbackClient = std::auto_ptr < ICallbackClientAdaptor > (new CNelCallbackClientAdaptor(this));
}
else
{
// use the replacement one
_CallbackClient = std::auto_ptr < ICallbackClientAdaptor > (adaptorReplacement);
}
}
< / xsl:if >
/// Connect the interface client to the callback server at the specified address and port
virtual void connectItf(NLNET::CInetAddress address)
{
NLNET::TCallbackItem *arrayPtr;
uint32 arraySize;
static bool callbackAdded = false;
if (!callbackAdded)
{
< xsl:if test = "@extend" >
// add callback array of the base interface class
< xsl:value-of select = "@extend" / > ClientItf::getCallbakArray(arrayPtr, arraySize);
_CallbackClient->addCallbackArray(arrayPtr, arraySize);
callbackAdded = true;
// add callback array of this interface
< / xsl:if >
getCallbakArray(arrayPtr, arraySize);
_CallbackClient->addCallbackArray(arrayPtr, arraySize);
}
_CallbackClient->setDisconnectionCallback (_cbDisconnection, this);
_CallbackClient->connect(address);
}
/** Must be called evenly, update the network subclass to receive message
* and dispatch invokation returns.
*/
virtual void update()
{
H_AUTO(< xsl:value-of select = "@name" / > _update);
try
{
_CallbackClient->update();
}
catch (...)
{
nlwarning("< xsl:value-of select = "@name" / > : Exception launch in callback client update");
}
}
< xsl:for-each select = "invoke" >
< xsl:call-template name = "makeMethodDoc" / >
void < xsl:value-of select = "@name" / > (< xsl:call-template name = "makeParamListNoStartingComma" / > )
{
#ifdef NL_DEBUG
nldebug("< xsl:value-of select = "../@name" / > Client::< xsl:value-of select = "@name" / > called");
#endif
NLNET::CMessage message("< xsl:value-of select = "@msg" / > ");
< xsl:for-each select = "param" >
< xsl:call-template name = "serialWrite" / >
< / xsl:for-each >
_CallbackClient->send(message);
}
< / xsl:for-each >
< xsl:for-each select = "return" >
static void cb_< xsl:value-of select = "@name" / > (NLNET::CMessage & message, NLNET::TSockId from, NLNET::CCallbackNetBase & netbase)
{
#ifdef NL_DEBUG
nldebug("< xsl:value-of select = "../@name" / > Client::cb_< xsl:value-of select = "@name" / > received from class '%s'", typeid(netbase).name());
#endif
ICallbackClientAdaptor *adaptor = static_cast< ICallbackClientAdaptor *> (netbase.getUserData());
< xsl:value-of select = "../@name" / > ClientItf *callback = (< xsl:value-of select = "../@name" / > ClientItf *)adaptor->getContainerClass();
if (callback == NULL)
return;
< xsl:for-each select = "param" >
< xsl:if test = "not(@array)" >
< xsl:text > < / xsl:text > < xsl:value-of select = "@type" / > < xsl:text > < / xsl:text > < xsl:value-of select = "@name" / > ;< xsl:text >
< / xsl:text >
< / xsl:if >
< xsl:if test = "@array = 'true'" >
< xsl:text > < / xsl:text > std::vector< < xsl:value-of select = "@type" / > > < xsl:value-of select = "@name" / > ;< xsl:text >
< / xsl:text >
< / xsl:if >
< / xsl:for-each >
< xsl:for-each select = "param" >
< xsl:call-template name = "serialRead" / >
< / xsl:for-each >
#ifdef NL_DEBUG
nldebug("< xsl:value-of select = "../@name" / > Client::cb_< xsl:value-of select = "@name" / > : calling on_< xsl:value-of select = "@name" / > ");
#endif
callback->on_< xsl:value-of select = "@name" / > (from< xsl:for-each select = "param" > , < xsl:value-of select = "@name" / > < / xsl:for-each > );
}
< / xsl:for-each >
/// Disconnection callback : the connection to the server is lost
virtual void on_< xsl:value-of select = "@name" / > Client_Disconnection(NLNET::TSockId from) =0;
< xsl:for-each select = "return" > < xsl:text >
< / xsl:text > < xsl:call-template name = "makeMethodDoc" / >
< xsl:text > virtual void on_< / xsl:text > < xsl:value-of select = "@name" / > (NLNET::TSockId from< xsl:call-template name = "makeParamList" / > ) =0;
< / xsl:for-each >
};
< / xsl:template >
<!-- ######################################################### -->
<!-- ##### PHP Layer 3 interface generation ### -->
<!-- ######################################################### -->
<!-- ##### php file #### -->
< xsl:template match = "callback_interface[@caller = 'php']" mode = "php" >
< xsl:if test = ".//param[@type ! = ' uint32 '
and @type != 'uint8'
and @type != 'std::string'
and @enum != 'smart']">
< xsl:message terminate = "yes" >
ERROR : PHP interface only support uint8, uint32, enum and std::string parameter in callback interface '< xsl:value-of select = "@name" / > .< xsl:value-of select = ".//param[@type != 'uint32' and @type != 'uint8' and @type != 'std::string']/../@name" / > '
< / xsl:message >
< / xsl:if >
< xsl:text > < ?php
/////////////////////////////////////////////////////////////////
// WARNING : this is a generated file, don't change it !
/////////////////////////////////////////////////////////////////
require_once('../tools/nel_message.php');
class < / xsl:text > < xsl:value-of select = "@name" / > extends CCallbackClient
{
< xsl:for-each select = "invoke" >
function < xsl:value-of select = "@name" / > (< xsl:call-template name = "makePhpArgListNoFollow" / > )
{
$msg = new CMessage;
$msg->setName("< xsl:value-of select = "@msg" / > ");
< xsl:for-each select = "param" >
< xsl:choose >
< xsl:when test = "@php_serial" >
< xsl:call-template name = "makeWriteSerial" >
< xsl:with-param name = "msgName" select = "'$msg'" / >
< xsl:with-param name = "varName" select = "@name" / >
< xsl:with-param name = "serialName" select = "concat('serial', @php_serial)" / >
< / xsl:call-template >
< / xsl:when >
< xsl:when test = "@enum" >
< xsl:call-template name = "makeWriteSerial" >
< xsl:with-param name = "msgName" select = "'$msg'" / >
< xsl:with-param name = "varName" select = "@name" / >
< xsl:with-param name = "serialName" select = "'serialEnum'" / >
< / xsl:call-template >
< / xsl:when >
< xsl:otherwise >
< xsl:call-template name = "makeWriteSerial" >
< xsl:with-param name = "msgName" select = "'$msg'" / >
< xsl:with-param name = "varName" select = "@name" / >
< xsl:with-param name = "serialName" select = "'serialUint32'" / >
< / xsl:call-template >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:if test = "not(return)" >
return parent::sendMessage($msg);
< / xsl:if >
< xsl:if test = "return" >
<!-- this is a two way call -->
$ret = "";
$ret = parent::sendMessage($msg);
if ($ret == false)
{
// error during send
$this->invokeError("< xsl:value-of select = "@name" / > ", "Error in 'sendMessage'");
return false;
}
$retMsg = parent::waitMessage();
if ($ret == false)
{
// error during send
$this->invokeError("< xsl:value-of select = "@name" / > ", "Error in 'waitMessage'");
return false;
}
if (!($retMsg->MsgName === "R_< xsl:value-of select = "@msg" / > "))
{
// error during send
$this->invokeError("< xsl:value-of select = "@name" / > ", "Invalid response, awaited 'R_< xsl:value-of select = "@msg" / > ', received '".$retMsg->MsgName."'");
return false;
}
// serial the return value
< xsl:choose >
< xsl:when test = "return/@php_serial" >
< xsl:call-template name = "makeReadSerial" >
< xsl:with-param name = "paramNode" select = "return" / >
< xsl:with-param name = "msgName" select = "'$retMsg'" / >
< xsl:with-param name = "varName" select = "'retValue'" / >
< xsl:with-param name = "serialName" select = "concat('serial', return/@php_serial)" / >
< / xsl:call-template >
< / xsl:when >
< xsl:when test = "return/@enum" >
$< xsl:value-of select = "@varName" / > = new < xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@type" / > ;
< xsl:call-template name = "makeReadSerial" >
< xsl:with-param name = "paramNode" select = "return" / >
< xsl:with-param name = "return" / >
< xsl:with-param name = "msgName" select = "'$retMsg'" / >
< xsl:with-param name = "varName" select = "'retValue'" / >
< xsl:with-param name = "serialName" select = "'serialEnum'" / >
< / xsl:call-template >
< / xsl:when >
< xsl:otherwise >
< xsl:call-template name = "makeReadSerial" >
< xsl:with-param name = "paramNode" select = "return" / >
< xsl:with-param name = "return" / >
< xsl:with-param name = "msgName" select = "'$retMsg'" / >
< xsl:with-param name = "varName" select = "'retValue'" / >
< xsl:with-param name = "serialName" select = "'serialUint32'" / >
< / xsl:call-template >
< / xsl:otherwise >
< / xsl:choose >
// return the return value
return $retValue;
< / xsl:if >
}
< / xsl:for-each >
function waitCallback()
{
$message = parent::waitMessage();
if ($message == false)
return false;
switch($message->MsgName)
{
< xsl:for-each select = "return" > case "< xsl:value-of select = "@msg" / > ":
$this->< xsl:value-of select = "@name" / > _skel($message);
break;
< / xsl:for-each > default:
return false;
}
return true;
}
< xsl:for-each select = "return" >
function < xsl:value-of select = "@name" / > _skel(& $message)
{
< xsl:for-each select = "param" >
< xsl:text > < / xsl:text >
< xsl:choose >
< xsl:when test = "@php_serial" >
< xsl:call-template name = "makeReadSerial" >
< xsl:with-param name = "paramNode" select = "." / >
< xsl:with-param name = "msgName" select = " '$message'" / >
< xsl:with-param name = "varName" select = "@name" / >
< xsl:with-param name = "serialName" select = "concat('serial', @php_serial)" / >
< / xsl:call-template >
< / xsl:when >
< xsl:when test = "@enum" >
$< xsl:value-of select = "@name" / > = new < xsl:value-of select = "//namespace/@name" / > _< xsl:value-of select = "@type" / > ;
< xsl:call-template name = "makeReadSerial" >
< xsl:with-param name = "paramNode" select = "." / >
< xsl:with-param name = "msgName" select = " '$message'" / >
< xsl:with-param name = "varName" select = "@name" / >
< xsl:with-param name = "serialName" select = "'serialEnum'" / >
< / xsl:call-template >
< / xsl:when >
< xsl:otherwise >
< xsl:call-template name = "makeReadSerial" >
< xsl:with-param name = "paramNode" select = "." / >
< xsl:with-param name = "msgName" select = " '$message'" / >
< xsl:with-param name = "varName" select = "@name" / >
< xsl:with-param name = "serialName" select = "'serialUint32'" / >
< / xsl:call-template >
< / xsl:otherwise >
< / xsl:choose >
< / xsl:for-each >
< xsl:text >
$this-> < / xsl:text > < xsl:value-of select = "@name" / > (< xsl:call-template name = "makePhpArgListNoFollow" / > );
}
< / xsl:for-each >
/////////////////////////////////////////////////////////////////
// Copy paste this part of code in your derived class
// and implement code to ract to incoming message
/////////////////////////////////////////////////////////////////
< xsl:for-each select = "return" >
< xsl:call-template name = "makeMethodDoc" / >
function < xsl:value-of select = "@name" / > (< xsl:call-template name = "makePhpArgListNoFollow" / > )
{
}
< / xsl:for-each > }
< xsl:text > ?>
< / xsl:text >
< / xsl:template >
<!-- ######################################### -->
<!-- ##### PHP Read serialisation code ###### -->
<!-- ######################################### -->
< xsl:template name = "makeReadSerial" >
< xsl:param name = "paramNode" / >
< xsl:param name = "msgName" / >
< xsl:param name = "varName" / >
< xsl:param name = "serialName" / >
< xsl:choose >
< xsl:when test = "$paramNode/@array" > $nbElem = 0;
< xsl:value-of select = "$msgName" / > ->serialUInt32($nbElem);
$< xsl:value-of select = "$varName" / > = array();
for ($i=0; $i< $nbElem;$i++)
{
< xsl:value-of select = "$msgName" / > ->< xsl:value-of select = "$serialName" / > ($item);
$< xsl:value-of select = "$varName" / > [] = $item;
}
< / xsl:when >
< xsl:otherwise > < xsl:value-of select = "$msgName" / > ->< xsl:value-of select = "$serialName" / > ($< xsl:value-of select = "$varName" / > );
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
<!-- ######################################### -->
<!-- ##### PHP Write serialisation code ###### -->
<!-- ######################################### -->
< xsl:template name = "makeWriteSerial" >
< xsl:param name = "msgName" / >
< xsl:param name = "varName" / >
< xsl:param name = "serialName" / >
< xsl:choose >
< xsl:when test = "@array" > < xsl:text > < / xsl:text > < xsl:value-of select = "$msgName" / > ->serialUint32(count($< xsl:value-of select = "@name" / > ));
foreach($< xsl:value-of select = "$varName" / > as $key=>$value)
< xsl:value-of select = "$msgName" / > ->< xsl:value-of select = "$serialName" / > ($value);
< / xsl:when >
< xsl:otherwise > < xsl:text > < / xsl:text > < xsl:value-of select = "$msgName" / > ->< xsl:value-of select = "$serialName" / > ($< xsl:value-of select = "$varName" / > );
< / xsl:otherwise >
< / xsl:choose >
< / xsl:template >
<!-- ######################################### -->
<!-- ##### Make a php parameter list ###### -->
<!-- ######################################### -->
< xsl:template name = "makePhpArgList" >
< xsl:for-each select = "param" > $< xsl:value-of select = "@name" / > , < / xsl:for-each >
< / xsl:template >
< xsl:template name = "makePhpArgListNoFollow" >
< xsl:for-each select = "param" > $< xsl:value-of select = "@name" / > < xsl:if test = "position() != last()" > , < / xsl:if > < / xsl:for-each >
< / xsl:template >
<!-- ################################################### -->
<!-- ##### Generate a cpp non template smart ptr ###### -->
<!-- ################################################### -->
< xsl:template name = "makePersistentPtrHeader" >
< xsl:param name = "className" / >
< xsl:variable name = "ptrName" select = "concat($className, 'Ptr')" / >
class < xsl:value-of select = "$ptrName" / >
{
friend class < xsl:value-of select = "$className" / > ;
const char *_FileName;
uint32 _LineNum;
// linked list of smart ptr
< xsl:value-of select = "$ptrName" / > *_NextPtr;
< xsl:value-of select = "$ptrName" / > *_PrevPtr;
< xsl:value-of select = "$className" / > *_Ptr;
void linkPtr();
void unlinkPtr();
public:
< xsl:value-of select = "$ptrName" / > ()
: _FileName(NULL),
_LineNum(0),
_Ptr(NULL),
_NextPtr(NULL),
_PrevPtr(NULL)
{
}
< xsl:value-of select = "$ptrName" / > (const < xsl:value-of select = "$ptrName" / > & other, const char *filename, uint32 lineNum)
: _FileName(filename),
_LineNum(lineNum),
_NextPtr(NULL),
_PrevPtr(NULL)
{
// point the same object
_Ptr = other._Ptr;
// insert the pointer in the list
linkPtr();
}
< xsl:value-of select = "$ptrName" / > (const < xsl:value-of select = "$ptrName" / > & other)
: _FileName(other._FileName),
_LineNum(other._LineNum),
_NextPtr(NULL),
_PrevPtr(NULL)
{
// point the same object
_Ptr = other._Ptr;
// insert the pointer in the list
linkPtr();
}
< xsl:value-of select = "$ptrName" / > (< xsl:value-of select = "$className" / > *objectPtr, const char *filename, uint32 lineNum)
: _FileName(filename),
_LineNum(lineNum),
_NextPtr(NULL),
_PrevPtr(NULL)
{
_Ptr = objectPtr;
linkPtr();
}
< xsl:value-of select = "$ptrName" / > & assign(const < xsl:value-of select = "$ptrName" / > & other, const char *filename, uint32 lineNum)
{
_FileName = filename;
_LineNum = lineNum;
unlinkPtr();
_Ptr = other._Ptr;
linkPtr();
return *this;
}
~< xsl:value-of select = "$ptrName" / > ()
{
unlinkPtr();
}
< xsl:value-of select = "$ptrName" / > & assign(< xsl:value-of select = "$className" / > *objectPtr, const char *filename, uint32 lineNum)
{
_FileName = filename;
_LineNum = lineNum;
unlinkPtr();
_Ptr = objectPtr;
linkPtr();
return *this;
}
< xsl:value-of select = "$ptrName" / > & operator =(const < xsl:value-of select = "$ptrName" / > & other)
{
return assign(other, __FILE__, __LINE__);
}
< xsl:value-of select = "$className" / > *operator ->()
{
return _Ptr;
}
const < xsl:value-of select = "$className" / > *operator ->() const
{
return _Ptr;
}
bool operator == (const < xsl:value-of select = "$ptrName" / > & other) const
{
return _Ptr == other._Ptr;
}
bool operator != (const < xsl:value-of select = "$ptrName" / > & other) const
{
return !operator ==(other);
}
bool operator == (const < xsl:value-of select = "$className" / > *object) const
{
return _Ptr == object;
}
bool operator != (const < xsl:value-of select = "$className" / > *object) const
{
return !operator ==(object);
}
/// Less then comparator : comparison on pointer object address
bool operator < (const < xsl:value-of select = "$ptrName" / > & other) const
{
return _Ptr < other._Ptr;
}
/// Used to walk thrue the linked list of pointer
< xsl:value-of select = "$ptrName" / > *getNextPtr()
{
return _NextPtr;
}
};
< / xsl:template >
< xsl:template name = "makePersistentPtrCpp" >
< xsl:param name = "className" / >
< xsl:variable name = "ptrName" select = "concat($className, 'Ptr')" / >
void < xsl:value-of select = "$ptrName" / > ::linkPtr()
{
nlassert(_NextPtr == NULL);
nlassert(_PrevPtr == NULL);
if (_Ptr != NULL)
{
_NextPtr = _Ptr->getFirstPtr();
if (_NextPtr != NULL)
{
_PrevPtr = _NextPtr->_PrevPtr;
_PrevPtr->_NextPtr = this;
_NextPtr->_PrevPtr = this;
}
else
{
_NextPtr = this;
_PrevPtr = this;
_Ptr->setFirstPtr(this);
}
}
}
void < xsl:value-of select = "$ptrName" / > ::unlinkPtr()
{
if (_NextPtr == NULL)
{
nlassert(_PrevPtr == NULL);
return;
}
if (_Ptr != NULL)
{
if (_NextPtr == this)
{
nlassert(_PrevPtr == this);
// last pointer !
_Ptr->setFirstPtr(NULL);
}
else
{
if (_Ptr->getFirstPtr() == this)
{
// the first ptr is the current one, we need to switch to next one
_Ptr->setFirstPtr(_NextPtr);
}
}
}
if (_NextPtr != this)
{
nlassert(_PrevPtr != this);
_NextPtr->_PrevPtr = _PrevPtr;
_PrevPtr->_NextPtr = _NextPtr;
}
_NextPtr = NULL;
_PrevPtr = NULL;
}
< / xsl:template >
< / xsl:stylesheet >