Merge branch 'feature/reflection-4996' into next

Fixes #4996
This commit is contained in:
Gunnar Beutner 2013-11-05 08:56:47 +01:00
commit 91034285a3
49 changed files with 325 additions and 208 deletions

View File

@ -39,7 +39,7 @@ namespace icinga
/** /**
* @ingroup cluster * @ingroup cluster
*/ */
class ClusterListener : public ReflectionObjectImpl<ClusterListener> class ClusterListener : public ObjectImpl<ClusterListener>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(ClusterListener); DECLARE_PTR_TYPEDEFS(ClusterListener);

View File

@ -35,7 +35,7 @@ class EndpointManager;
* *
* @ingroup cluster * @ingroup cluster
*/ */
class Endpoint : public ReflectionObjectImpl<Endpoint> class Endpoint : public ObjectImpl<Endpoint>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Endpoint); DECLARE_PTR_TYPEDEFS(Endpoint);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup compat * @ingroup compat
*/ */
class CheckResultReader : public ReflectionObjectImpl<CheckResultReader> class CheckResultReader : public ObjectImpl<CheckResultReader>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(CheckResultReader); DECLARE_PTR_TYPEDEFS(CheckResultReader);

View File

@ -33,7 +33,7 @@ namespace icinga
* *
* @ingroup compat * @ingroup compat
*/ */
class CompatLogger : public ReflectionObjectImpl<CompatLogger> class CompatLogger : public ObjectImpl<CompatLogger>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(CompatLogger); DECLARE_PTR_TYPEDEFS(CompatLogger);

View File

@ -33,7 +33,7 @@ namespace icinga
/** /**
* @ingroup compat * @ingroup compat
*/ */
class ExternalCommandListener : public ReflectionObjectImpl<ExternalCommandListener> class ExternalCommandListener : public ObjectImpl<ExternalCommandListener>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(ExternalCommandListener); DECLARE_PTR_TYPEDEFS(ExternalCommandListener);

View File

@ -37,7 +37,7 @@ namespace icinga
/** /**
* @ingroup compat * @ingroup compat
*/ */
class StatusDataWriter : public ReflectionObjectImpl<StatusDataWriter> class StatusDataWriter : public ObjectImpl<StatusDataWriter>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(StatusDataWriter); DECLARE_PTR_TYPEDEFS(StatusDataWriter);

View File

@ -34,7 +34,7 @@ namespace icinga
* *
* @ingroup ido * @ingroup ido
*/ */
class IdoMysqlConnection : public ReflectionObjectImpl<IdoMysqlConnection> class IdoMysqlConnection : public ObjectImpl<IdoMysqlConnection>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(IdoMysqlConnection); DECLARE_PTR_TYPEDEFS(IdoMysqlConnection);

View File

@ -34,7 +34,7 @@ namespace icinga
* *
* @ingroup ido * @ingroup ido
*/ */
class IdoPgsqlConnection : public ReflectionObjectImpl<IdoPgsqlConnection> class IdoPgsqlConnection : public ObjectImpl<IdoPgsqlConnection>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(IdoPgsqlConnection); DECLARE_PTR_TYPEDEFS(IdoPgsqlConnection);

View File

@ -29,7 +29,7 @@ namespace icinga
/** /**
* @ingroup demo * @ingroup demo
*/ */
class Demo : public ReflectionObjectImpl<Demo> class Demo : public ObjectImpl<Demo>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Demo); DECLARE_PTR_TYPEDEFS(Demo);

View File

@ -33,7 +33,7 @@ namespace livestatus
/** /**
* @ingroup livestatus * @ingroup livestatus
*/ */
class LivestatusListener : public ReflectionObjectImpl<LivestatusListener> class LivestatusListener : public ObjectImpl<LivestatusListener>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(LivestatusListener); DECLARE_PTR_TYPEDEFS(LivestatusListener);

View File

@ -31,7 +31,7 @@ namespace icinga
/** /**
* @ingroup notification * @ingroup notification
*/ */
class NotificationComponent : public ReflectionObjectImpl<NotificationComponent> class NotificationComponent : public ObjectImpl<NotificationComponent>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(NotificationComponent); DECLARE_PTR_TYPEDEFS(NotificationComponent);

View File

@ -35,7 +35,7 @@ namespace icinga
* *
* @ingroup perfdata * @ingroup perfdata
*/ */
class GraphiteWriter : public ReflectionObjectImpl<GraphiteWriter> class GraphiteWriter : public ObjectImpl<GraphiteWriter>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(GraphiteWriter); DECLARE_PTR_TYPEDEFS(GraphiteWriter);

View File

@ -34,7 +34,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class PerfdataWriter : public ReflectionObjectImpl<PerfdataWriter> class PerfdataWriter : public ObjectImpl<PerfdataWriter>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(PerfdataWriter); DECLARE_PTR_TYPEDEFS(PerfdataWriter);

View File

@ -30,12 +30,12 @@ add_library(base SHARED
dynamicobject.th dynamictype.cpp exception.cpp fifo.cpp filelogger.cpp dynamicobject.th dynamictype.cpp exception.cpp fifo.cpp filelogger.cpp
filelogger.th logger.cpp logger.th netstring.cpp networkstream.cpp object.cpp filelogger.th logger.cpp logger.th netstring.cpp networkstream.cpp object.cpp
objectlock.cpp process.cpp process-unix.cpp process-windows.cpp qstring.cpp objectlock.cpp process.cpp process-unix.cpp process-windows.cpp qstring.cpp
reflectionobject.cpp ringbuffer.cpp script.cpp script.th scriptfunction.cpp ringbuffer.cpp script.cpp script.th scriptfunction.cpp scriptfunctionwrapper.cpp
scriptfunctionwrapper.cpp scriptinterpreter.cpp scriptlanguage.cpp scriptinterpreter.cpp scriptlanguage.cpp scriptvariable.cpp serializer.cpp
scriptvariable.cpp socket.cpp stacktrace.cpp stdiostream.cpp stream_bio.cpp socket.cpp stacktrace.cpp stdiostream.cpp stream_bio.cpp stream.cpp
stream.cpp streamlogger.cpp streamlogger.th sysloglogger.cpp sysloglogger.th streamlogger.cpp streamlogger.th sysloglogger.cpp sysloglogger.th tcpsocket.cpp
tcpsocket.cpp threadpool.cpp timer.cpp tlsstream.cpp tlsutility.cpp threadpool.cpp timer.cpp tlsstream.cpp tlsutility.cpp unixsocket.cpp
unixsocket.cpp utility.cpp value.cpp workqueue.cpp zlibstream.cpp utility.cpp value.cpp workqueue.cpp zlibstream.cpp
) )
target_link_libraries(base ${CMAKE_DL_LIBS} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} cJSON mmatch) target_link_libraries(base ${CMAKE_DL_LIBS} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} cJSON mmatch)

View File

@ -34,7 +34,7 @@ class Component;
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API Application : public ReflectionObjectImpl<Application> { class I2_BASE_API Application : public ObjectImpl<Application> {
public: public:
DECLARE_PTR_TYPEDEFS(Application); DECLARE_PTR_TYPEDEFS(Application);

View File

@ -31,7 +31,7 @@ namespace icinga
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API ConsoleLogger : public ReflectionObjectImpl<ConsoleLogger> class I2_BASE_API ConsoleLogger : public ObjectImpl<ConsoleLogger>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(ConsoleLogger); DECLARE_PTR_TYPEDEFS(ConsoleLogger);

View File

@ -19,6 +19,7 @@
#include "base/dynamicobject.h" #include "base/dynamicobject.h"
#include "base/dynamictype.h" #include "base/dynamictype.h"
#include "base/serializer.h"
#include "base/netstring.h" #include "base/netstring.h"
#include "base/registry.h" #include "base/registry.h"
#include "base/stdiostream.h" #include "base/stdiostream.h"
@ -220,7 +221,7 @@ void DynamicObject::DumpObjects(const String& filename, int attributeTypes)
persistentObject->Set("type", type->GetName()); persistentObject->Set("type", type->GetName());
persistentObject->Set("name", object->GetName()); persistentObject->Set("name", object->GetName());
Dictionary::Ptr update = object->Serialize(attributeTypes); Dictionary::Ptr update = Serializer::Serialize(object, attributeTypes);
if (!update) if (!update)
continue; continue;
@ -279,7 +280,7 @@ void DynamicObject::RestoreObjects(const String& filename, int attributeTypes)
if (object) { if (object) {
ASSERT(!object->IsActive()); ASSERT(!object->IsActive());
Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'."); Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'.");
object->Deserialize(update, attributeTypes); Serializer::Deserialize(object, update, attributeTypes);
object->OnStateLoaded(); object->OnStateLoaded();
} }

View File

@ -34,17 +34,6 @@ namespace icinga
class DynamicType; class DynamicType;
/**
* The type of an attribute for a DynamicObject.
*
* @ingroup base
*/
enum AttributeType
{
Attribute_State = FAState,
Attribute_Config = FAConfig
};
enum DomainPriv enum DomainPriv
{ {
DomainPrivRead = (1<<0), DomainPrivRead = (1<<0),
@ -58,7 +47,7 @@ enum DomainPriv
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API DynamicObject : public ReflectionObjectImpl<DynamicObject> class I2_BASE_API DynamicObject : public ObjectImpl<DynamicObject>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(DynamicObject); DECLARE_PTR_TYPEDEFS(DynamicObject);
@ -105,8 +94,8 @@ public:
return dynamic_pointer_cast<T>(object); return dynamic_pointer_cast<T>(object);
} }
static void DumpObjects(const String& filename, int attributeTypes = Attribute_State); static void DumpObjects(const String& filename, int attributeTypes = FAState);
static void RestoreObjects(const String& filename, int attributeTypes = Attribute_State); static void RestoreObjects(const String& filename, int attributeTypes = FAState);
static void StopObjects(void); static void StopObjects(void);
protected: protected:

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include "base/dynamictype.h" #include "base/dynamictype.h"
#include "base/serializer.h"
#include "base/debug.h" #include "base/debug.h"
#include "base/objectlock.h" #include "base/objectlock.h"
@ -138,7 +139,7 @@ DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUp
DynamicObject::Ptr object = factory(); DynamicObject::Ptr object = factory();
object->Deserialize(serializedUpdate, Attribute_Config); Serializer::Deserialize(object, serializedUpdate, FAConfig);
return object; return object;
} }

View File

@ -31,7 +31,7 @@ namespace icinga
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API FileLogger : public ReflectionObjectImpl<FileLogger> class I2_BASE_API FileLogger : public ObjectImpl<FileLogger>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(FileLogger); DECLARE_PTR_TYPEDEFS(FileLogger);

View File

@ -46,7 +46,7 @@ struct LogEntry {
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API Logger : public ReflectionObjectImpl<Logger> class I2_BASE_API Logger : public ObjectImpl<Logger>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Logger); DECLARE_PTR_TYPEDEFS(Logger);

View File

@ -69,3 +69,18 @@ Object::SharedPtrHolder::operator Value(void) const
{ {
return m_Object; return m_Object;
} }
const Type *Object::GetReflectionType(void) const
{
return NULL;
}
void Object::SetField(int id, const Value& value)
{
throw std::runtime_error("Invalid field ID.");
}
Value Object::GetField(int id) const
{
throw std::runtime_error("Invalid field ID.");
}

View File

@ -48,6 +48,8 @@ class Value;
typedef shared_ptr<klass> Ptr; \ typedef shared_ptr<klass> Ptr; \
typedef weak_ptr<klass> WeakPtr typedef weak_ptr<klass> WeakPtr
class Type;
/** /**
* Base class for all heap-allocated objects. At least one of its methods * Base class for all heap-allocated objects. At least one of its methods
* has to be virtual for RTTI to work. * has to be virtual for RTTI to work.
@ -62,6 +64,10 @@ public:
Object(void); Object(void);
virtual ~Object(void); virtual ~Object(void);
virtual const Type *GetReflectionType(void) const;
virtual void SetField(int id, const Value& value);
virtual Value GetField(int id) const;
/** /**
* Holds a shared pointer and provides support for implicit upcasts. * Holds a shared pointer and provides support for implicit upcasts.
* *
@ -175,6 +181,16 @@ public:
} }
}; };
template<typename T>
class TypeImpl
{
};
template<typename T>
class ObjectImpl
{
};
} }
#endif /* OBJECT_H */ #endif /* OBJECT_H */

View File

@ -33,7 +33,7 @@ class ScriptInterpreter;
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API Script : public ReflectionObjectImpl<Script> class I2_BASE_API Script : public ObjectImpl<Script>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Script); DECLARE_PTR_TYPEDEFS(Script);

59
lib/base/serializer.cpp Normal file
View File

@ -0,0 +1,59 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "base/serializer.h"
#include "base/type.h"
#include <boost/smart_ptr/make_shared.hpp>
using namespace icinga;
Dictionary::Ptr Serializer::Serialize(const Object::Ptr& object, int attributeTypes)
{
const Type *type = object->GetReflectionType();
Dictionary::Ptr update = boost::make_shared<Dictionary>();
for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(i);
if ((field.Attributes & attributeTypes) == 0)
continue;
update->Set(field.Name, object->GetField(i));
}
return update;
}
void Serializer::Deserialize(const Object::Ptr& object, const Dictionary::Ptr& update, int attributeTypes)
{
const Type *type = object->GetReflectionType();
for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(i);
if ((field.Attributes & attributeTypes) == 0)
continue;
if (!update->Contains(field.Name))
continue;
object->SetField(i, update->Get(field.Name));
}
}

View File

@ -17,38 +17,30 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
#include "base/reflectionobject.h" #ifndef SERIALIZER_H
#include <boost/smart_ptr/make_shared.hpp> #define SERIALIZER_H
using namespace icinga; #include "base/i2-base.h"
#include "base/dictionary.h"
Dictionary::Ptr ReflectionObject::Serialize(int attributeTypes) const namespace icinga
{ {
Dictionary::Ptr update = boost::make_shared<Dictionary>();
for (int i = 0; i < GetFieldCount(); i++) { /**
ReflectionField field = GetFieldInfo(i); * Serializer utilities.
*
* @ingroup base
*/
class I2_BASE_API Serializer
{
public:
static Dictionary::Ptr Serialize(const Object::Ptr& object, int attributeTypes);
static void Deserialize(const Object::Ptr& object, const Dictionary::Ptr& update, int attributeTypes);
if ((field.Attributes & attributeTypes) == 0) private:
continue; Serializer(void);
};
update->Set(field.Name, GetField(i));
}
return update;
} }
void ReflectionObject::Deserialize(const Dictionary::Ptr& update, int attributeTypes) #endif /* SERIALIZER_H */
{
for (int i = 0; i < GetFieldCount(); i++) {
ReflectionField field = GetFieldInfo(i);
if ((field.Attributes & attributeTypes) == 0)
continue;
if (!update->Contains(field.Name))
continue;
SetField(i, update->Get(field.Name));
}
}

View File

@ -48,9 +48,8 @@ public:
return instance; return instance;
} }
private:
friend T *T::GetInstance(void);
private:
static T *m_Instance; static T *m_Instance;
}; };

View File

@ -33,7 +33,7 @@ namespace icinga
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API StreamLogger : public ReflectionObjectImpl<StreamLogger> class I2_BASE_API StreamLogger : public ObjectImpl<StreamLogger>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(StreamLogger); DECLARE_PTR_TYPEDEFS(StreamLogger);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup base * @ingroup base
*/ */
class I2_BASE_API SyslogLogger : public ReflectionObjectImpl<SyslogLogger> class I2_BASE_API SyslogLogger : public ObjectImpl<SyslogLogger>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(SyslogLogger); DECLARE_PTR_TYPEDEFS(SyslogLogger);

View File

@ -17,60 +17,41 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
#ifndef REFLECTIONOBJECT_H #ifndef TYPE_H
#define REFLECTIONOBJECT_H #define TYPE_H
#include "base/object.h" #include "base/i2-base.h"
#include "base/dictionary.h" #include "base/qstring.h"
#include <vector>
namespace icinga namespace icinga
{ {
enum ReflectionFieldAttribute enum FieldAttribute
{ {
FAConfig = 1, FAConfig = 1,
FAState = 2 FAState = 2
}; };
struct ReflectionField struct Field
{ {
int ID; int ID;
String Name; String Name;
int Attributes; int Attributes;
Value DefaultValue;
ReflectionField(int id, const String& name, int attributes, const Value& default_value = Empty) Field(int id, const String& name, int attributes)
: ID(id), Name(name), Attributes(attributes), DefaultValue(default_value) : ID(id), Name(name), Attributes(attributes)
{ } { }
}; };
enum InvokationType class I2_BASE_API Type
{
ITGet,
ITSet
};
class I2_BASE_API ReflectionObject : public Object
{ {
public: public:
DECLARE_PTR_TYPEDEFS(ReflectionObject); virtual Type *GetBaseType(void) const = 0;
virtual int GetFieldId(const String& name) const = 0; virtual int GetFieldId(const String& name) const = 0;
virtual ReflectionField GetFieldInfo(int id) const = 0; virtual Field GetFieldInfo(int id) const = 0;
virtual int GetFieldCount(void) const = 0; virtual int GetFieldCount(void) const = 0;
virtual void SetField(int id, const Value& value) = 0;
virtual Value GetField(int id) const = 0;
Dictionary::Ptr Serialize(int attributeTypes) const;
void Deserialize(const Dictionary::Ptr& update, int attributeTypes);
};
template<typename T>
class ReflectionObjectImpl
{
}; };
} }
#endif /* REFLECTIONOBJECT_H */ #endif /* TYPE_H */

View File

@ -34,7 +34,7 @@ namespace icinga
* *
* @ingroup db_ido * @ingroup db_ido
*/ */
class I2_DB_IDO_API DbConnection : public ReflectionObjectImpl<DbConnection> class I2_DB_IDO_API DbConnection : public ObjectImpl<DbConnection>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(DbConnection); DECLARE_PTR_TYPEDEFS(DbConnection);

View File

@ -31,7 +31,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API CheckCommand : public ReflectionObjectImpl<CheckCommand> class I2_ICINGA_API CheckCommand : public ObjectImpl<CheckCommand>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(CheckCommand); DECLARE_PTR_TYPEDEFS(CheckCommand);

View File

@ -35,7 +35,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API Command : public ReflectionObjectImpl<Command>, public MacroResolver class I2_ICINGA_API Command : public ObjectImpl<Command>, public MacroResolver
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Command); DECLARE_PTR_TYPEDEFS(Command);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API Domain : public ReflectionObjectImpl<Domain> class I2_ICINGA_API Domain : public ObjectImpl<Domain>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Domain); DECLARE_PTR_TYPEDEFS(Domain);

View File

@ -31,7 +31,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API EventCommand : public ReflectionObjectImpl<EventCommand> class I2_ICINGA_API EventCommand : public ObjectImpl<EventCommand>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(EventCommand); DECLARE_PTR_TYPEDEFS(EventCommand);

View File

@ -48,7 +48,7 @@ enum HostState
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API Host : public ReflectionObjectImpl<Host>, public MacroResolver class I2_ICINGA_API Host : public ObjectImpl<Host>, public MacroResolver
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Host); DECLARE_PTR_TYPEDEFS(Host);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API HostGroup : public ReflectionObjectImpl<HostGroup> class I2_ICINGA_API HostGroup : public ObjectImpl<HostGroup>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(HostGroup); DECLARE_PTR_TYPEDEFS(HostGroup);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API IcingaApplication : public ReflectionObjectImpl<IcingaApplication>, public MacroResolver class I2_ICINGA_API IcingaApplication : public ObjectImpl<IcingaApplication>, public MacroResolver
{ {
public: public:
DECLARE_PTR_TYPEDEFS(IcingaApplication); DECLARE_PTR_TYPEDEFS(IcingaApplication);

View File

@ -56,7 +56,7 @@ class NotificationCommand;
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API Notification : public ReflectionObjectImpl<Notification>, public MacroResolver class I2_ICINGA_API Notification : public ObjectImpl<Notification>, public MacroResolver
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Notification); DECLARE_PTR_TYPEDEFS(Notification);

View File

@ -33,7 +33,7 @@ class Notification;
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API NotificationCommand : public ReflectionObjectImpl<NotificationCommand> class I2_ICINGA_API NotificationCommand : public ObjectImpl<NotificationCommand>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(NotificationCommand); DECLARE_PTR_TYPEDEFS(NotificationCommand);

View File

@ -118,7 +118,7 @@ class EventCommand;
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API Service : public ReflectionObjectImpl<Service>, public MacroResolver class I2_ICINGA_API Service : public ObjectImpl<Service>, public MacroResolver
{ {
public: public:
DECLARE_PTR_TYPEDEFS(Service); DECLARE_PTR_TYPEDEFS(Service);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API ServiceGroup : public ReflectionObjectImpl<ServiceGroup> class I2_ICINGA_API ServiceGroup : public ObjectImpl<ServiceGroup>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(ServiceGroup); DECLARE_PTR_TYPEDEFS(ServiceGroup);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API TimePeriod : public ReflectionObjectImpl<TimePeriod> class I2_ICINGA_API TimePeriod : public ObjectImpl<TimePeriod>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(TimePeriod); DECLARE_PTR_TYPEDEFS(TimePeriod);

View File

@ -34,7 +34,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API User : public ReflectionObjectImpl<User>, public MacroResolver class I2_ICINGA_API User : public ObjectImpl<User>, public MacroResolver
{ {
public: public:
DECLARE_PTR_TYPEDEFS(User); DECLARE_PTR_TYPEDEFS(User);

View File

@ -32,7 +32,7 @@ namespace icinga
* *
* @ingroup icinga * @ingroup icinga
*/ */
class I2_ICINGA_API UserGroup : public ReflectionObjectImpl<UserGroup> class I2_ICINGA_API UserGroup : public ObjectImpl<UserGroup>
{ {
public: public:
DECLARE_PTR_TYPEDEFS(UserGroup); DECLARE_PTR_TYPEDEFS(UserGroup);

View File

@ -118,6 +118,7 @@ static char *lb_steal(lex_buf *lb)
class { return T_CLASS; } class { return T_CLASS; }
namespace { return T_NAMESPACE; } namespace { return T_NAMESPACE; }
code { return T_CODE; } code { return T_CODE; }
abstract { return T_ABSTRACT; }
config { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; } config { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; }
state { yylval->num = FAState; return T_FIELD_ATTRIBUTE; } state { yylval->num = FAState; return T_FIELD_ATTRIBUTE; }
enum { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; } enum { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; }

View File

@ -50,6 +50,7 @@ using namespace icinga;
%token T_INCLUDE "include (T_INCLUDE)" %token T_INCLUDE "include (T_INCLUDE)"
%token T_CLASS "class (T_CLASS)" %token T_CLASS "class (T_CLASS)"
%token T_CODE "code (T_CODE)" %token T_CODE "code (T_CODE)"
%token T_ABSTRACT "abstract (T_ABSTRACT)"
%token T_NAMESPACE "namespace (T_NAMESPACE)" %token T_NAMESPACE "namespace (T_NAMESPACE)"
%token T_STRING "string (T_STRING)" %token T_STRING "string (T_STRING)"
%token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)" %token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
@ -72,6 +73,7 @@ using namespace icinga;
%type <num> field_attributes %type <num> field_attributes
%type <num> field_attribute_list %type <num> field_attribute_list
%type <num> T_FIELD_ACCESSOR_TYPE %type <num> T_FIELD_ACCESSOR_TYPE
%type <num> abstract_specifier
%type <field> class_field %type <field> class_field
%type <fields> class_fields %type <fields> class_fields
%type <klass> class %type <klass> class
@ -163,20 +165,32 @@ code: T_CODE T_STRING
} }
; ;
class: T_CLASS T_IDENTIFIER inherits_specifier '{' class_fields '}' ';' class: abstract_specifier T_CLASS T_IDENTIFIER inherits_specifier '{' class_fields '}' ';'
{ {
$$ = new Klass(); $$ = new Klass();
$$->Name = $2; $$->Name = $3;
free($2); free($3);
if ($3) { if ($4) {
$$->Parent = $3; $$->Parent = $4;
free($3); free($4);
} }
$$->Fields = *$5; $$->Abstract = $1;
delete $5;
$$->Fields = *$6;
delete $6;
}
;
abstract_specifier: /* empty */
{
$$ = false;
}
| T_ABSTRACT
{
$$ = true;
} }
; ;

View File

@ -81,20 +81,140 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
{ {
std::vector<Field>::const_iterator it; std::vector<Field>::const_iterator it;
/* forward declaration */
if (klass.Name.find_first_of(':') == std::string::npos) if (klass.Name.find_first_of(':') == std::string::npos)
std::cout << "class " << klass.Name << ";" << std::endl << std::endl; std::cout << "class " << klass.Name << ";" << std::endl << std::endl;
/* TypeImpl */
std::cout << "template<>" << std::endl std::cout << "template<>" << std::endl
<< "class ReflectionObjectImpl<" << klass.Name << ">" << "class TypeImpl<" << klass.Name << ">"
<< " : public " << (klass.Parent.empty() ? "ReflectionObject" : klass.Parent) << std::endl << " : public Type, public Singleton<TypeImpl<" << klass.Name << "> >" << std::endl
<< "{" << std::endl
<< "public:" << std::endl;
/* GetBaseType */
std::cout << "\t" << "virtual Type *GetBaseType(void) const" << std::endl
<< "\t" << "{" << std::endl;
std::cout << "\t\t" << "return ";
if (!klass.Parent.empty())
std::cout << "Singleton<TypeImpl<" << klass.Parent << "> >::GetInstance()";
else
std::cout << "NULL";
std::cout << ";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* GetFieldId */
std::cout << "\t" << "virtual int GetFieldId(const String& name) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return StaticGetFieldId(name);" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* StaticGetFieldId */
std::cout << "\t" << "static int StaticGetFieldId(const String& name)" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "int offset = ";
if (!klass.Parent.empty())
std::cout << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
else
std::cout << "0";
std::cout << ";" << std::endl << std::endl;
int num = 0;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl
<< "\t\t\t" << "return offset + " << num << ";" << std::endl;
num++;
}
std::cout << std::endl
<< "\t\t" << "return ";
if (!klass.Parent.empty())
std::cout << "TypeImpl<" << klass.Parent << ">::StaticGetFieldId(name)";
else
std::cout << "-1";
std::cout << ";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* GetFieldInfo */
std::cout << "\t" << "virtual Field GetFieldInfo(int id) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return StaticGetFieldInfo(id);" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* StaticGetFieldInfo */
std::cout << "\t" << "static Field StaticGetFieldInfo(int id)" << std::endl
<< "\t" << "{" << std::endl;
if (!klass.Parent.empty())
std::cout << "\t\t" << "int real_id = id - " << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount();" << std::endl
<< "\t\t" << "if (real_id < 0) { return " << "TypeImpl<" << klass.Parent << ">::StaticGetFieldInfo(id); }" << std::endl;
std::cout << "\t\t" << "switch (";
if (!klass.Parent.empty())
std::cout << "real_id";
else
std::cout << "id";
std::cout << ") {" << std::endl;
num = 0;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
std::cout << "\t\t\t" << "case " << num << ":" << std::endl
<< "\t\t\t\t" << "return Field(" << num << ", \"" << it->Name << "\", " << it->Attributes << ");" << std::endl;
num++;
}
std::cout << "\t\t\t" << "default:" << std::endl
<< "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
<< "\t\t" << "}" << std::endl;
std::cout << "\t" << "}" << std::endl << std::endl;
/* GetFieldCount */
std::cout << "\t" << "virtual int GetFieldCount(void) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return StaticGetFieldCount();" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* StaticGetFieldCount */
std::cout << "\t" << "static int StaticGetFieldCount(void)" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return " << klass.Fields.size();
if (!klass.Parent.empty())
std::cout << " + " << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
std::cout << ";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
std::cout << "};" << std::endl << std::endl;
/* ObjectImpl */
std::cout << "template<>" << std::endl
<< "class ObjectImpl<" << klass.Name << ">"
<< " : public " << (klass.Parent.empty() ? "Object" : klass.Parent) << std::endl
<< "{" << std::endl << "{" << std::endl
<< "public:" << std::endl << "public:" << std::endl
<< "\t" << "DECLARE_PTR_TYPEDEFS(ReflectionObjectImpl<" << klass.Name << ">);" << std::endl; << "\t" << "DECLARE_PTR_TYPEDEFS(ObjectImpl<" << klass.Name << ">);" << std::endl << std::endl;
/* GetReflectionType */
std::cout << "\t" << "virtual const Type *GetReflectionType(void) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return TypeImpl<" << klass.Name << ">::GetInstance();" << std::endl
<< "\t" << "}" << std::endl << std::endl;
if (!klass.Fields.empty()) { if (!klass.Fields.empty()) {
/* constructor */ /* constructor */
std::cout << "public:" << std::endl std::cout << "public:" << std::endl
<< "\t" << "ReflectionObjectImpl<" << klass.Name << ">(void)" << std::endl << "\t" << "ObjectImpl<" << klass.Name << ">(void)" << std::endl
<< "\t" << "{" << std::endl; << "\t" << "{" << std::endl;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
@ -103,88 +223,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
std::cout << "\t" << "}" << std::endl << std::endl; std::cout << "\t" << "}" << std::endl << std::endl;
/* GetFieldId */
std::cout << "public:" << std::endl
<< "\t" << "virtual int GetFieldId(const String& name) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "int offset = ";
if (!klass.Parent.empty())
std::cout << klass.Parent << "::GetFieldCount()";
else
std::cout << "0";
std::cout << ";" << std::endl << std::endl;
int num = 0;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl
<< "\t\t\t" << "return offset + " << num << ";" << std::endl;
num++;
}
std::cout << std::endl
<< "\t\t" << "return ";
if (!klass.Parent.empty())
std::cout << klass.Parent << "::GetFieldId(name)";
else
std::cout << "-1";
std::cout << ";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* GetFieldInfo */
std::cout << "public:" << std::endl
<< "\t" << "virtual ReflectionField GetFieldInfo(int id) const" << std::endl
<< "\t" << "{" << std::endl;
if (!klass.Parent.empty())
std::cout << "\t\t" << "int real_id = id - " << klass.Parent << "::GetFieldCount();" << std::endl
<< "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetFieldInfo(id); }" << std::endl;
std::cout << "\t\t" << "switch (";
if (!klass.Parent.empty())
std::cout << "real_id";
else
std::cout << "id";
std::cout << ") {" << std::endl;
num = 0;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
std::cout << "\t\t\t" << "case " << num << ":" << std::endl
<< "\t\t\t\t" << "return ReflectionField(" << num << ", \"" << it->Name << "\", " << it->Attributes << ", " << "GetDefault" << it->GetFriendlyName() << "());" << std::endl;
num++;
}
std::cout << "\t\t\t" << "default:" << std::endl
<< "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
<< "\t\t" << "}" << std::endl;
std::cout << "\t" << "}" << std::endl << std::endl;
/* GetFieldCount */
std::cout << "public:" << std::endl
<< "\t" << "virtual int GetFieldCount(void) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return " << klass.Fields.size();
if (!klass.Parent.empty())
std::cout << " + " << klass.Parent + "::GetFieldCount()";
std::cout << ";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* SetField */ /* SetField */
std::cout << "protected:" << std::endl std::cout << "protected:" << std::endl
<< "\t" << "virtual void SetField(int id, const Value& value)" << std::endl << "\t" << "virtual void SetField(int id, const Value& value)" << std::endl
<< "\t" << "{" << std::endl; << "\t" << "{" << std::endl;
if (!klass.Parent.empty()) if (!klass.Parent.empty())
std::cout << "\t\t" << "int real_id = id - " << klass.Parent << "::GetFieldCount();" << std::endl std::cout << "\t\t" << "int real_id = id - TypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
<< "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl; << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl;
std::cout << "\t\t" << "switch ("; std::cout << "\t\t" << "switch (";
@ -225,7 +271,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
<< "\t" << "{" << std::endl; << "\t" << "{" << std::endl;
if (!klass.Parent.empty()) if (!klass.Parent.empty())
std::cout << "\t\t" << "int real_id = id - " << klass.Parent << "::GetFieldCount();" << std::endl std::cout << "\t\t" << "int real_id = id - TypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
<< "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetField(id); }" << std::endl; << "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetField(id); }" << std::endl;
std::cout << "\t\t" << "switch ("; std::cout << "\t\t" << "switch (";
@ -336,7 +382,9 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
{ {
stream->exceptions(std::istream::badbit); stream->exceptions(std::istream::badbit);
std::cout << "#include \"base/reflectionobject.h\"" << std::endl std::cout << "#include \"base/object.h\"" << std::endl
<< "#include \"base/type.h\"" << std::endl
<< "#include \"base/singleton.h\"" << std::endl
<< "#include \"base/debug.h\"" << std::endl << "#include \"base/debug.h\"" << std::endl
<< "#include \"base/value.h\"" << std::endl << "#include \"base/value.h\"" << std::endl
<< "#include \"base/array.h\"" << std::endl << "#include \"base/array.h\"" << std::endl

View File

@ -107,6 +107,7 @@ struct Klass
{ {
std::string Name; std::string Name;
std::string Parent; std::string Parent;
bool Abstract;
std::vector<Field> Fields; std::vector<Field> Fields;
}; };