Files
secondo/Algebras/DBService2/SecondoRecordAdapter.hpp

132 lines
4.5 KiB
C++
Raw Permalink Normal View History

2026-01-23 17:03:45 +08:00
#ifndef SECONDO_RECORD_ADAPTER_H
#define SECONDO_RECORD_ADAPTER_H
#include "Algebras/DBService2/DatabaseAdapter.hpp"
#include "NestedList.h"
extern NestedList* nl;
extern boost::recursive_mutex nlparsemtx;
#include <loguru.hpp>
namespace DBService
{
template<typename RecordType, typename RecordAdapterType>
class Record;
/*
Similar to the type mapping of Secondo Algebra modules, within the ORM
there is a need to map objects represented as nested list into
data structures. In the ORM these data structures are substypes of the
Record class.
In order to achieve the transformation of the nested listed list
representation into the Record subclass the Adapter Pattern is used.
See: https://refactoring.guru/design-patterns/adapter/cpp/example
The Adapter implictly acts as a factory method
(https://refactoring.guru/design-patterns/factory-method) to construct
Record objects such as Nodes, Relations, etc.
Template classes do not have a cpp file as their definition needs
to be done inside the header file.
See: https://bit.ly/3fKw1IS
*/
template <class RecordType, class RecordAdapterType>
class SecondoRecordAdapter {
public:
/*
Builds a vector of shared_ptr T (Nodes) from a resultList obtained
e.g. by executing a find statement.
The resultListOffset sets the offset from which relevant records
within the nested list are to be expected.
It is assumed that relevent entries are contained in the NL in a
particular attribute order.
*/
static std::vector<std::shared_ptr<RecordType> >
buildVectorFromNestedList(
std::string database, std::shared_ptr<DatabaseAdapter> dbAdapter,
ListExpr resultList, int resultListOffset = 0) {
std::vector<std::shared_ptr<RecordType> > records;
/* The resultList contains a header which we are not interested in.
* Example:
* (
* (rel (tuple ((Host text) (Port int) (Config text) (DiskPath text)
* (ComPort int) (TransferPort int) (TID tid))))
* (
* ('localhost' 1245 '' '/home/doesnt_exist/secondo' 9941 9942 1)
* ('localhost' 1245 '' '/home/doesnt_exist/secondo' 9941 9942 2)
* ('localhost' 1245 '' '/home/doesnt_exist/secondo' 9941 9942 3)
* ('localhost' 1245 '' '/home/doesnt_exist/secondo' 9941 9942 4)
* )
* )
*
* The list of records is the 2nd element
*/
LOG_F(INFO, "%s", "Acquiring lock for nlparsemtx...");
boost::unique_lock<boost::recursive_mutex> nlLock(nlparsemtx);
LOG_F(INFO, "%s", "Successfully acquired lock for nlparsemtx...");
ListExpr recordList = nl->Second(resultList);
while ( !nl->IsEmpty(recordList) ) {
// Obtain a record from the list of records.
// ('localhost' 1245 '' '/home/doesnt_exist/secondo' 9941 9942 1)
ListExpr currentRecordNL = nl->First(recordList);
std::shared_ptr<RecordType> currentRecord =
buildObjectFromNestedList(database, currentRecordNL,
resultListOffset);
currentRecord->setDatabase(database);
currentRecord->setDatabaseAdapter(dbAdapter);
records.push_back(currentRecord);
// Set the recordList to the reduced List without the currentRow
recordList = nl->Rest(recordList);
}
return records;
}
/*
Factory method constructing Record substypes from a given nested list
acting as an Adapter.
Input is a nested list.
Returns a newly constructed Record object of the Type T (e.g. Node).
*/
static std::shared_ptr<RecordType> buildObjectFromNestedList(
std::string database, ListExpr recordAsNestedList,
int resultListOffset = 0) {
/*
The static_cast makes the buildObjectFromNestedList implementation
"pluggable". When configuring specific SecondoRecordAdapter, e.g.
the SecondoRelationAdapter the SecondoRelationAdapter can inherit
from the SecondoRecordAdapter and override the buildObjectFromNestedList
function.
See: https://www.youtube.com/watch?v=-WV9vWjhI3g&ab_channel=BoQian
*/
return RecordAdapterType::buildObjectFromNestedList(
database, recordAsNestedList, resultListOffset);
}
};
} // namespace DBService
#endif