Skip to content

Commit

Permalink
Model and further serialization. Added virtual destructors for interf…
Browse files Browse the repository at this point in the history
…aces.
  • Loading branch information
cristianfrasineanu committed Nov 23, 2016
1 parent f21c487 commit 93aa3c6
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 47 deletions.
5 changes: 4 additions & 1 deletion app/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ void Console::loadViews(const fs::path &viewsFolder)
void Console::loadActions()
{
// TODO: load actions via config file
// The confirm is basically linked to the next view.
// For instance, the login view will have then next view the dashboard.
vector<char> actions = { 'q', 'b', 'n', 'c' };

this->actions = actions;
Expand All @@ -137,7 +139,8 @@ void Console::handleView()
buffer << viewFile.rdbuf();
this->currentView.setRawFormat(buffer.str());

// If there's any validation error inside the model
// If there's any validation error catch it and reload the view.
// TODO: Fix the memory leak when catching an error.
try
{
this->theController = Controller(this->currentView.getViewName(), buffer.str(), View::getViewExtension());
Expand Down
11 changes: 4 additions & 7 deletions app/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void Controller::prepareViewInput(const string &subChunk, const string &inputAli
map<string, string> currentInput;

cout << subChunk << " ";
cin >> userInput;
getline(cin, userInput);
cout << endl;

this->userInputs[inputAlias] = userInput;
Expand Down Expand Up @@ -122,12 +122,9 @@ void Controller::chopChunkAndGetAlias(string &chunk)
// Don't assign multiple Controllers, stupid.
void Controller::operator=(const Controller &controller)
{
if (controller.controllerName != NULL)
{
delete[] this->controllerName;
this->controllerName = new char[strlen(controller.controllerName) + 1];
strcpy(this->controllerName, controller.controllerName);
}
delete[] this->controllerName;
this->controllerName = new char[strlen(controller.controllerName) + 1];
strcpy(this->controllerName, controller.controllerName);
this->viewChunk = controller.viewChunk;
this->controllerAttributions = controller.controllerAttributions;
}
Expand Down
3 changes: 0 additions & 3 deletions app/Controller.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

#include "Helpers.h"
#include "Model.h"
Expand Down
6 changes: 3 additions & 3 deletions app/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ Model::Model()
void Model::sendSerializedInput()
{
// There's interaction with only one model on the view.
string modelName = this->parseEntityName(this->rawInput.begin()->first),
string entityName = this->parseEntityName(this->rawInput.begin()->first),
inputAlias;

if (this->repository == NULL)
{
this->attachEntity(modelName);
this->attachEntity(entityName);
}

for (map<string, string>::iterator it = this->rawInput.begin(); it != this->rawInput.end(); it++)
{
inputAlias = it->first;
inputAlias.erase(0, modelName.size() + 1);
inputAlias.erase(0, entityName.size() + 1);

this->serializedInput[inputAlias] = it->second;
}
Expand Down
5 changes: 0 additions & 5 deletions app/Model.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#include <iostream>
#include <string>
#include <vector>
#include <map>

#include "Helpers.h"
#include "RepositoryInterface.h"
#include "UserRepository.h"
Expand Down
5 changes: 5 additions & 0 deletions app/ModelInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "ModelInterface.h"

ModelInterface::~ModelInterface()
{
}
25 changes: 25 additions & 0 deletions app/ModelInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <fstream>
#include "Helpers.h"

using namespace std;

//---Model---
//----------------
// The contents of an entity are serialized as a structure with static components.
// Writing directly objects to files can yield great havoc afterwards as we are possibly writing addresses, not values.
// The model detects what to do with data when writing to file from the state of the attributes.
class ModelInterface {
private:
virtual void openIOStream() = 0;
protected:
map<string, string> attributes;
vector<string> protectedAttributes;
fstream io;
public:
virtual void save() = 0;
virtual void setAttributes(map<string, string> &) = 0;

virtual ~ModelInterface();
};
5 changes: 5 additions & 0 deletions app/RepositoryInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "RepositoryInterface.h"

RepositoryInterface::~RepositoryInterface()
{
}
20 changes: 10 additions & 10 deletions app/RepositoryInterface.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
#pragma once

#include <string>
#include <map>

#include "Helpers.h"
#include "ModelInterface.h"

using namespace std;

//---Entity---
//------------
// This entity acts like a repository interface between the accessor model and the actual model.
//---Repository---
//----------------
// This entity acts like a glue between the accessor model and the actual model.
// An example would be if we want to get all the records for a certain model.
// The controller sends the request, the accessor model determines which model is needed and through
// the repostory calls the methods responsible for retrieveing the data.
// the repository it calls the methods responsible for retrieving your data.
class RepositoryInterface {
private:
virtual void defineValidation() = 0;
virtual void receiveCleanInput(map<string, string> &) = 0;
protected:
map<string, string> ValidationRules;
map<string, string> ValidationErrors;
virtual void receiveCleanInput(map<string, string> &) = 0;

ModelInterface *model;
public:
virtual void writeNewRecord() = 0;
virtual void validateItems(map<string, string> &) = 0;

virtual void retrieveItemForActive() = 0;
virtual void retrieveAll() = 0;

virtual ~RepositoryInterface();
};
65 changes: 65 additions & 0 deletions app/UserModel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "UserModel.h"

void UserModel::save()
{
//this->io.write(reinterpret_cast<char *>(&this->User), sizeof(this->User));

cout << "Theoretically wrote the data into the file"
<< endl;
}

void UserModel::setAttributes(map<string, string> &cleanInputs)
{
for (map<string, string>::iterator it = cleanInputs.begin(); it != cleanInputs.end(); it++)
{
if (isInVector(this->protectedAttributes, it->first))
{
continue;
}
else if (it->first == "fullname")
{
strcpy(this->User.full_name, it->second.c_str());
}
else if (it->first == "email")
{
strcpy(this->User.email, it->second.c_str());
}
else if (it->first == "username")
{
strcpy(this->User.username, it->second.c_str());
}
else if (it->first == "password")
{
strcpy(this->User.password, it->second.c_str());
}
}

// If there's a new user, assign created_at with the current date.
if (strlen(this->User.full_name) != 0)
{
time_t t = time(nullptr);
strftime(this->User.created_at, sizeof(this->User.created_at), "%c", localtime(&t));
}
}

UserModel::~UserModel()
{
this->io.close();
}

string UserModel::pathToFile = "..\\database\\users.store";
void UserModel::openIOStream()
{
this->io.open(UserModel::pathToFile, ios::in | ios::out | ios::app | ios::binary);

if (!this->io.is_open())
{
cout << "Couldn't open " + UserModel::pathToFile;
}
}

UserModel::UserModel()
{
this->openIOStream();
this->protectedAttributes = { "created_at", "deleted_at", "role", "active" };
}
36 changes: 36 additions & 0 deletions app/UserModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <iostream>
#include <regex>
#include <iomanip>
#include <ctime>
#include <locale>

#include "ModelInterface.h"

class UserModel : public ModelInterface {
private:
static string pathToFile;

struct {
char full_name[255] = "";
char email[255] = "";
char username[20] = "";
char password[17] = "";
char created_at[50] = "";

// Soft deletes
char deleted_at[50] = "";
char role[10] = "user";
bool active = 1;
} User;

void openIOStream();
public:
// Open the IOStream and assign the protected attributes that shouldn't be changed by the user
UserModel();

void save();
void setAttributes(map<string, string> &);

// Set the active to false on logout
~UserModel();
};
28 changes: 17 additions & 11 deletions app/UserRepository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,39 @@

void UserRepository::defineValidation()
{
// Stand back, I am going to try Regex!
this->ValidationRules = {
{ "username", "^(?=.{8,19}([a-zA-Z0-9]+)$)(?![^a-zA-Z])(?!.*[!_\45.]{2})[a-zA-Z0-9.\45_]+$" },
{ "password", "^(?=.{5,16}$)(?=.*[A-Z])(?=.*[0-9])(?=.*[!\45_@.$#])[a-zA-Z0-9!\45_@.$#]+$" }
{ "fullname", "^(?=.*(?:[\\s\\-])([a-zA-Z]+\\s?)+)([a-zA-Z]+)(?:[\\s\\-]).*$" },
{ "email", "^(?!.*[._]{2})[a-z0-9._]+@[a-z0-9]+(\\.[a-z]{1,3}){1,2}$" },
{ "username", "^(?=.{7,19}$)(?![^a-zA-Z0-9])(?!.*[!_\\-\\.]{2})[a-zA-Z0-9\\.\\-_]+$" },
{ "password", "^(?=.{5,16}$)(?=.*[A-Z])(?=.*[0-9])(?=.*[!\\-_@.$#])[a-zA-Z0-9!\\-_@.$#]+$" }
};

this->ValidationErrors = {
{ "fullname", "Please enter a valid firstname and lastname." },
{ "email", "Please enter a valid email address." },
{ "username", "Your username should have 8-20 characters, should start only with a letter, doesn't repeat special characters and finishes with a letter or a number." },
{ "password", "Your password should habe 6-16 characters, and contain an uppercase letter, a number and a special character." }
{ "password", "Your password should habe 5-16 characters, and contain an uppercase letter, a number and a special character." },
};
}

UserRepository::UserRepository()
{
this->defineValidation();
this->model = new UserModel();
}

void UserRepository::receiveCleanInput(map<string, string> &cleanInput)
{
log(cleanInput, "cleanInput", "after validation");
// Load the record into the model
}

void UserRepository::writeNewRecord()
{
//
this->model->setAttributes(cleanInput);
this->model->save();
}

void UserRepository::validateItems(map<string, string> &serializedInput)
{
map<string, string> serializedCopy = serializedInput;

for (map<string, string>::iterator it = serializedCopy.begin(); it != serializedCopy.end(); it++)
for (map<string, string>::iterator it = serializedInput.begin(); it != serializedInput.end(); it++)
{
try
{
Expand Down Expand Up @@ -65,4 +66,9 @@ void UserRepository::retrieveAll()
// Print everything
}

UserRepository::~UserRepository()
{
delete this->model;
}


8 changes: 2 additions & 6 deletions app/UserRepository.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include <iostream>
#include <string>
#include <map>
#include <regex>

#include "RepositoryInterface.h"
#include "UserModel.h"

class UserRepository : public RepositoryInterface {
private:
Expand All @@ -12,11 +10,9 @@ class UserRepository : public RepositoryInterface {
public:
UserRepository();

void writeNewRecord();
void validateItems(map<string, string> &);

void retrieveItemForActive();
void retrieveAll();

// Set the active to false when destroying the object.
~UserRepository();
};
5 changes: 5 additions & 0 deletions app/app.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,20 @@
<ClCompile Include="Controller.cpp" />
<ClCompile Include="Helpers.cpp" />
<ClCompile Include="Model.cpp" />
<ClCompile Include="ModelInterface.cpp" />
<ClCompile Include="RepositoryInterface.cpp" />
<ClCompile Include="UserModel.cpp" />
<ClCompile Include="UserRepository.cpp" />
<ClCompile Include="View.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Console.h" />
<ClInclude Include="Controller.h" />
<ClInclude Include="ModelInterface.h" />
<ClInclude Include="RepositoryInterface.h" />
<ClInclude Include="Helpers.h" />
<ClInclude Include="Model.h" />
<ClInclude Include="UserModel.h" />
<ClInclude Include="UserRepository.h" />
<ClInclude Include="View.h" />
</ItemGroup>
Expand Down
Loading

0 comments on commit 93aa3c6

Please sign in to comment.