Solution: Command¶
Command Classes¶
#pragma once
#include <socialdb.h>
#include <string>
#include <variant>
#include <optional>
#include <tuple>
#include <vector>
class SocialDBCommand
{
public:
virtual ~SocialDBCommand() {}
virtual void execute(SocialDB&) = 0;
};
class SocialDBInsertCommand : public SocialDBCommand
{
public:
SocialDBInsertCommand(
const std::string& svnr,
const std::string& firstname,
const std::string& lastname)
: _svnr(svnr),
_firstname(firstname),
_lastname(lastname) {}
virtual void execute(SocialDB&) override;
void result() const;
private:
std::string _svnr;
std::string _firstname;
std::string _lastname;
std::optional<SocialDB::NotInserted> _error;
};
class SocialDBFindCommand : public SocialDBCommand
{
public:
SocialDBFindCommand(const std::string& svnr) : _svnr(svnr) {}
virtual void execute(SocialDB&) override;
SocialDB::Person result() const;
private:
std::string _svnr;
std::variant<SocialDB::Person, SocialDB::NotFound> _result;
};
class SocialDBDropCommand : public SocialDBCommand
{
public:
virtual void execute(SocialDB&) override;
void result() const {}
};
class SocialDBBulkInsertCommand : public SocialDBCommand
{
public:
SocialDBBulkInsertCommand() = default;
SocialDBBulkInsertCommand(std::initializer_list<std::tuple<std::string, std::string, std::string>>);
void add(const SocialDBInsertCommand&);
virtual void execute(SocialDB&) override;
private:
std::vector<SocialDBInsertCommand> _commands;
};
#include "social-db-commands.h"
void SocialDBInsertCommand::execute(SocialDB& db)
{
try {
db.insert(_svnr, _firstname, _lastname);
}
catch (const SocialDB::NotInserted& e) {
_error = e;
}
}
void SocialDBInsertCommand::result() const
{
if (_error)
throw _error.value();
}
void SocialDBFindCommand::execute(SocialDB& db)
{
try {
_result = db.find(_svnr);
}
catch (const SocialDB::NotFound& e) {
_result = e;
}
}
SocialDB::Person SocialDBFindCommand::result() const
{
if (const SocialDB::Person* p = std::get_if<SocialDB::Person>(&_result))
return *p;
else
throw std::get<SocialDB::NotFound>(_result);
}
void SocialDBDropCommand::execute(SocialDB& db)
{
db.drop();
}
SocialDBBulkInsertCommand::SocialDBBulkInsertCommand(
std::initializer_list<std::tuple<std::string, std::string, std::string>> init)
{
for (const auto& [svnr, firstname, lastname]: init)
_commands.push_back(SocialDBInsertCommand(svnr, firstname, lastname));
}
void SocialDBBulkInsertCommand::add(const SocialDBInsertCommand& ic)
{
_commands.push_back(ic);
}
void SocialDBBulkInsertCommand::execute(SocialDB& db)
{
for (auto& c: _commands)
c.execute(db);
}