Work on requirements management
This commit is contained in:
@@ -1,26 +1,51 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <dbus/api/api.h>
|
#include <dbus/api/api.h>
|
||||||
#include <sdi_toolBox/generic/uuid.h>
|
|
||||||
|
|
||||||
namespace api::requirement
|
namespace api::requirement
|
||||||
{
|
{
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
using TimePoint = std::chrono::system_clock::time_point;
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
enum class Status
|
||||||
|
{
|
||||||
|
Draft, // The requirement is in draft state and has not been finalized
|
||||||
|
InReview, // The requirement is currently being reviewed by stakeholders
|
||||||
|
Approved, // The requirement has been approved and is ready for implementation
|
||||||
|
Rejected // The requirement has been rejected and will not be implemented
|
||||||
|
};
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
struct Metadata
|
||||||
|
{
|
||||||
|
std::string uuid; // Unique identifier for the requirement, generated automatically
|
||||||
|
std::string id; // Unique identifier for the requirement, provided by the user (e.g., "REQ-001")
|
||||||
|
std::string author; // Name of the person who created the requirement
|
||||||
|
TimePoint created_at; // Creation timestamp
|
||||||
|
TimePoint updated_at; // Last update timestamp
|
||||||
|
};
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
struct Details
|
||||||
|
{
|
||||||
|
std::string name; // Short name or title of the requirement
|
||||||
|
std::string description; // Detailed description of the requirement
|
||||||
|
std::string acceptance_criteria; // Criteria that must be met for the requirement to be considered complete
|
||||||
|
bool is_smart; // SMART indicator (Specific, Measurable, Achievable, Relevant, Time-bound)
|
||||||
|
};
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
struct Classification
|
||||||
|
{
|
||||||
|
std::string type; // Type of the requirement (e.g., "Functional", "Non-Functional", "Performance", etc.)
|
||||||
|
std::string category; // Category of the requirement (e.g., "UI", "Backend", "Security", etc.)
|
||||||
|
int priority; // Priority level of the requirement (e.g., 1 for highest priority, 5 for lowest)
|
||||||
|
Status status; // Current status of the requirement (e.g., "Draft", "In Review", "Approved", "Rejected", etc.)
|
||||||
|
};
|
||||||
|
//--------------------------------------------------------------
|
||||||
struct Requirement
|
struct Requirement
|
||||||
{
|
{
|
||||||
std::string uuid;
|
Metadata metadata; // General information about the requirement
|
||||||
std::string parent_uuid;
|
Details details; // Detailed information about the requirement
|
||||||
std::string id;
|
Classification classification; // Classification information about the requirement
|
||||||
std::string type;
|
|
||||||
std::string name;
|
|
||||||
std::string description;
|
|
||||||
std::vector<Requirement> sub_requirements;
|
|
||||||
|
|
||||||
/* Default constructor */
|
|
||||||
Requirement()
|
|
||||||
{
|
|
||||||
uuid = sdi_toolBox::generic::UuidGenerator::uuid_v4(); // Generate a unique UUID for the requirement
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|
||||||
@@ -37,11 +62,11 @@ struct RequirementEvent : dBus::api::DefaultData<dBus::makeID("requirement.requi
|
|||||||
|
|
||||||
[[nodiscard]] std::string toString() const override
|
[[nodiscard]] std::string toString() const override
|
||||||
{
|
{
|
||||||
return std::format("RequirementEvent: id={}, name={}, subRequirementsCount={}",
|
// return std::format("RequirementEvent: id={}, name={}, subRequirementsCount={}",
|
||||||
requirementData.id,
|
// requirementData.id,
|
||||||
requirementData.name,
|
// requirementData.name,
|
||||||
requirementData.description,
|
// requirementData.description);
|
||||||
requirementData.sub_requirements.size());
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|||||||
73
src/core/projectManager/RequirementManager.cpp
Normal file
73
src/core/projectManager/RequirementManager.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include "RequirementManager.h"
|
||||||
|
|
||||||
|
#include "requirementItem.h"
|
||||||
|
|
||||||
|
#include <sdi_toolBox/generic/uuid.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace core::project;
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Default constructor */
|
||||||
|
RequirementManager::RequirementManager()
|
||||||
|
{
|
||||||
|
m_rootRequirement = make_shared<RequirementItem>(*this); // Create the root requirement item and set it as the root requirement
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Get the root requirement */
|
||||||
|
RequirementManager::RequirementItemPtr RequirementManager::getRootRequirement() const
|
||||||
|
{
|
||||||
|
return m_rootRequirement; // Return the root requirement item pointer
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Get the vector of child requirement items of the root requirement */
|
||||||
|
std::vector<RequirementManager::RequirementItemPtr> RequirementManager::getRootRequirementChild() const
|
||||||
|
{
|
||||||
|
return m_rootRequirement->getChildren(); // Return the vector of child requirement items of the root requirement
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Get a requirement by its UUID */
|
||||||
|
RequirementManager::RequirementItemPtr RequirementManager::getRequirement(const std::string &uuid) const
|
||||||
|
{
|
||||||
|
if (m_requirementsByUuid.contains(uuid))
|
||||||
|
return m_requirementsByUuid.at(uuid); // Return the requirement item pointer if found in the map
|
||||||
|
return {}; // Return nullptr if the requirement with the given UUID is not found
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Get the vector of child requirement items of a requirement by its UUID */
|
||||||
|
std::vector<RequirementManager::RequirementItemPtr> RequirementManager::getRequirementChildren(const std::string &uuid) const
|
||||||
|
{
|
||||||
|
if (m_requirementsByUuid.contains(uuid))
|
||||||
|
return m_requirementsByUuid.at(uuid)->getChildren(); // Return the vector of child requirement items if the requirement with the given UUID is found in the map
|
||||||
|
return {}; // Return an empty vector if the requirement with the given UUID is not found
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Generate a unique UUID string that is not already registered in the manager's internal map */
|
||||||
|
std::string RequirementManager::generateUniqueUuid() const
|
||||||
|
{
|
||||||
|
std::string uuid;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uuid = sdi_toolBox::generic::UuidGenerator::uuid_v4(); // Generate a random UUID v4 string
|
||||||
|
} while (isRequirementRegistered(uuid)); // Check if the generated UUID is already registered
|
||||||
|
|
||||||
|
return uuid; // Return the unique UUID string
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Check if a requirement with the given UUID is registered in the manager's internal map */
|
||||||
|
bool RequirementManager::isRequirementRegistered(const std::string &uuid) const
|
||||||
|
{
|
||||||
|
return m_requirementsByUuid.contains(uuid);
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Register a requirement in the manager's internal map for quick lookup by UUID */
|
||||||
|
void RequirementManager::registerRequirement(const RequirementItemPtr &requirement)
|
||||||
|
{
|
||||||
|
m_requirementsByUuid[requirement->metadata.uuid] = requirement;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Unregister a requirement from the manager's internal map */
|
||||||
|
void RequirementManager::unregisterRequirement(const std::string &uuid)
|
||||||
|
{
|
||||||
|
m_requirementsByUuid.erase(uuid);
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
42
src/core/projectManager/RequirementManager.h
Normal file
42
src/core/projectManager/RequirementManager.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace core::project
|
||||||
|
{
|
||||||
|
class RequirementItem;
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
class RequirementManager
|
||||||
|
{
|
||||||
|
using RequirementItemPtr = std::shared_ptr<RequirementItem>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RequirementManager(); // Default constructor
|
||||||
|
virtual ~RequirementManager() = default; // Default destructor
|
||||||
|
RequirementManager(const RequirementManager &obj) = delete; // Copy constructor
|
||||||
|
RequirementManager(RequirementManager &&obj) noexcept = delete; // Move constructor
|
||||||
|
RequirementManager &operator=(const RequirementManager &obj) = delete; // Copy assignment operator
|
||||||
|
RequirementManager &operator=(RequirementManager &&obj) noexcept = delete; // Move assignment operator
|
||||||
|
|
||||||
|
[[nodiscard]] RequirementItemPtr getRootRequirement() const; // Get the root requirement
|
||||||
|
[[nodiscard]] std::vector<RequirementItemPtr> getRootRequirementChild() const; // Get the vector of child requirement items of the root requirement
|
||||||
|
|
||||||
|
[[nodiscard]] RequirementItemPtr getRequirement(const std::string &uuid) const; // Get a requirement by its UUID
|
||||||
|
[[nodiscard]] std::vector<RequirementItemPtr> getRequirementChildren(const std::string &uuid) const; // Get the vector of child requirement items of a requirement by its UUID
|
||||||
|
|
||||||
|
// Requirement management functions
|
||||||
|
[[nodiscard]] std::string generateUniqueUuid() const; // Generate a unique UUID string that is not already registered in the manager's internal map
|
||||||
|
[[nodiscard]] bool isRequirementRegistered(const std::string &uuid) const; // Check if a requirement with the given UUID is registered in the manager's internal map
|
||||||
|
void registerRequirement(const RequirementItemPtr &requirement); // Register a requirement in the manager's internal map for quick lookup by UUID
|
||||||
|
void unregisterRequirement(const std::string &uuid); // Unregister a requirement from the manager's internal map
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RequirementItemPtr m_rootRequirement; // Root requirement of the current project
|
||||||
|
std::unordered_map<std::string, RequirementItemPtr> m_requirementsByUuid; // Map of requirement UUID to requirement pointer for quick lookup
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
} // namespace core::project
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "projectData.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace core::project;
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
/* Get the root requirement */
|
|
||||||
ProjectData::RequirementPtr ProjectData::getRootRequirement()
|
|
||||||
{
|
|
||||||
return m_rootRequirement;
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <api/requirement.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace core::project
|
|
||||||
{
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
class ProjectData
|
|
||||||
{
|
|
||||||
using RequirementPtr = std::shared_ptr<api::requirement::Requirement>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ProjectData() = default; // Default constructor
|
|
||||||
virtual ~ProjectData() = default; // Default destructor
|
|
||||||
ProjectData(const ProjectData &obj) = delete; // Copy constructor
|
|
||||||
ProjectData(ProjectData &&obj) noexcept = delete; // Move constructor
|
|
||||||
ProjectData &operator=(const ProjectData &obj) = delete; // Copy assignment operator
|
|
||||||
ProjectData &operator=(ProjectData &&obj) noexcept = delete; // Move assignment operator
|
|
||||||
|
|
||||||
RequirementPtr getRootRequirement(); // Get the root requirement
|
|
||||||
|
|
||||||
protected:
|
|
||||||
RequirementPtr m_rootRequirement; // Root requirement of the current project
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
} // namespace core::project
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "projectManager.h"
|
#include "projectManager.h"
|
||||||
|
|
||||||
#include "projectData.h"
|
#include "RequirementManager.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace core::project;
|
using namespace core::project;
|
||||||
@@ -117,7 +117,7 @@ void ProjectManager::on_projectOperationEvent(const ProjectOperationMessage_ptr
|
|||||||
/* Process a file creation event */
|
/* Process a file creation event */
|
||||||
void ProjectManager::on_projectCreateFileEvent(const ProjectOperationMessage_ptr &message)
|
void ProjectManager::on_projectCreateFileEvent(const ProjectOperationMessage_ptr &message)
|
||||||
{
|
{
|
||||||
m_projectData = make_shared<ProjectData>();
|
m_requirementManager = make_shared<RequirementManager>();
|
||||||
|
|
||||||
message->responsePromise.set_value();
|
message->responsePromise.set_value();
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ void ProjectManager::on_projectSaveFileEvent(const ProjectOperationMessage_ptr &
|
|||||||
/* Process a file close event */
|
/* Process a file close event */
|
||||||
void ProjectManager::on_projectCloseFileEvent(const ProjectOperationMessage_ptr &message)
|
void ProjectManager::on_projectCloseFileEvent(const ProjectOperationMessage_ptr &message)
|
||||||
{
|
{
|
||||||
m_projectData = {};
|
m_requirementManager = {};
|
||||||
message->responsePromise.set_value();
|
message->responsePromise.set_value();
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
namespace core::project
|
namespace core::project
|
||||||
{
|
{
|
||||||
class ProjectData;
|
class RequirementManager;
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
class ProjectManager : public dBus::Node
|
class ProjectManager : public dBus::Node
|
||||||
{
|
{
|
||||||
using ProjectPtr = std::shared_ptr<ProjectData>;
|
using RequirementManagerPtr = std::shared_ptr<RequirementManager>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProjectManager() = delete; // Default constructor
|
ProjectManager() = delete; // Default constructor
|
||||||
@@ -27,7 +27,7 @@ class ProjectManager : public dBus::Node
|
|||||||
protected:
|
protected:
|
||||||
std::filesystem::path m_filePath; // Path of the currently opened project file
|
std::filesystem::path m_filePath; // Path of the currently opened project file
|
||||||
|
|
||||||
ProjectPtr m_projectData; // Current project data, including the root requirement and all its sub-requirements
|
RequirementManagerPtr m_requirementManager; // Pointer to the requirement manager of the current project
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void openFile(const std::filesystem::path &filePath); // Open a project file and load the requirements
|
void openFile(const std::filesystem::path &filePath); // Open a project file and load the requirements
|
||||||
|
|||||||
56
src/core/projectManager/requirementItem.cpp
Normal file
56
src/core/projectManager/requirementItem.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "requirementItem.h"
|
||||||
|
|
||||||
|
#include "RequirementManager.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace core::project;
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Constructor */
|
||||||
|
RequirementItem::RequirementItem(RequirementManager &manager, const std::shared_ptr<RequirementItem> &parentRequirement)
|
||||||
|
: m_requirementManager(manager)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
metadata.uuid = m_requirementManager.generateUniqueUuid(); // Generate a unique UUID for this requirement item
|
||||||
|
m_parent = parentRequirement; // Set the m_parent requirement item
|
||||||
|
|
||||||
|
// Register this requirement item in the manager's internal map
|
||||||
|
m_requirementManager.registerRequirement(shared_from_this());
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Append a child requirement item to this requirement item */
|
||||||
|
void RequirementItem::appendChild(const api::requirement::Requirement &child)
|
||||||
|
{
|
||||||
|
// Create a new requirement item for the child requirement and set this requirement item as its m_parent
|
||||||
|
const auto childItem = make_shared<RequirementItem>(m_requirementManager);
|
||||||
|
childItem->metadata = child.metadata;
|
||||||
|
childItem->details = child.details;
|
||||||
|
childItem->classification = child.classification;
|
||||||
|
|
||||||
|
// Prepare requirement links
|
||||||
|
childItem->metadata.uuid = m_requirementManager.generateUniqueUuid(); // Generate a unique UUID for this requirement item
|
||||||
|
childItem->m_parent = shared_from_this();
|
||||||
|
|
||||||
|
// Register this requirement item in the manager's internal map
|
||||||
|
m_requirementManager.registerRequirement(childItem);
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Remove a child requirement item from this requirement item by its UUID */
|
||||||
|
void RequirementItem::removeChild(const std::string &childUuid)
|
||||||
|
{
|
||||||
|
// Unregister the child requirement item from the manager's internal map
|
||||||
|
m_requirementManager.unregisterRequirement(childUuid);
|
||||||
|
|
||||||
|
// Find the child requirement item with the given UUID
|
||||||
|
const auto it = ranges::find_if(m_children,
|
||||||
|
[&childUuid](const RequirementItemPtr &child)
|
||||||
|
{ return child->metadata.uuid == childUuid; });
|
||||||
|
if (it != m_children.end())
|
||||||
|
m_children.erase(it); // Remove the child requirement item from the vector of children
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
/* Get the vector of child requirement items of this requirement item */
|
||||||
|
std::vector<RequirementItem::RequirementItemPtr> RequirementItem::getChildren() const
|
||||||
|
{
|
||||||
|
return m_children;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------
|
||||||
38
src/core/projectManager/requirementItem.h
Normal file
38
src/core/projectManager/requirementItem.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <api/requirement.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace core::project
|
||||||
|
{
|
||||||
|
class RequirementManager;
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
class RequirementItem : public std::enable_shared_from_this<RequirementItem>
|
||||||
|
, public api::requirement::Requirement
|
||||||
|
{
|
||||||
|
using RequirementItemPtr = std::shared_ptr<RequirementItem>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RequirementItem() = delete; // Default constructor
|
||||||
|
virtual ~RequirementItem() = default; // Default destructor
|
||||||
|
RequirementItem(const RequirementItem &obj) = delete; // Copy constructor
|
||||||
|
RequirementItem(RequirementItem &&obj) noexcept = delete; // Move constructor
|
||||||
|
RequirementItem &operator=(const RequirementItem &obj) = delete; // Copy assignment operator
|
||||||
|
RequirementItem &operator=(RequirementItem &&obj) noexcept = delete; // Move assignment operator
|
||||||
|
|
||||||
|
explicit RequirementItem(RequirementManager &manager, // Constructor
|
||||||
|
const std::shared_ptr<RequirementItem> &parentRequirement = nullptr);
|
||||||
|
|
||||||
|
// Children management functions
|
||||||
|
void appendChild(const api::requirement::Requirement &child); // Append a child requirement item to this requirement item
|
||||||
|
void removeChild(const std::string &childUuid); // Remove a child requirement item from this requirement item by its UUID
|
||||||
|
[[nodiscard]] std::vector<RequirementItemPtr> getChildren() const; // Get the vector of child requirement items of this requirement item
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RequirementManager &m_requirementManager; // Reference to the requirement manager that owns this requirement item
|
||||||
|
std::weak_ptr<RequirementItem> m_parent; // Weak pointer to the m_parent requirement item (nullptr for root)
|
||||||
|
std::vector<RequirementItemPtr> m_children; // Vector of shared pointers to child requirement items
|
||||||
|
};
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
} // namespace core::project
|
||||||
Reference in New Issue
Block a user