You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
7.9 KiB
C++
239 lines
7.9 KiB
C++
/***************************************************************************
|
|
* Copyright (C) gempa GmbH *
|
|
* All rights reserved. *
|
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
|
* *
|
|
* GNU Affero General Public License Usage *
|
|
* This file may be used under the terms of the GNU Affero *
|
|
* Public License version 3.0 as published by the Free Software Foundation *
|
|
* and appearing in the file LICENSE included in the packaging of this *
|
|
* file. Please review the following information to ensure the GNU Affero *
|
|
* Public License version 3.0 requirements will be met: *
|
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
|
* *
|
|
* Other Usage *
|
|
* Alternatively, this file may be used in accordance with the terms and *
|
|
* conditions contained in a signed written agreement between you and *
|
|
* gempa GmbH. *
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef SEISCOMP_CORE_FACTORY_H
|
|
#define SEISCOMP_CORE_FACTORY_H
|
|
|
|
|
|
#include <map>
|
|
#include <vector>
|
|
#include <string>
|
|
#include "rtti.h"
|
|
|
|
|
|
namespace Seiscomp {
|
|
namespace Core {
|
|
namespace Generic {
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
/** \brief Template based class factory interface
|
|
|
|
Class factories are build upon polymorphic types.
|
|
In order to provide an generalized factory interface, a template
|
|
class is used to implement factories for different class hierarchies.
|
|
Objects are created by a classname.
|
|
|
|
The current implementation sits on top of a custom RTTI implementation.
|
|
A classname in the factory is the same as the one defined by the RTTI
|
|
object. One could think of an implementation where different names could
|
|
be useful. Therefore the static method getClassName(const T*) has been
|
|
implemented. It does not call (T*)->className() but uses its own
|
|
dictionaries to fetch the classname.
|
|
|
|
To create an object, use the following code
|
|
\code
|
|
ClassFactoryInterface<MyBaseClassType>::create("MyClassName");
|
|
\endcode
|
|
*/
|
|
template <typename ROOT_TYPE>
|
|
class ClassFactoryInterface {
|
|
public:
|
|
//! The type that represents the root class of the hierarchie.
|
|
typedef ROOT_TYPE RootType;
|
|
typedef std::map<std::string, ClassFactoryInterface<ROOT_TYPE>*> ClassPool;
|
|
typedef std::map<const RTTI*, std::string> ClassNames;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Xstruction
|
|
// ----------------------------------------------------------------------
|
|
protected:
|
|
//! Constructor
|
|
ClassFactoryInterface(const RTTI* typeInfo, bool reregister = false);
|
|
|
|
public:
|
|
//! Destructor
|
|
virtual ~ClassFactoryInterface();
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Public Interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! Creates an instance of the class with the passed in name
|
|
static ROOT_TYPE* Create(const char* className);
|
|
static ROOT_TYPE* Create(const std::string& className);
|
|
|
|
//! Returns the registered classname for an object
|
|
static const char* ClassName(const ROOT_TYPE*);
|
|
|
|
//! Returns the registered classname for a type
|
|
static const char* ClassName(const RTTI*);
|
|
|
|
//! Looks up a class factory for a given class name
|
|
static ClassFactoryInterface* FindByClassName(const char* className);
|
|
|
|
static bool IsTypeOf(const char* baseName, const char* derivedName);
|
|
|
|
//! Returns the number of registered classes
|
|
static unsigned int NumberOfRegisteredClasses();
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Protected interface
|
|
// ----------------------------------------------------------------------
|
|
protected:
|
|
//! Returns the class id for the objects the factory can create
|
|
const RTTI* typeInfo() const;
|
|
|
|
//! Returns the name of the class (as given during construction) which can be created
|
|
//! by this factory
|
|
const char* className() const;
|
|
|
|
//! Derived classes override this method to do the actual creation
|
|
virtual ROOT_TYPE* create() const = 0;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Implementation
|
|
// ----------------------------------------------------------------------
|
|
private:
|
|
static ClassPool &Classes();
|
|
static ClassNames &Names();
|
|
|
|
//! Adds a factory to the classpool
|
|
//! \return whether the factory has been added or not
|
|
static bool RegisterFactory(ClassFactoryInterface* factory, bool reregister = false);
|
|
|
|
//! Removes a factory from the classpool
|
|
//! \return whether the factory has been removed or not
|
|
static bool UnregisterFactory(ClassFactoryInterface* factory);
|
|
|
|
|
|
private:
|
|
const RTTI* _typeInfo;
|
|
};
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
#define IMPLEMENT_CLASSFACTORY(BaseClass, APIDef) \
|
|
template class APIDef Seiscomp::Core::Generic::ClassFactoryInterface<BaseClass>
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
/** \brief Template based class factory for an abstract class
|
|
|
|
The class factory for an abstract class of a class hierarchie.
|
|
It only registeres the root classname but does not create
|
|
an object.
|
|
*/
|
|
template <typename ROOT_TYPE, typename TYPE>
|
|
class AbstractClassFactory : public ClassFactoryInterface<ROOT_TYPE> {
|
|
public:
|
|
//! The type that represents the actual polymorphic class.
|
|
typedef TYPE Type;
|
|
|
|
public:
|
|
AbstractClassFactory(const char*);
|
|
|
|
protected:
|
|
//! Always returns nullptr
|
|
ROOT_TYPE* create() const;
|
|
};
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
/** \brief Template based class factory
|
|
|
|
Each polymorphic type must be registered with the class factory.
|
|
This is done via a simple declaration:
|
|
\code
|
|
Factory<MyBaseClassType,MyClassType> MyFactory("MyClassName");
|
|
\endcode
|
|
|
|
It is however recommended that the REGISTER_CLASS macro is used.
|
|
\code
|
|
REGISTER_CLASS(MyClass)
|
|
\endcode
|
|
*/
|
|
template <typename ROOT_TYPE, typename TYPE>
|
|
class ClassFactory : public ClassFactoryInterface<ROOT_TYPE> {
|
|
public:
|
|
//! The type that represents the actual polymorphic class.
|
|
typedef TYPE Type;
|
|
|
|
public:
|
|
ClassFactory(const char*, bool reregister = false);
|
|
|
|
protected:
|
|
//! The actual creation
|
|
ROOT_TYPE* create() const;
|
|
};
|
|
|
|
|
|
#define REGISTER_ABSTRACT_CLASS_VAR(BaseClass, Class) \
|
|
Seiscomp::Core::Generic::AbstractClassFactory<BaseClass, Class> __##Class##Factory__(#Class)
|
|
|
|
#define REGISTER_ABSTRACT_CLASS(BaseClass, Class) \
|
|
static REGISTER_ABSTRACT_CLASS_VAR(BaseClass, Class)
|
|
|
|
#define REGISTER_CLASS_VAR(BaseClass, Class) \
|
|
Seiscomp::Core::Generic::ClassFactory<BaseClass, Class> __##Class##Factory__(#Class, false)
|
|
|
|
#define REGISTER_CLASS(BaseClass, Class) \
|
|
static REGISTER_CLASS_VAR(BaseClass, Class)
|
|
|
|
#define REREGISTER_CLASS_VAR(BaseClass, Class) \
|
|
Seiscomp::Core::Generic::ClassFactory<BaseClass, Class> __##Class##Factory__(#Class, true)
|
|
|
|
#define REREGISTER_CLASS(BaseClass, Class) \
|
|
static REREGISTER_CLASS_VAR(BaseClass, Class)
|
|
|
|
#define DECLARE_CLASSFACTORY_FRIEND(BaseClass, Class) \
|
|
friend class Seiscomp::Core::Generic::ClassFactory<BaseClass, Class>
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
#include "factory.inl"
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|