Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+406
View File
@@ -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