Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+406
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Construction of MapObjects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
// Own
|
||||
#include "generic_object_factory.h"
|
||||
#include "object_container.h"
|
||||
#include "abstract_map_object.h"
|
||||
#include "situation_map_utils.h"
|
||||
#include <Common/ref_pointer.h>
|
||||
#include <situation_map_export.h>
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
|
||||
// Qt
|
||||
#include <QMap>
|
||||
|
||||
#include <typeindex>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
// forward
|
||||
class Map;
|
||||
|
||||
|
||||
using FactoryMapKey = std::type_index;
|
||||
using FactoryMapData = QSharedPointer<GenericObjectFactoryBase>;
|
||||
using FactoryMap = QMap<FactoryMapKey, FactoryMapData>;
|
||||
|
||||
|
||||
/**
|
||||
* @brief The MapSingleton struct maps between
|
||||
* INTERFACE (type_index) and GenericObjectFactory
|
||||
* It´s a singleton. Therefore this map has to be set only once per process until it is cleared.
|
||||
*/
|
||||
struct SITUATIONMAP_EXPORT MapSingleton
|
||||
{
|
||||
static FactoryMap &getFactoryMap();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The ObjectFactory class is basically responsible for creation of all objects of type AbstractMapObject.
|
||||
* The complete range of tasks includes:
|
||||
* - creates objects of type AbstractMapObject and deriving classes
|
||||
* - initialize (call init() ofAbstractMapObject) and
|
||||
* - store them (within ObjectContainer)
|
||||
* - stores an ObjectContainer (with its IdGenerator)
|
||||
*
|
||||
* <b>Example:
|
||||
*
|
||||
* \code
|
||||
// Pre-condition :
|
||||
// Initialize objectFactory:
|
||||
SituationMap::ObjectFactory::registerMe(typeid(SituationMap::Participant),
|
||||
new SituationMap::GenericObjectFactory<SituationMap::ParticipantImpl>() );
|
||||
// : Pre-condition
|
||||
|
||||
...
|
||||
|
||||
SituationMap::ObjectFactory& objFac = d->m_map->objectFactory();
|
||||
|
||||
// use an LOGICAL layer (not basemap)
|
||||
QString layername("ParticipantLayerName");
|
||||
|
||||
SituationMap::RefPointer<SituationMap::Participant> objPtr;
|
||||
objPtr = objFac.create<SituationMap::Participant>("ParticipantLayerName", // use an LOGICAL layer (not basemap)
|
||||
"ParticipantId1" // debugInfo (may contain SimId)
|
||||
);
|
||||
* \endcode
|
||||
*
|
||||
* \sa Map
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT ObjectFactory
|
||||
{
|
||||
public:
|
||||
/*! \name Construction, Destruction */
|
||||
//@{
|
||||
/**
|
||||
* @brief Contructor.
|
||||
* @param map to be used..
|
||||
*/
|
||||
explicit ObjectFactory(Map *map)
|
||||
: m_logger(getLogger("ObjectFactory"))
|
||||
, m_map(map) {}
|
||||
virtual ~ObjectFactory() = default; ///< Destructor
|
||||
|
||||
ObjectFactory(const ObjectFactory &other) = delete;
|
||||
ObjectFactory &operator=(ObjectFactory &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Set the ObjectContainer to be used.
|
||||
* @param objectContainer to be used.
|
||||
*/
|
||||
void setObjectContainer(const QSharedPointer<ObjectContainer> &objectContainer);
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @brief Translate uniqueMapId to native AbstractMapObject.
|
||||
* @param uniqueId to get.
|
||||
* @return AbstractMapObject if found, otherwise null.
|
||||
*/
|
||||
AbstractMapObject *idToMapObject(const UniqueMapId &uniqueId) const;
|
||||
|
||||
Map* map() { return m_map; }
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Initialize MapObject.
|
||||
* @param obj MapObject to be initialized.
|
||||
* @param map Map to which the mapObject belongs to.
|
||||
* @param logicalLayerName (logical) layer on which the object should be created.
|
||||
* @return True on success; otherwise false.
|
||||
*/
|
||||
bool initMapObject(AbstractMapObject *obj, Map *map, UniqueMapId uid, const QString &logicalLayerName);
|
||||
|
||||
friend class MapImpl; // to support MapImpl::doClickMapObject
|
||||
|
||||
/**
|
||||
* @brief Translate type_index of
|
||||
* the interface class to the corresponding type_index of implementation class.
|
||||
* @param interface_IN Type to be translated.
|
||||
* @param bOk true is found, otherwise false.
|
||||
* @return requested type_index of implementation class.
|
||||
*/
|
||||
std::type_index interfaceToImplementation(const std::type_index &interface_IN, bool *bOk = nullptr);
|
||||
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// create by (interface) type
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/*! \name Create */
|
||||
//@{
|
||||
|
||||
/**
|
||||
* @brief Create MapObject of required type.
|
||||
* @param uniqueMapId Define the uniqueId of MapObject, be careful to use a valid and unused id
|
||||
* @param logicalLayerName (logical) layer on which the object should be created.
|
||||
* @param debugInfo Set debugInfo
|
||||
* @return MapObject of required type on success; otherwise null.
|
||||
*/
|
||||
template<typename INTERFACE_TYPE>
|
||||
RefPointer<INTERFACE_TYPE> create(const UniqueMapId &uniqueMapId,
|
||||
const QString &logicalLayerName, // external: via type
|
||||
const QString &debugInfo = QString())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " create requested for ..."
|
||||
<< ", debugInfo='" << debugInfo << "'"
|
||||
<< ", logicalLayerName='" << logicalLayerName << "'";
|
||||
|
||||
if (!isMapReady())
|
||||
{
|
||||
FATAL_LOG(m_logger) << LOGFUNCTION << " create failed"
|
||||
<< ", map not ready yet"
|
||||
<< ", debugInfo='" << debugInfo << "'";
|
||||
return RefPointer<INTERFACE_TYPE>();
|
||||
}
|
||||
|
||||
|
||||
if (logicalLayerName.isEmpty())
|
||||
{
|
||||
FATAL_LOG(m_logger) << LOGFUNCTION << " create failed"
|
||||
<< ", logicalLayerName is empty"
|
||||
<< ", debugInfo='" << debugInfo << "'";
|
||||
return RefPointer<INTERFACE_TYPE>();
|
||||
}
|
||||
|
||||
|
||||
std::type_index key(typeid(INTERFACE_TYPE));
|
||||
const QString &name = QString::fromLatin1(key.name());
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " create requested for ... name='" << name << "'"
|
||||
<< ", debugInfo='" << debugInfo << "'";
|
||||
|
||||
if (MapSingleton::getFactoryMap().contains(key))
|
||||
{
|
||||
RefPointer<INTERFACE_TYPE> obj(MapSingleton::getFactoryMap().value(key)->makeObj(debugInfo));
|
||||
if (obj.valid() && initMapObject(obj.get(), m_map, uniqueMapId, logicalLayerName))
|
||||
{
|
||||
return obj; // the caller will receive the requested type :-)
|
||||
}
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed, name='" << name << "'";
|
||||
obj->removeMySelf(); // cleanup
|
||||
return RefPointer<INTERFACE_TYPE>();
|
||||
}
|
||||
FATAL_LOG(m_logger) << LOGFUNCTION << " create failed, name= '" << name << "'"
|
||||
<< ", factoryMap.size() = " << MapSingleton::getFactoryMap().count();
|
||||
return RefPointer<INTERFACE_TYPE>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create MapObject of required type.
|
||||
* @param logicalLayerName (logical) layer on which the object should be created.
|
||||
* @param debugInfo Set debugInfo
|
||||
* @return MapObject of required type on success; otherwise null.
|
||||
*/
|
||||
template<typename INTERFACE_TYPE>
|
||||
RefPointer<INTERFACE_TYPE> create(const QString &logicalLayerName, // external: via type
|
||||
const QString &debugInfo = QString())
|
||||
{
|
||||
return create<INTERFACE_TYPE>(SituationMap::INVALID_MAP_ID, logicalLayerName, debugInfo);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/*! \name Count */
|
||||
//@{
|
||||
/**
|
||||
* @brief Number of objects.
|
||||
* @return Current number of objects.
|
||||
*/
|
||||
qint32 count() const;
|
||||
//@}
|
||||
|
||||
/*! \name Check */
|
||||
//@{
|
||||
/**
|
||||
* @brief Check uniqueMapId.
|
||||
* @param uniqueMapId to be checked.
|
||||
* @return Returns true if uniqueId is valid; otherwise returns false.
|
||||
* @note Prefer SituationMap::isUniqueMapIdValid() due to runtime aspects.
|
||||
*/
|
||||
static bool isUniqueIdValid(const UniqueMapId &uniqueMapId);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check the existence <B>not</B> regarding the type.
|
||||
* @param uniqueId to lookup.
|
||||
* @return Returns true if container contains an occurrence; otherwise returns false.
|
||||
*/
|
||||
bool contains(const UniqueMapId &uniqueMapId) const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check the existence <B>regarding</B> the type.
|
||||
* @param uniqueMapId to lookup.
|
||||
* @return Returns true if container contains an occurrence; otherwise returns false.
|
||||
*/
|
||||
template<typename INTERFACE_TYPE>
|
||||
bool contains(const UniqueMapId &uniqueMapId)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " contains requested for uniqueMapId=" << uniqueMapId;
|
||||
|
||||
bool containsId = contains(uniqueMapId);
|
||||
|
||||
if (containsId)
|
||||
{
|
||||
// 1 typeid Interface to typeid Impl:
|
||||
bool bOk = false;
|
||||
std::type_index keyRequestedImpl = interfaceToImplementation(typeid(INTERFACE_TYPE), &bOk);
|
||||
if (bOk)
|
||||
{
|
||||
// 2. retrieve out of internal container:
|
||||
AbstractMapObject *mapObj = idToMapObject(uniqueMapId);
|
||||
|
||||
if (!mapObj)
|
||||
return false;
|
||||
|
||||
// 3. compare retrieved objectTYPE with requested (IMPL)TYPE:
|
||||
// std::type_index(typeid(*baseClass)) == std::type_index(typeid(*subClass))
|
||||
containsId = std::type_index(typeid(*mapObj)) == keyRequestedImpl;
|
||||
}
|
||||
else
|
||||
{
|
||||
FATAL_LOG(m_logger) << LOGFUNCTION << " contains failed, name= '" << typeid(INTERFACE_TYPE).name() << "'"
|
||||
<< " factoryMap.size() = " << MapSingleton::getFactoryMap().count();
|
||||
}
|
||||
}
|
||||
return containsId;
|
||||
|
||||
} // ObjectFactory::contains
|
||||
//@}
|
||||
|
||||
|
||||
/*! \name Access */
|
||||
//@{
|
||||
|
||||
/**
|
||||
* @brief Get all UniqueIds.
|
||||
* @return All UniqueIds.
|
||||
*/
|
||||
QList<UniqueMapId> getAllKeys() const;
|
||||
|
||||
/**
|
||||
* @brief Get all Objects.
|
||||
* @return Container with all objects.
|
||||
*/
|
||||
QList < RefPointer<AbstractMapObject> > getAllObjects() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get access the object.
|
||||
* @param uniqueId to lookup.
|
||||
* @return Pointer to AbstractMapObject (Base class).
|
||||
*/
|
||||
RefPointer<AbstractMapObject> get(const UniqueMapId &uniqueMapId) const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get access to object <B>regarding</B> the type.
|
||||
* @param uniqueId to lookup.
|
||||
* @return Pointer to object (adaquate type).
|
||||
*/
|
||||
template<typename INTERFACE_TYPE>
|
||||
RefPointer<INTERFACE_TYPE> get(const UniqueMapId &uniqueMapId) const
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " get requested for uniqueMapId=" << uniqueMapId;
|
||||
|
||||
// lookup in internal container:
|
||||
RefPointer<AbstractMapObject> mapObj = get(uniqueMapId);
|
||||
|
||||
return RefPointer<INTERFACE_TYPE>(mapObj); // implicit dynamic_cast
|
||||
}
|
||||
|
||||
/*! \name Clear */
|
||||
//@{
|
||||
/**
|
||||
* @brief Clear all objects within associated ObjectContainer
|
||||
*/
|
||||
void clearObjects();
|
||||
|
||||
/**
|
||||
* @brief Clear static register of GenericObjectFactory
|
||||
* (created using registerMe())
|
||||
*/
|
||||
static void clearRegister();
|
||||
//@}
|
||||
|
||||
/*! \name Register */
|
||||
//@{
|
||||
|
||||
template <typename IMPL_TYPE>
|
||||
friend class RegisterFactory; // to support 'REGISTER_TYPE'
|
||||
static void registerMe(const std::type_index &key, GenericObjectFactoryBase *factory)
|
||||
{
|
||||
LOGGER_T logger = getLogger("ObjectFactory");
|
||||
DEBUG_LOG(logger) << LOGFUNCTION
|
||||
<< " IF '" << key.name() << "'"
|
||||
<< " to IMPL '" << factory->getTypeIndexOfImplementation().name() << "')";
|
||||
MapSingleton::getFactoryMap()[key] = FactoryMapData(factory);
|
||||
|
||||
}
|
||||
//@}
|
||||
|
||||
|
||||
private:
|
||||
LOGGER_T m_logger; ///< Interface of the Logging-Facility
|
||||
|
||||
Map *m_map = nullptr;
|
||||
QSharedPointer<ObjectContainer> m_objectContainer;
|
||||
|
||||
bool isMapReady() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Option for registration
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief The RegisterFactory class for registering the types to be created by ObjectFactory.
|
||||
*/
|
||||
template <typename IMPL_TYPE>
|
||||
class SITUATIONMAP_EXPORT RegisterFactory final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param key type_index to be registered
|
||||
*/
|
||||
explicit RegisterFactory(const std::type_index &key)
|
||||
{
|
||||
GenericObjectFactoryBase *genericFactory = new GenericObjectFactory<IMPL_TYPE>;
|
||||
ObjectFactory::registerMe(key, genericFactory);
|
||||
}
|
||||
|
||||
~RegisterFactory() = default;
|
||||
|
||||
// create by (interface) type
|
||||
// can be used to register by put that macro at the end of the implementation (cpp)
|
||||
#define REGISTER_TYPE(interfaceType, implType) \
|
||||
namespace { \
|
||||
static RegisterFactory<implType> s_factory( typeid(interfaceType) ); \
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace SituationMap
|
||||
|
||||
Reference in new issue
Block a user